Jak uruchomić lokalny skrypt bash na zdalnych komputerach przez ssh?

51

Szukam sposobu na przeniesienie konfiguracji z jednego komputera centralnego na kilka komputerów zdalnych bez potrzeby instalowania czegokolwiek na komputerach zdalnych.

Celem jest zrobienie czegoś takiego, jak w przypadku narzędzi takich jak cfengine, ale na zestawie komputerów, na których nie skonfigurowano agentów. To może być dobra technika konfigurowania cfagentna zestawie istniejących zdalnych komputerów.

tremoloqui
źródło
Podobne w SO: stackoverflow.com/q/305035/435605
AlikElzin-kilaka
1
Rzeczywiste pytania mają 23 pozytywne głosy, w których duplikat na SO ma 55: P
MoJo

Odpowiedzi:

55

Możesz przekazać skrypt i wykonać go efemerycznie, przesyłając go i wykonując powłokę.

na przykład

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

Oczywiście "ls -l; echo 'Hello World'"część można zastąpić skryptem bash przechowywanym w pliku na komputerze lokalnym.

na przykład

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

Twoje zdrowie!

tremoloqui
źródło
2
Jak uruchomić ten skrypt jako sudo na zdalnym systemie. Eg Gdybym był zalogowany na zdalnym serwerze, zwykle uruchamiałbym to jako sudo -u testuser script.sh
Sharjeel
Co jeśli skrypt, który wywołuję, wymaga interakcji użytkownika?
Abhimanyu Srivastava
20

Można to zrobić na kilka sposobów.

1:

ssh user@remote_server 'bash -s' < localfile

2:

cat localfile  | ssh user@remote_server

3:

ssh user@remote_server "$(< localfile)"

numer 3 to mój preferowany sposób, pozwala on na interaktywne polecenia np su -S service nginx restart

(# 1 wykorzysta resztę skryptu jako dane wejściowe do pytania o hasło podczas korzystania su -S).

Paul Verschoor
źródło
4
Odnośnie uruchomienia lokalnego skryptu na zdalnej maszynie - Czy istnieje sposób wysłania zmiennej jako argumentu na zdalną maszynę ...? tzn. wraz ze skryptem chcę wysłać zmienną (zawierającą wiele wierszy) jako argument na maszynę zdalną. Skrypt zamierza następnie użyć zmiennej.
13

Polecam do tego celu sieć Pythona:

#!/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

Aby rozpocząć, powinieneś móc skorzystać z powyższego. Zajrzyj do doskonałej dokumentacji Fabric, aby zrobić resztę. Jako uzupełnienie można całkowicie napisać skrypt w programie Fabric - nie trzeba go kopiować, należy jednak pamiętać, że aby zmienić skrypt na wszystkich komputerach, wystarczy edytować kopię lokalną i ponownie wdrożyć. Co więcej, przy nieco więcej niż podstawowym użyciu interfejsu API, możesz zmodyfikować skrypt w oparciu o host, na którym jest on aktualnie uruchomiony i / lub inne zmienne. To coś w rodzaju pythonicznego oczekiwania.

Sam Halicke
źródło
Nie sądzę, że to dokładnie odpowiada na pytanie, ale podoba mi się ten pomysł i mogłem zobaczyć Fabric jako przydatne narzędzie.
tremoloqui
1
@tremoloqui Fabric to otoki Pythona wokół ssh - nic nie musi być instalowane na komputerach docelowych, z wyjątkiem wypychania skryptu. Co, jeśli przepisane jako seria poleceń Fabric (używając runi sudo), nie jest nawet potrzebne.
Izkata,
5

Właśnie do tego służy Ansible. Nie ma agenta, wystarczy utworzyć plik tekstowy o nazwie:

/etc/ansible/hosts

z treściami, które wyglądają mniej więcej tak:

[webhosts]
web[1-8]

Określiłoby to, że maszyny „web1, web2 ... web8” znajdują się w grupie „webhosts”. Następnie możesz robić takie rzeczy jak:

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

zrestartować usługę apache2 na wszystkich twoich komputerach, używając sudo.

Możesz wykonywać polecenia w locie, takie jak:

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

lub możesz uruchomić skrypt lokalny na zdalnym komputerze:

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

lub możesz utworzyć podręcznik (poszukaj szczegółów w dokumentacji) z pełną konfiguracją, którą chcesz, aby Twoje serwery były zgodne i wdrożyć za pomocą:

ansible-playbook webplaybook.yml

Zasadniczo możesz zacząć używać go jako narzędzia wiersza poleceń do uruchamiania poleceń na wielu serwerach i rozszerzyć jego użycie do kompletnego narzędzia konfiguracyjnego, jeśli uznasz to za stosowne.

seumasmac
źródło
3
Lubię ansible tak samo jak następny facet, ale jeśli pyta o skrypt, to ansible ma naprawdę fajny moduł skryptowy :ansible webhosts -m script script.sh
ptman
1
Wszystkie pozostałe odpowiedzi dotyczą skryptu bash, ale nie o to specjalnie prosił. Powiedział tylko, że wypycham config na zdalne komputery. Ale dobra wzmianka o module skryptu :)
seumasmac
Głosuj na tę odpowiedź! Oto jak to zrobić!
pisklęta
@ptman Właśnie zauważyłem, że chociaż nie wspomina o skrypcie w pytaniu, robi to w tytule! Przepraszam. Zaktualizowałem.
seumasmac
3

Jak wyjaśniono w tej odpowiedzi , możesz użyć heredoc :

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

Musisz być ostrożny z heredoc, ponieważ po prostu wysyła tekst, ale tak naprawdę nie czeka na odpowiedź. Oznacza to, że nie będzie czekać na wykonanie poleceń.

BЈовић
źródło
1

Odpowiedź tutaj ( https://stackoverflow.com/a/2732991/4752883 ) działa świetnie, jeśli próbujesz uruchomić skrypt na zdalnym komputerze z systemem Linux za pomocą plinklub ssh. Będzie działać, jeśli skrypt ma wiele wierszy linux.

** Jednak jeśli próbujesz uruchomić skrypt wsadowy znajdujący się na linux/windowskomputerze lokalnym , a Twój komputer zdalny jest w stanie Windows, i składa się z wielu wierszy przy użyciu **

plink root@MachineB -m local_script.bat

to nie zadziała.

Zostanie wykonana tylko pierwsza linia skryptu. Jest to prawdopodobnie ograniczenie plink.

Rozwiązanie 1:

Aby uruchomić wielowierszowy skrypt wsadowy (zwłaszcza jeśli jest stosunkowo prosty i składa się z kilku wierszy):

Jeśli oryginalny skrypt partii jest następujący

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

możesz łączyć linie razem za pomocą separatora „&&” w następujący sposób w swoim local_script.batpliku w następujący sposób https://stackoverflow.com/a/8055390/4752883 :

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

Po tej zmianie możesz uruchomić skrypt, jak wskazano tutaj przez @ JasonR.Coombs: https://stackoverflow.com/a/2732991/4752883

Rozwiązanie 2:

Jeśli skrypt wsadowy jest stosunkowo skomplikowany, może być lepiej użyć skryptu wsadowego, który zawiera polecenie plink, a także następujące czynności, jak wskazano tutaj @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
alpha_989
źródło
0

Dlaczego nie po prostu najpierw skopiować skrypt, a następnie go uruchomić?

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

Oczywiście powinieneś uważać, aby nie przesłać go do miejsca, w którym można pisać na całym świecie, aby nikt inny nie mógł nim manipulować przed uruchomieniem go (prawdopodobnie jako root).

Dave Vogt
źródło
1
Powodem, dla którego nie chcę przesyłać skryptu, jest to, że nie trzeba nim zarządzać i niesie ze sobą wspomniane ryzyko. Wydaje mi się również, że jest to prostsze niż wieloetapowy proces przesyłania, przetwarzania i (opcjonalnie) usuwania.
tremoloqui
0

Przepisz skrypt w taki sposób, że każda komenda w nim jest już poprzedzona ssh, a nazwa hosta / ip lub lista takich jest przekazywana do skryptu jako argument (zakładając, że masz skonfigurowane uwierzytelnianie bez hasła / ssh-agent). Może być konieczne trochę pracy, aby poprawnie przekazać kody błędów / zwrotów z poleceń zdalnych ....

rackandboneman
źródło
0

Jeśli skrypt nie jest zbyt duży, a używasz bash lub ksh ...

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

Zarówno stdin, jak i stdout działają poprawnie, ale skrypt jest ograniczony do wielkości argumentu (zwykle około 100k). Argumenty skryptu mogą działać na końcu wiersza, prawdopodobnie po dodatkowym argumencie „-”. „-T” do przydzielenia pty jest opcjonalne.

Uwaga: To myli ukończenie bashu, nie naciskaj klawisza Tab.

użytkownik3710044
źródło