如何将变量从本地服务器传递到远程服务器?

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 都未定义。此外,我不想手动输入位置路径,因为它们可以随时更改,如果手动完成,在代码中更改它们会很痛苦。

les*_*ana 5

变量不会在单引号之间扩展。

使用双引号并转义内部双引号:

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包含空格或其他奇怪的字符,可能会搞砸。


Sté*_*las 5

一个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 的。