Search code examples
bashsshpid

Get PID of nohup process through ssh


I would like to get the PID of a process I start through ssh.

I have a bash script and here is what I wrote:

SSH_COMMAND='ssh'
cmd=`eval $my_cmd`
PROG_CMD="$program $cmd"
$SSH_COMMAND root@server "(nohup $PROG_CMD) & echo "'$!'" > prog.pid"

Note that variables "program" and "my_cmd" are defined in a JSON file (and contain, respectively, my program and the command to start my program).

My program is started on the server exactly the way it is supposed to start but I do not have the correct PID (i.e : the PID of program) in the prog.pid file.

EDIT : I did an echo of the SSH_COMMAND and I got :

 ssh root@server (my_program args > output.log 2>&1 & ) & echo $! > prog.pid

args : arguments of my_program

output.log : log file of my program


Solution

  • Don't use (command &) &. Just use (command) & (or just command &). With (command &) &, Bash needs to fork another sub-shell to run the command so $! would be the PID of the sub-shell other than the command.

    See following example:

    $ (nohup sleep 1234 > /dev/null 2>&1 &) &
    [1] 44420      <=== this is the PID of the sub-shell which died immediately
    $
    [1]+  Done  ( nohup sleep 1234 > /dev/null 2>&1 & )
    $ ps p 44420   <=== as you can see this PID does not exist any more
       PID TTY      STAT   TIME COMMAND
    $ ps -C sleep u
    USER        PID  TTY      STAT START   TIME COMMAND
    root      44421  pts/13   S    17:48   0:00 sleep 1234
    $ kill 44421
    

    This would work fine:

    $ (nohup sleep 1234 > /dev/null 2>&1) &
    [1] 44424         <=== this is the PID of the sleep command
    $ ps p 44424 u
    USER        PID  TTY      STAT START   TIME COMMAND
    root      44424  pts/13   S    17:49   0:00 sleep 1234