Search code examples
pythonlinuxsshtimeout

Option for SSH to timeout after a short time? ClientAlive & ConnectTimeout don't seem to do what I need them to do


I'm sending a command by SSH. This particular command happens to tell the machine to reboot. Unfortunately this hangs my SSH session and does not return so that my script is unable to continue forwards onto other tasks.

I've tried various combinations of modifying the command itself to include "exit" and or escape commands but in none of those cases does the machine pick up on both the reboot and the command to close the SSH session. I've also tried ConnectTimeout and ClientAlive options for SSH but they seem to make the restart command ignored.

Is there some obvious command that I'm missing here?


Solution

  • Well, nobody has posted any answers that pertain to SSH specifically, so I'll propose a SIGALRM solution like here: Using module 'subprocess' with timeout

    class TimeoutException(Exception): # Custom exception class
      pass
    
    def TimeoutHandler(signum, frame): # Custom signal handler
      raise TimeoutException
    
    # Change the behavior of SIGALRM
    OriginalHandler = signal.signal(signal.SIGALRM,TimeoutHandler)
    
    # Start the timer. Once 30 seconds are over, a SIGALRM signal is sent.
    signal.alarm(30)
    
    # This try/except loop ensures that you'll catch TimeoutException when it's sent.
    try:
      ssh_foo(bar) # Whatever your SSH command is that hangs.
    except TimeoutException:
      print "SSH command timed out."
    
    # Reset the alarm stuff.
    signal.alarm(0)
    signal.signal(signal.SIGALRM, OriginalHandler)
    

    This basically sets a timer for 30 seconds and then tries to execute your code. If it fails to complete before time runs out, a SIGALRM is sent, which we catch and turn into a TimeoutException. That forces you to the except block, where your program can continue.