Bash
如何在 ssh 和 sudo 的使用中轉義 shell 中的引號?
總而言之:
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