views:

90

answers:

3

I am calling another shell script testarg.sh within my main script. the logfiles of testarg.sh are stored in $CUSTLOGS in the below format

testarg.DDMONYY.PID.log example: testarg.09Jun10.21165.log

In the main script after the testarg process gets completed i need to grep the log file for the text "ERROR" and "COMPLETED SUCCESSFULLY". How do i get the PID of the process and combine with DDMONYY for grepping. Also i need to check whether file exists before grepping

$CUSTBIN/testarg.sh

$CUSTBIN/testarg.sh
rc=$?
if [ $rc -ne 0 ]; then
          return $CODE_WARN
fi
+2  A: 

You may background testarg.sh, which puts its pid into $!, and then wait for it:

#! /bin/bash
...

$CUSTBIN/testarg.sh &

LOGFILE=testarg.$(date +%d%b%y).$!.log       # testarg.09Jun10.12345.log

wait $!

# ... $? is set as you expect ...

[ -f $LOGFILE ] && grep {pattern} $LOGFILE

...
pilcrow
I dont want to submit the testarg.sh as a background job. in this case what can i do?
Arav
It won't be "backgrounded" in the sense of an interactive shell's backgrounded commands. The `wait` builtin will behave synchronously, which it what you want -- think of it as a little extra work to get the PID of a child command.
pilcrow
Thanks a lot for the info... So there is no racing if i use wait $!
Arav
+1  A: 

There are two simple ways to get the PID of some process you've just spawned.

One would be to modify the program being spawned (the subprocess) to have it write its PID to a file. You'd then read it therefrom with something like:

 $CUSTBIN/testarg.sh
 TSTARGSPID=$(cat /var/run/custbin.testarg.pid)

Another more elegant method would be:

 $CUSTBIN/testarg.sh &
 TSTARGSPID=$!
 wait
 # Do stuff with PID and output files
Jim Dennis
@Jim, you've got a race if `testarg.sh` exits during the assignment to TSTARGSPID. In that case `wait` will return immediately, and `$?` will be zero. That's assuming no earlier, forked and forgotten child processes, which would be worse... I think you want `wait $TSTARGSPID`.
pilcrow
@pilcrow: It's not a race. Re-read the docs for your shell. Under bash the $! stores the most recent process which was started in the background. Even if you put the wait before the assignment the code will work (at least under bash but probably under others as well).$! does NOT search the process table. THAT would be a race and it's one reason I didn't even suggest it as an obscure third alternative.
Jim Dennis
@Jim, the problem is with `$?`, not with `$!`. You're right, however, it's not a race. It's merely that `$?` will reflect the exit of the argumentless `wait`, rather than the exit code of the backgrounded process. (My misunderstanding, sorry!)
pilcrow
Thanks a lot for the info
Arav
+2  A: 

If you can modify testarg.sh and it doesn't otherwise output anything, just change it to output its log file with a line like:

echo testarg.$(date +%blah).$$.log

then use:

fspec=$($CUSTBIN/testarg.sh)

in your parent.


Alternatively, you can provide a wrapper function to do the work:

#!/bin/bash
function fgpid() {
        "$@" &
        pid=$!
        ps -ef | grep ${pid} | sed 's/^/DEBUG:/' >&2 # debugging
        wait ${pid}
        echo ${pid}
}
fspec=testarg.$(date +%d%b%y).$(fgpid sleep 5).log
echo ${fspec}

This produces:

pax> ./qq.sh
DEBUG:pax    2656    2992 con  15:27:00 /usr/bin/sleep
testarg.09Jun10.2656.log

as expected.


Or this if you think your executable may output something. This one stores the PID into a variable:

#!/bin/bash
function fgpid() {
        "$@" &
        pid=$!
        ps -ef | grep ${pid} | sed 's/^/DEBUG:/' >&2 # debugging
        wait ${pid}
}
fgpid sleep 5
fspec=testarg.$(date +%d%b%y).${pid}.log
echo ${fspec}
paxdiablo
Careful, that `grep ${pid}` will match any process whose argv matches `${pid}`, most notably the `grep` itself. Also, it'll match anyone whose PPID (or TTY, I suppose) is a textual subset of `${pid}`
pilcrow
but I like your approach anyway. +1
pilcrow
The grep is for debugging and has no effect on the solution other than as a test to make sure it works. You raise a good point however and, if I was relying on that for anything important, this is when I would berate myself with my cat'o'nine tails :-)
paxdiablo
Thanks a lot for the info
Arav