在bash

时间:2016-12-14 19:22:43

标签: bash

我正在尝试实现一个定时功能。如果定时器超时,则应该杀死函数/命令。如果函数/命令完成,则计时器不应使bash等待计时器超时。

(cmdpid=$BASHPID; \
    ( sleep 60; kill $cmdpid 2>/dev/null) &  \
    child_pid=$!; \
    ssh remote_host /users/jj/test.sh; \
    kill -9 $child_pid)

test.sh可能会在60秒内完成,也可能不会完成。这很好。

但是当我想得到test.sh的结果时,它回应了" SUCESS"或" FAILURE",我尝试了

result=$(cmdpid=$BASHPID; \
    ( sleep 60; kill $cmdpid 2>/dev/null) &  \
    child_pid=$!; \
    ssh remote_host /users/jj/test.sh; \
    kill -9 $child_pid)

这里它等待计时器退出。我可以看到" kill -9 $ child_pid"使用set -x命令执行,但kill并没有真正杀死子shell。

2 个答案:

答案 0 :(得分:1)

解决这个问题的一种方法是在一个单独的脚本上运行计时器,比如MyTimerTest,它从(比如)MainScriptTest调用,但是单独运行,然后完成任何一个脚本第一个"杀死"另一个。例如:

MainScriptTest上你可以把它放在开头:

nohup /folder/MyTimerTest > /dev/null 2>&1 &

MainScriptTest上你可以把它放在最后:

killall MyTimerTest > /dev/null 2>&1

MyTimerTest可能是这样的:

#!/bin/bash
sleep 60
killall MainScriptTest > /dev/null 2>&1
exit 0

注意:具有混合大写和小写字母的脚本的长名称(例如:MainScriptTest)是有意的,killall区分大小写,这有助于防止它杀死应该删除的内容不。为了非常安全,除了更长的名称之外,您甚至可能想要添加一个令牌,例如:MainScriptTest88888或类似的东西。

修改:感谢gilez,他建议使用timeout命令。如果你的系统可以使用它,可以像这样做一个快速的单行程序:

timeout 60 bash -c "/folder/MainScriptTest"

使用timeout很方便。但是,如果MainScriptTest创建独立的子进程(例如通过调用:nohup /folder/OtherScript &),那么timeout将不会终止这些子进程,并且退出将不会是干净的。

我给出的第一个解决方案更长,但可以通过将它们添加到MainScriptTest来自定义以杀死这些子进程(或任何其他进程),例如:

killall OtherScript > /dev/null 2>&1

答案 1 :(得分:1)

找到其他方式。

result=$( ssh $remote_host /users/jj/test.sh ) & mypid=$!
( sleep 10; kill -9 $mypid ) &
wait $mypid