shell脚本的并行处理方法——multi.sh介绍

本文介绍了一个利用multi.sh与dowork.sh脚本实现文本数据并行处理的方法,通过创建多个线程同时处理不同文本内容,显著提高了处理效率。特别适用于大规模文本数据的快速处理场景。

最近工作接触到了一些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挺好用的,所以记在这里,大家学习!

<think>嗯,用户现在的问题是如何在shell脚本中调用Makefile的特定target。根据之前的对话,用户已经了解了shell脚本中使用target的几种情况,包括处理参数、调用Makefile目标以及管理系统服务。现在需要结合用户提供的引用内容来详细回答这个问题。 首先,用户提到的引用[1]和[2]提到了Makefile和Shell脚本的交互,特别是引用[1]中的策略提到Makefile通过$(shell ...)函数调用Shell脚本,而Shell脚本处理具体任务。这可能涉及到如何在Makefile中调用shell脚本,但现在用户的问题相反,是shell脚本如何调用Makefile的target。 引用[2]详细说明了Makefile的结构,包括target、prerequisites和commands。引用[4]解释了Makefile的执行流程,特别是默认情况下寻找第一个target。引用[5]展示了Makefile中如何执行shell命令,并且变量传递的问题。用户的问题可能涉及到如何在shell脚本中正确调用Makefile的target,并处理变量传递的问题。 用户可能在开发自动化构建流程,希望用shell脚本作为入口,调用不同的Makefile target来执行不同的构建步骤。比如,在持续集成/持续部署(CI/CD)中,shell脚本可能负责协调多个构建步骤,而每个步骤由Makefile的target处理。 需要确定几种方法:直接调用make命令指定target、传递变量、处理多个target、错误处理以及目录切换。根据引用[4],在shell脚本中执行make命令时,可以通过-f指定Makefile文件,如果不在当前目录需要切换目录或者使用路径。引用[5]中的例子显示在Makefile中使用shell函数执行命令,但用户的问题是关于shell脚本调用Makefile,所以重点应放在shell脚本中如何调用make命令。 此外,用户可能遇到变量传递的问题,如引用[3]提到的,如果在不同目录执行make命令,变量可能无法正确传递到调用的shell脚本中。需要建议在调用make时通过命令行参数传递变量,例如使用VAR=value的形式。 还需要考虑错误处理,比如在shell脚本中检查make命令的退出状态,确保某target失败后脚本能正确处理。引用[1]中的错误处理提到exit 1,这在shell脚本中也适用,通过检查$?变量判断上一条命令是否成功。 最后,用户可能需要示例代码,展示如何在shell脚本中调用不同的target,传递变量,处理错误等。结合引用中的例子,给出具体的代码示例,如调用make -C指定目录,或者使用变量覆盖等。</think>### Shell脚本调用Makefile Target的完整实现方案 在Shell脚本中调用Makefile的特定目标(target)是自动化构建系统的常见需求,以下通过五种典型场景详细说明实现方法: --- #### 一、基础调用方式 **场景**:直接调用当前目录下Makefile的目标 ```bash #!/bin/bash # 脚本:build.sh echo "=== 清理构建环境 ===" make clean echo "=== 编译主程序 ===" make build echo "=== 运行单元测试 ===" make test ``` **执行原理**: - 使用标准`make [target]`语法调用目标 - 按顺序执行clean/build/test三个目标[^4] --- #### 二、跨目录调用 **场景**:项目存在子模块时调用不同目录的Makefile ```bash #!/bin/bash # 脚本multi_build.sh # 构建核心模块 make -C core_module/ release # 构建前端界面 make -C frontend/ minify-css # 组合打包 make -C packaging/ create-installer ``` **技术要点**: - `-C`参数指定Makefile所在目录[^4] - 支持并行执行:添加`&`符号实现并发构建 --- #### 三、参数化构建 **场景**:通过脚本参数动态指定构建参数 ```bash #!/bin/bash # 脚本:param_build.sh BUILD_TYPE=${1:-debug} # 默认debug模式 PLATFORM=${2:-linux} # 默认linux平台 make BUILD_MODE=$BUILD_TYPE TARGET_OS=$PLATFORM ``` **执行示例**: ```bash $ ./param_build.sh release windows ``` **变量传递**: - Makefile中通过`$(BUILD_MODE)`接收参数[^3] - 支持默认值设置增强健壮性 --- #### 四、错误处理机制 **场景**:严格验证构建过程结果 ```bash #!/bin/bash # 脚本:safe_build.sh make compile || { echo "编译阶段失败,终止构建" >&2 exit 1 } make package && make upload || { echo "打包/上传阶段失败" >&2 exit 2 } ``` **错误代码处理**: - `||`操作符捕获前序命令的非零退出码 - 自定义退出代码便于问题定位[^1] --- #### 五、高级组合应用 **场景**:混合环境变量与目标调用 ```bash #!/bin/bash # 脚本:deploy.sh export DEPLOY_ENV="production" export BUILD_NUMBER=$(git rev-parse --short HEAD) make prepare-env && \ make docker-build && \ make k8s-deploy ``` **环境管理**: - `export`设置的环境变量可在Makefile中通过`$(DEPLOY_ENV)`访问[^5] - 链式调用确保前置条件满足 --- ### 最佳实践建议 1. **路径处理**:使用`$(MAKE) -C path/to/makefile`确保跨平台兼容性 2. **调试模式**:添加`make --debug=basic`输出详细构建信息 3. **性能优化**:对独立任务使用`make -j [n]`启用并行构建 4. **版本控制**:建议将Makefile与脚本共同纳入Git仓库管理[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值