Как запустить локальный скрипт с пробелами в аргументах на удаленной машине через несколько SSH?

Как запустить локальный скрипт с пробелами в аргументах на удаленной машине через несколько SSH?

Аналогично моему вопросуздесь, за исключением множественного ssh, и аналогичноэтот вопросно с пробелами в аргументах...

Я хотел бы запустить локальный скрипт test.shна удаленном сервере через несколько SSH. test.shпринимает аргумент, который часто состоит из нескольких слов.

тест.ш:

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

вызов_тест.ш

#!/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}и printf %q(описанные ниже) будут использовать $'...'формат экранирования кавычек, который может не поддерживаться удаленной оболочкой..

После исправления последней строки вашего 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"

Кроме того, вместо того, чтобы передавать свой скрипт через stdin, что неэффективно (bash будет выполнять системный вызов read для каждого байта при чтении скрипта из stdin), вы можете просто поместить весь скрипт и его аргументы в переменную:

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

Связанный контент