2017-03-01 59 views
1

這些命令如何導致不同的輸出?ssh命令引用有什麼不同?

⋊> ssh host bash -c 'cd /tmp; pwd' 
/home/manu 
⋊> ssh host "bash -c 'cd /tmp; pwd'" 
/tmp 

到類似的問題here的回答說:

尾隨參數組合成被傳遞到作爲參數傳遞給你的登錄shell對-c選項一個字符串遠程機器。

*的情況下,我可以理解這一點,但在本例中哪些部分將在本地進行評估?另外,在bash命令之前的--沒有幫助。

+0

看到這個職位:奇怪的「上海-c」行爲時,通過SSH運行(http://unix.stackexchange.com/questions/340221/strange-sh-c-behavior- when-run-through-ssh) – codeforester

+1

@codeforester,...儘管我認爲這應該超出'sh -c',因爲這肯定是一個在其他場景中相關的問題。 –

回答

6

這裏要理解的是,ssh只是簡單地連接它的參數(與$*一樣),並將該連接的字符串傳遞給sh -c


因此,在的情況下:

ssh josh-play bash -c 'cd /tmp; pwd' 

... SSH運行:

sh -c 'bash -c cd /tmp; pwd' 

...因此,SH運行:

bash -c cd /tmp 
pwd 

。 ..和你可以測試自己,bash -c cd /tmp並沒有太多的用處ul(它運行的腳本文本僅包含cd; /tmp作爲參數存儲,但腳本文本從不讀取其參數,因此沒有意義)。此外,只要bash退出,我們又回到了父項sh過程中,其中cd從未運行過。

傳遞給你的外殼句法引號完全喪失,而pwd是由您手動觸發(在這種用法,只是調用cd不帶任何參數的bash不會調用 - /tmp$1,但該腳本作爲參數傳遞給cd從不解除引用該變量),而是通過ssh隱式調用的sh


如果你知道你的遠程sh由bash或ksh的提供 - 外殼支持$''分機 - 你可以做任意argv數組以下(在這種情況下bash-ccd /tmp; pwd) :

# ask your shell to generate an eval-safe quoted form of your argument list 
printf -v rmt_cmd '%q ' bash -c 'cd /tmp; pwd' 

# pass that through to be run by the remote sh -c 
ssh josh-play "$rmt_cmd" 

需要說明上述的是,如果您的參數列表可以包含換行符或隱藏字符,printf %q在bash或ksh可以在形式POSIX SH不保證能夠讀取逃避它。爲了避免這種情況:

# ask your shell to generate an eval-safe quoted form of your argument list 
printf -v rmt_cmd '%q ' bash -c 'cd /tmp; pwd' 

# ...and use bash to evaluate that quoted form. 
ssh josh-play 'exec bash -s' <<<"$rmt_cmd"