我试图将变量传递给 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_parameter
或AcceptEnv LC_*
(有时默认情况下会这样做),否则这将不起作用sshd
。
您的示例中的错误消息Undefined variable
表明远程用户的登录 shell 是csh
或tcsh
。最好显式调用 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_config
SendEnv
-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 了。