Shell腳本的並行處理


本隨筆主要講述在shell編程中實現任務並發處理。

參考自:https://www.cnblogs.com/pmars/archive/2012/11/15/2771609.html

一、調度腳本

#!/bin/sh

help()
{
    echo "使用說明:"
    echo " $0 子進程腳本 [slots]"

    exit
}

if [ $# -lt 1 ]; then help; fi

#總任務數量
nJobs=4671
nSlots=${2:-8}
#設定工作目錄
WORK_PATH=`pwd`
#設定工作腳本
work_script=$1
#actor下載地址
URL_ACTOR="https://www.meituri.com/t"
URL=$URL_ACTOR
#中斷退出標志變量
exit_flag=0
#臨時測試變量
flag=0
flag_set=1

exit_generate(){
	if [ $exit_flag -eq 1 ]; then
		echo "檢測到重復操作,強制退出,會丟失保存數據"
                exit 1
	fi
	exit_flag=1
	echo "保存配置文件"
	echo "flag=$flag flag_set=$flag_set cjob=$cjob nJobs=$nJobs" > config.ini
    echo "等待子線程結束..."
    while [ ${finish} -eq 0 ]; do
        finish=1
        idx=1
        while [ ${idx} -le ${nSlots} ]; do
            if [ -f $$_lock_${idx}.lck ]; then
                finish=0
                jobsDump ${idx}
            else
                rm -f "$$_dump_${idx}.dmp"
                jobsDump ${idx} "本線程任務已結束..."
            fi
        idx=$((idx + 1))
        done
	sleep 1
    done
    echo "所有子線程已經全部結束,正常退出!"
	exit 1
}

exit_2(){
	echo "捕獲中斷信號:SIGINT"
	exit_generate
}

exit_15(){
	echo "捕獲中斷信號:SIGTERM"
	exit_generate
}

#設置中斷捕獲響應
trap exit_2 2
trap exit_15 15
jobsInit()
{
    clear
    echo "$1"", ${nSlots} downloader"

    idx=1
    while [ $idx -le ${nSlots} ]; do
        printf "\033[01;34mSlot %2d:\033[00m " $idx
        idx=$((idx + 1))
    done
}

jobsDump()
{
    printf "\033[01;34mSlot %2d:\033[00m `date +%H:%M:%S` " $1

    if [ -f $$_dump_$1.dmp ]; then
        echo "`head -n1 $$_dump_$1.dmp`"
    elif [ v"$2" != "v" ]; then
        echo "$2"
    fi
}

jobsInfo()
{
    echo $*
}
if [ -f config.ini ]; then
    echo "讀取配置文件,恢復上一次的下載記錄"
	. ./config.ini
else
	# clean dir	
	rm -rf Downloads
	rm -f weblinklist.txt
    cjob=0
fi
# Process jobs

finish=0
jobs_name="任務"

while [ ${finish} -eq 0 ]; do
    jobsInfo "正在處理 ${cjob}/${nJobs} $jobs_name..."
    finish=1
    idx=1
    while [ ${idx} -le ${nSlots} ]; do
        if [ -f $$_lock_${idx}.lck ]; then
            finish=0
            jobsDump ${idx}
        else
            rm -f "$$_lock_${idx}.lck" "$$_dump_${idx}.dmp"
            jobsDump ${idx} "空閑."

            if [ ${cjob} -lt ${nJobs} ]; then
                finish=0
          #這里調度工作腳本,可以在這前面寫邏輯生成調度腳本的參數

          #這里通過新開shell來執行,防止調度腳本被中斷后工作腳本一同遭殃
sh $work_script $$ ${idx} "$$_lock_${idx}.lck" "$$_dump_${idx}.dmp" $WORK_PATH $flag $URL $flag_set & #創建/更新目錄鎖文件 #touch "$$_lock_${idx}.lck"; # Dump process info jobsDump ${idx} "已分配任務,工作中..." cjob=$((cjob + 1)) fi fi idx=$((idx + 1)) done sleep 1 done echo "所有任務已完成" #刪除創建的所有臨時文件 rm -f $$_*

 調度腳本主要負責調度用於執行真正工作任務的工作腳本,同時承擔向工作腳本傳不同的參數來向工作腳本下發不同的任務。

本腳本在原有參考的基礎上進行了改進,新增中斷捕獲(兩次中斷強制退出),可以在結束任務的時候依舊保證各工作腳本的工作不被打斷,同時監控各工作腳本的運行情況,此時不會再下發新任務,同時會保存當前的工作記錄,可用於下一次啟動的恢復上次工作的位置;修改了鎖文件創建的邏輯,由被調度腳本創建並自行銷毀,解決捕獲中斷可能造成的鎖文件存在但工作任務未被調度的情況。

二、工作腳本

#!/bin/sh

# dowork.sh
# 調用方法和參數總結
# 該腳本被multi.sh調用執行,傳遞給腳本7-8個參數
# param 1: PID of multi.sh
# param 2: slot number
# param 3: lock file name
# param 4: info file name
# param 5: working dir
# param 6: working flag (set 0 to actorParser, set 1 to downloadParser)


#創建線程鎖文件,標識線程運行態
touch "$3";
#配置文件
#wget下載參數配置
#重試次數:5,超時時間:5
tries=5
timeout=5
#宏參量定義
output=`pwd`/$4

#配置文件結束

#主程序起始點
#向output輸出的信息可以被調度腳本所打印 echo "子進程接受下發任務,准備處理,工作標志flag=$6" > $output # 在這上面可以寫該腳本需要完成命令 echo "$2當前任務執行完畢,退出" > $output # 腳本運行完了,在這里將鎖文件刪除,multi.sh就可以知道該腳本執行完畢了 rm -f $3

 該腳本用於接受來自調度腳本下發的任務並運行,通過創建的info文件向調度腳本實時匯報自身工作狀態。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM