Search code examples
bashsshpidnohup

Execute a script through ssh and store its pid in a file on the remote machine


I am not able to store any PID in a file on the remote machine when running a script in background through ssh.

I need to store the PID of the script process in a file in purpose to kill it whenever needed. When running the exact command on the remote machine it is working, why through ssh it is not working so ?

What is wrong with the following command:

ssh user@remote_machine "nohup ./script.sh > /dev/null 2>&1 & echo $! > ./pid.log"

Result: The file pid.log is created but empty.

Expected: The file pid.log should contain the PID of the running script.


Solution

  • Use

    ssh user@remote_machine 'nohup ./script.sh > /dev/null 2>&1 & echo $! > ./pid.log'
    

    OR

    ssh user@remote_machine "nohup ./script.sh > /dev/null 2>&1 & echo \$! > ./pid.log"
    

    Issue: Your $! was getting expanded locally, before calling ssh at all.

    Worse, before calling the ssh command, if there was a process stared in the background, then $! would have expanded to that and complete ssh command would have got expanded to contain that PID as argument to echo.

    e.g.

    $ ls &
    [12342] <~~~~ This is the PID of ls
    $ <~~~~ Prompt returns immediately because ls was stared in background. 
    myfile1 myfile2 <~~~~ Output of ls.
    [1]+  Done                    ls
    #### At this point, $! contains 12342
    $ ssh user@remote "command & echo $! > pidfile"
    # before even calling ssh, shell internally expands it to:
    $ ssh user@remote "command & echo 12342 > pidfile"
    

    And it will put the wrong PID in the pidfile.