我有一些需要管理的 Juniper SSG 防火墙,我希望能够从一些监控脚本向它们发送命令。我使用公钥配置了 SSH 访问,并且能够自动登录防火墙。
当我以交互方式运行 SSH 时,一切正常:
$ssh <firewall IP>
FIREWALL-> <command>
<command output>
FIREWALL-> exit
Connection to <firewall IP> closed.
$
但是当我尝试从命令行运行该命令时,它不起作用:
$ssh <firewall IP> <command>
$
当然,当向远程 Linux 机器发送命令时,这个方法可以正常工作:
$ssh <linux box IP> <command>
<command output>
$
为什么会发生这种情况?以交互方式运行 SSH 和在 SSH 命令行上指定要运行的命令有什么区别?
更新:
它也适用于 Cisco 路由器。只有 Juniper 防火墙似乎有此行为。
从 SSH 的调试输出来看,连接似乎已正确建立,但 Juniper 框在发送命令时以 EOF 回复,而 Linux 框则以实际命令输出回复:
Linux:
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug2: channel 0: send open
debug1: Entering interactive session.
debug2: callback start
debug2: client_session2_setup: id 0
debug1: Sending command: uptime
debug2: channel 0: request exec confirm 0
debug2: callback done
debug2: channel 0: open confirm rwindow 0 rmax 32768
debug2: channel 0: rcvd adjust 131072
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
16:44:44 up 25 days, 1:06, 3 users, load average: 0.08, 0.02, 0.01
debug2: channel 0: rcvd eof
debug2: channel 0: output open -> drain
debug2: channel 0: obuf empty
debug2: channel 0: close_write
debug2: channel 0: output drain -> closed
debug2: channel 0: rcvd close
debug2: channel 0: close_read
debug2: channel 0: input open -> closed
debug2: channel 0: almost dead
debug2: channel 0: gc: notify user
debug2: channel 0: gc: user detached
debug2: channel 0: send close
debug2: channel 0: is dead
debug2: channel 0: garbage collecting
debug1: channel 0: free: client-session, nchannels 1
debug1: Transferred: stdin 0, stdout 0, stderr 0 bytes in 0.1 seconds
debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 0.0
debug1: Exit status 0
瞻博:
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug2: channel 0: send open
debug1: Entering interactive session.
debug2: callback start
debug2: client_session2_setup: id 0
debug1: Sending environment.
debug1: Sending env LANG = en_US.UTF-8
debug2: channel 0: request env confirm 0
debug1: Sending command: get system
debug2: channel 0: request exec confirm 0
debug2: callback done
debug2: channel 0: open confirm rwindow 2048 rmax 1024
debug2: channel 0: rcvd eof
debug2: channel 0: output open -> drain
debug2: channel 0: obuf empty
debug2: channel 0: close_write
debug2: channel 0: output drain -> closed
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug2: channel 0: rcvd close
debug2: channel 0: close_read
debug2: channel 0: input open -> closed
debug2: channel 0: almost dead
debug2: channel 0: gc: notify user
debug2: channel 0: gc: user detached
debug2: channel 0: send close
debug2: channel 0: is dead
debug2: channel 0: garbage collecting
debug1: channel 0: free: client-session, nchannels 1
debug1: Transferred: stdin 0, stdout 0, stderr 0 bytes in 0.2 seconds
debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 0.0
debug1: Exit status 1
答案1
当您指定要运行的命令时,SSH 不会分配伪 TTY。请尝试添加“-t”选项来覆盖此问题。
答案2
在命令行上传递命令与在 shell 中输入命令不同。在第一种情况下,shell 需要解析参数,而在后一种情况下,它需要从标准输入读取行。
如果它是一个愚蠢的(或者说是有限的,如果你喜欢这样称呼它)交互式 shell,那么它很可能没有被编码来支持这两种方式(我在实践中见过这种行为)。但是,由于 shell 显然支持键入命令,因此如果您只是将所有命令发送到其标准输入,您可能会更幸运。像这样:
echo command | ssh ...
答案3
这在 SRX240 上有效:
( echo 'sh conf|d s|n'; echo 'quit' ) | ssh [email protected] "cli"
可以通过使用 bash heredoc 来进一步改进,这样您就可以将完整的语句粘贴到其中,但这个例子现在应该足以指导您。
heredoc 示例应像这样工作:(未经测试)
cat << EOF | ssh [email protected]
sh conf|d s|n
quit
EOF
答案4
就像有人评论的那样,尝试添加 -t,甚至 -tt 来强制执行。据说这个解决方法可以修复类似的问题。
事实上,我遇到了与此相关的问题,除了对我来说它是从 CLI 工作,但不能通过 cron 工作。