Bash

如何在 ssh 和 sudo 的使用中轉義 shell 中的引號?

  • January 19, 2017

總而言之:

question和example可以在本地測試:

sh -c "echo 'how to print single quote here'"

細節:

我有這樣的配置:

upload_server = ('192.168.1.1', 10051)

現在我需要一個 shell 腳本來替換伺服器配置。在本地,我可以用 sed 做到這一點:

sed -E 's/(    upload_server = ).*/\\1('\"'$a'\"', 10051)/g' config.py

但是有大量機器必須更改配置。

一個適當的計劃是ssh與 for..in 一起使用:

for i in `cat hosts`; do ssh $i "cmd"; done

但是要更改配置還需要一個sudo,它看起來像這樣:

for i in `cat hosts`; do ssh $i "sudo -c \"cmd\""; done

現在在 sed 中:

upload_server=123.123.123.123
upload_server_port=1000
cmd="sed -E 's/(    upload_server = ).*/\\1('\"\"'\"'${upload_server}'\"'\"\"', ${upload_server_port})/g' config.py"
ssh $i "sudo -c \"${cmd}\""

配置結果:

upload_server = (123.123.123.123, 1000)

應該是這樣的:

upload_server = ('123.123.123.123', 1000)

現在我對引號的用法很困惑。:(

在這種情況下,您可以通過在標準輸入上傳遞 sed 腳本來完全繞過引用問題。SSH 將本地標準輸入路由到遠端程序,sudo 只是讓它保持打開狀態,sed 可以在標準輸入上讀取它的腳本。您可以使用此處的文件為標準輸入傳遞內容。

for i in `cat hosts`; do
 ssh "$i" 'sudo sed -f - …' <<'EOF'
s/(    upload_server = ).*/\1("$a", 10051)/g
EOF
done

更一般地說,您可以通過 SSH 在標準輸入上傳遞一個 shell 片段,而不必擔心引用,只要您不需要在標準輸入上傳遞數據。

for i in `cat hosts`; do
 ssh "$i" sudo sh <<'EOF'
sed 's/(    upload_server = ).*/\1("$a", 10051)/g' …
EOF
done

從您的問題中不清楚您是否打算插入"$a"到配置文件中,或者本地 shell 中"something"變數的值在哪裡。如果要引用局部變數,則使用帶插值的here文件,並使用反斜杠保護here文件。請注意,由於 sed 和第二個片段中的遠端 shell 解析,變數的值不能包含任何字元或換行符。a``something``$\```\/'

 ssh "$i" sudo sh <<EOF
sed 's/(    upload_server = ).*/\\1("$a", 10051)/g' …
EOF

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