Red*_*son 4 shell bash environment-variables quoting
我试图将一个变量从我的本地服务器 (location1) 传递到远程服务器 (location2)。该代码的目的是从远程服务器的预定义位置复制文件。简单来说,我想使用预定义的路径将文件从 location2 复制到 location1,其中 location1 在本地服务器上,location2 是远程服务器。看代码段:
$location1=somewhere/on/local_server
$location2=somewhere/on/remote_server
sshpass -p "password" \
ssh username@74.11.11.11 'su -lc "cp -r $location2 $location1";'
Run Code Online (Sandbox Code Playgroud)
我得到的错误是 $location1 和 $location2 都未定义。此外,我不想手动输入位置路径,因为它们可以随时更改,如果手动完成,在代码中更改它们会很痛苦。
变量不会在单引号之间扩展。
使用双引号并转义内部双引号:
sshpass -p "password" \
ssh username@74.11.11.11 "su -lc \"cp -r $location2 $location1\";"
Run Code Online (Sandbox Code Playgroud)
或关闭单引号并再次打开它们:
sshpass -p "password" \
ssh username@74.11.11.11 'su -lc "cp -r '$location2' '$location1'";'
Run Code Online (Sandbox Code Playgroud)
bash 自动进行字符串连接。
注意:未测试。如果$locationX
包含空格或其他奇怪的字符,可能会搞砸。
一个shell变量,就是:shell的一个变量。该ssh
命令或sshd
远程主机上启动的 shell无法访问客户端 shell 的该变量。
导出的shell 变量作为环境变量传递给执行的命令。因此,如果您导出location1
它,它将作为环境变量传递给ssh
. 如果您使用SendEnv
ssh
配置指令(通过-o
或~/.ssh/config
或/etc/ssh/ssh_config
...),ssh
将尝试将其发送到sshd
远程主机。
但是,要使其正常工作,sshd
需要有一个AcceptEnv
允许接收该变量的配置指令。但是,出于安全原因,通常情况并非如此。
然而,许多默认的 ssh/sshd 部署允许传递名称以LC_
(用于本地化)开头的变量。所以你可以利用它:
LC_location1=$location1 LC_location2=$location2 ssh host
'su -lc '\''cp -r -- "$LC_location2" "$LC_location1"'\''
Run Code Online (Sandbox Code Playgroud)
或者,您可以让本地 shell 扩展传递给远程 shell 的命令行中的变量:
ssh host "su -lc 'cp -r -- $location2 $location1'"
Run Code Online (Sandbox Code Playgroud)
但这相当于运行:
eval eval "cp -r -- $location2 $location1"
Run Code Online (Sandbox Code Playgroud)
也就是说,这些变量不作为参数传递给cp
,它们被解释(两次)作为 shell(远程用户的登录 shell,以及sh
启动者su
)代码,因此$location1
,例如/somewhere;rm -rf /
,如果是,这将产生巨大的后果。
正确的方法是为远程 shell 正确地转义那些。由于炮弹的两个层面,你需要逃脱单引号两次(这里使用ksh93
/ bash
/zsh
语法):
escaped_location1=\'${location1//\'/\'\\\'\'}\'
escaped_location1=${escaped_location1//\'/\'\\\'\'}
escaped_location2=\'${location2//\'/\'\\\'\'}\'
escaped_location2=${escaped_location2//\'/\'\\\'\'}
ssh host "su -lc 'cp -r -- $escaped_location2 $escaped_location1'"
Run Code Online (Sandbox Code Playgroud)
这假设远程用户的登录 shell 是类似 Bourne 的。