Bash:等待超时

新手上路,请多包涵

在 Bash 脚本中,我想做类似的事情:

 app1 &
pidApp1=$!
app2 &
pidApp2=$1

timeout 60 wait $pidApp1 $pidApp2
kill -9 $pidApp1 $pidApp2

即,在后台启动两个应用程序,并给它们 60 秒的时间来完成它们的工作。然后,如果他们没有在那个间隔内完成,杀死他们。

不幸的是,上述方法不起作用,因为 timeout 是可执行文件,而 wait 是 shell 命令。我尝试将其更改为:

 timeout 60 bash -c wait $pidApp1 $pidApp2

但这仍然不起作用,因为 wait 只能在同一个 shell 中启动的 PID 上调用。

有任何想法吗?

原文由 user1202136 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 683
2 个回答

将 PID 写入文件并像这样启动应用程序:

 pidFile=...
( app ; rm $pidFile ; ) &
pid=$!
echo $pid > $pidFile
( sleep 60 ; if [[ -e $pidFile ]]; then killChildrenOf $pid ; fi ; ) &
killerPid=$!

wait $pid
kill $killerPid

这将创建另一个进程,该进程会在超时期间休眠并在该进程尚未完成时终止该进程。

如果进程完成得更快,则删除 PID 文件并终止杀手进程。

killChildrenOf 是一个脚本,它获取所有进程并杀死某个 PID 的所有子进程。有关实现此功能的不同方法,请参阅此问题的答案: Best way to kill all child processes

如果您想跳出 BASH,您可以将 PID 和超时写入一个目录并监视该目录。每分钟左右,阅读条目并检查哪些进程仍然存在以及它们是否已超时。

编辑 如果你想知道进程是否已经成功终止,你可以使用 kill -0 $pid

EDIT2 或者您可以尝试流程组。 kevinarpe 说:要获得 PID(146322)的 PGID:

 ps -fjww -p 146322 | tail -n 1 | awk '{ print $4 }'

在我的情况下:145974。然后 PGID 可以与 kill 的特殊选项一起使用以终止组中的所有进程: kill -- -145974

原文由 Aaron Digulla 发布,翻译遵循 CC BY-SA 3.0 许可协议

您的示例和接受的答案都过于复杂,为什么您 不仅 使用 timeout ,因为这 正是 它的用例? The timeout command even has an inbuilt option ( -k ) to send SIGKILL after sending the initial signal to terminate the command ( SIGTERM by默认)如果在发送初始信号后命令仍在运行(参见 man timeout )。

如果脚本不一定需要 wait 并在等待后恢复控制流,这只是一个问题

timeout -k 60s 60s app1 &
timeout -k 60s 60s app2 &
# [...]

但是,如果确实如此,则只需保存 timeout PID 即可:

 pids=()
timeout -k 60s 60s app1 &
pids+=($!)
timeout -k 60s 60s app2 &
pids+=($!)
wait "${pids[@]}"
# [...]

例如

$ cat t.sh
#!/bin/bash

echo "$(date +%H:%M:%S): start"
pids=()
timeout 10 bash -c 'sleep 5; echo "$(date +%H:%M:%S): job 1 terminated successfully"' &
pids+=($!)
timeout 2 bash -c 'sleep 5; echo "$(date +%H:%M:%S): job 2 terminated successfully"' &
pids+=($!)
wait "${pids[@]}"
echo "$(date +%H:%M:%S): done waiting. both jobs terminated on their own or via timeout; resuming script"

.

 $ ./t.sh
08:59:42: start
08:59:47: job 1 terminated successfully
08:59:47: done waiting. both jobs terminated on their own or via timeout; resuming script

原文由 Adrian Frühwirth 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题