zoukankan      html  css  js  c++  java
  • 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挺好用的,所以记在这里,大家学习!

  • 相关阅读:
    Spring攻略学习笔记(3.00)AOP核心概念和术语
    zoj 3494
    第43周星期五
    findBugs学习小结
    第42周星期日
    Cookie知识小结
    第42周星期三
    第42周星期六
    第43周星期四小结
    第43周星期二
  • 原文地址:https://www.cnblogs.com/pmars/p/2771609.html
Copyright © 2011-2022 走看看