和我的問題類似這裡,除了多個 ssh,並且類似於這個問題但參數中有空格......
我想test.sh
透過多個 ssh 在遠端伺服器上運行本地腳本。test.sh
接受一個經常有多個單字的論點。
測試.sh:
#!/bin/bash
while getopts b: opt;
do
case $opt in
b)
bval="$OPTARG"
;;
esac
done
echo $bval
呼叫測試.sh
#!/bin/bash
# Do some stuff
PHRASE="multi word arg"
ssh -A user@host1 "bash -s" -- < ./test.sh -b "${PHRASE@Q}"
並運行./call_test.sh
,這會正確輸出
multi word arg
但是當我將最後一行更改call_test.sh
為以下內容時:
ssh -A user@host1 ssh -A user@host2 "bash -s" -- < ./test.sh -b "${PHRASE@Q}"
並運行./call_test.sh
,它輸出:
multi
基本上,從單一 SSH 更改為多個 SSH 打破了我的多詞爭論。
我認為多個 ssh 命令在每一步都會解開多個單字參數的引號,但我不確定如何防止這種情況。有什麼想法如何成功地將多字參數傳遞給跨多個 ssh 運行的腳本嗎?
編輯:
我相信這個答案解決我遇到的問題。
答案1
如果透過 2 個 ssh 指令傳遞它,則必須對字串進行兩次引號轉義。透過額外的PHRASE=${PHRASE@Q}
作業來做到這一點。
但請注意,${var@Q}
and printf %q
(如下所述)都將使用$'...'
引號轉義格式,遠端 shell 可能不支援該格式。
test.sh
將腳本的最後一行修復echo "$bval"
為echo $bval
:
PHRASE="multi word arg"
PHRASE=${PHRASE@Q}
ssh -A user@host1 ssh -A user@host2 "bash -s" -- < ./test.sh -b "${PHRASE@Q}"
multi word arg
${var@P}
您可以使用舊版的 bash 不支援的擴充形式,而不是使用printf -v var %q
:
PHRASE="multi word arg"
printf -v PHRASE %q "$PHRASE"
printf -v PHRASE %q "$PHRASE"
ssh -A user@host1 ssh -A user@host2 "bash -s" -- < ./test.sh -b "$PHRASE"
另外,您可以將整個腳本及其參數放在一個變數中,而不是透過標準輸入提供腳本,這是低效的(當從標準輸入讀取腳本時,bash 將為每個位元組執行讀取系統調用):
printf -v cmd 'bash -c %q bash -b %q' "$(cat test.sh)" 'multi word wahterve'
printf -v cmd %q "$cmd"
ssh localhost ssh localhost "$cmd"
multi word wahterve