当前位置: 首页 > 知识库问答 >
问题:

Bash:等待超时

卫才哲
2023-03-14

在Bash脚本中,我想做如下操作:

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

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

一、 例如,在后台启动两个应用程序,并给他们60秒时间完成工作。然后,如果他们没有在这段时间内完成,就杀了他们。

不幸的是,上面的方法行不通,因为< code>timeout是一个可执行文件,而< code>wait是一个shell命令。我试着把它改成:

timeout 60 bash -c wait $pidApp1 $pidApp2

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

有什么想法吗?

共有3个答案

戎洛城
2023-03-14

下面是亚伦·迪古拉的答案的简化版,它使用了亚伦·迪古拉在评论中留下的< code>kill -0技巧:

app &
pidApp=$!
( sleep 60 ; echo 'timeout'; kill $pidApp ) &
killerPid=$!

wait $pidApp
kill -0 $killerPid && kill $killerPid

在我的例子中,我既想set-e-x安全又想返回状态码,所以我使用了:

set -e -x
app &
pidApp=$!
( sleep 45 ; echo 'timeout'; kill $pidApp ) &
killerPid=$!

wait $pidApp
status=$?
(kill -0 $killerPid && kill $killerPid) || true

exit $status

退出状态143表示SIGTERM,几乎可以肯定是来自我们的超时。

潘智刚
2023-03-14

将PID写入文件并启动应用程序,如下所示:

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

wait $pid
kill $killerPid

这将创建另一个进程,该进程会为超时而Hibernate,如果到目前为止尚未完成该进程,则会终止该进程。

如果进程完成得更快,PID文件将被删除,killer进程将终止。

killChildrenOf 是一个脚本,它获取所有进程并杀死某个 PID 的所有子级。有关实现此功能的不同方法,请参阅此问题的答案:终止所有子进程的最佳方法

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

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

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

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

就我而言:145974。然后,PGID可以与特殊的kill选项一起使用,以终止组中的所有进程:kill -- -145974

洪承天
2023-03-14

您的示例和公认的答案都过于复杂,为什么您不仅使用timeout,因为这正是它的用例?timeout命令甚至有一个内置选项(-k)在发送初始信号后发送SIGKILL以终止命令(SIGTERM默认情况下)如果命令在发送初始信号后仍在运行(请参阅man timeout)。

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

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

然而,如果是这样的话,只需保存< code > time out 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
 类似资料:
  • 问题内容: 我正在使用Ubuntu 16.04 问题答案: 我遇到了这个问题,终于找到了答案。我一直在使用Marionette驱动程序,该驱动程序不再适用于FF版本53和Selenium 3.5或更高版本。该GeckoDriver文档显示系统属性应该如何引用。 我从以下位置更改了代码: 至: 现在我的本地Firefox运行正常。 希望这对其他人有帮助。

  • 问题内容: 在Bash脚本中,我想执行以下操作: 即,在后台启动两个应用程序,并给它们60秒以完成其工作。然后,如果他们没有在该时间间隔内完成,请杀死他们。 不幸的是,上述内容不起作用,因为它是可执行文件,而它是Shell命令。我尝试将其更改为: 但这仍然行不通,因为只能在同一外壳程序内启动的PID上进行调用。 有任何想法吗? 问题答案: 将PID写入文件并像这样启动应用程序: 这将创建另一个hi

  • 问题内容: 我使用Node.js和TypeScript,并且使用。这是我的测试用例: 我想为整个功能设置一个超时时间。即如果要花费2秒,花费0.5秒,花费5秒,我想在3秒钟后让我抛出错误的超时。 正常调用是一个问题,因为范围丢失了: 而且我不能用普通的方式抓住它: 有关如何解决的任何想法? 问题答案: 您可以使用超时: 您必须将其包装在诺言中才能使用。

  • 问题内容: 我想知道WebDriver等待超时和隐式等待超时之间的技术差异。 问题答案: 如文档中所述: 在内部设置将用于所有连续搜索的超时。如果找不到该元素,它将尝试在指定的时间内反复查找该元素。它仅执行此操作,不能强制执行其他任何操作- 它等待元素显示。 ,或者只是您用于特定搜索的一次计时器。它具有更大的可扩展性,意味着您可以将其设置为等待可能需要的任何条件。通常,您可以使用一些预构建的元素来

  • 问题内容: 我正在使用Hibernate,试图模拟2个并发更新到数据库中的同一行。 编辑:我将em1.getTransaction()。commit移到em1.flush()之后;我没有收到任何StaleObjectException,两个事务已成功提交。 我在上遇到以下异常。为什么? 问题答案: 好吧,您正试图陷入僵局,并且成功了:-) Transaction1开始,与您的实体更新(和锁定)行。

  • 我一直在尝试使用android studio emulator,但我无法在emulator上运行我的应用程序。当我运行我的应用程序时,它会显示带有以下详细信息的模拟器: > Hax已启用 Hax ram\U尺寸0x40000000 HAX正在工作,emulator以快速virt模式运行。 端口5554上的控制台;5555港口ADB 之后,将进入下一个选项卡启动应用程序,并显示等待设备联机。之后显示