Як запустити локальний скрипт bash на віддалених машинах через ssh?


51

Я шукаю спосіб перенести конфігурацію з однієї центральної машини на кілька віддалених машин без необхідності нічого встановлювати на віддалені машини.

Мета полягає в тому, щоб зробити щось на зразок того, що ви знайдете, як на таких інструментах cfengine, але на наборі машин, на яких не встановлені агенти. Це насправді може бути хорошою технікою налаштування cfagentна набір існуючих віддалених машин.



1
Насправді питання має 23 відгуки, де у дубліката на ПС є 55: P
MoJo

Відповіді:


55

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

напр

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

Ура!


2
Як зробити цей запуск як sudo на віддаленій системі. Наприклад, якщо я був увійшов на віддалений сервер, я зазвичай запускав би це як sudo -u testuser script.sh
Sharjeel

Що робити, якщо сценарій, до якого я дзвоню, передбачає взаємодію користувачів ???
Абхіманью Срівастава

20

Існує кілька способів зробити це.

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.)


4
Щодо запуску локального скрипту на віддаленій машині - чи є спосіб надіслати змінну як аргумент на віддалену машину ..? тобто разом зі сценарієм, я хочу надіслати змінну (що має кілька рядків) як аргумент на віддалену машину. Потім сценарій має намір використовувати змінну.

13

Я б рекомендував Тканину python для цієї мети:

#!/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 . Як додаток, цілком можливо написати сценарій повністю в межах Fabric - копіювання не потрібно, однак слід зазначити, що для зміни сценарію на всіх машинах вам потрібно буде лише відредагувати локальну копію та повторно розмістити. Крім того, маючи трохи більше, ніж основне використання API, ви можете змінювати скрипт, виходячи з того, на якому хості він зараз працює та / або інших змінних. Це свого роду пітонічне очікування.


Я не думаю, що це точно відповідає на питання, але мені подобається ідея, і я міг бачити Тканину як корисний інструмент.
tremoloqui

1
@tremoloqui Тканина - це питона обгортка навколо ssh - нічого не потрібно встановлювати на цільових машинах, окрім того, що скрипт буде натиснений. Які, якщо вони переписані як ряд команд Fabric (за допомогою runта sudo), навіть не потрібні.
Ізката

5

Саме для цього використовується 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"

або ви можете створити ігрову книгу (переглянути детальну документацію) з повною конфігурацією, якій ви хочете, щоб ваші сервери відповідали та розгортали її:

ansible-playbook webplaybook.yml

В основному ви можете почати використовувати його як інструмент командного рядка для запуску команд на декількох серверах і розширити його використання на повний інструмент конфігурації, як вважаєте за потрібне.


3
Мені подобається ansible так само, як наступний хлопець, але якщо він запитує про сценарій, то ansible має дуже гарний модуль сценарію :ansible webhosts -m script script.sh
ptman

1
Всі інші відповіді містять сценарій bash, але це не те, що він спеціально просив. Він просто сказав, що підштовхує конфігурацію до віддалених машин. Але хороша згадка про модуль сценарію :)
seumasmac

Будь ласка, проголосуйте за цю відповідь! Це спосіб це зробити!
пташенята

@ptman Я тільки що помітив, що, хоча він не згадує сценарій у питанні, він робить це в заголовку! Вибачте. Я оновив.
seumasmac

3

Як пояснено у цій відповіді, ви можете використовувати heredoc :

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

Ви повинні бути обережними з heredoc, тому що він просто надсилає текст, але насправді він не чекає відповіді. Це означає, що він не чекатиме виконання ваших команд.


1

Відповідь тут ( 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:

Якщо ваш пакетний сценарій порівняно складний, може бути краще використовувати пакетний скрипт, який інкапсулює команду pluink, а також наступний, як зазначено тут @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

0

Чому б просто не скопіювати сценарій спочатку, а потім запустити його?

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

Звичайно, ви повинні бути обережними, щоб не завантажувати його до місця, що записується у світі, так що ніхто інший не міг би поспішати з ним до запуску (можливо, як root).


1
Причиною я не хочу завантажувати скрипт, тому не потрібно керувати ним та мати згадані вами ризики. Також мені здається, що це простіше, ніж багатоетапний процес завантаження, обробки та (необов'язково) видалення.
tremoloqui

0

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


0

Якщо сценарій не надто великий, і ви використовуєте bash або ksh ...

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

І stdin, і stdout працюють правильно, але сценарій обмежений розміром аргументу (зазвичай близько 100 к). Аргументи до сценарію можуть працювати в кінці рядка, можливо, після додаткового аргументу "-". "-T" для виділення pty необов'язково.

Остерігайтеся. Це заплутує вкладку, що не завершує роботу, не потрапляйте на вкладку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.