tchrist@convex.COM (Tom Christiansen) (08/12/90)
In article <BRISTER.90Aug10222433@westworld.decwrl.dec.com> brister@decwrl.dec.com (James Brister) writes: >I'd like to have a shell script run a command, but if that command doesn't >finish in X seconds, then the script should kill it, if the command >finishes sooner then the script should immediately continue. Any ideas on >how one could achieve this? Here's timeout.c; syntax is 'timeout seconds command'. --tom #include <stdio.h> #include <signal.h> #include <sysexits.h> #include <sys/wait.h> int pid,count; union wait status; int bang(); char **commands; main(ac,av) char **av; { if (ac < 3) { usage: fprintf (stderr, "usage: %s seconds command\n",*av); exit (EX_USAGE); } if ((count=atoi(av[1])) < 1) { fprintf (stderr, "seconds (%s) malformed or nonpositive\n",av[1]); goto usage; } commands = &av[2]; switch (pid=fork()) { default: parent(); /* NOTREACHED */ break; case 0: child(); /* NOTREACHED */ case -1: perror("fork"); exit(EX_OSERR); /* NOTREACHED */ } } parent() { (void) signal(SIGALRM,bang); alarm(count); while(wait(&status) != pid) /* VOID */; if (WIFSIGNALED(status)) exit(-status.w_termsig); exit(status.w_retcode); } bang() { fprintf(stderr,"Timeout!\n"); (void) signal(SIGALRM,SIG_DFL); (void) kill(pid,SIGTERM); if (kill(pid,0)) { sleep(1); (void) kill(pid,SIGKILL); } exit(EX_TEMPFAIL); } child() { execvp(*commands,commands); perror(*commands); _exit(EX_DATAERR); /* NOTREACHED */ } /* lint output: * timeout.c: */ -- Tom Christiansen {uunet,uiucdcs,sun}!convex!tchrist Convex Computer Corporation tchrist@convex.COM "EMACS belongs in <sys/errno.h>: Editor too big!"
maart@cs.vu.nl (Maarten Litmaath) (08/16/90)
In article <3716@sactoh0.UUCP>, jak@sactoh0.UUCP (Jay A. Konigsberg) writes: )... )command & # execute in background What if the command is supposed to run in the _foreground_? The following timeout shell script can be easily converted to a C program if desired. --------------------cut here-------------------- #!/bin/sh # @(#)timeout 6.2 90/03/01 Maarten Litmaath prog=`basename $0` usage="Usage: $prog [-signal] [timeout] [:interval] [+delay] [--] <command>" SIG=-KILL # default signal sent to the process when the timer expires, # unless a delay option has been given: then it is -TERM sigopt=0 timeout=60 # default timeout interval=15 # default interval between checks if the process is still alive delay= # (if specified) the delay between posting the given signal and # destroying the process (kill -KILL) while : do case $1 in --) shift break ;; -*) SIG=$1 sigopt=1 ;; [0-9]*) timeout=$1 ;; :*) EXPR='..\(.*\)' interval=`expr x"$1" : "$EXPR"` ;; +*) EXPR='..\(.*\)' delay=`expr x"$1" : "$EXPR"` case $sigopt in 0) SIG=-TERM esac ;; *) break esac shift done case $# in 0) echo "$usage" >&2 exit 2 esac ( for t in $timeout $delay do while test $t -gt $interval do sleep $interval kill -0 $$ || exit t=`expr $t - $interval` done sleep $t kill $SIG $$ && kill -0 $$ || exit SIG=-KILL done ) 2> /dev/null & exec "$@" -- "UNIX was never designed to keep people from doing stupid things, because that policy would also keep them from doing clever things." (Doug Gwyn)