首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >远程主机上捕获的命令输出(SSH通过Cron)为空

远程主机上捕获的命令输出(SSH通过Cron)为空
EN

Stack Overflow用户
提问于 2017-05-22 15:11:24
回答 1查看 1.9K关注 0票数 2

下面是一个脚本,它登录到远程主机(一个Cisco IOS-XR路由器)并通过SSH运行一个命令。这样做的目的是获取命令的结果(一个整数),以便由Cacti绘制它。仙人掌运行此脚本时每5分钟运行一次,这是正常的投票例程:

代码语言:javascript
运行
复制
#!/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 (当我使用/path/to/script/script.sh 10.0.0.1在Cacti服务器上运行脚本时)运行良好。但是,当Cacti cronjob运行时,输出只是空的。因此,在我对Cacti服务器的SSH会话中,输出是:

代码语言:javascript
运行
复制
$ ./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编辑给了Cacti用户,脚本运行得很好。因此,这似乎是特定于它作为一个cronjob运行的,SSH命令的输出正在被神奇地重定向到某个地方,我不知道在哪里或者为什么。

为了尝试和调试这一点,我在脚本中添加了以下行(直接在#!/bin/bash下),并等待Cacti 5分钟轮询间隔运行(当脚本每5分钟调用一次时,我可以在Cacti日志中看到);

代码语言:javascript
运行
复制
exec >/tmp/stdout.log 2>/tmp/stderr.log
set -x

stdout.log只包含与cacti.log相同的ucastv4_used:stderr.log文件包含远程SSH主机的登录横幅,没有其他任何内容。SSH输出到哪里去了?

我已经厌倦了将脚本中的SSH行更改为输出文件,然后从那里读取:

代码语言:javascript
运行
复制
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添加到脚本中,我可以在stdout.log文件中看到设置了$PS1,如果没有-i,则不会打印任何内容。但是,仍然没有来自SSH命令的输出。SSH输出的命令在哪里?

我还尝试使用ssh ..... | tee /tmp/output,以便输出应该显示在/tmp/output/tmp/stdout.log中,但两者都是空的。

我可以在远程路由器上看到SSH会话正在启动并运行命令。这是来自debug ssh server

代码语言:javascript
运行
复制
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会话中轮询这个路由器主机,并且脚本工作得很好(进一步指出了在非交互外壳中SSH输出是如何蒸发的问题):

代码语言:javascript
运行
复制
$ 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当我通过交互式SSH会话运行脚本到Cacti服务器时,以及当它通过Cacti的轮询间隔/cron作业运行时,我捕获了调试日志。我已经编写了diff输出,我能找到的唯一有趣的不同之处(除了SSH更改和Cacti服务器更改的临时源端口等)如下:

代码语言:javascript
运行
复制
*** 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服务器使用命令输出进行响应)?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-12 12:20:04

  • 首先,告诉SSH客户端不要分配带有-T选项的PTY,因为显然cron没有。
  • 然后在stdin上给它无限的东西,这样它就会一直运行直到stdout打开,我们有/dev/零正是为了这个目的。

RAW_OUTPUT=$(timeout $TIMEOUT sshpass -e ssh -T -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null $USER@$HOST "$CMD" </dev/zero 2>/dev/null)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44116461

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档