Bash: Start Remote Python Application Through Ssh and Get Its Pid

Bash: start remote python application through ssh and get its PID

Thanks to Kingslndian i solved it by making one single command that did the three steps i required, so with that avoided the problem of running in different shells:

 ssh root@myserver 'python /root/python/run_dev_server.py > /dev/null 2>&1 & echo $! > "dmr.pid"'

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

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.

Bash: Using SSH to start a long-running remote command and collect its PID

Try this instead:

read -r pid \
< <(ssh 10.10.10.46 'nohup mbuffer >/tmp/mtest </dev/null 2>/tmp/mtest.err & echo $!')

Three important changes:

  • Use of nohup (you could also get a similar effect with the bash built-in disown)
  • Redirection of stdin and stderr to files (preventing them from holding handles that connect, eventually, to your terminal).
  • Use of single quotes for the remote command (with double-quotes, expansions happen before ssh is started, so the $! you get is the PID of the most recently started local background process).

Get PID of a remote process started with sshpass

sshpass -p password ssh user@ipaddr /bin/bash << EOF
nohup process > /dev/null 2>&1 & echo $! > pid_file
cat pid_file
EOF

The thing is that $! get's expanded not on the remote computer, but on your computer. When using the Here document, variable names are replaced by their values. So it gets expanded to whatever process you have had run in the background on you computer. You need to execute echo $! on the remote computer. That's why it's good to use -c and to always properly enclose the arguments.

sshpass -p password ssh user@ipaddr /bin/bash -c 'nohup process >/dev/null 2>&1 & echo $! > pid_file'

or you can just escape the $!:

sshpass -p password ssh user@ipaddr /bin/bash <<EOF
nohup process > /dev/null 2>&1 & echo \$! > pid_file
cat pid_file
EOF

or the best is to use quoted here string delimiter:

sshpass -p password ssh user@ipaddr /bin/bash <<'EOF'
nohup process > /dev/null 2>&1 & echo $! > pid_file
cat pid_file
EOF

ssh run script in background and get its pid

ssh some.host './script & echo $!'

how can i ssh into a server, and read a pid file and bring back the #?

Easiest way is with backticks.

 my $output = `ssh server -l myid -i /home/myid/.ssh/authorized_keys some_command`;

$output will contain the output of your ssh command.

How to run a script in the background even after I logout SSH?

Run nohup python bgservice.py & to get the script to ignore the hangup signal and keep running. Output will be put in nohup.out.

Ideally, you'd run your script with something like supervise so that it can be restarted if (when) it dies.

Conditionally run subprocess over ssh, while appending output to a (potentially remote) file

You're not going to get something that's safe and correct in a one-liner without making it unreadable; better not to try.

Note that we're using a shell here: In the local case we explicitly call shell=True, whereas in the remote case ssh always, implicitly starts a shell.

import shlex
import subprocess

def startBackgroundCommand(argv, outputFile, remoteHost=None, andGetPID=False):
cmd_str = ' '.join(shlex.quote(word) for word in argv)
if outputFile != None:
cmd_str += ' >%s' % (shlex.quote(outputFile),)
if andGetPID:
cmd_str += ' & echo "$!"'
if remoteHost != None:
p = subprocess.Popen(['ssh', remoteHost, cmd_str], stdout=subprocess.PIPE)
else:
p = subprocess.Popen(cmd_str, stdout=subprocess.PIPE, shell=True)
return p.communicate()[0]

# Run your command locally
startBackgroundCommand(['python', 'script.py', 'arg_1'],
outputFile='file.log', andGetPID=True)

# Or run your command remotely
startBackgroundCommand(['python', 'script.py', 'arg_1'],
remoteHost='foo.example.com', outputFile='file.log', andGetPID=True)


Related Topics



Leave a reply



Submit