Ich habe ein Skript, das eine Verbindung zu einem Remote-Server herstellt und prüfe, ob ein Paket installiert ist:
ssh root@server 'bash -s' < myscript.sh
myscript.sh:
OUT=`rpm -qa | grep ntpdate`
if [ "$OUT" != "" ] ; then
echo "ntpdate already installed"
else
yum install $1
fi
Dieses Beispiel könnte vereinfacht werden. Hier ist myscript2.sh
das gleiche Problem:
read -p "Package is not installed. Do you want to install it (y/n)?" choise
Mein Problem ist, dass Bash meine Antworten nicht interaktiv lesen kann.
Gibt es eine Möglichkeit, lokales Skript remote auszuführen, ohne die Möglichkeit zu verlieren, Benutzer dazu aufzufordern?
Antworten:
Versuchen Sie so etwas:
Das
-t
erzwingt eine tty-Zuweisung,$(<your_script)
liest die gesamte Datei und übergibt in diesem Fall den Inhalt als ein Argument anssh
, das von der Shell des Remote-Benutzers ausgeführt wird.Wenn das Skript Parameter benötigt, übergeben Sie diese nach dem Skript:
Funktioniert für mich, ich bin mir nicht sicher, ob es universell ist.
quelle
your script
, während die Vorteile der in Ihrer Antwort verwendeten Syntax beibehalten werden? Mitssh -t yourserver "$(<your_script --some_arg)"
nur Ergebnissen inbash: --some_arg: command not found
.ssh ... $(<script) script_arg1 script_arg2 ...
Ihr Problem besteht darin, dass
ssh
eine nicht interaktive Anmeldeshell auf dem Remotecomputer gestartet wird. Die naheliegende einfache Lösung wäre, das Skript auf den Remote-Server zu kopieren und von dort aus auszuführen:Wenn das Kopieren aus irgendeinem Grund nicht möglich ist, ändere ich das Skript, um zunächst eine Verbindung herzustellen und zu überprüfen, ob
$1
es installiert ist, und stelle die Verbindung dann wieder her und installiere es nach Bedarf:quelle
$OUT=$(ssh root@server rpm -qa | grep "$1");
Beenden geschlossen, und die zweite Verbindung dauert genauso lange wie die erste. Liege ich falsch?ssh -M foo.example.com sleep 99999999
oderssh -M foo.example.com read <somefifo
als Master aus und töte es explizit (mitkill
oderecho done >somefifo
), wenn du fertig bist.Hier ist eine gute Erklärung .
Also habe ich das Skript angepasst
und das hat nicht funktioniert.
Deshalb habe ich das Skript auf die Fernbedienung verschoben, um die lokale Umleitung auf ssh zu vermeiden. (Meine Befehle befinden sich in einer Datei mit dem Namen f )
Das hat funktioniert. Hier ist die Ausgabe:
Da @terdon erwähnte, dass die ursprüngliche Absicht darin bestand, lokale Skripte aus der Ferne auszuführen, kann die Fernkopie automatisiert werden. Dies ist nur ein Beispiel für eine einzige Zeile.
quelle
bash -s < script.sh
wie das OP ausgeführt? Könnten Sie die Erklärung in Ihre Antwort aufnehmen, anstatt sie zu verlinken?Ich habe in der Vergangenheit mehrere Male nach Lösungen für dieses Problem gesucht, jedoch nie eine völlig zufriedenstellende gefunden. Wenn Sie in ssh umleiten, verlieren Sie Ihre Interaktivität. Zwei Verbindungen (scp / ssh) sind langsamer und Ihre temporäre Datei kann herumliegen. Und das ganze Skript auf der Kommandozeile endet oft in der Flucht vor der Hölle.
Kürzlich habe ich festgestellt, dass der Befehlszeilenpuffer normalerweise ziemlich groß ist ('getconf ARG_MAX> 2MB, wo ich nachgeschaut habe). Und das brachte mich zum Nachdenken darüber, wie ich dies nutzen und das entstehende Problem lindern könnte.
Das Ergebnis ist:
oder mit einem Here-Dokument und einer Katze:
Ich habe diese Idee erweitert, um ein voll funktionsfähiges BASH-Beispielskript zu erstellen
sshx
, das beliebige Skripten (nicht nur BASH) ausführen kann, wobei Argumente auch lokale Eingabedateien sein können, und zwar über ssh. Sehen Sie hier .quelle
"
Zeichen, die maskiert werden müssen. Und es ist auch auf BASH-Skripte beschränkt. Meine Lösung ist ein allgemeiner Fall für jeden Skriptinhalt einer installierten Skriptsprache. Außerdem demonstriere ich in sshx die Serialisierung von Argumentdateien, was ziemlich geschickt ist.echo "$(cat my_script | base64)" | base64 --decode
Aussehen Äquivalent (ish) zucat my_script | base64 | base64 --decode
, die viel wie ein No-op aussieht.echo "ARG1=$1, USER=$USER, END"
. a)$ ssh host "$(<my_bash)" foo
->ARG1=, USER=user, END foo
. b)$ ssh host bash "<(echo $(cat my_bash|base64) | base64 --decode)" foo
->ARG1=foo, USER=user, END
. Hier läuft (a) effektiv:bash -c $'#!/bin/bash\necho "ARG1=$1, USER=$USER, END" foo'
oder ähnliches. Beachten Sie, dass das Argument nicht funktioniert. Wo (b) ausgeführt wird :bash <(echo IyEvY...5EIgo= | base64 --decode) foo
. (2) Ich habe base64 als Transportkodierung verwendet.