linux shell超时时间,Linux-Bash:等待超时

Linux-Bash:等待超时

在Bash脚本中,我想执行以下操作:

app1 &

pidApp1=$!

app2 &

pidApp2=$1

timeout 60 wait $pidApp1 $pidApp2

kill -9 $pidApp1 $pidApp2

也就是说,在后台启动两个应用程序,并给它们60秒以完成其工作。 然后,如果他们没有在该间隔内完成,请杀死他们。

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

timeout 60 bash -c wait $pidApp1 $pidApp2

但这仍然不起作用,因为只能在同一外壳程序内启动的PID上调用wait。

有任何想法吗?

user1202136 asked 2020-07-08T04:15:25Z

6个解决方案

53 votes

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

如果脚本不一定需要timeout并在等待后恢复控制流,则只需

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 answered 2020-07-08T04:16:51Z

21 votes

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

pidFile=...

( app ; rm $pidFile ; ) &

pid=$!

echo $pid > $pidFile

( sleep 60 ; if [[ -e $pidFile ]]; then killChildrenOf $pid ; fi ; ) &

killerPid=$!

wait $pid

kill $killerPid

这将创建另一个休眠超时的进程,如果尚未完成,则终止该进程。

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

kill -- -145974是用于获取所有进程并杀死某个PID的所有子代的脚本。 有关实现此功能的不同方法,请参见此问题的答案:杀死所有子进程的最佳方法

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

编辑如果您想知道该进程是否已成功终止,则可以使用kill -- -145974

EDIT2或者您可以尝试处理组。 kevinarpe说:要获取PID的PGID(146322):

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

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

Aaron Digulla answered 2020-07-08T04:16:13Z

4 votes

这是Aaron Digulla答案的简化版本,它使用了Aaron Digulla在评论中留下的set -e -x技巧:

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,几乎可以肯定是我们超时了。

Bryan Larsen answered 2020-07-08T04:17:20Z

1 votes

我编写了一个bash函数,该函数将等到PID完成或超时为止,如果超时超过则返回非零值,并打印所有未完成的PID。

function wait_timeout {

local limit=${@:1:1}

local pids=${@:2}

local count=0

while true

do

local have_to_wait=false

for pid in ${pids}; do

if kill -0 ${pid} &>/dev/null; then

have_to_wait=true

else

pids=`echo ${pids} | sed -e "s/${pid}//g"`

fi

done

if ${have_to_wait} && (( $count < $limit )); then

count=$(( count + 1 ))

sleep 1

else

echo ${pids}

return 1

fi

done

return 0

}

要使用它只是wait_timeout $timeout $PID1 $PID2 ...

JonatasTeixeira answered 2020-07-08T04:17:45Z

0 votes

在我的2c中,我们可以将Teixeira的解决方案归结为:

try_wait() {

# Usage: [PID]...

for ((i = 0; i < $#; i += 1)); do

kill -0 $@ && sleep 0.001 || return 0

done

return 1 # timeout or no PIDs

} &>/dev/null

Bash的try_wait接受小数秒,并且0.001s = 1 ms = 1 KHz =充足的时间。 但是,UNIX在文件和进程方面没有漏洞。 timeout wait PID完成很少。

$ cat &

[1] 16574

$ try_wait %1 && echo 'exited' || echo 'timeout'

timeout

$ kill %1

$ try_wait %1 && echo 'exited' || echo 'timeout'

exited

我们必须回答一些棘手的问题才能走得更远。

为什么try_wait没有超时参数? 也许是因为timeout wait PID、try_wait、wait和wait -n命令可以更准确地告诉机器我们想要什么。

为什么首先将try_wait内置到Bash中,以使timeout wait PID无法正常工作? 也许只有这样,Bash才能实施适当的信号处理。

考虑:

$ timeout 30s cat &

[1] 6680

$ jobs

[1]+ Running timeout 30s cat &

$ kill -0 %1 && echo 'running'

running

$ # now meditate a bit and then...

$ kill -0 %1 && echo 'running' || echo 'vanished'

bash: kill: (NNN) - No such process

vanished

无论是在材料领域还是在机器领域,我们都需要一些运行的基础,我们也需要等待的基础。

当try_wait发生故障时,您几乎不知道为什么。 除非你写该过程或其手册中提到的情况,没有办法确定合理的超时值。

在编写过程之后,您可以实现适当的TERM处理程序,甚至响应“ Auf Wiedersehen!”。 通过命名管道发送给它。 那么即使对于像try_wait这样的咒语,你也有一些基础:-)

Andreas Spindler answered 2020-07-08T04:18:41Z

0 votes

app1 &

app2 &

sleep 60 &

wait -n

user1931823 answered 2020-07-08T04:18:57Z

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值