Hi all,
I have a query on killing a child process, if it takes more than 10 minutes
myparent.sh has the following
#!/bin/sh
echo "My Parent Script"
home/guru/initiateServer.sh
The initiateServer is a child process and this might take 20 or more minutes to return. I want to kill this process, if it is taking more than 10 minutes.
Please advice on what to do? Thanks all in advance
Your title had the answer, make it a child process and have the main process time the return of the child process.
#!/bin/sh
echo "My Parent Script"
home/guru/initiateServer.sh &
pid=$!
sleep 600
if [ kill -0 $pid ] {
echo "killing initiateServer as it took too long to complete"
kill $pid # you could optionally add a -9 in there if the server has a sigterm handler
}
Good point, also had a cup of coffee and wrote if loop in shell syntax and caught kill -0 return correctly.
New improved scriipt, now with max wasted time of 10 seconds...
#!/bin/sh
echo "My Parent Script"
home/guru/initiateServer.sh &
pid=$!
for i in {0..60} ; do
kill -0 $pid
if [ $? -eq 1 ] ; then
exit
fi
sleep 10
done
kill $pid
Alternatively if this is a subroutine in a larger script use return rather than exit.
You risk either killing an innocent process that happens to have been created later on with the same process id (especially if you are running as the super-user) but you will probably be generating mail. I would go with Skrynesaver's suggestion. Far safer. It might be worth investing a little time in listing the process details at the start and at the end to ensure you are definitely killing the same process.
NAME
timeout - run command with bounded time
SYNOPSIS
timeout [-signal] time command ...
DESCRIPTION
timeout executes a command and imposes an elapsed time limit. The
command is run in a separate POSIX process group so that the right
thing happens with commands that spawn child processes.
and
NAME
timelimit - effectively limit the absolute execution time of a process
SYNOPSIS
timelimit [-q] [-S killsig] [-s warnsig] [-T killtime] [-t warntime]
command [arguments ...]
DESCRIPTION
The timelimit utility executes a given command with the supplied
arguments and terminates the spawned process after a given time with a
given signal. If the process exits before the time limit has elapsed,
timelimit will silently exit, too.
Both were in the Debian repository, there may be others as well.
The following is POSIX-compatible and never signals an "innocent process":
set -m
sh -c '(/path/to/task; kill 0) & (sleep 600; kill 0) &' &
A more readable alternative:
set -m
sh <<'EOF' &
(/path/to/task; kill 0) &
(sleep 600; kill 0) &
EOF
If it should wait:
set -m
sh <<'EOF' &
(/path/to/task; kill 0) &
p=$!
(sleep 600; kill 0) &
wait
EOF
wait
set -m ensures that the non-interactive background shell (and all of its children) which does all the work is placed in its own, dedicated process group, regardless of whether the main script is invoked from an interactive shell or not. From within that process group, any member can signal all other members without affecting outsiders. Even if a pid is reused, it will not be signaled because it will no longer be a member of the process group.
Naturally, stdout and stderr should likely be redirected.
I've made it work on AIX (4.3.3, 5.1 & 6.1) , HP-UX (11.11i) and RHEL (6.3)
I saved and ran this demo:-
set -m
date
sh <<'EOF' &
(ping -c 50 localhost ; kill 0) &
p=$!
(sleep 6; kill 0) &
wait
EOF
wait
date
I got the output:-
$ script_timeout_demo
Thu 6 Jun 13:59:05 2013
PING loopback (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=0 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=255 time=0 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=255 time=0 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=255 time=0 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=255 time=0 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=255 time=0 ms
64 bytes from 127.0.0.1: icmp_seq=6 ttl=255 time=0 ms
Terminated
Thu 6 Jun 13:59:11 2013
$
I had to change the ping command on HP-UX, because that syntax is ping localhost -n 50
Some give variations on the Terminated message, but that can be handled/ignored/re-directed.
So, alister - absolutely fantastic. You should see some of the rubbish I've coded in the past to try to do the same sort of thing. I regret that I can only thank a post once.
Could you please post your code, or a simplified yet fully-functional structural equivalent?
Your "99%" solution is probably more like a "99.9999%" solution. It's extremely unlikely that you need anything better. However, I'm interested to see if yours is a situation in which I cannot make my approach work.
So long as the only things in the process group are the monitored and monitoring processes, I don't see why kill 0 cannot be used.
Regards,
Alister
---------- Post updated at 04:53 PM ---------- Previous update was at 04:44 PM ----------
Regarding rubbish code, we've all been there. I have actually never used this code; it is something I come up with yesterday while pondering this thread and the possibility of a portable solution without a pid race. For that reason I appreciate your multi-platform testing. Thank you very much.