Я ищу способ перенести конфигурацию с одной центральной машины на несколько удаленных без необходимости устанавливать что-либо на удаленных машинах.
Цель состоит в том, чтобы сделать что-то похожее на такие инструменты, как 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
Ура!
Есть несколько способов сделать это.
ssh user@remote_server 'bash -s' < localfile
cat localfile | ssh user@remote_server
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
.
Чтобы запустить многострочный пакетный скрипт (особенно если он относительно простой, состоящий из нескольких строк):
Если ваш исходный пакетный сценарий выглядит следующим образом
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
Если ваш пакетный сценарий относительно сложен, может быть лучше использовать пакетный сценарий, который инкапсулирует команду 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, не нажимайте вкладку.