在 ssh 中传递变量

在 ssh 中传递变量

我试图将变量传递给 ssh 远程但不起作用。我的代码是:

#!/bin/bash
set -x
conexion="[email protected]"
parameter="$1"
ssh -T $conexion <<'ENDSSH' 
clear
echo "$parameter"
ENDSSH

我执行:

./script.sh try

它对我说:

parameter: Undefined variable.

有什么帮助吗?

答案1

传递变量(环境变量)ssh是可能的,但通常受到限制。

您需要告诉客户发送它们。以 OpenSSH 为例,即:

ssh -o SendEnv=parameter host cmd...

但您还需要服务器接受它(AcceptEnv使用 OpenSSH 的配置指令)。接受任何变量都会带来很大的安全风险,因此默认情况下通常不会这样做,尽管某些 ssh 部署允许某些名称空间下的某些变量(例如LC_*在某些 OpenSSH 部署中)。

您还需要在调用之前导出变量ssh,例如:

LC_parameter="$parameter" ssh -o SendEnv=LC_parameter host csh << 'END'
echo $LC_parameter:q
END

上面,我们将 shell 变量的内容$parameter bash作为LC_parameter环境变量传递给ssh.ssh将其发送到sshd,如果它接受它,则将其作为环境变量传递给用户的登录 shell,然后将其传递给该csh命令(然后可以扩展它)。

host但如前所述,除非计算机管理员在配置中添加了AcceptEnv LC_parameterAcceptEnv LC_*(有时默认情况下会这样做),否则这将不起作用sshd

您的示例中的错误消息Undefined variable表明远程用户的登录 shell 是cshtcsh。最好显式调用 shell 以避免意外(ssh host csh也意味着不请求 tty,因此您不需要-T)。请注意$LC_parameter:q语法,这是csh逐字传递变量内容的方法,而不是"$LC_parameter"如果变量包含换行符则不起作用。

如果使用LC_*变量不是一个选项,那么您也可以使用客户shell(bash在您的情况下)扩展变量。一个天真的方法是

ssh host csh << END
echo "$variable"
END

但这是危险的,因为变量的内容将由远程 shell 解释。如果$variable含有`reboot`或者"; reboot; : "举例的话,那就会产生不好的后果。

因此,您首先需要确保变量在远程 shell 的语法中正确引用。在这里,我会避免csh难以可靠地完成的地方并使用sh/ bash/ksh代替。

使用辅助函数进行 sh 引用:

shquote() {
  awk -v q=\' -v b='\\' '
    BEGIN{
      for (i=1; i<ARGC; i++) {
        gsub(q, q b q q, ARGV[i])
       printf "%s ", q ARGV[i] q
      }
      print ""
      exit
    }' "$@"
}

并调用ssh为:

ssh host sh << END
parameter=$(shquote "$parameter")
echo "\$parameter"
END

看看我们如何转义第三个$,因此 的扩展$parameter是由远程 shell 完成的,而不是本地 shell 完成的。

答案2

除了其他技巧(例如传递LC_*环境变量)之外,您还可以执行以下操作:

PARAMETER="123"
ssh user@host PARAMETER="$PARAMETER" bash -s <<- 'EOF'
    echo $PARAMETER
EOF

该方法的优点是不需要export PARAMETER,将其名称添加到远程主机上的配置中AcceptEnv(如果名称不是从 开始) ,添加到本地主机上(到或 到)。LC_/etc/ssh/sshd_configSendEnv-o/etc/ssh/ssh_config

答案3

删除ENDSSH第四行的引号应该会有所帮助。

礼貌:@Archemar 对问题的评论。

警告正如 @StéphaneChazelas 在此答案的评论中所述,此解决方案将导致$parameter此处文档中的变量被本地 shell 扩展,这意味着变量的内容将被远程 shell 解释为 shell 代码,这意味着它引入了命令注入漏洞。所以一般情况下不鼓励这样做。

答案4

在双引号内插入单引号:

$ file_name="one two"
$ ssh remote ls "'$file_name'"
ls: cannot access 'one two': No such file or directory

该变量首先被替换,而不删除单引号。这样内容就被单引号发送到 ssh 了。

相关内容