Bash

如何將變數從本地伺服器傳遞到遠端伺服器?

  • November 16, 2015

我正在嘗試將變數從本地伺服器(位置 1)傳遞到遠端伺服器(位置 2)。該程式碼的目的是從預定義位置的遠端伺服器複製文件。簡單來說,我想使用預定義的路徑將文件從 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";'

我得到的錯誤是兩者 $ location1 and $ location2 未定義。另外,我不想手動輸入位置路徑,因為它們可能隨時更改,如果手動完成,在程式碼中更改它們會很痛苦。

變數不會在單引號之間展開。

使用雙引號並轉義內部雙引號:

sshpass -p "password" \
 ssh username@74.11.11.11 "su -lc \"cp -r $location2 $location1\";"

或關閉單引號並再次打開它們:

sshpass -p "password" \
 ssh username@74.11.11.11 'su -lc "cp -r '$location2' '$location1'";'

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"'\''

或者,您可以讓本地 shell 擴展命令行中傳遞給遠端 shell 的變數:

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

但這相當於執行:

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

也就是說,這些變數沒有作為參數傳遞給cp,它們被解釋(兩次)為 shell(遠端使用者的登錄 shell,以及由sh啟動su)程式碼,所以如果$location1是 例如/somewhere;rm -rf /,那將產生戲劇性的後果。

正確的方法是正確地轉義遠端 shell 的那些。因為有兩級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'"

假設遠端使用者的登錄 shell 類似於 Bourne。

引用自:https://unix.stackexchange.com/questions/134114