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

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

我正在尝试将变量从本地服务器(位置 1)传递到远程服务器(位置 2)。该代码的目的是从远程服务器的预定义位置复制文件。简单来说,我想使用预定义路径将文件从 location2 复制到 location1,其中 location1 位于本地服务器上,location2 是远程服务器。看代码段:

$location1=somewhere/on/local_server
$location2=somewhere/on/remote_server

sshpass -p "password" \
  ssh [email protected] 'su -lc "cp -r $location2 $location1";'

我得到的错误是 $location1 和 $location2 都未定义。另外,我不想手动输入位置路径,因为它们可以随时更改,并且如果手动完成,在代码中更改它们将很痛苦。

答案1

shell 变量就是:shell 的变量。该ssh命令或远程主机上启动的 shellsshd无法访问客户端 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"'\''

或者,您可以让本地 shell 扩展传递到远程 shell 的命令行中的变量:

ssh host "su -lc 'cp -r -- $location2 $location1'"

但这相当于运行:

eval eval "cp -r -- $location2 $location1"

也就是说,这些变量不会作为参数传递给cp,它们会被解释(两次)为 shell(远程用户的登录 shell,并由 启动shsu代码,因此如果$location1/somewhere;rm -rf /,则会产生戏剧性的后果。

正确的方法是正确转义远程 shell。因为有两级shell,所以需要对单引号进行两次转义(这里使用//ksh93语法):bashzsh

escaped_location1=\'${location1//\'/\'\\\'\'}\'
escaped_location1=${escaped_location1//\'/\'\\\'\'}
escaped_location2=\'${location2//\'/\'\\\'\'}\'
escaped_location2=${escaped_location2//\'/\'\\\'\'}
ssh host "su -lc 'cp -r -- $escaped_location2 $escaped_location1'"

假设远程用户的登录 shell 与 Bourne 类似。

答案2

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

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

sshpass -p "password" \
  ssh [email protected] "su -lc \"cp -r $location2 $location1\";"

或关闭单引号并再次打开它们:

sshpass -p "password" \
  ssh [email protected] 'su -lc "cp -r '$location2' '$location1'";'

bash 自动执行字符串连接。

注意:未测试。如果$locationX包含空格或其他奇怪的字符,可能会搞砸。

答案3

除了莱斯马纳的回答之外:您应该引用他的第二个示例中的变量。

sshpass -p "password" \
  ssh [email protected] 'su -lc "cp -r '\\\"$location2\\\"' '\\\"$location1\\\"'";'

答案4

看看我为更新我们的服务而编写的这个脚本。

PROJ=$2将被传递到远程运行环境。

function update-env () {
    env=$1
    proj=$2

    # script for update test env
    ssh -A root@$2.$1.test.com PROJ=$2 'bash -s' <<'ENDSSH'
        # commands to run on remote host
        su gmuser
        cd /srv/apps/$PROJ
        /usr/bin/git pull
        exit
        supervisorctl restart $PROJ
    ENDSSH
}

相关内容