Reputation: 129
I am trying to implement a timed function. If the timer times out the function/command should be killed. If the function/command finishes, the timer should not make the bash to wait for the timer to timeout.
(cmdpid=$BASHPID; \
( sleep 60; kill $cmdpid 2>/dev/null) & \
child_pid=$!; \
ssh remote_host /users/jj/test.sh; \
kill -9 $child_pid)
The test.sh may or may not finish in 60 seconds. This worked fine.
But when I want to get the result of the test.sh, which echoes "SUCESS" or "FAILURE", I tried with
result=$(cmdpid=$BASHPID; \
( sleep 60; kill $cmdpid 2>/dev/null) & \
child_pid=$!; \
ssh remote_host /users/jj/test.sh; \
kill -9 $child_pid)
Here it waits for timer to exit. I can see the "kill -9 $child_pid" is executed, using set -x command, but the kill is not really killing the sub-shell.
Upvotes: 3
Views: 1222
Reputation: 129
Found some other way.
result=$( ssh $remote_host /users/jj/test.sh ) & mypid=$!
( sleep 10; kill -9 $mypid ) &
wait $mypid
Upvotes: 1
Reputation: 2093
One way to tackle this problem would be to run the timer on a separate script, say MyTimerTest
, which is called from the (say) MainScriptTest
but runs separately, and then whichever script that finishes first "kills" the other. For example:
On MainScriptTest
you could put this at the beginning:
nohup /folder/MyTimerTest > /dev/null 2>&1 &
On MainScriptTest
you could put this at the very end:
killall MyTimerTest > /dev/null 2>&1
The MyTimerTest
could be something like this:
#!/bin/bash
sleep 60
killall MainScriptTest > /dev/null 2>&1
exit 0
Note: the long name for the scripts with mixed capital and lowercase letters (ex.: MainScriptTest
) is on purpose, killall
is case sensitive and that helps to preclude it from killing something it should not. To be very safe, you might want to even add a token in addition to the longer name, like: MainScriptTest88888
or something like that.
Edit: Thanks to gilez
, who suggested the use of the timeout
command. If that is available to you on your system, one could do a quick one-liner like this:
timeout 60 bash -c "/folder/MainScriptTest"
Using timeout
is convenient. However, if MainScriptTest
creates independent child processes (for example by calling: nohup /folder/OtherScript &
) then timeout
would not kill those child processes, and the exit would not be clean.
The first solution I gave is longer, but it could be customized to kill those child processes (or any other processes you want) by adding them to the MainScriptTest
, like for example:
killall OtherScript > /dev/null 2>&1
Upvotes: 1