Назад | Перейти на главную страницу

Как запустить локальный сценарий bash на удаленных машинах через ssh?

Я ищу способ перенести конфигурацию с одной центральной машины на несколько удаленных без необходимости устанавливать что-либо на удаленных машинах.

Цель состоит в том, чтобы сделать что-то похожее на такие инструменты, как cfengine, но на множестве машин, на которых не настроены агенты. На самом деле это может быть хорошим методом настройки cfagent на множестве существующих удаленных машин.

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

например

echo "ls -l; echo 'Hello World'" | ssh me@myserver /bin/bash

Естественно, "ls -l; echo 'Hello World'" часть может быть заменена сценарием bash, хранящимся в файле на локальном компьютере.

например

cat script.sh | ssh me@myserver /bin/bash

Ура!

Есть несколько способов сделать это.

1:

ssh user@remote_server 'bash -s' < localfile

2:

cat localfile  | ssh user@remote_server

3:

ssh user@remote_server "$(< localfile)"

номер 3 - мой предпочтительный способ, он позволяет интерактивные команды, например. su -S service nginx restart

(# 1 будет использовать остальную часть скрипта как ввод для вопроса о пароле, когда вы используете su -S.)

Для этой цели я бы порекомендовал Python Fabric:

#!/usr/bin/python
# ~/fabfile.py

from fabric_api import *

env.hosts = ['host1', 'host2']
def deploy_script():
    put('your_script.sh', 'your_script.sh', mode=0755)
    sudo('./your_script.sh')

# from shell
$ fab deploy_script

Вы должны уметь использовать вышесказанное, чтобы начать работу. Проконсультируйтесь с Fabric's отлично документация делать все остальное. В качестве дополнения, вполне возможно написать свой сценарий полностью в Fabric - копирование не требуется, однако следует отметить, что для изменения сценария на всех машинах вам нужно будет только отредактировать локальную копию и повторно развернуть. Кроме того, немного больше, чем базовое использование API, вы можете изменить скрипт в зависимости от того, на каком хосте он в настоящее время работает, и / или других переменных. Это своего рода питоническое ожидание.

Это именно то, для чего используется Ansible. Агента нет, вам просто нужно создать текстовый файл с именем:

/etc/ansible/hosts

с содержанием, которое выглядит примерно так:

[webhosts]
web[1-8]

Это будет указывать на то, что машины «web1, web2 ... web8» находятся в группе «webhosts». Затем вы можете делать такие вещи, как:

ansible webhosts -m service -a "name=apache2 state=restarted" --sudo

чтобы перезапустить службу apache2 на всех ваших машинах, используя sudo.

Вы можете выполнять на лету такие команды, как:

ansible webhosts -m shell -a "df -h"

или вы можете запустить локальный сценарий на удаленном компьютере:

ansible webhosts -m script -a "./script.sh"

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

ansible-playbook webplaybook.yml

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

Как объяснено в этот ответ ты можешь использовать Heredoc :

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

Вы должны быть осторожны с heredoc, потому что он просто отправляет текст, но на самом деле не ждет ответа. Это означает, что он не будет ждать выполнения ваших команд.

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

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

plink root@MachineB -m local_script.bat

это не сработает.

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

Решение 1:

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

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

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

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

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

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

Решение 2:

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

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

Почему бы просто не скопировать сценарий, а затем запустить его?

scp your_script.sh the_server:
ssh the_server "chmod +x your_script.sh; ./your_script.sh"

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

Перепишите сценарий так, чтобы каждая команда в нем уже является с префиксом ssh и имя хоста / ip или их список передается сценарию в качестве аргумента (при условии, что у вас настроена аутентификация с ключом без пароля / ssh-agent). Для правильной передачи кодов ошибок / возврата из удаленных команд может потребоваться некоторая работа ....

Если сценарий не слишком велик, и вы используете bash или ksh ...

ssh vm24 -t bash -c "$(printf "%q" "$(< shell-test.sh )")"

И stdin, и stdout работают правильно, но сценарий ограничен размером аргумента (обычно около 100 КБ). Аргументы сценария могут работать в конце строки, возможно, после дополнительного аргумента «-». «-T» для выделения pty не является обязательным.

Осторожно: это сбивает с толку завершение bash, не нажимайте вкладку.