7

I use Paramiko for establishing SSH connection with some target device and I want to execute reboot command.

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(zip_hostname, username=username, password=password, timeout=1)
try:
    stdin, stdout, stderr = ssh.exec_command("/sbin/reboot -f")
    # .........
    # some code
    # .........
except AuthenticationException, e:
    print ''
finally:
    ssh.close()

But after executing ssh.exec_command("/sbin/reboot -f") "some code" does not execute because program is stuck in exec_command (the disconnection takes place caused by rebooting). What should I do to solve my problem?

5 Answers 5

8

Try this:

ssh.exec_command("/sbin/reboot -f > /dev/null 2>&1 &")

All the output of reboot is redirected to /dev/null to make it produce no output and it is started in the background thanks to the '&' sign in the end. Hopefully the program won't hang on that line this way, because the remote shell gives the prompt back.

Sign up to request clarification or add additional context in comments.

Comments

3

All you need to do is to call channel.exec_command() instead of the high-level interface client.exec_command()

# exec fire and forget
timeout=0.5
transport = ssh.get_transport()
chan = ssh.get_transport().open_session(timeout=timeout)
chan.settimeout(timeout)
try:
  chan.exec_command(command)
except socket.timeout:
  pass

1 Comment

This, above all helped me most. The other solutions seemed too hacky. I've been "living" with the stuck program after host reboot for a long, long time. This has finally solved it. Many thanks!
2

Get the transport from the ssh and set the keepalive using:

transport = ssh.get_transport()
transport.set_keepalive(5)

This sets the keepalive to 5 seconds; mind you I would have expected the timeout=1 to have achieved the same thing.

4 Comments

As long as output is continuously produced, none of keepalive and timeout will be triggered since they are measuring contiguous idle time of the data line.
The situation was the issuing of a reboot command, which will terminate the other end of the ssh connection abruptly. The purpose of the keepalive is to detect this situation quickly.
Not exactly. Surprisingly enough, reboot eventually does a graceful termination of the ssh channel, as the system sends a TERM signal to sshd which makes it behave so. As of my understanding, this was what OP did not want to wait for to happen.
The key is eventually. The use of reboot-f skips the standard shutdown process, there is no signal sent to sshd in that situation; you rely on TCP timeouts. I’m not seeing the same issue as the OP, though, so I think this line of commentary is moot.
1

I was having this issue and managed to avoid it by switching to this command:

/sbin/shutdown -r now

Note this command does not result in any STDOUT or STDERR output

Comments

0

In case you or anyone else gets stuck trying to reboot host with sudo using forwarding agents (ssh keys) or in my case (yubikey)

If you look at this as bash you would reboot a host as non root user like this.

ssh -t -A user@hostname sudo /sbin/reboot

For the -A flag, from ssh man page

Enables forwarding of the authentication agent connection. This can also be specified on a per-host basis in a configuration file. Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the agent’s Unix-domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent.*

For the -t flag, from ssh man page

Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.*

So lets break this down into how you would do this in paramiko

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=host, username=username)
s = ssh.get_transport().open_session()
paramiko.agent.AgentRequestHandler(s)

ssh.exec_command("sudo /sbin/reboot", get_pty=True)

For authentication forwarding (-A flag in bash ssh command) for paramiko

ssh = paramiko.SSHClient() #'ssh' is client variable 
s = ssh.get_transport().open_session() #get 'ssh' transport and open sessions assigned to 's' variable
paramiko.agent.AgentRequestHandler(s) #call in 's' to the forwarding agent for current ssh session

Now for force pseudo-tty allocation (-t flag in bash ssh command) for paramiko

ssh.exec_command("sudo /sbin/reboot", get_pty=True)

Adding 'get_pty=True' to exec_command will allow you execute sudo /sbin/reboot

Hope this helps, everyone's environments are different but this should work as it the exact same thing as if you ran it as bash.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.