Unix脚本部分命令未生效:并行执行子脚本后日志追加失败的原因及解决方法
问题解析与解决方案
嘿,作为曾经也踩过shell后台进程坑的过来人,我来给你掰扯清楚这个问题~
为什么你看不到test 1 completed那行日志?
你的问题本质是两个原因叠加导致的:
- 没有等待后台进程执行完毕
你用&把test1.sh和test2.sh放到后台运行后,invoke_test.sh不会等它们跑完,会立刻执行后面的echo追加命令——这时候test1.sh还在sleep 5,test2.sh还在sleep 10,完全没执行完。 - 日志写入的偏移量冲突
test1.sh用>打开output1.log时,会先清空文件,然后持有这个文件的写描述符。当invoke_test.sh的echo命令追加内容到日志末尾后,test1.sh的写指针还停留在它上次写入(running test1.sh)的位置。等test1.sh睡醒执行最后一行echo时,会从这个位置开始写入,直接覆盖掉你刚追加的test 1 completed内容。
如何实现预期效果?
核心就是先等待两个后台脚本完全执行完毕,再追加日志,用shell的wait命令就能轻松搞定。
修改后的invoke_test.sh代码如下:
echo "invoke script started" # 启动两个后台脚本 sh test1.sh > output1.log & sh test2.sh > output2.log & # 等待所有后台子进程执行完毕 wait # 现在再追加日志 echo "test 1 completed " >> output1.log echo "test 2 completed " >> output2.log
代码解释:
&:把脚本放到后台运行,不阻塞当前脚本的执行。wait:不带参数时,会让当前脚本暂停,直到所有后台子进程都执行完成才继续往下走。- 等后台的
test1.sh和test2.sh都跑完并关闭日志文件后,再执行echo追加命令,就不会出现覆盖问题了。
预期日志效果
执行修改后的invoke_test.sh后,output1.log的内容会变成:
running test1.sh test1.sh completed test 1 completed
output2.log同理,会包含test 2 completed那行内容。
内容的提问来源于stack exchange,提问作者Anirudh
相关产品推荐
相关产品推荐

