BASH:如何用trap或命名管道捕获进程替换(tar)的退出码?
捕获进程替换中tar命令的退出码解决方案
你遇到的核心问题是:进程替换<(...)运行在独立子shell中,子shell内赋值的CHECK变量无法传递回父shell,所以父shell里的CHECK为空。下面提供几种不用临时文件的解决方案:
方案1:使用命名管道传递退出码
命名管道是内存级临时通道,不会生成磁盘文件,适合传递退出码这类小数据:
# 创建命名管道 mkfifo tar_exit_pipe # 后台启动while循环+进程替换,同时将tar退出码写入管道 while IFS= read -r LINE; do some_command_processing "$LINE" done < <(tar PJcvf none.tar.xz /none_exist 2>&1; echo $? > tar_exit_pipe) & # 从管道读取退出码 CHECK=$(cat tar_exit_pipe) # 清理命名管道 rm tar_exit_pipe # 等待后台的while循环执行完毕 wait echo "tar命令的退出码:$CHECK"
方案2:使用bash协同进程(coproc)
coproc可以同时捕获子进程的输出和退出状态,无需额外管道文件:
# 启动协同进程,执行tar并最后输出退出码 coproc TAR_PROC { tar PJcvf none.tar.xz /none_exist 2>&1; echo $?; } # 读取协同进程的输出,分离正常日志和退出码 while IFS= read -r LINE <&"${TAR_PROC[0]}"; do # 判断是否为数字格式的退出码 if [[ "$LINE" =~ ^[0-9]+$ ]]; then CHECK=$LINE break fi some_command_processing "$LINE" done # 关闭协同进程的文件描述符 exec {TAR_PROC[0]}>&- echo "tar命令的退出码:$CHECK"
方案3:利用文件描述符传递退出码
通过exec创建自定义文件描述符,将退出码从子shell传递到父shell:
# 创建文件描述符,关联到读取退出码的子shell exec {EXIT_FD}> >(read -r CHECK; : ) # 执行while循环,进程替换内将tar退出码写入文件描述符 while IFS= read -r LINE; do some_command_processing "$LINE" done < <(tar PJcvf none.tar.xz /none_exist 2>&1; echo $? >&$EXIT_FD) # 关闭文件描述符,触发子shell的read命令完成 exec {EXIT_FD}>&- echo "tar命令的退出码:$CHECK"
关于trap的说明
trap主要用于捕获信号(比如SIGINT、SIGTERM),无法直接捕获子进程的退出码,因此不适合解决这个问题。
内容的提问来源于stack exchange,提问作者Krzysztof Filipiak
相关产品推荐
相关产品推荐

