У меня есть скрипт, который подключается к удаленному серверу и проверяет, установлен ли какой-либо пакет:
ssh root@server 'bash -s' < myscript.sh
myscript.sh:
OUT=`rpm -qa | grep ntpdate`
if [ "$OUT" != "" ] ; then
echo "ntpdate already installed"
else
yum install $1
fi
Этот пример может быть упрощен. Вот myscript2.sh
что имеет ту же проблему:
read -p "Package is not installed. Do you want to install it (y/n)?" choise
Моя проблема в том, что Bash не может читать мои ответы в интерактивном режиме.
Есть ли способ выполнить локальный сценарий удаленно, не теряя возможность подсказывать пользователю?
Ответы:
Попробуйте что-то вроде этого:
Эти
-t
силы на выделении терминала,$(<your_script)
считывает весь файл и в этом случае передает содержимое в качестве одного аргументаssh
, который будет выполняться оболочкой удаленного пользователя.Если сценарию нужны параметры, передайте их после сценария:
Работает на меня, не уверен, что это универсально, хотя.
источник
your script
, сохранив при этом преимущества синтаксиса, который вы использовали в своем ответе? Используяssh -t yourserver "$(<your_script --some_arg)"
только результаты вbash: --some_arg: command not found
.ssh ... $(<script) script_arg1 script_arg2 ...
Ваша проблема в том, что
ssh
на удаленной машине запускается неинтерактивная оболочка входа в систему. Очевидным простым решением было бы скопировать скрипт на удаленный сервер и запустить его оттуда:Если по какой-либо причине копирование невозможно, я бы изменил сценарий, чтобы сначала подключиться и проверить,
$1
установлено ли, а затем повторно подключиться и установить, если необходимо:источник
$OUT=$(ssh root@server rpm -qa | grep "$1");
выхода, а затем второе соединение займет столько же времени, сколько и первое. Я ошибаюсь?ssh -M foo.example.com sleep 99999999
илиssh -M foo.example.com read <somefifo
как мастер и убейте это явно (с помощьюkill
илиecho done >somefifo
), когда вы закончите.Вот хорошее объяснение .
Поэтому я адаптировал скрипт к
и это не сработало.
поэтому я переместил скрипт на удаленный компьютер, чтобы избежать локального перенаправления на ssh. (Мои команды находятся в файле с именем f )
Это сработало. Вот вывод:
Как упомянул @terdon, первоначальная цель заключалась в удаленном запуске локальных сценариев, удаленное копирование может быть автоматизировано, это всего лишь один пример, все в одной строке.
источник
bash -s < script.sh
как это делал OP? Не могли бы вы включить объяснение в свой ответ вместо ссылки на него?В прошлом я несколько раз искал решения этой проблемы, но так и не нашел полностью удовлетворительного. Проникновение в ssh теряет вашу интерактивность. Два соединения (scp / ssh) медленнее, и ваш временный файл может остаться без дела. И весь сценарий в командной строке часто заканчивается выходом из ада.
Недавно я столкнулся с тем, что размер буфера командной строки обычно довольно большой ('getconf ARG_MAX> 2MB, где я посмотрел). И это заставило меня задуматься о том, как я мог бы использовать это и смягчить проблему побега.
Результат:
или используя здесь документ и кошку:
Я расширил эту идею, чтобы создать полностью работающий пример сценария BASH,
sshx
который может запускать произвольные сценарии (не только BASH), где аргументы также могут быть локальными входными файлами, поверх ssh. Смотрите здесь .источник
"
символов, которые необходимо экранировать. А также это ограничено скриптами BASH. Мое решение - это общий случай для любого содержимого сценария любого установленного языка сценариев. Далее, в sshx я дополнительно демонстрирую сериализацию файлов аргументов, что довольно изящно.echo "$(cat my_script | base64)" | base64 --decode
выглядите эквивалентно (-ish)cat my_script | base64 | base64 --decode
, что выглядит как неоперативный.echo "ARG1=$1, USER=$USER, END"
. а)$ ssh host "$(<my_bash)" foo
->ARG1=, USER=user, END foo
. б)$ ssh host bash "<(echo $(cat my_bash|base64) | base64 --decode)" foo
->ARG1=foo, USER=user, END
. Здесь (а) эффективно работает:bash -c $'#!/bin/bash\necho "ARG1=$1, USER=$USER, END" foo'
или что-то подобное. Обратите внимание, что арг не работает. Где (б) работает:bash <(echo IyEvY...5EIgo= | base64 --decode) foo
. (2) Я использовал base64 в качестве транспортной кодировки.