use*_*034 7 ssh shell-script here-document
我正在尝试将变量传递给 ssh 远程但不起作用。我的代码是:
#!/bin/bash
set -x
conexion="user@xx.yy.zz.pp"
parameter="$1"
ssh -T $conexion <<'ENDSSH'
clear
echo "$parameter"
ENDSSH
Run Code Online (Sandbox Code Playgroud)
我执行:
./script.sh try
Run Code Online (Sandbox Code Playgroud)
它说我:
parameter: Undefined variable.
Run Code Online (Sandbox Code Playgroud)
有什么帮助吗?
传递变量(环境变量)ssh
是可能的,但通常受到限制。
您需要告诉客户发送它们。例如使用 OpenSSH,它是:
ssh -o SendEnv=parameter host cmd...
Run Code Online (Sandbox Code Playgroud)
但是您还需要服务器接受它(AcceptEnv
OpenSSH 的配置指令)。接受任何变量都会带来很大的安全风险,因此通常默认情况下不会这样做,尽管某些 ssh 部署允许某些命名空间下的某些变量(例如LC_*
在某些 OpenSSH 部署中)。
您还需要在调用之前导出变量ssh
,例如:
LC_parameter="$parameter" ssh -o SendEnv=LC_parameter host csh << 'END'
echo $LC_parameter:q
END
Run Code Online (Sandbox Code Playgroud)
上面,我们将$parameter
bash
shell 变量的内容作为LC_parameter
环境变量传递给ssh
. ssh
将其发送给sshd
,如果它接受它,则将其作为环境变量传递给用户的登录外壳,然后将其传递给该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
Run Code Online (Sandbox Code Playgroud)
但这会很危险,因为变量的内容会被远程 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
}' "$@"
}
Run Code Online (Sandbox Code Playgroud)
并调用ssh
为:
ssh host sh << END
parameter=$(shquote "$parameter")
echo "\$parameter"
END
Run Code Online (Sandbox Code Playgroud)
看看我们如何转义第三个,$
以便扩展$parameter
由远程 shell 完成,而不是本地 shell。
ENDSSH
删除第四行的引号应该会有所帮助。
礼貌:@Archemar 对问题的评论。
\n\n警告正如 @St\xc3\xa9phaneChazelas 在对此答案的评论中所述,此解决方案将导致$parameter
此处文档中的变量被本地 shell 扩展,这意味着变量的内容将被解释为 shell 代码通过远程 shell,这意味着它引入了命令注入漏洞。所以一般情况下不鼓励这样做。