• 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 "33[01;34mSlot %2d:33[00m " $idx
            idx=$((idx + 1))
        done
    }
    
    jobsDump()
    {
        printf "33[01;34mSlot %2d:33[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文件向调度脚本实时汇报自身工作状态。

  • 相关阅读:
    JavaScript 把函数作为参数进行传值
    面向微服务的企业云计算架构转型
    bzoj1009 GT考试 (kmp+矩阵优化dp)
    noiac64 sort (二分答案)
    luogu1983 车站分级 (拓扑排序)
    loj6157 A ^ BProblem (并查集)
    bzoj1831 逆序对 (dp+树状数组)
    luogu2282/bzoj1219 历史年份 (dp+hash+二分+线段树)
    bzoj3702/bzoj2212 二叉树 (线段树合并)
    cf1073G Yet Another LCP Problem (SA+权值线段树)
  • 原文地址:https://www.cnblogs.com/jsp1256/p/9826654.html
Copyright © 2020-2023  润新知