Каков самый чистый способ ssh и запустить несколько команд в Bash?

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

ssh blah_server "ls; pwd;"

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

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

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

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

Изменить

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

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

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

Ответы

Ответ 1

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

  ssh otherhost < < EOF ls some_folder;. /someaction.sh 'некоторые параметры' PWD. /some _other_action 'другие параметры'
EOF
Код>

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

  ssh otherhost/bin/bash < < EOF
Код>

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

  ssh otherhost/bin/bash < < EOF
touch "/tmp/${NAME}" 
EOF
Код>

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

Ответ 2

Измените свой script локально, а затем передайте его в ssh, например.

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

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

ls some_folder
./someaction.sh
pwd;

Ответ 3

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

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

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

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

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

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

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

Ответ 4

Чтобы соответствовать вашему образцу кода, вы можете обернуть свои команды внутри одного или двух qoutes. Например

ssh blah_server "
  ls
  pwd
"

Ответ 5

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

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

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

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

ssh [email protected] 'bash -s' < /path/to/commands-inc.sh

Мне никогда не приходило в голову.

Ответ 6

Поместите все команды на script, и его можно запустить как

ssh <remote-user>@<remote-host> "bash -s" <./remote-commands.sh

Ответ 7

SSH и выполните несколько команд в Bash.

Разделяйте команды с точкой с запятой внутри строки, переданной в эхо, все переданные в команду 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

Ответ 8

Мысль:

Оберните свои длинные команды в bash script, scp на конечный сервер, выполните его с помощью ssh и добавьте команду delete-self в конце script.

Ответ 9

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

#!/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

Ответ 10

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

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

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

Перечислил удаленный хост/домашний каталог (зарегистрированный как 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.)

Ответ 11

Самый простой способ настроить вашу систему на использование одиночных сеансов ssh по умолчанию с мультиплексированием.

Это можно сделать, создав папку для сокетов:

mkdir ~/.ssh/controlmasters

И затем добавив следующее в вашу конфигурацию .ssh:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/controlmasters/%[email protected]%h:%p.socket
    ControlMaster auto
    ControlPersist 10m

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

Спасибо @terminus answer, http://www.cyberciti.biz/faq/linux-unix-osx-bsd-ssh-multiplexing-to-speed-up-ssh-connections/ и https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing.

Ответ 12

Опубликованные ответы с использованием многострочных строк и нескольких сценариев 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"