Search code examples
bashpidsu

Getting a PID from a Background Process Run as Another User


Getting a background process ID is easy to do from the prompt by going:

$ my_daemon &
$ echo $!

But what if I want to run it as a different user like:

su - joe -c "/path/to/my_daemon &;"

Now how can I capture the PID of my_daemon?


Solution

  • Succinctly - with a good deal of difficulty.

    You have to arrange for the su'd shell to write the child PID to a file and then pick the output. Given that it will be 'joe' creating the file and not 'dex', that adds another layer of complexity.

    The simplest solution is probably:

    su - joe -c "/path/to/my_daemon & echo \$! > /tmp/su.joe.$$"
    bg=$(</tmp/su.joe.$$)
    rm -f /tmp/su.joe.$$   # Probably fails - joe owns it, dex does not
    

    The next solution involves using a spare file descriptor - number 3.

    su - joe -c "/path/to/my_daemon 3>&- & echo \$! 1>&3" 3>/tmp/su.joe.$$
    bg=$(</tmp/su.joe.$$)
    rm -f /tmp/su.joe.$$
    

    If you're worried about interrupts etc (and you probably should be), then you trap things too:

    tmp=/tmp/su.joe.$$
    trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
    su - joe -c "/path/to/my_daemon 3>&- & echo \$! 1>&3" 3>$tmp
    bg=$(<$tmp)
    rm -f $tmp
    trap 0 1 2 3 13 15
    

    (The caught signals are HUP, INT, QUIT, PIPE and TERM - plus 0 for shell exit.)

    Warning: nice theory - untested code...