Какой самый простой способ использовать ssh и запускать несколько команд в Bash? - PullRequest
307 голосов
/ 10 декабря 2010

У меня уже есть настроенный агент ssh, и я могу запускать команды на внешнем сервере в скрипте Bash, выполняя такие вещи:

ssh blah_server "ls; pwd;"

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

Итак, есть ли способ сделать это за один раз, заключенный в скобки, или что-то в этом роде?Я ищу что-то вроде:

ssh blah_server (
   ls some_folder;
   ./someaction.sh;
   pwd;
)

В принципе, я буду рад любому решению, пока оно чистое.

Редактировать

Комупоясните, я говорю о том, что это часть более крупного скрипта bash.Другим людям может понадобиться разобраться со сценарием, поэтому я бы хотел сохранить его в чистоте.Я не хочу иметь bash-скрипт с одной строкой, которая выглядит следующим образом:

ssh blah_server "ls some_folder; ./someaction.sh 'some params'; pwd; ./some_other_action 'other params';"

, потому что он чрезвычайно уродлив и труден для чтения.

Ответы [ 12 ]

413 голосов
/ 10 декабря 2010

Как насчет Bash Здесь документ :

ssh otherhost << EOF
  ls some_folder; 
  ./someaction.sh 'some params'
  pwd
  ./some_other_action 'other params'
EOF

Чтобы избежать проблем, упомянутых @Globalz в комментариях, возможно, вам удастся (в зависимости от того, что вы делаете на удаленном сайте) заменить первую строку на

ssh otherhost /bin/bash << EOF

Обратите внимание, что вы можете выполнить подстановку переменных в документе Here, но вам, возможно, придется столкнуться с проблемами цитирования. Например, если вы заключите в кавычки «предельную строку» (т. Е. EOF в приведенном выше), то вы не сможете выполнять подстановки переменных. Но без цитирования предельной строки переменные подставляются. Например, если вы определили $NAME выше в своем сценарии оболочки, вы можете сделать

ssh otherhost /bin/bash << EOF
touch "/tmp/${NAME}"
EOF

, и в месте назначения otherhost будет создан файл с именем того, что вы присвоили $NAME. Другие правила, касающиеся цитирования сценариев оболочки, также применимы, но они слишком сложны, чтобы их здесь приводить.

113 голосов
/ 10 декабря 2010

Отредактируйте ваш скрипт локально, затем передайте его в ssh, например,

cat commands-to-execute-remotely.sh | ssh blah_server

, где commands-to-execute-remotely.sh выглядит как ваш список выше:

ls some_folder
./someaction.sh
pwd;
35 голосов
/ 27 июня 2013

Чтобы соответствовать вашему примеру кода, вы можете заключить команды в одинарные или двойные кавычки. Например

ssh blah_server "
  ls
  pwd
"
32 голосов
/ 10 декабря 2010

Я вижу два пути:

Сначала вы создаете управляющий сокет следующим образом:

 ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip>

и запускаете свои команды

 ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip> -t <yourcommand>

Таким образом, вы можете написатькоманда ssh без фактического переподключения к серверу.

Вторым будет динамическое создание сценария, scp его запуск и запуск.

18 голосов
/ 27 августа 2014

Это также можно сделать следующим образом.Поместите ваши команды в скрипт, назовите его command-inc.sh

#!/bin/bash
ls some_folder
./someaction.sh
pwd

Сохраните файл

Теперь запустите его на удаленном сервере.

ssh user@remote 'bash -s' < /path/to/commands-inc.sh

Никогда не подводил для меня.

10 голосов
/ 05 мая 2014

Поместите все команды в скрипт, и он может быть запущен как

ssh <remote-user>@<remote-host> "bash -s" <./remote-commands.sh
8 голосов
/ 07 мая 2015

SSH и запуск нескольких команд в Bash.

Отдельные команды с точкой с запятой в строке, передаваемые в echo, все передаются в команду ssh. Например:

echo "df -k;uname -a" | ssh 192.168.79.134

Pseudo-terminal will not be allocated because stdin is not a terminal.
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sda2       18274628 2546476  14799848  15% /
tmpfs             183620      72    183548   1% /dev/shm
/dev/sda1         297485   39074    243051  14% /boot
Linux newserv 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux
6 голосов
/ 28 октября 2016

Для любого, кто споткнулся здесь, как я, - мне удалось избежать точки с запятой и новой строки:

Первый шаг: точка с запятой. Таким образом, мы не нарушаем команду ssh:

ssh <host> echo test\;ls
                    ^ backslash!

Перечислен удаленный каталог hosts / home (вошел как root), тогда как

ssh <host> echo test;ls
                    ^ NO backslash

в списке текущего рабочего каталога.

Следующий шаг: разрыв строки:

                      v another backslash!
ssh <host> echo test\;\
ls

Здесь снова указан удаленный рабочий каталог - улучшено форматирование:

ssh <host>\
  echo test\;\
  ls

Если действительно лучше, чем здесь документ или цитаты из пунктирных линий - ну, не мне решать ...

(Использование bash, Ubuntu 14.04 LTS.)

4 голосов
/ 16 октября 2015

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

#!/bin/bash
ssh <my_user>@<my_host> "bash -s" << EOF
    # here you just type all your commmands, as you can see, i.e.
    touch /tmp/test1;
    touch /tmp/test2;
    touch /tmp/test3;
EOF
3 голосов
/ 04 июля 2017

Опубликованные ответы с использованием многострочных строк и нескольких сценариев bash у меня не сработали.

  • Длинные многострочные строки трудно поддерживать.
  • Отдельные скрипты bash не поддерживают локальные переменные.

Вот функциональный способ ssh и запуска нескольких команд при сохранении локального контекста.

LOCAL_VARIABLE=test

run_remote() {
    echo "$LOCAL_VARIABLE"
    ls some_folder; 
    ./someaction.sh 'some params'
    ./some_other_action 'other params'
}

ssh otherhost "$(set); run_remote"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...