编写 SSH 脚本以重启 GrandStream 手机

问题描述

我在我们的网络上使用数百个可通过 SSH 访问的独立设备。我在这里以 GrandStream GXP2200 手机为例,因为它最容易解释。

我们的 GrandStream GXP2200 手机可以通过 SSH 访问,您可以通过 SSH 执行基本功能,例如重启或升级固件。使用 Putty 远程重启手机很容易;只需输入用户名密码,输入reboot命令,按y,然后回车。然后手机将尽职尽责地重新启动。

我需要能够编写此脚本。理想情况下,我的脚本是一个批处理文件,每个设备一行,即

plink -t [email protected] -pw <password> -m commands.txt

plink -t [email protected] -pw <password> -m commands.txt

...等等

我可以拥有一个用于固件升级、重启或更改特定设置的脚本,然后能够将其部署到许多设备上。看起来这应该很容易,尤其是使用 Plink 之类的东西。我在 Windows 上有很多经验,但在 Linux 上没有那么多经验。我真的很想在 Windows 上完成此操作,但如果需要,我不反对启动 Ubuntu VM。我已经阅读了使用 expect 脚本和 bash 脚本的示例,并且我已经阅读了关于管道字符串和将 unicode 字符代码放入文本文件并以各种方式重定向内容......但是我试过的都没有效果

主要问题是无法发送完成命令所需的击键。例如,当通过 SSH 向手机发送重启命令时,它会询问您是否真的要重启,如果是,请按 y,然后输入。在 commands.txt 中,如果需要,我可以逐行列出一堆命令。但是,如果其中任何一个需要用户交互,它就会卡住。例如,当手机收到 reboot 命令时,它会提示您按 y 然后按 Enter。据我所知,Plink 没有办法发送这些击键,因为它在从 reboot 发送下一行之前等待 commands.txt 命令完成。

第二个问题是,由于这些独立的网络设备相当简单,内置命令(例如 reboot不支持选项,例如 /y。事实上,这些手机在检测到有效命令后完全停止解析来自终端的输入。例如,如果我使用 Putty 登录并键入我的命令,但在末尾添加了一堆随机垃圾,例如 rebootlkq2jq3pyjq 并按 Enter,它的作用与我只键入 reboot 一样。

我可以用来远程重启手机的唯一方法是手动登录网络界面并单击重启按钮。我可以弄清楚 HTML,但是当涉及到 PHP 或 Java 或任何 Web 界面正在使用时,我迷路了。我希望能够利用网络界面上那个按钮的代码

TLDR:如何在通过脚本化 SSH 连接发送 y 命令后发送 Enterreboot?互联网上有很多人在寻找解决此问题的方法

:: 编辑::

在这种情况下,我的最佳选择似乎是 expect。它似乎旨在解决此类问题。不幸的是,Windows 的 expect 是个笑话。

  1. 好的文档是不存在的。它要么太先进,要么太简单,要么不完整,要么过时。
  2. 某些下载或版本不包含所有需要的文件
  3. tcl 无法找到 ssh (C:\Windows\System32\OpenSSH\ssh.exe) 即使我可以在这台机器上的任何命令提示符下输入 ssh 并且它工作正常并且我已经添加了我的 {{1} } 我的用户 tcl 和系统 Path 环境变量的路径并重新启动。
  4. Path/tcl 看起来它想与 expect 一起工作(它不会抱怨找不到文件),但无论我尝试什么选项,它总是说 plink 我尝试的最后一个命令是 The request is not supported. 并且它返回了 spawn plink -ssh 172.27.4.0

所以是的,我要尝试 Ubuntu。我会根据结果在编辑或答案中写下我的结果。

解决方法

目标:使用自动化脚本通过 SSH 远程重启网络设备。

解决方案:在 Linux 机器上使用 expect 脚本。

工作脚本:

#!/usr/bin/expect -f

set send_slow {1 .1}
proc send {ignore arg} {
        sleep .1
        exp_send -s -- $arg
}

set timeout -1
spawn ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 [email protected]
match_max 100000
expect -exact "\[email protected]'s password: "
send -- "password\r"
expect -exact "\r
GXP2200 > "
send -- "reboot\r"
expect -exact "reboot\r
You have chosen to reboot.\r
Do you want to continue (y/N)?"
send -- "y\r"
expect eof

使用在 Ubuntu 上运行的 expect 对我来说是最好的解决方案。我今天花了大约 4 个小时试图让 expect 在 Windows 上工作(我非常不成功)。因此,我没有使用 Windows,而是启动了一个 Ubuntu 20 Server VM,安装了 expectsudo apt install expect,使用 autoexpect 生成脚本,编辑该脚本,并且我已经有了一个工作脚本模板不到 1 小时。我在 Linux 版本中没有看到任何奇怪的环境怪癖或语法问题。我的 Linux-foo 不是很强大,但我很快就弄明白了。

我计划将其扩展到不仅用于重启,而且还用于在大量 IP 电话、网络交换机、网络摄像头和可能的一些 Linux 服务器上编写设置更改脚本。