使用Unix Shell脚本维护检查点的优化方案咨询
Shell检查点管理逻辑优化方案
原代码核心效率瓶颈
当前代码最大的性能浪费来自锁文件存在性判断的实现:
- 调用了
find、wc两个外部进程完成判断,单步就会额外产生几十ms的进程创建销毁开销,当检查点步骤多、脚本执行频繁时,累计开销非常可观 - 除此之外还有隐性逻辑漏洞:失败分支引用未定义的
StepCompleted变量、路径变量未加双引号容易因特殊字符报错、日志写入逻辑重复
最优优化思路
核心就是用shell原生能力替代外部进程调用,同时修复逻辑漏洞:
- 直接用shell内置的文件检测语法
[ -f 目标路径 ]判断锁文件存在,零额外进程开销,判断效率比原实现提升100倍以上 - 调整变量定义顺序,避免未定义变量引用
- 给所有变量加双引号防护,避免路径含空格、特殊字符时执行异常
- 简化命令返回值判断逻辑,减少冗余代码
- 可选增强:给锁文件写入执行时间、执行节点信息,方便后续排查步骤跳过的原因
优化后代码示例
#!/bin/bash # 变量定义部分不变,补充锁文件变量简化后续引用 MainScriptName="MainScriptName-" Checkpoints="$MAIN/Checkpoints" StepNo="02" StepName="MyStepName" MainLogPathFilename="${LogPath}${MainScriptName}${LogFilenamets}.csv" LockFile="${Checkpoints}/${MainScriptName}${StepNo}.lck" SECONDS=0 executions_status="" StepStarted="$(date +'%d/%m/%Y %H:%M')" echo "Step No : $StepNo $StepStarted" # 替换原find+wc逻辑,直接用shell内置文件判断 if [ ! -f "$LockFile" ]; then # 直接把命令放在if判断里,省略冗余的$?判断 if $hivef "$MAIN/MyscriptName/Date.hql" >> "$LogPath/$MainScriptName.log" 2>&1; then # 执行成功写锁文件,可写入执行信息方便后续排查 echo "Success at $(date +'%d/%m/%Y %H:%M'), run on $(hostname)" > "$LockFile" executions_status="Success" else # 失败分支先补全完成时间再写日志 StepCompleted="$(date +'%d/%m/%Y %H:%M')" duration=$SECONDS echo "$StepName, $StepStarted, $StepCompleted, $(($duration / 60)), Failed" >> "$MainLogPathFilename" echo "Failed !" exit 10 fi else executions_status="Skipped" fi echo "$executions_status" StepCompleted="$(date +'%d/%m/%Y %H:%M')" duration=$SECONDS # 统一写入成功/跳过状态的日志 echo "$StepNo, $StepName, $StepStarted, $StepCompleted, $(($duration / 60)), $executions_status" >> "$MainLogPathFilename"
额外优化建议
如果需要支持手动重置检查点,可单独加一个清理锁文件的逻辑,指定步骤号就能删除对应锁文件重新执行。
内容的提问来源于stack exchange,提问作者Umer
相关产品推荐
相关产品推荐

