Shell-Skript: ssh auf die entfernte Maschine, dann beenden: 'exit' funktioniert nicht

53001
Marius Hofert

Ich habe ein Shell-Skript des folgenden Typs:

#!/bin/bash  ssh mylogin@myremotemachine.com echo "Hi" exit 

Ich führe es lokal aus, um etwas auf einem Remote-Server auszuführen (dargestellt durch "Echo" Hi "). Wenn ich es ausführe, sehe ich jedoch die Eingabeaufforderung auf dem Remote-Server - daher wird der Befehl 'exit' nicht ausgeführt. Wenn ich dann an der Remote-Eingabeaufforderung manuell "exit" eingebe, sehe ich "Verbindung zu myremotemachine.com" geschlossen und dann "Hi". Wie kann ich das Shell-Skript so einrichten, dass es korrekt beendet wird und mir die (lokale) Eingabeaufforderung zeigt, von der ich es ausgeführt habe?

https://unix.stackexchange.com/questions/89747/ssh-exits-after-quit-case-in-bash-script und ssh und shell durch ssh: wie beenden? scheinen etwas verwandt zu sein, aber ich konnte die dort präsentierten Ideen nicht anpassen./

AKTUALISIEREN

Die folgende, nicht so minimale Version führt dazu Unmatched '..

#!/bin/bash  date=`date "+%Y-%m-%d"` rsync -acxzP --delete --link-dest=/u3/mylogin/backup/old_backup /home/mylogin mylogin@myremotemachine.com:/u3/mylogin/backup/$date\_backup ssh mylogin@myremotemachine.com bash -c "' rm -f /u3/mylogin/backup/old_backup ln -s $date\_backup /u3/mylogin/backup/old_backup exit '" 

Wenn ich die Anführungszeichen in diesem Snippet entferne, bekomme ich: bash: -c: option requires an argumentunddate: Undefined variable.

2

4 Antworten auf die Frage

7
R J

Dies sollte Ihr Problem lösen.

ssh mylogin@myremotemachine.com << HERE rm -f /u3/mylogin/backup/old_backup ln -s $date\_backup /u3/mylogin/backup/old_backup HERE 

Oder Sie können Folgendes tun. Legen Sie alle Befehle, die Sie auf dem Remote-Host ausführen möchten, in einem separaten Skript ab. Geben Sie einen Namen wie remote.sh

Führen Sie nun folgendes aus

ssh mylogin@myremotemachine.com 'bash -s' < /path/to/remote.sh 

Wo remote.sh enthält.

rm -f /u3/mylogin/backup/old_backup ln -s $date\_backup /u3/mylogin/backup/old_backup 
Hallo RJ, danke für deine Hilfe. Ich bevorzuge die erste Lösung (mir war die zweite bekannt). Ich bekomme jedoch 'Pseudo-Terminal wird nicht zugewiesen, da stdin kein Terminal ist. Warnung: Kein Zugriff auf tty (Ungültige Dateideskriptor). Daher keine Jobsteuerung in dieser Shell. "Die Befehle werden jedoch wie erwartet ausgeführt. Marius Hofert vor 9 Jahren 1
Hallo Marius. Das ist eine freundliche Erinnerung von ssh, dass das Skript ein Job ist, der keinen Zugriff auf TTY hat, anstelle der üblichen erwarteten Binärdatei. Daher können Sie es nicht mit Strg + c unterbrechen oder mit Strg + z oder anderen interaktiven Befehlen unterbrechen. Es ist harmlos und kann ignoriert werden. R J vor 9 Jahren 1
okay danke. Das ist eine schöne Lösung. Marius Hofert vor 9 Jahren 0
1
barlop

Du kannst tun

$ssh user@comp echo abc<ENTER>

dann wird dieser Befehl ausgeführt (abc ausgegeben) und beendet

Vielen Dank! Ist das gleichbedeutend mit dem Hinzufügen eines Zeilenvorschubzeichens am Ende eines Skripts, um den Wageneinlauf zu simulieren? Manchmal funktioniert alles auch ohne. Wann ist das ein Muss? Ich habe dazu eine Frage: https://unix.stackexchange.com/questions/362203/wenn-do-i-need-a-carriage-return-at-the-end-of-my-job-script-sended -by-ssh. Wäre schön, wenn du das dort erklären könntest. Sibbs Gambling vor 7 Jahren 0
@SibbsGambling Ich bin mir nicht sicher, ob du missverstanden wirst .. bedeutet, drücken Sie die Eingabetaste. Um neue Zeilen am Ende eines Skripts zu erhalten, bin ich mir nicht sicher, ich verwende * nix nicht so viel. barlop vor 7 Jahren 0
1
Ctark

Obwohl die Antwort von Barlops richtig ist, denke ich, dass wir sie erweitern können, um sie klarer zu machen. Da Sie anscheinend ein Skript verwenden, würde ich Folgendes vorschlagen:

#!/bin/bash  ssh mylogin@myremotemachine.com "echo Hi\!" 

Zusätzliche Lektüre: Ich schlage auch vor, dass Sie auch Sonderzeichen untersuchen, und wenn Sie sie entkommen müssen, da Bash Ausrufezeichen automatisch in doppelten Anführungszeichen parsen wird. Sie können dieses Problem lösen, indem Sie entweder einfache Anführungszeichen verwenden oder den umgekehrten Schrägstrich verwenden, um es zu "entkommen".

Bearbeiten:

#!/bin/bash date=`date "+%Y-%m-%d"` rsync -acxzP --delete --link-dest=/u3/mylogin/backup/old_backup /home/mylogin mylogin@myremotemachine.com:/u3/mylogin/backup/$date\_backup ssh mylogin@myremotemachine.com ' date=`date "+%Y-%m-%d"` rm -f /u3/mylogin/backup/old_backup ln -s $date\_backup /u3/mylogin/backup/old_backup ' 

Wenn ich eine vereinfachte Version ausprobierte, funktioniert die Datumsvariable ohne Ausgabe. Möglicherweise wird dadurch die Ausgabe von bash -c korrigiert. Auch der Exit wird am Ende nicht benötigt, wenn der letzte Befehl ausgeführt wird, wird die SSH-Sitzung automatisch geschlossen.

Hallo Ctark, danke für deine Hilfe. Es gibt keine Sonderzeichen. Offensichtlich ist das "Echo" hier nur ein minimales Beispiel. Es gibt verschiedene Codezeilen, die remote ausgeführt werden können. Ich bin mir also nicht sicher, wie sehr dieses "Schreiben alles in einer Zeile" helfen sollte ... es gibt tatsächlich mehrere Codezeilen Marius Hofert vor 9 Jahren 0
... aber du hast recht. Wenn ich alles in eine Zeile stecke, funktioniert der 'exit'. Hmmm ... aber das Skript ist dann nicht mehr lesbar :-( Kann man geschweifte Klammern oder eine Art Gruppierung verwenden? Marius Hofert vor 9 Jahren 0
In diesem Fall würde ich diesen Link vorschlagen: http://www.unixmantra.com/2014/03/a-simple-way-to-send-multiple-line-commands-over-ssh.html Es scheint im Grunde was zu haben du fragst. (Ich könnte kopieren einfügen, aber es gibt viele Informationen, und es führt Sie durch WARUM es funktioniert, also lernen Sie es auch!) Ctark vor 9 Jahren 1
Es enthält viele Informationen, danke. Es ist jedoch nicht der "allgemein beste" Ansatz. Der auf EOF basierende Ansatz hat für mich nicht funktioniert (gleiche Gründe wie in dem von Ihnen angegebenen Link). Ich habe dann den Ansatz "bash -c" versucht. Wenn ich den Code aber wie vorgeschlagen in "'...'" einkapsle, erhalte ich 2x "Unmatched". "." Wenn Sie nur ein Paar Anführungszeichen verwenden (entweder einfach oder doppelt), erhalte ich die Option `bash: -c: ein Argument '. Der Code wird ausgeführt, also sind wir nah dran :-) Marius Hofert vor 9 Jahren 0
Der einfachste Weg wäre, die SSH einfach mit einfachen Anführungszeichen zu verwenden, ABER wenn Sie andere Anführungszeichen im Rest des Skripts haben, das Sie verwenden möchten, wird es durcheinander geraten. Wenn Sie alle Anführungszeichen in dem Skript, das Sie ausführen möchten, in Anführungszeichen ändern können, ist dies einfach: ssh $ host 'Zeile 1 Zeile2 Zeile3 "einige Parameter"' Am Ende dieses Artikels spricht der Autor über den Versuch, Single zu verwenden Zitate, aber es scheint nicht sehr zu gefallen, und er spricht nicht über eine Lösung. Wenn Sie keine Variablen oder einfache Anführungszeichen benötigen, können Sie einfach das erste Beispiel verwenden. Ctark vor 9 Jahren 1
Der Ansatz "... batch -c" ist am besten (da er auch ein anderes kleines Problem löst, das ich mit dem Skript hatte). Die Beobachtung bleibt jedoch bestehen: Wenn ich die Aussagen in verschiedenen Zeilen schreibe, erhalte ich die "Unmatched". `Fehler / Warnungen. Nur wenn ich sie in die gleiche Zeile schreibe (`;` -separated), funktioniert es voll. Seltsam (?), Da es auf der Website, auf die Sie zeigen, zu funktionieren schien. Marius Hofert vor 9 Jahren 0
Ist es möglich, die verschiedenen Zeilen zu posten, klingt das so, als würden einige einzelne Anführungszeichen verwenden. Wenn dies der Fall ist, erhalten Sie hier Ihre unvergleichlichen Fehler. Wenn Sie Semikolons verwenden, haben Sie kein offenes / geschlossenes Anführungszeichen. Ich kann nicht mehr, bis ich den Code sehe, den Sie verwenden. Ctark vor 9 Jahren 1
Hallo, ich habe den ursprünglichen Beitrag mit einer nicht so minimalen Version aktualisiert. Wie Sie sehen, handelt es sich im Wesentlichen um ein Skript, um über `rsync` eine Sicherung auf einem Remote-Computer durchzuführen. Der eigentliche `rsync'-Befehl ist etwas komplizierter, aber das sollte keine Rolle spielen. Marius Hofert vor 9 Jahren 0
Nehmen Sie die doppelten Anführungszeichen vom Anfang und vom Ende heraus und machen Sie es wie folgt: `ssh mylogin@myremotemachine.com bash -c 'rm -f / u3 / mylogin / backup / old_backup old_backup exit '`Testen Sie einfach so etwas, wenn es funktioniert, fügen Sie dann Dinge hinzu, bis es kaputt geht, und gehen Sie von dort weiter. Ctark vor 9 Jahren 0
Wenn ich das mache (und die Zeilenumbrüche dementsprechend habe; siehe Update oben), erhalte ich die `bash: -c: Option erfordert ein Argument` und` date: Undefined variable.`. Marius Hofert vor 9 Jahren 0
Angenommen, Ihr aktualisiertes Skript ist alles, was Sie tun. Können Sie die Datumsvariable in die ssh verschieben und die bash -c entfernen? Sehen Sie sich meine aktualisierte Antwort an. Ctark vor 9 Jahren 0
Wenn ich "Datum" nach "innen" schiebe, erhielt ich "Datum: undefinierte Variable". Da dies ein Shell-Problem war, habe ich die Anweisung `bash` direkt vor der` date`-Variable eingefügt (um in eine bash zu wechseln, sodass das `date` definiert wird), aber dann erhielt ich die` bash: -c: -Option erfordert ein Argument ". Marius Hofert vor 9 Jahren 0
Auch wenn Sie einen anderen Weg gefunden haben, eine aktualisierte Antwort für alle anderen, die darüber stolpern. Der Grund, warum Sie eine undefinierte Variable erhalten haben, ist auf den Befehl rsync zurückzuführen, der date verwendet. Daher benötigen Sie ihn sowohl innerhalb als auch außerhalb des Skripts ssh (sofern Sie nicht bash -c verwenden und wenn Sie andere Probleme haben). Ich bin froh, dass du endlich eine Lösung gefunden hast, die funktioniert hat. Ctark vor 9 Jahren 1
1
Kamil

Vielleicht haben Sie am Ende des Skripts keinen Zeilenumbruch?

Wenn LFnach dem Beenden keine leere Zeile (genau ein Zeilenvorschubzeichen) vorhanden ist, "drückt" das Skript nicht programmgesteuert die Eingabetaste.

Hallo, danke für das Helfen, ich habe das Skript überprüft und hatte zwei Newlines dort, also war das nicht das Problem. Marius Hofert vor 9 Jahren 0
Ich habe dazu eine Frage: https://unix.stackexchange.com/questions/362203/wenn-do-i-need-a-carriage-return-at-the-end-of-my-job-script-sended -by-ssh. Wäre schön, wenn du das dort erklären könntest. Sibbs Gambling vor 7 Jahren 0