当我想从 bash shell 重启 D-Link DWL-3200-AP 接入点时,我使用以下命令连接到 AP ssh
,然后只需reboot
在 CLI 界面中输入即可。大约 30 秒后,AP 重新启动:
# 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
听起来不错吧?但不幸的是,出于某种原因,ssh 客户端进程永远不会退出(也许 AP 终止 ssh 服务器的速度有点太快了,我不知道)。我的 ssh 客户端进程完全被阻止了(即使我等待几分钟,也不会发生任何事情)。我总是必须等待 AP 重新启动,然后打开另一个 shell,找到 ssh 客户端进程 ID(使用ps aux | grep ssh
),然后使用 终止 ssh 进程kill <pid>
。这很烦人。
所以我决定编写一个 python 脚本来重启 AP。该脚本使用 python-pexpect 通过 ssh 连接到 AP 的 CLI 接口,并尝试启动“reboot”命令。脚本如下所示:
#!/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
该脚本正确连接到 AP(我尝试运行除 之外的其他一些命令reboot
,它们工作正常),它发送命令reboot
,等待一分钟,然后终止 ssh 进程。问题是:这一次,AP 永远不会重新启动!我不知道为什么。
有人有解决办法吗?
答案1
在您的第一个场景中(从 ssh 登录重新启动):如果您的设备真的重新启动后,所有进程都会被终止,包括连接到 ssh 客户端的进程。您不必在重新启动后登录来终止旧进程,因为它们不存在!我怀疑您的 ssh 客户端没有妥善处理远程端连接的强制关闭,因此它挂起了。您应该能够在本地系统上关闭/终止它。
抱歉,我对 了解不多expect
,因此对其具体问题没有建议。但是,如果您想编写远程重启脚本,可能可以通过密钥文件设置无密码 ssh 登录,然后执行ssh root@mydevice reboot
。
答案2
如果您正在使用 OpenSSH 客户端,我建议阅读手册页 ssh(1) 和 ssh_config(5) 中的“转义字符”部分 - 您可以随时在客户端中通过键入转义字符后跟一个点来强制终止会话。
至于问题的核心,路由器中的 ssh 守护程序可能未收到有关关闭的通知,因此它永远不会关闭会话,而这会导致您的客户端等待 TCP 超时。在这种情况下,设置 ServerAliveInterval 是相当合理的(您还应该能够在每个主机的基础上在 ssh 配置文件中设置它)。
你也可能对此有兴趣OpenWRT。
答案3
我尝试了各种 ssh 选项,最后我想我找到了一种解决方法。
只需将ServerAliveInterval
ssh 选项添加到 ssh 客户端命令即可,如下所示:
command = "ssh -o ServerAliveInterval=10 %(user)s@%(host)s"%{"user":sys.argv[2], "host":sys.argv[1]}
接下来发生的情况是,该过程完全阻止(不重新启动 AP)约 10 秒钟,然后 AP 重新启动,并在 60 秒休眠后,脚本正常结束。
我仍然希望有一个更好的解决方案或解释为什么这可以解决问题!
谢谢