Bash环境下YAD多进度条结合后台进程的退出状态获取问题
解决YAD多进度条下获取子进程退出状态的问题
我来帮你搞定这个YAD多进度条和子进程退出状态的问题!你现在的写法里有几个关键问题导致拿不到正确的退出状态,咱们一步步拆解并解决:
问题根源
你原来的脚本里,把脚本放到子shell后台运行时,X=$!和Y=$!都是子shell的局部变量,父shell根本拿不到这些PID;而且管道会创建额外的子shell环境,进一步导致变量和退出状态无法正确传递。另外,直接把后台进程的输出通过管道传给YAD,还可能因为输出缓冲或进程调度的问题,导致YAD无法正确接收进度信息。
解决方案:用临时文件存储退出状态+进程合并输出
下面是修正后的主脚本,核心思路是用临时文件单独记录每个脚本的退出状态,同时把两个脚本的输出合并后传给YAD:
#!/bin/bash # 创建临时文件,用来存储每个脚本的退出状态 status_file1=$(mktemp) status_file2=$(mktemp) # 运行Script1:输出进度到stdout,退出状态写入临时文件 (./Script1.sh; echo $? > "$status_file1") & pid1=$! # 运行Script2:同样处理 (./Script2.sh; echo $? > "$status_file2") & pid2=$! # 合并两个脚本的输出,传给YAD多进度条 # 用tail -f监听两个进程的输出,直到它们都结束 tail -f --pid="$pid1" --pid="$pid2" <(./Script1.sh) <(./Script2.sh) | \ yad --multi-progress --bar "Bar1:"NORM --bar "Bar2:"NORM # 等待两个脚本完全执行完毕 wait "$pid1" wait "$pid2" # 读取并输出退出状态 status1=$(cat "$status_file1") status2=$(cat "$status_file2") echo "Script 1 returned $status1" echo "Script 2 returned $status2" # 清理临时文件 rm "$status_file1" "$status_file2"
关键细节说明
- 临时文件存储状态:子shell里的退出状态无法直接传递到父shell,所以用
mktemp创建临时文件来保存每个脚本的$?值,父shell可以安全读取。 - 合并输出到YAD:用
<(./Script1.sh)这种进程替换语法,把两个脚本的输出合并成一个数据流传给YAD,确保进度条能正确接收所有进度更新。 - 等待进程完成:用
wait命令确保两个脚本都执行完毕后再读取退出状态,避免读取到空文件或错误值。
可选优化:用命名管道替代进程替换
如果你觉得进程替换的方式不够直观,也可以用命名管道来合并输出:
#!/bin/bash # 创建命名管道 yad_pipe=$(mktemp -u) mkfifo "$yad_pipe" # 启动YAD读取管道内容 yad --multi-progress --bar "Bar1:"NORM --bar "Bar2:"NORM < "$yad_pipe" & yad_pid=$! # 运行脚本并输出到管道,同时记录退出状态 (./Script1.sh > "$yad_pipe"; echo $? > script1.status) & pid1=$! (./Script2.sh > "$yad_pipe"; echo $? > script2.status) & pid2=$! # 等待脚本执行完毕,关闭管道 wait "$pid1" "$pid2" rm "$yad_pipe" # 等待YAD关闭 wait "$yad_pid" # 读取状态 echo "Script 1 returned $(cat script1.status)" echo "Script 2 returned $(cat script2.status)" rm script1.status script2.status
这样也能达到同样的效果,而且管道的方式对新手来说可能更容易理解。
内容的提问来源于stack exchange,提问作者Jon Bell
相关产品推荐
相关产品推荐

