我需要一个 bash 脚本,在对服务器执行ssh
或命令时自动启动。我这样做:scp
ssh
scp
ssh -i path/to/key me@server some_command
或者
scp -i path/to/key file_to_copy me@server:/destination_folder
我的脚本应该检测启动了什么命令(ssh
或scp
),然后如果需要则解析参数(在此示例中为some_command
)。
为了使该脚本自动启动,我在中添加了一个命令authorized_keys
,如下所示:
command="~/script",no-pty,no-x11-forwarding,no-agent-forwarding ssh-rsa ...
好的,现在假设script
是:
#!/usr/bin/env bash
echo "hello"
echo "hello1"
echo "hello2"
好了,这样做之后ssh -i path/to/key me@server some_command
,我看到我的 shell(“客户端”)上打印了“hello”、“hello1”、“hello2”。完美。
但当这样做的时候scp -i path/to/key file_to_copy me@server:/destination_folder
,我只看到我的 shell (客户端)上打印了“hello”。
为什么?我该如何避免这种情况?请注意,如果echo
我对某个cat
文件执行一些操作而不是执行一些操作,那么在命令的情况下scp
,它只会打印第一行!(并且该ssh
命令再次运行良好并打印所有行)。
多谢!
答案1
SSH 命令的标准输出并不总是您的终端。
scp、rsync 或 git 等工具实际上几乎完全通过 stdin/stdout 与服务器端组件进行通信 - 并且它们希望接收符合其自身协议的消息,而不仅仅是随机的 ASCII 文本。
因此,当本地scp
客户端在发送请求之前收到任何文本时,它会将其视为协议违规。它会打印第一行只是为了友善,但随后退出,因为它无法与远程 scp 处理程序通信,并且向用户传递消息不是其功能的一部分。
其他工具根本不会打印任何文本。例如,rsync 只会报告错误:
$ rsync badserver:test.c /tmp
protocol version mismatch -- is your shell clean?
rsync error: protocol incompatibility (code 2) at compat.c(178) [Receiver=3.1.3]
Git 和其他使用 SSH 作为传输方式的工具也是如此:它们希望完全控制 stdin 和 stdout,就像使用 TCP 连接一样。(有些客户端确实会传递写入标准错误使用>&2
,但大多数不会;OpenSSH scp 不会,PuTTY pscp 也不会。)
没有完全通用的方法可以通过 shellscript 显示任意消息。但是如果你只需要一个基本的问候语,你可以显示静止的使用 sshdBanner
选项的消息 – 例如 OpenSSH 服务器可以根据用户名、组、IP 地址和 支持的其它条件提供不同的消息Match
。SSH 客户端将识别横幅消息,将其与正常的 stdout/stderr 区分开来。
答案2
您无法打印任何事物在使用 SCP 或 SFTP 等严格协议的会话中。这样做会破坏协议。使用scp
(OpenSSH 命令行 SCP 客户端),如果您将输出打印到 stderr,它可能会起作用。但您可能会破坏其他 SCP 客户端(例如我的 WinSCP)。
改用 SSH 横幅。
有关类似主题,请参阅:
但是你真的希望命令在客户端打印任何内容吗?你不只是想调试/测试你的脚本吗?你考虑过将输出写入服务器上的文件中吗?