下面是一个脚本,它登录到远程主机(Cisco IOS-XR 路由器)并通过 SSH 运行单个命令。这个想法是获取命令的结果(一个整数),以便它可以由 Cacti 绘制。Cacti 在运行正常轮询例程时每 5 分钟运行一次此脚本:
#!/bin/bash
if [[ -z $1 ]]
then
exit 1
fi
HOST="$1"
USER="cact-ssh-user"
TIMEOUT=10s
export SSHPASS="aaaaaaaaaaaaa"
CMD="show controllers np struct IPV4-LEAF-FAST-P np0 | in Entries"
RAW_OUTPUT=$(timeout $TIMEOUT sshpass -e ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null $USER@$HOST "$CMD" 2>/dev/null)
GRT_UCASTV4_USED=$(echo -n "$RAW_OUTPUT" | grep "Entries" | awk '{print $6}' | tr -d "," | tr -d " ")
echo -n "ucastv4_used:$GRT_UCASTV4_USED"
此命令通过交互式 shell 可以正常工作(当我在 Cacti 服务器上使用/path/to/script/script.sh 10.0.0.1
.
$ ./script 10.0.0.1
ucastv4_used:1234
在 Cacti 日志中,输出为:05/22/2017 03:35:21 PM - SPINE: Poller[0] Host[69] TH[1] DS[6837] SCRIPT: /opt/scripts/cacti-scripts/asr9001-get-tcam-ucast-usage.sh 10.0.0.1, output: ucastv4_used:
我已经su
'ed 给 Cacti 用户,并且脚本工作得很好。所以这似乎特定于它作为 cronjob 运行,来自 SSH 命令的输出被神奇地重定向到某个地方,我不知道在哪里或为什么。
为了尝试调试它,我在脚本中添加了以下几行(直接在 下#!/bin/bash
)并等待 Cacti 5 分钟轮询间隔运行(我可以在 Cacti 日志中看到每 5 分钟调用一次脚本);
exec >/tmp/stdout.log 2>/tmp/stderr.log
set -x
stdout.log
仅包含与该文件ucastv4_used:
相同的内容,cacti.log
并且该stderr.log
文件包含远程 SSH 主机的登录横幅,仅此而已。SSH 输出到哪里去了?
我已经厌倦了将脚本中的 SSH 行更改为输出到文件,然后从那里读取:
timeout $TIMEOUT sshpass -e ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null $USER@$HOST "$CMD" > /tmp/output 2>/dev/null
GRT_UCASTV4_USED=$(grep "Entries" /tmp/output | awk '{print $6}' | tr -d "," | tr -d " ")
该文件/tmp/output
为空,因此GRT_UCASTV4_USED
变量也为空。stdout.log
最终和以前一样:ucastv4_used:
我还尝试更改#!/bin/bash
为#!/bin/bash -i
强制进行交互式会话。-i
如果我添加echo $PS1
到脚本中,我可以在设置的stdout.log
文件中看到这种$PS1
情况,而没有-i
它则不会打印任何内容。但是 SSH 命令仍然没有输出。SSH 输出的命令去哪了?
我也尝试过使用ssh ..... | tee /tmp/output
,以便输出应该显示出来/tmp/output
,/tmp/stdout.log
但两者都是空白的。
我可以在远程路由器上看到 SSH 会话正在进入并运行命令。这是来自debug ssh server
:
RP/0/RSP0/CPU0:May 22 14:52:57.976 UTC: SSHD_[65909]: (open_master_file) command added show controllers np struct IPV4-LEAF-FAST-P np0 | in Entries
此外,由于这是通过我与 Cacti 服务器的交互会话工作的,我猜问题出在那里,而不是路由器。我也相信 Cacti 它本身不是问题,我可以触发脊椎从我的交互式 SSH 会话中轮询这个路由器主机,并且脚本工作正常(进一步指出一些问题,即在非交互式 shell 中如何 SSH 输出正在蒸发):
$ cd /usr/local/spine/bin
$ ./spine -V 7 69 69
...
05/22/2017 04:06:56 PM - SPINE: Poller[0] Host[69] TH[1] DS[6837] SCRIPT: /opt/scripts/cacti-scripts/asr9001-get-tcam-ucast-usage.sh 10.0.0.1, output: ucastv4_used:658809
因此,似乎 SSH 输出被重定向到某个地方,我无法“获取它”,或者路由器以某种方式知道这是一个非交互式 SSH 客户端并且没有发回任何内容。我还能如何调试这个?
更新 1在 Cisco 路由器上
使用debug ssh server
时,当我通过与 Cacti 服务器的交互式 SSH 会话运行脚本以及通过 Cacti 的轮询间隔/cron 作业运行脚本时,我捕获了调试日志。我已经diff
编辑了输出,我能找到的唯一有趣的外观差异(除了 SSH PID 更改和 Cacti 服务器的临时源端口更改等内容)如下:
*** 132,145 ****
(sshd_interactive_shell) *** removing alarm
sshd_interactive_shell - ptyfd = 46
event_contex_init done
! sshd_ptytonet - Channel 1 Received EOT (bytes:1)
! sshd_ptytonet - Channel 1 exec command executed sending CHANNEL_CLOSE
! (close_channel), pid:182260085, sig rcvd:1, state:10 chan_id:1
! addrem_ssh_info_tuple: REMOVE Inside the critical Section %pid:182260085
! Cleanup sshd process 182260085, session id 1, channel_id 1
! addrem_ssh_info_tuple: REMOVE exiting the Critical Section %pid:182260085
close_channel: Accounting stopped: scriptaccount
! In delete channel code, pid:182260085, sig rcvd:1, state:10 chan_id:1
Sending Exit Status: 0 sig: 1
Sending Channel EOF msg
Sending Channel close msg for remote_chan_id = 0 chan_id = 1
--- 134,147 ----
(sshd_interactive_shell) *** removing alarm
sshd_interactive_shell - ptyfd = 46
event_contex_init done
! Pad_len = 6, Packlen = 12
! sshd_nettopty: EOF received. Disconnecting session
! (close_channel), pid:182329717, sig rcvd:1, state:10 chan_id:1
! addrem_ssh_info_tuple: REMOVE Inside the critical Section %pid:182329717
! Cleanup sshd process 182329717, session id 1, channel_id 1
! addrem_ssh_info_tuple: REMOVE exiting the Critical Section %pid:182329717
close_channel: Accounting stopped: scriptaccount
! In delete channel code, pid:182329717, sig rcvd:1, state:10 chan_id:1
Sending Exit Status: 0 sig: 1
Sending Channel EOF msg
Sending Channel close msg for remote_chan_id = 0 chan_id = 1
上半部分是我与 Cacti 服务器的交互会话。我注意到在上半区sshd_ptytonet - Channel 1 Received EOT (bytes:1)
,而通过 cronjob 调试显示sshd_nettopty: EOF received. Disconnecting session
。非交互式会话是否只是将我的 SSH 命令传递给远程主机并尽快退出(因此它不会等待 SSH 服务器响应命令输出)?