ssh usrname@ip 'bash -c "for i in 1 2 3; do date;sleep 1;done" '
效果很好,這是上述命令的輸出:
Sun Jun 1 11:02:12 CST 2022
Sun Jun 1 11:02:13 CST 2022
Sun Jun 1 11:02:14 CST 2022
而下面的命令遇到錯誤:
ssh usrname@ip 'bash -c "for i in $(seq 1 3); do date;sleep 1;done" '
這是錯誤訊息:
bash: -c: line 1: syntax error near unexpected token `2'
bash: -c: line 1: `2'
令人困惑的是,它for i in $(seq 1 3); do date;sleep 1;done在本地 bash 或遠程 bash 中運行良好。
提示:您可以通過更換到您的計算機來嘗試ssh usrname@ip 'bash -c "for i in 1 2 3; do date;sleep 1;done" '在您的本地計算機上提供服務。sshdip
uj5u.com熱心網友回復:
您將在本地運行命令時得到完全相同的錯誤(即沒有ssh):
$ bash -c "for i in $(seq 1 3); do date;sleep 1;done"
bash: -c: line 1: syntax error near unexpected token `2'
bash: -c: line 1: `2'
它發生的原因與事物擴展的順序以及分詞發生(或不發生)的時間有關。具體來說,這是因為該部分在作為要執行的命令的一部分傳遞給之前$(seq 1 3)被擴展但是因為它在雙引號中,所以它不受分詞的影響,所以數字之間的換行符保持不變而不是被轉換為單詞之間的中斷。您可以通過打開跟蹤來看到這一點:bashset -x
$ set -x
$ bash -c "for i in $(seq 1 3); do date;sleep 1;done"
seq 1 3
bash -c 'for i in 1
2
3; do date;sleep 1;done'
bash: -c: line 1: syntax error near unexpected token `2'
bash: -c: line 1: `2'
...所以它seq 1 3 首先運行。這將列印“1”、“2”和“3”,它們之間帶有換行符,因此它們就是如何包含在bash -c. 然后 bash 將換行符視為命令分隔符,并且您不能在for要迭代的事物串列中間放置命令分隔符。所以bash看到 a2它期望 a 的地方done,然后恐慌。
它正常作業的原因是因為你通常把它放在$(seq 1 3)一個沒有雙引號的背景關系中,所以換行符只是變成了分詞符。相比:
$ echo $(seq 1 3) # No double-quotes, newlines convert to word breaks
1 2 3
$ echo "$(seq 1 3)" # With double-quotes, newlines are retained
1
2
3
您可以通過轉義來解決此問題,$以延遲對$( )替換的解釋,直到它被傳遞給bash -c(這是在應用和洗掉雙引號之后):
$ bash -c "for i in \$(seq 1 3); do date;sleep 1;done"
Sat Jun 11 23:55:54 PDT 2022
Sat Jun 11 23:55:55 PDT 2022
Sat Jun 11 23:55:56 PDT 2022
(如果ssh整個事情都用單引號引起來,那么這也應該可以解決,這樣本地外殼就不會弄亂它。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/491432.html
