shell腳本的並行處理方法——multi.sh介紹


最近工作接觸到了一些Linux上面的文本處理,數據量還是蠻大的,不可避免的學期了shell,awk等腳本語言。

在文本處理的過程中發現:

1,文本的數量比較大

2,文本的內容相似,可以用同樣的腳本處理

3,串行處理文本速度較慢

這自然會想到,如何才能並行多線程處理文本呢,就是因為這個需求,導致下面腳本程序的誕生。

multi.sh,主要工作就是多次調用同一腳本處理不同文本內容,互不干擾。

View Code
#!    /bin/bash

# multi.sh
# Shell script with MultiProcess
#
# Created by xingming on 12-9-3.

LC_ALL=zh_CN.UTF-8
export LC_ALL

function help()
{
    echo "Usage:"
    echo " $0 proc job_file [slots]"

    exit
}

if [ $# -lt 2 ]; then help; fi
if [ ! -f $2 ]; then help; fi

fJobs=$2;
nJobs=`cat ${fJobs} | wc -l | sed 's, ,,g'`
nSlots=${3:-9}

function jobsInit()
{
    clear
    echo "$1"", ${nSlots} parser"

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

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

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

function jobsInfo()
{
    tput cup 1 0
    tput el
    echo $*
}


jobsInit "Examining ${nJobs} jobs in directory '`pwd`' now"


# Process jobs
cjob=0
finish=0
while [ ${finish} -eq 0 ]; do
    jobsInfo "Processing ${cjob}/${nJobs} jobs..."

    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" "$$_parm_${idx}.opt"
            jobsDump ${idx} "Empty."

            if [ ${cjob} -lt ${nJobs} ]; then
                finish=0

                touch "$$_lock_${idx}.lck";
                head -n $((cjob + 1)) ${fJobs} | tail -n1 > "$$_parm_${idx}.opt"

                # Call process
                #  param 1: PID of multi.sh
                #  param 2: slot number
                #  param 3: lock file name
                #  param 4: info file name
                #  param 5: param file name
                $1 $$ ${idx} "$$_lock_${idx}.lck" "$$_dump_${idx}.dmp" "$$_parm_${idx}.opt" &

                # Dump process info
                jobsDump ${idx} "Process job..."
                cjob=$((cjob + 1))
            fi
        fi

        idx=$((idx + 1))
    done

    sleep 1
done

tput cup $((nSlots + 2)) 0
echo "All finished."

rm -f $$_*

# vim:ft=sh:ai:cindent:noet:sm:sw=4:ts=4

調用方式,bash /path..path/multi.sh /path...path/dowork.sh /path...path/filenames.txt 30

分解為      上面這一段是調用腳本的方法   上面這一段是調用腳本需要傳遞的參數

參數1:/path...path/dowork.sh 是多線程運行的腳本,他是用來處理大量重復文本的。

參數2:/path...path/filenames.txt 是上面的腳本需要處理的文本數據的全路徑名稱匯總的txt文件

參數3:30 為多線程並行的數量

其實multi.sh 的實現方式也很簡單,他會針對每一個線程創建一個文件,之后將這個文件名稱傳遞給調用的線程,之后會不斷的去查看這個文件是否還存在,(因為線程腳本需要做的事情就是工作完了給multi.sh創建的文件刪除),如果不存在了,說明上一個創建的線程已經工作完畢了,這個時候multi.sh需要在創建一個新的線程(如果還有工作需要完成的話)。

dowork.sh 這個腳本也很容易實現,其工作時,multi.sh會傳遞過來5個參數

# 該腳本被multi.sh調用執行,傳遞給腳本五個參數
# param 1: PID of multi.sh  ---> 基本上沒有用過,不過特殊情況下會使用
# param 2: slot number    ---> 基本上沒有用過,不過特殊情況下會使用
# param 3: lock file name    ---> 作為鎖的文件名稱,腳本運行完畢需要將其刪除
# param 4: info file name    ---> 輸出文件,腳本有什么需要輸出的信息,可將其重定向到這個文件,multi.sh會調用輸出到終端顯示
# param 5: param file name  ---> 參數文件

View Code
#!    /bin/bash

# dowork.sh
# 調用方法和參數總結
# 該腳本被multi.sh調用執行,傳遞給腳本五個參數
# param 1: PID of multi.sh
# param 2: slot number
# param 3: lock file name
# param 4: info file name
# param 5: param file name
# write by xingming on 2012年11月8日11:39:42

# 取出參數文件的全路徑信息
logfilepath=`cat $5`                    # 日志文件名稱的完全路徑

# 先對文件進行解壓縮
echo "這句話會被multi.sh輸出到終端顯示..." > $4

# 在這里可以做該腳本需要完成的內容
...
...
...

echo "腳本執行完畢..." > $4

# 腳本運行完了,在這里將鎖文件刪除,multi.sh就可以知道該腳本執行完畢了
rm -f $3

# all work done!

如此簡單的就將單線程的腳本轉化為了多線程運行是不是很cool呢?

我最近在工作中,越來越發現multi.sh挺好用的,所以記在這里,大家學習!


免責聲明!

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



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