[英]Wait for process to finish, or user input
I have a backgrounded process that I would like to wait for (in case it fails or dies), unless I receive user input. 我有一个后台进程,我想等待(如果它失败或死亡),除非我收到用户输入。 Said another way, the user input should interrupt my waiting.
换句话说,用户输入应该中断我的等待。
Here's a simplified snippet of my code 这是我的代码的简化片段
#!/bin/bash
...
mplayer -noconsolecontrols "$media_url" &
sleep 10 # enough time for it to fail
ps -p $!
if [ $? -ne 0 ]
then
fallback
else
read
kill $!
fi
The line that I particularly dislike is sleep 10
, which is bad because it could be too much time, or not enough time. 我特别不喜欢的是
sleep 10
,这很糟糕,因为它可能是太多时间,或者时间不够。
Is there a way to wait $! || read
有没有办法
wait $! || read
wait $! || read
wait $! || read
or the equivalent? wait $! || read
或等效?
Use kill -0
to validate that the process is still there and read
with a timeout of 0 to test for user input. 使用
kill -0
验证进程是否仍在那里并以超时0 read
以测试用户输入。 Something like this? 像这样的东西?
pid=$!
while kill -0 $pid; do
read -t 0 && exit
sleep 1
done
Original 原版的
ps -p
to check the process. ps -p
检查进程。 read -t 1
to wait for user input. read -t 1
等待用户输入。
pid=$!
got_input=142
while ps -p $pid > /dev/null; do
if read -t 1; then
got_input=$?
kill $pid
fi
done
This allows for branching based whether the process died, or was killed due to user input. 这允许基于过程是否死亡或由于用户输入而被杀死的分支。
All credit to gubblebozer. 所有归功于gubblebozer。 The only reason I'm posting this answer is the claim by moderators that my edits to his post constituted altering his intent.
我发布此答案的唯一原因是主持人声称我对其帖子的编辑构成了改变他的意图。
Anti Race-Condition 反竞争条件
First off, a race condition involving pids is (very likely) not a concern if you're fairly quick, because they're reused on a cycle . 首先,如果你相当快,一个涉及pids的竞争条件(很可能)不是问题,因为它们会在一个循环中重复使用 。
Even so, I guess anything is possible... Here's some code that handles that possibility, without breaking your head on traps. 即便如此,我猜任何事都有可能......这里有一些处理这种可能性的代码,而不会破坏你的陷阱。
got_input=142
while true; do
if read -t 1; then
got_input=$?
pkill --ns $$ name > /dev/null
break
elif ! pgrep --ns $$ name > /dev/null; then
break
fi
done
Now, we've accomplished our goal, while (probably) completely eliminating the race condition. 现在,我们已经完成了我们的目标,同时(可能)完全消除了竞争条件。
Any loop with a sleep
or similar timeout in it, will introduce a race condition. 任何具有
sleep
或类似超时的循环都会引入竞争条件。 It's better to actively wait
for the process to die, or, in this case, to trap the signal that's sent when a child dies. 最好主动
wait
过程死亡,或者在这种情况下,捕获孩子死亡时发送的信号。
#!/bin/bash
set -o monitor
trap stop_process SIGCHLD
stop_process()
{
echo sigchld received
exit
}
# the background process: (this simulates a process that exits after 10 seconds)
sleep 10 &
procpid=$!
echo pid of process: $procpid
echo -n hit enter:
read
# not reached when SIGCHLD is received
echo killing pid $procpid
kill $procpid
I'm not 100% sure this eliminates any race condition, but it's a lot closer than a sleep
loop. 我不是百分百肯定这可以消除任何竞争条件,但它比
sleep
循环更接近。
edit: the shorter, less verbose version 编辑:更短,更简洁的版本
#!/bin/bash
set -o monitor
trap exit SIGCHLD
sleep 5 &
read -p "hit enter: "
kill $!
edit 2: setting the trap before starting the background process prevents another race condition in which the process would die before the trap was installed 编辑2:在启动后台进程之前设置陷阱可防止进程在安装陷阱之前死亡的另一种竞争条件
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.