8

I am finding hard to run a process on a remote SSH server at background using Paramiko. I used :

stdin, stdout, stderr = ssh.exec_command('executefile.py &') 

and found that no process of executefile.py was found running.

Then I tried using other way as including a backward slash:

stdin, stdout, stderr = ssh.exec_command('executefile.py \&') 

This method worked. There was an instance running on machine but no surprise, it was not running at background. I could come to know as it is not running at background as when code stuck at second line after this code. It was

all_inf = stdout.readlines()

Now code was not going beyond above line unless the process of the script was killed.

I am learning Paramiko, any help is appreciated.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
user2033758
  • 1,848
  • 3
  • 16
  • 16

5 Answers5

25

I've tried all the methods described here and here without success, and finally realized that you need to use channels instead of using the SSHClient directly for calling exec_command (this does not work in background):

client = paramiko.SSHClient()
client.connect(ip_address, username='root', pkey=paramiko_key, timeout=5)
client.exec_command('python script.py > /dev/null 2>&1 &')

You should create and use a channel, this works in background:

client = paramiko.SSHClient()
client.connect(ip_address, username='root', pkey=paramiko_key, timeout=5)
transport = client.get_transport()
channel = transport.open_session()
channel.exec_command('python script.py > /dev/null 2>&1 &')

So nohup, dtach, screen, etc, are actually not necessary.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Ariel Camino
  • 259
  • 3
  • 3
  • 2
    Just FYI, you do not even need the `&`. – Wyrmwood Aug 21 '19 at 23:12
  • For me the first code work too. Actually the `SSHClient.exec_command` internally does the same what the second code. The only difference is that it returns output streams. Maybe that can make the difference in some cases. Closing them might solve the difference. – Martin Prikryl Feb 14 '21 at 09:02
  • unfortunalty, that doesnt work for me:( After closing client, the remote process exits too :( – Ladenkov Vladislav Jul 31 '21 at 11:43
  • It's ok for me to use in enbedded system, but not in linux PC. using `invoke_shell` to solve the problem. – ching-yu Feb 16 '23 at 09:19
4

You can try:

stdin, stdout, stderr = ssh.exec_command('nohup python executefile.py >/dev/null 2>&1 &') 
cizixs
  • 12,931
  • 6
  • 48
  • 60
3

exec_command isn't executing the command in an interactive shell, so "running a process in the background" doesn't really make sense.

If you really want to do this, you could use the command nohup to start your process, and keep it alive when the session exits. Remember that you can't get stdin, stdout, or stderr when you do this, since you are detaching the process from the shell, so redirect them accordingly.

JimB
  • 104,193
  • 13
  • 262
  • 255
1

I tried transport class and it was really great. Here's the code I used:

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname = "host_ip", username = "un"], password = "up")
channel = ssh.get_transport().open_session()
pty = channel.get_pty()
shell = ssh.invoke_shell()
shell.send("cd /my/directory/; nohup ./exec_name > /dev/null 2>&1 &\n")

But I still don't know how to kill it using python scripts; I have an open question about it here.

EDIT 1:

I have solved my problem about killing the process somehow; you can check it.

Community
  • 1
  • 1
Zeinab Abbasimazar
  • 9,835
  • 23
  • 82
  • 131
1

You could try using screen

screen -d -m ping 8.8.8.8

This is would start a screen and ping 8.8.8.8. You can view this screen by using

screen -ls

and attach using

screen -D <<screen_name>>

Note that the screen will terminate after the command has finished executing.

shivram
  • 469
  • 2
  • 10
  • 26