【问题标题】:How to execute a remote command over ssh with arguments?如何通过带有参数的 ssh 执行远程命令?
【发布时间】:2013-09-01 09:57:07
【问题描述】:

在我的.bashrc 中,我定义了一个稍后可以在命令行中使用的函数:

function mycommand() {
    ssh user@123.456.789.0 cd testdir;./test.sh "$1"
}

使用该命令时,只在远程主机上执行cd命令; test.sh 命令在本地主机上执行。这是因为分号分隔了两个不同的命令:ssh 命令和test.sh 命令。

我尝试如下定义函数(注意单引号):

function mycommand() {
    ssh user@123.456.789.0 'cd testdir;./test.sh "$1"'
}

我试图将cd 命令和test.sh 命令放在一起,但参数$1 没有得到解决,这与我赋予函数的内容无关。总是尝试执行命令

./test.sh $1

在远程主机上。

如何正确定义mycommand,所以脚本test.sh在切换到目录testdir后在远程主机上执行,并能够将mycommand的参数传递给test.sh ?

【问题讨论】:

  • 这与要点无关,但您可能希望使用&& 而不是分号来加入远程主机上执行的命令:cd testdir && ./test.sh "$1"。使用该表单(因为在 bash 中评估 && 短路),如果 cd 失败,则不会执行第二个命令,并且您不会无意中在 user 中运行不同的 test.sh主目录。

标签: linux bash ssh


【解决方案1】:

改为这样做:

function mycommand {
    ssh user@123.456.789.0 "cd testdir;./test.sh \"$1\""
}

您仍然需要将整个命令作为单个字符串传递,但在该单个字符串中,您需要先扩展 $1,然后才能将其发送到 ssh,因此您需要使用 ""

更新

实际上,另一种正确的方法是使用printf %q 正确引用参数。即使参数包含空格、单引号、双引号或任何其他可能对 shell 具有特殊含义的字符,这也会使参数安全解析:

function mycommand {
    printf -v __ %q "$1"
    ssh user@123.456.789.0 "cd testdir;./test.sh $__"
}
  • 使用function 声明函数时,不需要()
  • 不要仅仅因为您是 POSIXist 就对此发表评论。

【讨论】:

  • @JoSo 是的,这就是它的基础,所以根据使用情况,用户可以选择清理他需要的参数。关于基本的ssh,可能没有更好的方法——除非你先进行文件传输,等等。
  • @JoSo 是的,更好的方法是定义一个引用函数,如quote() { printf "'%q'" "$1"; },然后执行ssh user@host "cd testdir; ./test.sh $(quote "$1")"
  • @augurar,差不多,但%q 结果是自引用的;用文字引号包围它们是不必要的或不正确的。 printf -v arg_str '%q ' "$1"; ssh user@host "cd testdir; ./test.sh $arg_str" 就够了。
  • @CharlesDuffy 为什么你需要添加空间?
  • @konsolebox,仅针对直接情况,并不是真的,但是如果添加更多参数而不是将它们全部混合在一起,则成语会缩放。
【解决方案2】:

恢复一个旧线程,但没有列出这种非常干净的方法。

function mycommand() {
    ssh user@123.456.789.0 <<+
    cd testdir;./test.sh "$1"
+
}

【讨论】:

  • 如果$1 将扩展为具有" 和可扩展字符(如$`)的字符串,这将失败。
  • 它不会“失败”。它与执行任何带参数的非 ssh 命令具有相同的效果。 OP 并没有要求学习双重转义论点。只是如何让他的第二个命令执行他已经打算的 [whatever] 参数。
  • 如果用户询问如何通过 ssh 执行某些操作,那么有理由期望任何答案都涵盖特定于 ssh 的警告(即在运行代码时不存在的警告)本地)。双重扩展(以及由此引起的 shell 注入漏洞)是这样的警告之一,cd testdir; ./test.sh "$1" 直接在本地 shell 中运行时不存在,但在给定的代码中确实存在。
  • 我不认为你会支持一个展示 SQL 注入漏洞实践的数据库问题的答案,但是有人通过 mycommand '$(rm -rf ~)' 运行任意远程代码的可能性同样严重.
  • (...问题是,使您的代码安全所需的更改相当小:printf -v argv_str '%q ' "$@"; ssh user@host "bash -s $argv_str" &lt;&lt;'+',其余的可以保持原样;引用 heredoc 的 + sigil防止其扩张)。
【解决方案3】:

这是一个适用于 AWS 云的示例。场景是从自动缩放启动的某些机器需要在另一台服务器上执行一些操作,通过 SSH 传递新生成的实例 DNS

# Get the public DNS of the current machine (AWS specific)
MY_DNS=`curl -s http://169.254.169.254/latest/meta-data/public-hostname`


ssh \
    -o StrictHostKeyChecking=no \
    -i ~/.ssh/id_rsa \
    user@remotehost.example.com \
<< EOF
cd ~/
echo "Hey I was just SSHed by ${MY_DNS}"
run_other_commands
# Newline is important before final EOF!

EOF

【讨论】:

    【解决方案4】:

    我正在使用以下命令从本地计算机远程执行命令:

    ssh -i ~/.ssh/$GIT_PRIVKEY user@$IP "bash -s" < localpath/script.sh $arg1 $arg2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 2021-02-23
      • 1970-01-01
      • 2018-06-19
      • 2013-11-22
      • 2015-07-25
      相关资源
      最近更新 更多