如何单独捕获Bash子shell的stderr并与stdout分离?
分离捕获子shell的标准输出与错误输出
要单独捕获子shell的stderr并与stdout分离,你可以用以下两种方法实现:
方法一:使用命名管道(推荐,子shell仅执行一次)
这种方法通过创建临时命名管道,让子shell的stdout和stderr分别写入不同管道,父进程再通过文件描述符读取内容:
# 创建临时命名管道 mkfifo stdout_pipe stderr_pipe # 在后台启动子shell,将stdout写入stdout_pipe,stderr写入stderr_pipe ( sleep 1 && echo success && cat file-not-found ) >stdout_pipe 2>stderr_pipe & # 将文件描述符3关联到stdout_pipe,4关联到stderr_pipe exec 3<stdout_pipe 4<stderr_pipe # 读取子shell的stdout cat <&3 # 输出:success # 读取子shell的stderr(确认是否为空) cat <&4 # 输出:cat: file-not-found: 没有那个文件或目录 # 清理临时管道 rm stdout_pipe stderr_pipe
方法二:使用双重进程替换(简单但子shell执行两次)
如果你的子shell命令没有副作用(比如不会修改文件、不依赖外部状态变化),可以直接用两个进程替换分别捕获stdout和stderr:
# 将stdout绑定到fd3,stderr绑定到fd4 exec 3< <(sleep 1 && echo success && cat file-not-found) \ 4< <(sleep 1 && echo success && cat file-not-found 2>&1 >/dev/null) # 读取stdout cat <&3 # 输出:success # 读取stderr(验证是否为空) cat <&4 # 输出:cat: file-not-found: 没有那个文件或目录
关键说明
- 方法一中,子shell仅执行一次,stdout和stderr分别写入对应管道,避免了重复执行命令的问题。
- 方法二中,第二个进程替换通过
2>&1 >/dev/null将stderr重定向到stdout,同时丢弃原stdout,从而只获取错误输出。
内容的提问来源于stack exchange,提问作者Rovanion
相关产品推荐
相关产品推荐

