在Bash脚本中,我希望执行以下操作:
app1 &
pidApp1=$!
app2 &
pidApp2=$1
timeout 60 wait $pidApp1 $pidApp2
kill -9 $pidApp1 $pidApp2
也就是说,在后台启动两个应用程序,给予它们60秒的时间完成工作,如果它们没有在60秒内完成工作,就杀死它们。
不幸的是,上面的命令不起作用,因为timeout
是一个可执行文件,而wait
是一个shell命令。
timeout 60 bash -c wait $pidApp1 $pidApp2
但这仍然不起作用,因为wait
只能在同一shell中启动的PID上调用。
有什么想法吗?
9条答案
按热度按时间uoifb46i1#
你的例子和公认的答案都过于复杂,既然这正是
timeout
的用例,为什么不 * 仅 * 使用timeout
呢?timeout
命令甚至有一个内置选项(-k
)在发送终止命令的初始信号之后发送SIGKILL
(默认为SIGTERM
),如果在发送初始信号后命令仍在运行(请参见man timeout
)。如果脚本不一定需要
wait
并在等待后恢复控制流,则只需但是,如果是这样,也可以通过保存**
timeout
**PID来实现:例如
。
ocebsuys2#
将PID写入文件并启动应用程序,如下所示:
这将创建另一个进程,该进程在超时期间休眠,如果到目前为止还没有完成,则会终止该进程。
如果进程完成得更快,则删除PID文件并终止杀手进程。
killChildrenOf
是一个脚本,用于获取所有进程并终止某个PID的所有子进程。有关实现此功能的不同方法,请参阅此问题的答案:Best way to kill all child processes如果你想跳出BASH,你可以把PID和超时写入一个目录,然后监视这个目录,每隔一分钟左右,读取条目,检查哪些进程还在运行,它们是否超时了。
EDIT如果要了解进程是否已成功终止,可以使用
kill -0 $pid
EDIT2或者您可以尝试进程组。kevinarpe表示:要获取PID(146322)的PGID:
在我的例子中:145974。然后PGID可以与一个特殊的kill选项一起使用,以终止组中的所有进程:
kill -- -145974
ru9i0ody3#
下面是亚伦·迪古拉答案的简化版本,它使用了亚伦·迪古拉在评论中留下的
kill -0
技巧:在我的例子中,我希望
set -e -x
安全并返回状态码,所以我使用了:退出状态143表示SIGTERM,几乎可以肯定是由于超时。
vq8itlhq4#
我编写了一个bash函数,它将等待PID完成或超时,如果超时则返回非零值,并打印所有未完成的PID。
要使用它,只需
wait_timeout $timeout $PID1 $PID2 ...
lhcgjxsq5#
把我的2c代入,我们可以把特谢拉的解简化为:
Bash的
sleep
接受小数秒,0.001s = 1 ms = 1 KHz =充足的时间,然而,UNIX在文件和进程方面没有漏洞。我们必须回答一些棘手的问题才能取得进展。
为什么
wait
没有超时参数?可能是因为timeout
,kill -0
,wait
和wait -n
命令可以更精确地告诉机器我们想要什么。为什么
wait
一开始就内置在Bash中,这样timeout wait PID
就不工作了?也许只是为了让Bash能够实现正确的信号处理。考虑:
无论是在物质世界还是在机器中,我们都需要一些可以奔跑的地面,我们也需要一些可以等待的地面。
kill
失败时,你几乎不知道为什么。除非你写了这个过程,或者它的手册命名了这种情况,否则没有办法确定一个合理的超时值。try_wait
:-)lx0bsm1f6#
您可以使用“read”内部命令的超时。
以下命令将终止未终止的作业,并在最多60秒后显示已完成作业的名称:
它的工作原理是创建一个包含所有后台作业的子shell,这个子shell的输出被读入一个bash数组变量,可以根据需要使用该变量(在本例中是打印数组+元素计数)。
确保在读取命令所在的子shell中引用${jobarr}(因此使用括号),否则${jobarr}将为空。
读命令结束后,所有的子shell将自动静音(不被杀死)。你必须自己杀死它们。
9rnv2umw7#
7fhtutme8#
又一个 * 超时 * bash的脚本
运行许多子进程,总超时。使用bash的最新特性,我编写了以下代码:
样品运行:
-m
开关允许您选择一个浮动为 * 最大时间 *(以秒为单位)。为了进行测试,我编写了以下脚本
1.0000
和9.9999
秒之间选择随机持续时间n0
和8
之间的随机行数。(他们无法输出任何内容)。$$
)、要打印的剩余行数和总持续时间(秒)。一次运行此脚本5次,超时时间为5.0秒:
rpppsulh9#
有一些进程在从timeout调用时不能很好地工作。我遇到了一个问题,需要在qemu示例周围放置一个timeout catch,如果您调用
它会一直挂着。
我的解决方案
还要注意的是,超时并不总是会杀死后代进程,这取决于您从超时中派生的cmd的复杂程度。