peters@cubsvax.UUCP (Peter S. Shenkin) (07/22/86)
DESCRIPTION: after: a procedure that waits until a particular running process terminates, then initiates a new process. This runs under csh, but should be easily translatable to bsh or ksh. USAGE: after pid shellscript [seconds] "pid" is the pid number of a running job. "shellscript" is the name of an executable file which contains commands to be executed once the process number "pid" has terminated. "seconds" is an optional integer which specifies how often "after" will test for termination of process number "pid". If not specified, 900 seconds (i.e., every 15 minutes) is the default. MOTIVATION: I often run very long, cpu-intensive jobs on our VAX 11/780, which runs ULTRIX. If I have two of these jobs running simultaneously, they generally take considerably longer to complete than if they run sequentially, even if I'm the only one on the machine. In addition, if they run sequentially, I get to see the results of the first long before the second terminates. If I know in advance I'm going to run two in a row, I can execute a script that runs them in order, or else enter the two jobs on a line separated by a semi-colon. Sometimes, however, I don't decide to run job2 until job1 has already started; also, setting up such a job sometimes takes a good deal of preparation, and I'd like to start job1, then turn my attention to preparing the input for job2, then tell job2 to start after job1 finishes, then go home. INSTALLATION: Install the first file, "after", in your ~/bin, and the second file, "awkfinafter", in your ~/etc. If you don't like these directories, pick ones you do; if you change the directory for awkfinafter, you'll have to change the assignment of awkfin in "after" to correspond. PHILOSOPHICAL RUMINATIONS: This script seems too simple to post, yet too useful not to. The way it works is to create an awk program file using sed to insert the process id supplied to after. Then the output of ps is awk-ed, and if the process id is not found, the shellscript given to after is executed. If it is found, after "sleep"s for the time interval given (or for a default time of 15 minutes) before trying again. (It might sound simpler to search the output of ps using "fgrep pid", but ps will return a line for the fgrep job, so the search will always succeed!) Note that "after" will not terminate until the script it runs terminates; that means that if you've used "after" to queue up job2 to run after job1 terminates, you can use the pid of that "after" to run a second "after" which queues up job3, and rest assured that job3 will not commence until job2 terminates. And so on ad infinitum (or at least ad nauseum). Enjoy! If you like it a lot or think it's dumb or something drop me a line. Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA ----------------------file $home/bin/after begins here-------------------------- # # "after". 21jul86. runs a shell script after a running process has finished # Peter S. Shenkin Columbia Univ. Biology Dept., NY, NY 10027 # {philabs,rna}!cubsvax!peters cubsvax!peters@columbia.ARPA # parse command line, and set sleep interval if not specified if( $#argv == 3 ) then set seconds=$3 else if( $#argv == 2 ) then set seconds=900 else echo 'usage: after pid shellscript [seconds, default=900 ]' exit endif # initialize internal variables set awkfin=$home/etc/awkfinafter set awkfout=/tmp/after$$ # create awk program file sed -e s/@@/$1/ $awkfin> $awkfout # take a breather for $seconds; check for pid; # when no longer found, run script ($2), cleanup and exit while 1 sleep $seconds if( 0 == `ps | awk -f $awkfout` ) then $2 /bin/rm $awkfout exit endif end ----------------------file $home/bin/after ends here-------------------------- ----------------------file $home/etc/awkfinafter starts here------------------ BEGIN { found = 0 } $1 == @@ { found = 1; exit } END { print found } ----------------------file $home/etc/awkfinafter ends here------------------
stan@amc.UUCP (Stan Tazuma) (07/25/86)
In article <515@cubsvax.UUCP> peters@cubsvax.UUCP (Peter S. Shenkin) writes: > >DESCRIPTION: >after: a procedure that waits until a particular running process terminates, > then initiates a new process. This runs under csh, but should be > easily translatable to bsh or ksh. > I think it's a useful tool, but there are simpler ways to do it (at least under a BSD Unix (which includes the Ultrix you're using)). Here's a program I came up with a while back. It's called waitp. It has the same args. as "after". ------------waitp.c------------ /* this program will wait until a given process dies * e.g. waitp 10309 10 * * 3/12/85 - skt */ #include <stdio.h> #define DEFAULT_PAUSE 30 extern errno; main(argc,argv) int argc; char **argv; { char *cmdname = argv[0]; int pid; register ret; register sleep_time = (argc > 2) ? atoi(argv[2]) : DEFAULT_PAUSE ; if (argc == 1) { fprintf(stderr, "usage: %s pid [ pause-time ]\n", cmdname); exit(1); } pid = atoi(argv[1]); while ((ret = getpgrp(pid)) >= 0) if (sleep_time > 0) sleep(sleep_time); /* getpgrp returns -1 when the process goes away, and * sets errno == 3 (ESRCH in /usr/include/errno.h) */ /* printf("getpgrp returned %d\n", ret); */ /* printf("errno is %d\n", errno); */ exit(0); } ----------------- The way to use this is as follows. Suppose you start a job in the background. Then you want to run another job after that one completes. First do a "jobs" to find out the pid of the first job; let's suppose the pid is 12345. Then run the job: waitp 12345; <arbitrary command> & -------------- If you want to do it as a shell script, the ps command can be used to look at an arbitrary process, by pid. E.g., --------------(first, in csh since your script was in csh) #! /bin/csh -f set pid = $1 if ($#argv == 2) then set sleep_time = $2 else set sleep_time = 30 endif while (1) if ( { ps \#$pid } ) then >/dev/null sleep $sleep_time else exit 0 endif end --------------(here, in sh since sh probably has less impact on the system) #! /bin/sh pid=$1 sleep_time=${2-30} while : do if ps \#$pid >/dev/null then sleep $sleep_time else exit 0 fi done --------------- For AT&T Unix versions, getpgrp() doesn't behave in the above way (waitp.c). The AT&T ps command can be used to look at a specific process, though using a different ps argument than above. Stan Tazuma Applied Microsystems Corp. ...uw-beaver!tikal!amc!stan