如何通过 ssh 传递 bash 的 $@ 并考虑参数中的空格?

如何通过 ssh 传递 bash 的 $@ 并考虑参数中的空格?

我想方便地从我的服务器读取日志。我正在尝试编写一个脚本,journalctl从我的服务器读取输出,并将我传递给脚本的参数应用于要journalctl调用的脚本。我可能想要应用各种过滤器,所以我希望将脚本的参数转换为journalctl的参数。例如

bin/log --since '2 days ago'

会运行

ssh host journalctl --since '2 days ago'

我尝试了这个:

#/usr/bin/env bash
ssh host journalctl "$@"

但是当我打电话时

bin/log --since '2 days ago'

我只是说:

Failed to parse timestamp: 2

好的,我们得到了一个带有空格的参数,当作为 SSH 命令的一部分传递时,该参数似乎会转换为多个参数。然后我尝试了以下操作:

#/usr/bin/env bash
ssh host bash -c 'journalctl autotests "$@"'

您可能猜到这并不能满足我的需要。

我到底该如何传递$@ssh?

答案1

这个问题:如何通过 ssh 执行复杂的命令行有点相关。我的回答集中在没有任何东西在本地扩展的情况;如果你想$@在本地扩展,这会让事情变得更复杂。不过,链接的资源可能会让你对这些事情的工作原理有所了解。

对于你来说,最简单的方法是使用Q运算符(参见这是我的另一个答案):

#!/usr/bin/env bash
ssh host "journalctl autotests ${@@Q}"

上述代码在纯 中无法运行sh,您需要 (local) bash。问题中的“shebang”是#/usr/bin/env bash,它不是 shebang,只是注释;shebang 应该以 开头#!。上述代码使用了正确的 shebang。

请注意如果你这样做:

ssh host bash -c "journalctl autotests ${@@Q}"

那么远程端的 shell 代码将缺少一层引号。如果你真的需要,bash -c那么你可以这样做:

#!/usr/bin/env bash
cmd="journalctl autotests ${@@Q}"
ssh host "bash -c ${cmd@Q}"

额外使用 可@Q为您提供所需的额外引用(或转义)级别。但在这种情况下,您很可能bash -c根本不需要,我给您的第一个命令应该可以工作。

相关内容