最近工作接觸到了一些Linux上面的文本處理,數據量還是蠻大的,不可避免的學期了shell,awk等腳本語言。
在文本處理的過程中發現:
1,文本的數量比較大
2,文本的內容相似,可以用同樣的腳本處理
3,串行處理文本速度較慢
這自然會想到,如何才能並行多線程處理文本呢,就是因為這個需求,導致下面腳本程序的誕生。
multi.sh,主要工作就是多次調用同一腳本處理不同文本內容,互不干擾。

#! /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 ---> 參數文件

#! /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挺好用的,所以記在這里,大家學習!