Аналогично моему вопросуздесь, за исключением множественного 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