ste*_*veb 8 bash pipe process-substitution exit-status
This question is similar to the following link, but focused on using the command line (bash shell).
Using a simple example, when doing the following command:
$ cat <(date); echo $?
Fri Jul 7 21:04:38 UTC 2017
0
Run Code Online (Sandbox Code Playgroud)
The exit value is 0 as expected.
In the following command there is an error introduced on purpose, but the return value is still 0:
$ cat <(datE); echo $?
bash: datE: command not found...
Similar command is: 'date'
0
Run Code Online (Sandbox Code Playgroud)
Is there a way to catch that there was an error in the process substitution when run on the command line (i.e. without having to put it into a script) ?
The solution in the included link above kills the script that is running the command.
在 中bash,进程替换作为后台作业启动。您可以使用以下命令获取最后一个进程的主导进程的 pid,$!并且可以使用与wait thatpid其他后台作业类似的方式获取其退出状态:
$ bash -c 'cat <(exit 3); wait "$!"; echo "$?"'
3
Run Code Online (Sandbox Code Playgroud)
现在,如果您需要在同一个命令中使用两个进程替换(如 中所示),那么这将无济于事diff <(cmd1) <(cmd2)。
$ bash -c 'cat <(exit 3) <(exit 4); wait "$!"; echo "$?"'
4
Run Code Online (Sandbox Code Playgroud)
上面的pidexit 3丢失了
它可以通过这种技巧恢复:
unset -v p1 p2
x='!'
cat <(exit 3) ${!x#${p1=$!}} <(exit 4) ${!x#${p2=$!}}
Run Code Online (Sandbox Code Playgroud)
其中两个 pid 都存储在$p1和中$p2,但这没有用,因为只有最后一个被插入到 shell 的作业表中,并且wait将拒绝等待,$p1错误地声称它不是此 shell 的子级,即使$p1尚未终止:
$ cat test-script
unset -v p1 p2
x='!'
set -o xtrace
cat <(echo x; exec >&-; sleep 1; exit 3) ${!x#${p1=$!}} <(exit 4) ${!x#${p2=$!}}
ps -fH
wait "$p1"; echo "$?"
wait "$p2"; echo "$?"
$ bash test-script
++ echo x
++ exec
++ sleep 1
+ cat /dev/fd/63 /dev/fd/62
++ exit 4
x
+ ps -fH
UID PID PPID C STIME TTY TIME CMD
chazelas 15393 9820 0 21:44 pts/4 00:00:00 /bin/zsh
chazelas 17769 15393 0 22:19 pts/4 00:00:00 bash test-script
chazelas 17770 17769 0 22:19 pts/4 00:00:00 bash test-script
chazelas 17772 17770 0 22:19 pts/4 00:00:00 sleep 1
chazelas 17776 17769 0 22:19 pts/4 00:00:00 ps -fH
+ wait 17770
test-script: line 6: wait: pid 17770 is not a child of this shell
+ echo 127
127
+ wait 17771
+ echo 4
4
$ ++ exit 3
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅 @mosvy对Run asynchronoustasks andretrieve their exit code and output in bash的回答
Dop*_*oti -1
In your example:
cat <(datE); echo $?
Run Code Online (Sandbox Code Playgroud)
发生的情况是datE抛出错误并且不生成任何输出。然后它会抛出一个错误代码。然而,(空)输入随后被呈现给它cat,它高兴地什么也没有咀嚼,现在你的退出代码为零。
如果去掉中间步骤,它会按您的预期工作:
$ datE; echo $?
datE: command not found
127
Run Code Online (Sandbox Code Playgroud)
如果您想bash中止管道中的任何故障和任何未捕获的错误,请运行以下两个命令:
set -e
set -o pipefail
Run Code Online (Sandbox Code Playgroud)
其他 shell 可能提供类似的设置。