我想在给定的时间内监视过程的输出。除了给我运行命令的返回值之外,下面的命令可以满足我的所有要求。
cmd='cat <<EOF
My
Three
Lines
EOF
exit 2
'
perl -pe "if (/Hello/) { print \$_; exit 1 }" <(echo "$cmd" | timeout
5 bash)
有人能获得该返回值吗?我在这里查看了其他问题,但是在这种情况下,没有答案适用。
答案 0 :(得分:2)
wait
Bash仅使收集版本4.4中的进程替换的退出状态成为可能。由于无论如何我们都需要该版本,最好也使用自动FD分配。 :)
exec {psfd}< <(echo "hello"; exit 3); procsub_pid=$!
cat <&$psfd # read from the process substitution so it can exit
exec {psfd}<&- # close the FD
wait "$procsub_pid" # wait for the process to collect its exit status
echo "$?"
...正确返回:
3
在您的代码上下文中,可能类似于:
cmd() { printf '%s\n' My Three Lines; exit 2; }
export -f cmd
exec {psfd}< <(timeout 5 bash -c cmd); ps_pid=$!
perl -pe "if (/Hello/) { print \$_; exit 1 }" <&$psfd
echo "Perl exited with status $?"
wait "$ps_pid"; echo "Process substitution exited with status $?"
...作为输出发射:
Perl exited with status 0
Process substitution exited with status 2
虽然可以在最近的Shell版本中解决此问题,但通常来说,进程替换会占用退出状态。更重要的是,在给出的示例中根本不需要它们。
如果设置pipefail
shell选项,则管道中任何组件(不仅是最后一个组件)的退出状态都将反映在管道的退出状态中。因此,您无需使用进程替换也可以尊重perl
的退出状态。
#!/usr/bin/env bash
set -o pipefail
cmd() { printf '%s\n' My Three Lines; exit 2; }
export -f cmd
timeout 5 bash -c 'cmd' | perl -pe "if (/Hello/) { print \$_; exit 1 }"
printf '%s\n' \
"Perl exited with status ${PIPESTATUS[1]}" \
"Process substitution exited with status ${PIPESTATUS[0]}"