it-swarm.com.ru

Как использовать SSH для запуска сценария Shell на удаленной машине?

Я должен запустить сценарий оболочки (Windows/Linux) на удаленной машине.

У меня настроен SSH на компьютере A и B. Мой сценарий находится на компьютере A, который будет выполнять часть моего кода на удаленной машине, машине B.

Локальные и удаленные компьютеры могут быть системами на базе Windows или Unix.

Есть ли способ запустить это с помощью plink/ssh?

1122
Arun

Если компьютер A является Windows-модулем, вы можете использовать Plink (часть PuTTY ) с параметром -m, и он будет выполнять локальный сценарий на удаленном сервере.

plink [email protected] -m local_script.sh

Если машина A является системой на основе Unix, вы можете использовать:

ssh [email protected] 'bash -s' < local_script.sh

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

1103
Jason R. Coombs

Это старый вопрос, и ответ Джейсона работает нормально, но я хотел бы добавить это:

ssh [email protected] <<'ENDSSH'
#commands to run on remote Host
ENDSSH

Это также можно использовать с командами su и, которые требуют ввода пользователем. (обратите внимание, ' избежал heredoc)

Правка: так как этот ответ продолжает получать бит трафика, я бы добавил еще больше информации для этого замечательного использования heredoc:

Вы можете вкладывать команды с этим синтаксисом, и это единственный способ, которым кажется, что вложение работает (в здравом смысле)

ssh [email protected] <<'ENDSSH'
#commands to run on remote Host
ssh [email protected] <<'END2'
# Another bunch of commands on another Host
wall <<'ENDWALL'
Error: Out of cheese
ENDWALL
ftp ftp.secureftp-test.com <<'ENDFTP'
test
test
ls
ENDFTP
END2
ENDSSH

На самом деле вы можете поговорить с некоторыми службами, такими как telnet, ftp и т.д. Но помните, что heredoc просто отправляет stdin в виде текста, он не ждет ответа между строками

Правка: Я только что узнал, что вы можете сделать отступы внутри вкладок , если вы используете <<-END!

ssh [email protected] <<-'ENDSSH'
    #commands to run on remote Host
    ssh [email protected] <<-'END2'
        # Another bunch of commands on another Host
        wall <<-'ENDWALL'
            Error: Out of cheese
        ENDWALL
        ftp ftp.secureftp-test.com <<-'ENDFTP'
            test
            test
            ls
        ENDFTP
    END2
ENDSSH

(Я думаю, что это должно работать)

Также смотрите http://tldp.org/LDP/abs/html/here-docs.html

561
Yarek T

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

Это застало меня в прошлом.

Например:

[email protected]> ssh [email protected] "echo \$HOME"

распечатывает/home/user2

в то время как

[email protected]> ssh [email protected] "echo $HOME"

распечатывает/home/user

Другой пример:

[email protected]> ssh [email protected] "echo hello world | awk '{print \$1}'"

распечатывает "привет" правильно.

232
dogbane

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

ssh [email protected] ARG1=$ARG1 ARG2=$ARG2 'bash -s' <<'ENDSSH'
  # commands to run on remote Host
  echo $ARG1 $ARG2
ENDSSH

Я нашел это исключительно полезным, сохранив все это в одном сценарии, чтобы он был очень удобочитаемым и поддерживаемым.

Почему это работает. ssh поддерживает следующий синтаксис:

ssh user @ Host remote_command

В bash мы можем указать переменные среды, которые нужно определить до запуска команды в одной строке, например

ENV_VAR_1 = 'значение1' ENV_VAR_2 = 'значение2' bash -c 'echo $ ENV_VAR_1 $ ENV_VAR_2'

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

Таким образом, мы объединяем эти две функции и ответ YarekT, чтобы получить:

ssh user @ Host ARG1 = $ ARG1 ARG2 = $ ARG2 'bash -s' << 'ENDSSH' ...

В этом случае мы устанавливаем ARG1 и ARG2 в локальные значения. Отправка всего после user @ Host как remote_command. Когда удаленный компьютер выполняет команду ARG1 и ARG2 устанавливаются локальные значения, благодаря локальной оценке командной строки, которая определяет переменные среды на удаленном сервере, а затем выполняет команду bash -s с использованием этих переменных. Вуаля.

143
chubbsondubs
<hostA_Shell_Prompt>$ ssh [email protected] "ls -la"

Это запросит у вас пароль, если только вы не скопировали открытый ключ пользователя hostA в файл author_keys в каталоге пользователя .ssh. Это позволит проводить аутентификацию без пароля (если она принята в качестве метода авторизации в конфигурации сервера ssh)

100
Vinko Vrsalovic

Я начал использовать Fabric для более сложных операций. Для Fabric требуется Python и ​​несколько других зависимостей, но только на клиентском компьютере. Сервер должен быть только ssh-сервером. Я считаю, что этот инструмент гораздо более мощный, чем сценарии Shell, переданные SSH, и стоит того, чтобы его настроить (особенно если вам нравится программирование на Python). Fabric обрабатывает выполняемые сценарии на нескольких хостах (или хостах определенных ролей), помогает упростить идемпотентные операции (такие как добавление строки в скрипт конфигурации, но не, если она уже есть), и позволяет создавать более сложную логику (такую ​​как Python язык может предоставить).

26
Jason R. Coombs

Попробуйте запустить ssh [email protected] sh ./script.unx.

10
Jeremy

Предполагая, что вы хотите сделать это автоматически с "локального" компьютера, без ручного входа на "удаленный" компьютер, вам нужно посмотреть расширение TCL, известное как Expect, оно разработано именно для такой ситуации. Я также предоставил ссылку на скрипт для входа/взаимодействия через SSH.

https://www.nist.gov/services-resources/software/expect

http://bash.cyberciti.biz/security/expect-ssh-login-script/

9
George Jempty

Я использую этот для запуска сценария Shell на удаленной машине (проверено на/bin/bash):

ssh [email protected] . /home/deploy/path/to/script.sh
2
Is Ma

Ответ здесь ( https://stackoverflow.com/a/2732991/475288 ) отлично работает, если вы пытаетесь запустить скрипт на удаленной машине Linux с помощью plink или ssh. Это будет работать, если скрипт имеет несколько строк на linux.

** Однако, если вы пытаетесь запустить пакетный скрипт, расположенный на локальном компьютере linux/windows, а ваш удаленный компьютер - Windows, и он состоит из нескольких строк, используя **

plink [email protected] -m local_script.bat

не будет работать.

Будет выполнена только первая строка скрипта. Это, вероятно, ограничение plink.

Решение 1:

Чтобы запустить многострочный пакетный скрипт (особенно, если он относительно простой и состоит из нескольких строк):

Если ваш оригинальный пакетный скрипт выглядит следующим образом

cd C:\Users\ipython_user\Desktop 
python filename.py

вы можете объединить строки, используя разделитель "&&", как показано в файле local_script.bat: https://stackoverflow.com/a/8055390/475288 :

cd C:\Users\ipython_user\Desktop && python filename.py

После этого изменения вы можете запустить скрипт, как указано здесь @ JasonR.Coombs: https://stackoverflow.com/a/2732991/475288 с помощью:

`plink [email protected] -m local_script.bat`

Решение 2:

Если ваш пакетный сценарий относительно сложен, может быть лучше использовать пакетный сценарий, который инкапсулирует команду plink, а также как указано здесь @Martin https://stackoverflow.com/a/32196999/475288 :

rem Open tunnel in the background
start plink.exe -ssh [username]@[hostname] -L 3307:127.0.0.1:3306 -i "[SSH
key]" -N

rem Wait a second to let Plink establish the tunnel 
timeout /t 1

rem Run the task using the tunnel
"C:\Program Files\R\R-3.2.1\bin\x64\R.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe
1
alpha_989

если вы хотите выполнить команду, подобную этой, команда temp=`ls -a` echo $temp в `` вызовет ошибки.

команда ниже решит эту проблему ssh [email protected] ''' temp=`ls -a` echo $temp '''

1
Jinmiao Luo

Этот bash-скрипт запускает ssh на целевой удаленной машине и запускает некоторую команду на удаленной машине, не забудьте установить ожидаемую часть перед запуском (на mac brew install expect)

#!/usr/bin/expect
set username "enterusenamehere"
set password "enterpasswordhere"
set hosts "enteripaddressofhosthere"
spawn ssh  [email protected]$hosts
expect "[email protected]$hosts's password:"
send -- "$password\n"
expect "$"
send -- "somecommand on target remote machine here\n"
sleep 5
expect "$"
send -- "exit\n"
0
Mohammed Rafeeq