Неверная спецификация перенаправления stdio "% h:% p"

[ОС - macOS, Shell - Bash]

У меня есть небольшой сценарий bash, который генерирует команду ssh на основе входных параметров. Сгенерированная команда:

ssh -o ProxyCommand='ssh <bastion_name> -W %h:%p' -A -D <port> <username>@<destination_host_name>

Скрипт сохраняет эту команду в переменной, скажем, cmd, где

cmd="ssh -o ProxyCommand='ssh $1 -W %h:%p' -A -D $3 $4@$2"

где $ 1 = имя_бастиона, $ 2 = имя_хоста_назначения, $ 3 = порт и $ 4 = имя пользователя.

а затем он пытается выполнить команду, например,

echo "Executing --> $cmd"
$cmd

но он завершается следующей ошибкой,

Bad stdio forwarding specification '%h:%p''

Но поскольку я повторяю cmd, я копирую пасту прямо в терминал, и она работает без ошибок.

Обратите внимание, что имя бастиона разрешается через конфигурацию ssh, в которой есть имя пользователя и другие атрибуты, определенные для этого хоста бастиона.

В чем проблема, потому что очевидно, что команда верна?

Не помещайте команды в переменные, они предназначены для данных, а не для исполняемого кода. См. BashFAQ # 50: Я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу! Либо выполните команду напрямую, либо используйте функцию, либо (при необходимости) используйте массив.

Gordon Davisson 31.10.2018 13:14

Могут быть сценарии, в которых вы намереваетесь сохранить исполняемый файл как данные. Вот пример такого сценария: создайте сценарий, который будет перебирать переменные среды, соответствующие определенному шаблону, и выполнять команду, переданную через аргумент.

Hendrik Prinsloo 31.10.2018 15:03
1
2
8 674
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Старайтесь не использовать eval, потому что это зло.

Всегда указывайте свои переменные (если у вас нет причин не делать этого). Никогда не $cmd, всегда "$cmd".

Используйте массивы bash:

cmd=(ssh -o ProxyCommand='ssh '"$1"' -W %h:%p' -A -D "$3" "$4@$2")

echo "Executing -->" "${cmd[@]}"
"${cmd[@]}"

Подробнее о цитировании здесь.

@edit: вынул часть $1 из одинарных кавычек, потому что намерение OP состоит в том, чтобы расширить ее. Исправлено выполнение -> строка.

Это не работает в macOS. cmd=(ssh -o ProxyCommand='ssh $1 -W %h:%p' -A -D "$3" "$4@$2")echo "$cmd" Выход -> ssh

Vijayant 01.11.2018 05:54
cmd=("-o ProxyCommand='ssh $bastion -W %h:%p' -A -D $port $user@$host") eval "ssh ${cmd[@]}" Это сработало. Я думаю, вы хотели убрать ssh из массива. Также он не работает без eval.
Vijayant 01.11.2018 12:19

Я имею в виду именно то, что я написал ... В первом комментарии echo "$cmd" равен echo "${cmd[0]}" - он будет печатать только первый элемент массива. Используйте echo "${cmd[@]}", чтобы распечатать их все. Во втором комментарии eval "ssh ${cmd[@]}" - зло - cmd=("-o ... ; rm -rf / "); eval "ssh ${cmd[@]}"; отформатирует ваш привод. Вы можете sshargs=$(-o ProxyCommand=' ' ...); ssh "${sshargs[@]}";. Он работает на моем компьютере. Я отредактирую сообщение, потому что, вероятно, вы хотите, чтобы $1 тоже расширился. Вы можете прочитать про цитирование здесь.

KamilCuk 01.11.2018 15:34

Моя проблема, эхо было неправильным, я пропустил печать всех элементов массива, но команда не запускалась без eval. В любом случае у меня есть решение, опубликованное в качестве ответа. Кроме того, согласование с eval - зло, но для моего случая использования его безопасно.

Vijayant 02.11.2018 05:37

Это работает,

cmd=("-o ProxyCommand='ssh $bastion -W %h:%p' -A -D $port $user@$host")
echo "Executing --> $cmd"
eval "ssh ${cmd[@]}"

Не используйте eval - единственная причина, по которой он здесь работает, заключается в том, что вы неправильно указали кавычки при определении массива. По сути, здесь есть две ошибки (цитирование и eval), которые по большей части нейтрализуют друг друга. Но только в основном. Лучше сразу получить правильное цитирование. См. Последнее изменение @ KamilCuk.

Gordon Davisson 02.11.2018 09:22

Другие вопросы по теме