У меня уже настроен агент 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';"
потому что это чрезвычайно уродливо и трудно читать.
Как насчет 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 также применимы, но слишком сложны для перехода сюда.
Измените свой script локально, а затем передайте его в ssh, например.
cat commands-to-execute-remotely.sh | ssh blah_server
где commands-to-execute-remotely.sh
выглядит как ваш список выше:
ls some_folder
./someaction.sh
pwd;
( echo $mycmd $myvar ; ...) | ssh myhost
- как и в случае с cat, вы точно знаете, что входит в поток команд ssh. И, конечно, подобная оболочка в сценарии может быть многострочной для удобства чтения - см. Linuxjournal.com/content/bash-sub-shells
commands-to-execute-remotely.sh
?
Я вижу два пути:
Сначала вы создаете контрольный сокет следующим образом:
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
и его запуск.
Чтобы соответствовать вашему образцу кода, вы можете обернуть свои команды внутри одного или двух qoutes. Например
ssh blah_server "
ls
pwd
"
Это также можно сделать следующим образом. Поместите свои команды в script, назовите его command-inc.sh
#!/bin/bash
ls some_folder
./someaction.sh
pwd
Сохраните файл
Теперь запустите его на удаленном сервере.
ssh user@remote 'bash -s' < /path/to/commands-inc.sh
Мне никогда не приходило в голову.
bash -s
?
#!/bin/bash
действительно используется?
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
Поместите все команды на script, и его можно запустить как
ssh <remote-user>@<remote-host> "bash -s" <./remote-commands.sh
bash -s
?
Для тех, кто наткнулся на меня, как на меня, я добился успеха в том, что вы избегали точки с запятой и новой строки:
Первый шаг: точка с запятой. Таким образом, мы не нарушаем команду 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.)
Это хорошо работает для создания скриптов, так как вам не нужно включать другие файлы:
#!/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
Мысль:
Оберните свои длинные команды в bash script, scp
на конечный сервер, выполните его с помощью ssh
и добавьте команду delete-self в конце script.
Самый простой способ настроить вашу систему на использование одиночных сеансов ssh по умолчанию с мультиплексированием.
Это можно сделать, создав папку для сокетов:
mkdir ~/.ssh/controlmasters
И затем добавив следующее в вашу конфигурацию .ssh:
Host *
ControlMaster auto
ControlPath ~/.ssh/controlmasters/%r@%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.
Опубликованные ответы с использованием многострочных строк и нескольких сценариев 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"
ssh
вызовом?scp
,ssh
и выполнить. Это будет самый чистый путь, я думаю.