I have a shell script that checks a file state.txt, deletes fit.bin if state.txt is empty. I cron this at 2am, I will want the script to stop by 8am irrespective of the value of state.txt, any ideas?
#!/usr/bin/ksh
while true; do
if [[ -s ~/state.txt ]] ; then
echo
else
rm ~/fit.bin
exit
fi ;
sleep 961
done
exit
Maybe i oversee something, but i think you are doing it more complicated than necessary: put one script in cron at 2 am, put a second one which kills the first one (if it is running at all) in cron at 8 am. You can create a "PID file" at the start of the first script which you remove at program end:
#! /bin/ksh
typeset fPID="/var/run/${0##*/}"
trap "rm -f $fPID" 0
if [ ! -e "$fPID" ] ; then
print - "$$" > "$fPID"
else
print -u2 "Error: Program already running"
exit 2
fi
[.... your script code here ....]
exit 0
This is your work script, which you will start at 2 am. It cannot be started twice (the second instance would terminate). Trap 0 is a "virtual trap" (for lack of a better word), which is not executed upon getting a certain signal but on exiting the shell process (^= terminating the script in any way).
The content of the PID file is only the PID of the running script instance.
Your termination script looks like this:
#! /bin/ksh
typeset fPID="/var/run/yourscript"
if [ -e "$fPID" ] ; then
kill -15 $(cat "$fPID")
sleep 5
kill -9 $(cat "$fPID") # in case the script doesn't end itself
rm -f "$fPID"
else
print -u2 "Warning: yourscript already terminated"
fi
[.....put any cleanup code here.....]
exit 0
Note that both scripts are only rough sketches. You might want to add all sorts of checks, ifs and whens.
Thanks bakunin. For example, if script terminates successfully at 2:30am, and the PID is reassigned to another process before 8am, won't that cause a process to be terminated wrongfully when the second script is run at 8am??
First: it is highly unlikely that the PID is recycled so fastly. PIDs are - for a reason - supposed to be almost random.
Second: even this small chance is further reduced to absolute zero because the terminating script will delete its PID file upon ending. "trap 0" is executed every time the script ends, regardless of how it ends. The action part of the cleanup script will only run when the PID file exists, not when the PID is in use. This means: when the script terminates at 2:30 it will remove the PID file, at 8:00 the cleanup script will start, fail to find a PID script (the "if [ - e file..." will evaluate to "false") and the cleanup script will do nothing (in fact it will issue the warning, see the else-part).
This is an elegant solution, and the one-liner that can be inserted into any script. I didn't bother with PID=$$ , I just issue the kill direct at $$ and it worked very well.
There could be cases on old Unix especially where having a subprocess kill it's parent could result in a zombie... so might have to disassociate the subprocess using something like a nohup that disconnects from the pseudo tty, etc...
But in general, it works (everything is Linux nowadays)