When I want to reboot my D-Link DWL-3200-AP access point from my bash shell, I connect to the AP using ssh
and I just type reboot
in the CLI interface. After about 30 seconds, the AP is rebooted:
# ssh [email protected]
[email protected]'s password: ********
Welcome to Wireless SSH Console!! ['help' or '?' to see commands]
Wireless Driver Rev 4.0.0.167
D-Link Access Point wlan1 -> reboot
Sound's great? Well unfortunately the ssh client process never exits, for some reason (maybe the AP kills the ssh server a bit too fast, I don't know). My ssh client process is completely blocked (even if I wait for several minutes, nothing happens). I always have to wait for the AP to reboot, then open another shell, find the ssh client process ID (using ps aux | grep ssh
) then kill the ssh process using kill <pid>
. That's quite annoying.
So I decided to write a python script to reboot the AP. The script connects to the AP's CLI interface via ssh, using python-pexpect, and it tries to launch the "reboot" command. Here's what the script looks like:
#!/usr/bin/python
# usage: python reboot_ap.py {host} {user} {password}
import pexpect
import sys
import time
command = "ssh %(user)s@%(host)s"%{"user":sys.argv[2], "host":sys.argv[1]}
session = pexpect.spawn(command, timeout=30) # start ssh process
response = session.expect(r"password:") # wait for password prompt
session.sendline(sys.argv[3]) # send password
session.expect(" -> ") # wait for D-Link CLI prompt
session.sendline("reboot") # send the reboot command
time.sleep(60) # make sure the reboot has time to actually take place
session.close(force=True) # kill the ssh process
The script connects properly to the AP (I tried running some other commands than reboot
, they work fine), it sends the reboot
command, waits for one minute, then kills the ssh process. The problem is: this time, the AP never reboots! I have no idea why.
Any solution, anyone?
In your first scenario (rebooting from ssh login): If your device is really rebooting, then all processes are killed, including the one connected to your ssh client. You shouldn't have to login after a reboot to kill old processes, since they cannot exist! I suspect your ssh client is not gracefully handling the forcible closing of the connection on the remote side, and so it hangs. You should be able to just close/kill it on your local system.
Sorry, I don't know much about
expect
, so I have no advice about its particular issues. However, if you want to script a remote reboot, it may be possible to set up passwordless ssh login via a keyfile, and then just dossh root@mydevice reboot
.If you are using OpenSSH client, I suggest reading section "ESCAPE CHARACTERS" in the man pages ssh(1) and ssh_config(5) - you can forcefully terminate the session at any time in the client by typing the escape character followed by a dot.
As for the core of the problem, the ssh daemon in the router probably isn't notified about the shut-down, so it never closes the session and that leaves your client waiting for a TCP time-out. Setting ServerAliveInterval is a rather reasonable in this case (you should be also able to set this in the ssh configuration file on a per-host basis).
You might also be interested in OpenWRT.
I fooled around with ssh options, and I think I just found a work-around.
Just add the
ServerAliveInterval
ssh option to the ssh client command like this:What happens then is that the process blocks completely (without rebooting the AP) for about 10 seconds, then the AP reboots, and after the 60 seconds sleep, the script ends properly.
I would still appreciate a better solution or an explanation of why this solves the problem at all!
Thanks