Shell-Script

如何通過多個 SSH 在遠端機器上執行帶有空格的本地腳本?

  • October 3, 2020

類似於我的問題here,除了有多個ssh,並且類似於這個問題,但參數中有空格……

我想test.sh通過多個 ssh 在遠端伺服器上執行本地腳本。test.sh接受一個通常包含多個單詞的參數。

test.sh:

#!/bin/bash
while getopts b: opt;
do
 case $opt in
   b)
      bval="$OPTARG"
      ;;
 esac
done
echo $bval

call_test.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 執行的腳本?

編輯:

我相信這個答案可以解決我遇到的問題。

如果通過 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

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