stadt@cs.utwente.nl (Richard van de Stadt) (11/12/90)
How do I get the return value of a shell script or program that was started (from a shell script) in the background? -- R.R. van de Stadt (Richard) Email: stadt@cs.utwente.nl
weimer@ssd.kodak.com (Gary Weimer) (11/14/90)
In article <1990Nov12.110248@cs.utwente.nl> stadt@cs.utwente.nl (Richard van de Stadt) writes: > > >How do I get the return value of a shell script or program that was >started (from a shell script) in the background? First the example: ------------------------- CUT HERE ---------------------- #!/bin/csh -fb #should also work with /bin/sh rm not_a_real_file_to_get_error >& /dev/null # redirection necessary for # background processes #this must be the very next statement echo "status of rm was $status" > /dev/tty # could be redirected to # any file ------------------------- CUT HERE ---------------------- rm is just the command I chose (sp?), could be any program or script. redirection necessary because background processes die if they try to access stdin or stdout. $status is the important thing here. It contains the return value (exit status) of the last command executed. you didn't specify how you wanted to "get" this value. Redirecting the echo to /dev/tty will print it to the console. Usually $status is used (at least I used it..) in a conditional statement (if, switch, etc.) Hope this answers your (vague) question. Gary Weimer
dberg@informix.com (David I. Berg) (11/14/90)
>In article <1990Nov12.110248@cs.utwente.nl> stadt@cs.utwente.nl (Richard van de Stadt) writes: >> >> >>How do I get the return value of a shell script or program that was >>started (from a shell script) in the background? > >#!/bin/csh -fb #should also work with /bin/sh > >rm not_a_real_file_to_get_error >& /dev/null # redirection necessary for > # background processes >#this must be the very next statement >echo "status of rm was $status" > /dev/tty # could be redirected to > # any file There are two possibilities here; one, you merely want to retrieve the exit status of a spawned processes, or two, you want to return a value generated by the spawned process, or both) The above illustrated example does the former, assuming the spawned process exits with a status (eg. exit n, where n is the status value). The following example does both: In the foreground script: # set answer = `create_answer` if ($status > 0) then echo "Message about create_answer if status > 0" exit end if echo $answer In the script create answer: # set xyz = some value or algorithm set exitcode = some value to indicate success or failure (or anything else) of this script. (0 usually means normal execution; > 0 otherwise) echo $xyz exit $exitcode
stadt@cs.utwente.nl (Richard van de Stadt) (11/14/90)
With this posting I want to explain with an example why I want to know
the exit value of a process that was started in background. From reactions
of some of you (thank you very much) I understand that the question was a
bit vague.
First of all I'm not a newcomer to UNIX (know it since 1983).
I didn't ask how to get an exit value of a process, because I already
know that's in $?. I also know that the process id of the last process
started in background is in $!.
When I worked at Philips Telecomunication and Data Systems, one of my
tasks was system management of some Philips P9000 computers.
For a 'normal' user it was rather complicated to format a floppy disk,
so I wanted to write a shell script to automate the various actions.
In order to get a floppy formatted the following had to be done:
For floppies that were previously formatted it was straightforward:
One had to insert a floppy disk and then type the commands
'attent /dev/dk1' to let the system get the name of the floppy,
'dvstat /dev/dk1' to see what the name of the floppy was,
'dkformat /vol/<name_of_floppy>' to start the format process.
(Once tape and disknames are known to the system, they are called volumes,
and their names used as references).
So all commands could be started after each other in foreground. From the
output of dkformat one could see if the process had ended successful. Also
$? contained a value not equal to zero if something went wrong.
The trouble comes when you want to format a new ('maiden') floppy.
After inserting a new floppy, the format command had to be entered first,
since 'attent /dev/dk1' does not work for floppies that have no name yet:
'dkformat -m /vol/<new_name>' (m for maiden).
The format command then waits for the 'attent /dev/dk1' command to be entered,
after which the format process is really starting.
If you have only one terminal, where only one command shell can be active,
you have to start dkformat in the background, to be able to enter
'attent /dev/dk1'.
If you build a script around this you want to know if the process has
finished correctly. Started by hand, one could see if the format process
had ended correctly by looking at the output messages given.
I wanted to write a script that tells a user to insert a floppy, press
return after doing so. Then starting up the format process (in background)
and exit, so the user can go on doing other things. After the format process
is ready a message is shown on the screen whether the floppy has been
formatted successfully or unsuccessfully.
So what I wanted was something like:
-------------------------------------------------------------------------
#! /bin/sh
#name of script: floppyformat
doit () { # a function
attent /dev/dk1 #find out if -m option must be used (new floppy)
case $? in
0) # not a new floppy
dkformat /vol/name_of_floppy >/dev/null 2>&1 #no output on screen
exitval=$?
break ;;
*) # a new floppy
dkformat -m /vol/new_name >/dev/null 2>&1 & #no output on screen
sleep 10 # be sure process is started
# actually done by looping on pid
attent /dev/dk1 # give what dkformat is waiting for
wait # wait for format process to have finished
exitval='exit_value_of_last_process_started_in_background' ;;
esac
case $exitval in
0) echo "Floppy was formatted successfully" ;;
*) echo "<beep>Format process failed. Try other floppy"
esac
} # end of function
echo -n "Insert floppy and press return "
read return
doit & #start format process in background and exit immediately
------------------------------------------------------------------------
I went around the problem by redirecting the output of dkformat to a
temporary file and later searching this file for some specific string
that indicated that the format process had been successful.
The script above is not the original, since it's been a bit too long
to remember all the details. It's the idea what it't about.
Hope things are a bit clearer now
Richard
--
R.R. van de Stadt (Richard)
Email: stadt@cs.utwente.nl
casper@fwi.uva.nl (Casper H.S. Dik) (11/14/90)
stadt@cs.utwente.nl (Richard van de Stadt) writes: >With this posting I want to explain with an example why I want to know >the exit value of a process that was started in background. From reactions >of some of you (thank you very much) I understand that the question was a >bit vague. >First of all I'm not a newcomer to UNIX (know it since 1983). >I didn't ask how to get an exit value of a process, because I already >know that's in $?. I also know that the process id of the last process >started in background is in $!. In that case you know enough: wait [ n ] Wait for the background process whose process ID is n and report its termination status. If n is omitted, all the shell's currently active background processes are waited for and the return code will be zero. The solution would be: job & proc=$! rest ... wait $proc if [ $? = 1 ]; then ... job failed ... ; fi Or in your script: ------------------------------------------------------------------------ #! /bin/sh #name of script: floppyformat doit () { # a function attent /dev/dk1 #find out if -m option must be used (new floppy) case $? in 0) # not a new floppy dkformat /vol/name_of_floppy >/dev/null 2>&1 #no output on screen exitval=$? break ;; *) # a new floppy dkformat -m /vol/new_name >/dev/null 2>&1 & #no output on screen proc=$! sleep 10 # be sure process is started # actually done by looping on pid attent /dev/dk1 # give what dkformat is waiting for # wait # wait for format process to have finished wait $proc # wait for format process to have finished # exitval='exit_value_of_last_process_started_in_background' ;; exitval="$?" ;; esac case $exitval in 0) echo "Floppy was formatted successfully" ;; *) echo "<beep>Format process failed. Try other floppy" esac } # end of function echo -n "Insert floppy and press return " read return doit & #start format process in background and exit immediately ------------------------------------------------------------------------ -- Casper H.S. Dik, casper@fwi.uva.nl, NIC: !cd151
mark@hsi86.hsi.com (Mark Sicignano) (11/15/90)
In article <1990Nov14.100834@cs.utwente.nl> stadt@cs.utwente.nl (Richard van de Stadt) writes: ... > break ;; > *) # a new floppy > dkformat -m /vol/new_name >/dev/null 2>&1 & #no output on screen > sleep 10 # be sure process is started > # actually done by looping on pid > attent /dev/dk1 # give what dkformat is waiting for > wait # wait for format process to have finished > exitval='exit_value_of_last_process_started_in_background' ;; > esac ... read the man page on sh(1)... particularly the "wait" command. Wouldn't this work? dkformat -m /vol/new_name > /dev/null 2>&1 & sleep 10 attent /dev/dk1 wait $! exitval=$? wait will wait for a particular process id, if one is given, and will return the exit status of the process id. $! is the pid of the last command ran in the background. In other words, the wait will wait for your dkformat to exit and will return the status, which you can get from $?. You had all of the pieces to the puzzle yourself, just didn't put them together right. Have fun! -mark -- Mark Sicignano ...!uunet!hsi!mark 3M Health Information Systems mark@hsi.com