bash - bash: wait for single process from a pipeline
问题描述
I'm starting 2 processes, where one pipes into the other and then background them both. I want to wait until the second process finishes to then decide the faith of the first one.
The following snippet gives the output I'm expecting ("exit 1"). However, wait
seems to wait for both processes to be finished (so 5 seconds), which is not what I want.
What have I misunderstood about wait
?
How can I make it wait for just the second process in the pipeline and decide to wait for the first one (or kill it) later?
#!/bin/sh
{
sleep 5
exit 5
} | {
sleep 1
exit 1
} &
wait $!
echo "exit $?"
解决方案
You don't have misunderstood the wait
builtin behavior. You have misunderstood the shell pipe processing instead.
The wait
command behaves as expected, it waits for the end of the subshell from the right part of the pipe (the sleep 1
) and it waits for five seconds because this right part doesn't effectively terminate until its pipe input is closed. Its pipe input is closed only when the left part of the pipe closes it on its termination (the sleep 5
), thus after five seconds.
To wait for the right part of the pipe, you can use signal to know when the right part is about to finish like that :
#!/bin/dash
{
sleep 5
exit 5
} | {
sleep 1
kill -s USR1 $$
exit 1
} &
trap "echo \"Second shell finished\";" USR1
wait $!
echo "exit $?"
This way, you'll get a signal from the right part and the wait
command will then only wait until it get these signal (the wait
command wait for any signal state change, not only termination). The kill -s USR1 $$
send the USR1 signal to the parent shell. Beware that it can imply termination for the process of the current subshell, you have to know how the process will handle USR1 (i guess sleep
ignores it).
However, you can't then get the right exit code from the shell of the right part of the pipe, as it is not effectively terminated until its pipe input is closed. To be more precise, you'll get here the exit status 138 which is the the signal status USR1 (value 10) plus the POSIX signal base (128), not the subshell exit status. You can use different signals (USR1, USR2 (POSIX), non POSIX: .. USR64) to signify an exit status or use the subshell STDOUT or an environment variable to transmit an exit status instead if required.
推荐阅读
- android - Android App Bundle 使用了错误的密钥签名
- angular - 在角度材料下拉列表中预选一个值
- algorithm - 使用 1 个自由交换和相邻交换对 N 的排列进行排序
- python - 我刚刚在我的 Windows 11 上安装了 Python,它在命令提示符中打开,就像一个难看的窗口。如何更改界面?
- docker - docker容器自动创建和删除
- r - 在 R DT 数据表中,如何创建复杂的表头表
- c# - C# Deedle 数据框替换列
价值观 - php - 删除授权后 Laravel API
- tcp - 用户代理邮件服务器和用户代理邮件服务器在电子邮件中的异同?
- discord.js - 新服务器加入时发送带有服务器 ID、服务器名称、成员计数的嵌入