Tuesday, November 25, 2008

Caller and Callee

Suppose you have developed a central alerting script (callee) that all your other scripts (caller) will execute if certain threshold is reached. In your alert script, you definitely want to inform the user where this alert is initiated. Now the question is how can I find out who called me.

In Bash shell, you can rely on the PPID environment variable to determine the parent process ID (PPID) in order to find out who actually called you. However, this PPID variable will not be available in Bourne shell. In order to write cross-platform script, it is better to rely on Bourne shell because it is definitely available in almost all UNIXes. FYI, the default shell for root account in Solaris is still Bourne shell (/bin/sh) and the shell for single-user mode is the statically-link Bourne shell (/sbin/sh). Over the years, I prefer to write in Bourne shell ("the lowest common denominator for shell") unless there is a performance issue.

In Bash, you can simply use the PPID

$ cat caller.bash
#! /bin/sh

./callee.sh

$ cat callee.bash
#! /bin/sh

pgrep $PPID

$ ./caller.bash
./caller.bash

In Bourne shell, I came up with this function that uses AWK to store the 'ppid' and 'command' in an associative array using the pid as the index. In Solaris or even other UNIX, you can ask 'ps' to output (-o) only those columns that you are interested in and in my case they are pid (process id), ppid (parent process id) and args (command with arguments). You must be wondering why we output only those information that is needed for the downstream commands ? It is for performance and easy parsing reason. Here is a typical scenario.

$ cat caller.sh
#! /bin/sh

./callee.sh

$ cat callee.sh
#! /bin/sh

caller()
{
        ps -ef -o 'pid,ppid,args' | \
        awk '
        NR>1 {
                ppid[$1]=$2

                # if command is /bin/*sh, use the name of the script
                if ( $3 ~ /^\/bin\/.*sh$/ ) {
                        command[$1]=$4
                } else {
                        command[$1]=$3
                }
        }
        END {
                print command[ppid['$$']]
        }'
}

caller

$ ./caller.sh
./caller.sh

Labels: ,

0 Comments:

Post a Comment

<< Home