SSH dazu bringen, einen Befehl im Hintergrund auf dem Zielcomputer auszuführen

StackOverflow https://stackoverflow.com/questions/29142

  •  09-06-2019
  •  | 
  •  

Frage

Dies ist eine Folgefrage zur Wie verwendet man SSH in einem Shell-Skript? Frage.Wenn ich einen Befehl auf dem Remote-Computer ausführen möchte, der im Hintergrund auf diesem Computer ausgeführt wird, wie kann ich dann den SSH-Befehl zurückgeben?Wenn ich versuche, einfach das kaufmännische Und-Zeichen (&) am Ende des Befehls einzufügen, bleibt es einfach hängen.Die genaue Form des Befehls sieht so aus:

ssh user@target "cd /some/directory; program-to-execute &"

Irgendwelche Ideen?Zu beachten ist, dass bei Anmeldungen am Zielcomputer immer ein Textbanner angezeigt wird, und das habe ich auch getan SSH Schlüssel so eingerichtet, dass kein Passwort erforderlich ist.

War es hilfreich?

Lösung

Ich hatte dieses Problem in einem Programm, das ich vor einem Jahr geschrieben habe – die Antwort ist ziemlich kompliziert.Sie müssen sowohl Nohup als auch die Ausgabeumleitung verwenden, wie im Wikipedia-Artikel erläutert neinhup, zur Vereinfachung hierher kopiert.

Nohuping -Hintergrundjobs sind beispielsweise nützlich, wenn sie über SSH angemeldet sind, da Hintergrundjobs aufgrund einer Rennerkrankung anmelden können [2].Dieses Problem kann auch überwunden werden, indem alle drei E/A -Streams umgeleitet werden:

nohup myprogram > foo.out 2> foo.err < /dev/null &

Andere Tipps

Dies war für mich die sauberste Art, es zu tun:

ssh -n -f user@host "sh -c 'cd /whereever; nohup ./whatever > /dev/null 2>&1 &'"

Das Einzige, was danach ausgeführt wird, ist der eigentliche Befehl auf dem Remote-Computer

Leiten Sie fds um

Die Ausgabe muss mit umgeleitet werden &>/dev/null Dies leitet sowohl stderr als auch stdout nach /dev/null um und ist ein Synonym für >/dev/null 2>/dev/null oder >/dev/null 2>&1.

Klammern

Der beste Weg ist die Verwendung sh -c '( ( command ) & )' wo Befehl alles ist.

ssh askapache 'sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Nohup-Shell

Sie können nohup auch direkt verwenden, um die Shell zu starten:

ssh askapache 'nohup sh -c "( ( chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Schöner Start

Ein weiterer Trick besteht darin, nice zum Starten des Befehls/der Shell zu verwenden:

ssh askapache 'nice -n 19 sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Ich wollte nur ein funktionierendes Beispiel zeigen, das Sie ausschneiden und einfügen können:

ssh REMOTE "sh -c \"(nohup sleep 30; touch nohup-exit) > /dev/null &\""

Wenn Sie die Verbindung nicht offen halten können/können, können Sie Folgendes verwenden Bildschirm, wenn Sie die Rechte zur Installation haben.

user@localhost $ screen -t remote-command
user@localhost $ ssh user@target # now inside of a screen session
user@remotehost $ cd /some/directory; program-to-execute &

So trennen Sie die Bildschirmsitzung: Strg-A D

So listen Sie Bildschirmsitzungen auf:

screen -ls

So fügen Sie eine Sitzung erneut hinzu:

screen -d -r remote-command

Beachten Sie, dass screen innerhalb jeder Sitzung auch mehrere Shells erstellen kann.Ein ähnlicher Effekt kann mit erreicht werden tmux.

user@localhost $ tmux
user@localhost $ ssh user@target # now inside of a tmux session
user@remotehost $ cd /some/directory; program-to-execute &

So trennen Sie die tmux-Sitzung: Strg-B D

So listen Sie Bildschirmsitzungen auf:

tmux list-sessions

So fügen Sie eine Sitzung erneut hinzu:

tmux attach <session number>

Die standardmäßige tmux-Steuertaste „Strg-B', ist etwas schwierig zu verwenden, aber es gibt mehrere tmux-Beispielkonfigurationen, die mit tmux geliefert werden und die Sie ausprobieren können.

Der schnellste und einfachste Weg ist die Verwendung des Befehls „at“:

ssh user@target „at now -f /home/foo.sh“

Ich denke, Sie müssen einige dieser Antworten kombinieren, um das zu bekommen, was Sie wollen.Wenn Sie nohup in Verbindung mit dem Semikolon verwenden und das Ganze in Anführungszeichen setzen, erhalten Sie:

ssh user@target "cd /some/directory; nohup myprogram > foo.out 2> foo.err < /dev/null"

was bei mir zu funktionieren scheint.Mit nohup müssen Sie das & nicht an den auszuführenden Befehl anhängen.Wenn Sie die Ausgabe des Befehls nicht lesen müssen, können Sie auch Folgendes verwenden

ssh user@target "cd /some/directory; nohup myprogram > /dev/null 2>&1"

um alle Ausgaben nach /dev/null umzuleiten.

Das hat bei mir vielleicht mal funktioniert:

ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh </dev/null >/dev/null 2>&1 & " 

Wenn ich tatsächlich einen komplizierten Befehl auf einem Remote-Computer ausführen muss, füge ich den Befehl gerne in ein Skript auf dem Zielcomputer ein und führe dieses Skript einfach mit ssh aus.

Zum Beispiel:

# simple_script.sh (located on remote server)

#!/bin/bash

cat /var/log/messages | grep <some value> | awk -F " " '{print $8}'

Und dann führe ich einfach diesen Befehl auf dem Quellcomputer aus:

ssh user@ip "/path/to/simple_script.sh"

Ich habe versucht, das Gleiche zu tun, aber mit der zusätzlichen Komplexität, die ich versucht habe, es von Java aus zu machen.Auf einem Computer, auf dem Java ausgeführt wird, habe ich versucht, ein Skript auf einem anderen Computer im Hintergrund (mit Nohup) auszuführen.

Von der Befehlszeile aus funktionierte Folgendes:(Möglicherweise benötigen Sie „-i keyFile“ nicht, wenn Sie es nicht für die SSH-Verbindung zum Host benötigen.)

ssh -i keyFile user@host bash -c "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\""

Beachten Sie, dass es in meiner Befehlszeile nach dem „-c“ ein Argument gibt, das vollständig in Anführungszeichen steht.Aber damit es am anderen Ende funktioniert, benötigt es immer noch die Anführungszeichen, also musste ich darin maskierte Anführungszeichen einfügen.

Von Java aus hat Folgendes funktioniert:

ProcessBuilder b = new ProcessBuilder("ssh", "-i", "keyFile", "bash", "-c",
 "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\"");
Process process = b.start();
// then read from process.getInputStream() and close it.

Es war ein bisschen Versuch und Irrtum nötig, bis es funktionierte, aber jetzt scheint es gut zu funktionieren.

Du kannst es so machen...

sudo /home/script.sh -opt1 > /tmp/script.out &

Es erschien mir ganz praktisch, ein zu haben Fernbedienung tmux-Sitzung mit der tmux new -d <shell cmd> Syntax wie folgt:

ssh someone@elsewhere 'tmux new -d sleep 600'

Dadurch wird eine neue Sitzung gestartet elsewhere Der Host- und SSH-Befehl auf dem lokalen Computer kehrt fast sofort zur Shell zurück.Sie können dann eine SSH-Verbindung zum Remote-Host herstellen und tmux attach zu dieser Sitzung.Beachten Sie, dass es nichts mit der lokalen Ausführung von tmux zu tun hat, sondern nur mit der Remote-Ausführung!

Wenn Sie außerdem möchten, dass Ihre Sitzung nach Abschluss der Aufgabe bestehen bleibt, fügen Sie nach Ihrem Befehl einfach einen Shell-Launcher hinzu. Vergessen Sie jedoch nicht, Folgendes in Anführungszeichen zu setzen:

ssh someone@elsewhere 'tmux new -d "~/myscript.sh; bash"'

Ich denke, das ist es, was Sie brauchen:Zuerst müssen Sie installieren sshpass auf Ihrer Maschine.Dann können Sie Ihr eigenes Skript schreiben:

while read pass port user ip; do
sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE

Gehen Sie zunächst wie folgt vor:

Melden Sie sich bei A als Benutzer a an und generieren Sie ein Paar Authentifizierungsschlüssel.Geben Sie keine Passphrase ein:

a@A:~> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa): 
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A

Erstellen Sie nun mit ssh ein Verzeichnis ~/.ssh als Benutzer b auf B.(Das Verzeichnis existiert möglicherweise bereits, was in Ordnung ist):

a@A:~> ssh b@B mkdir -p .ssh
b@B's password: 

Hängen Sie schließlich den neuen öffentlichen Schlüssel von a an b@B:.ssh/authorized_keys an und geben Sie ein letztes Mal das Passwort von b ein:

a@A:~> cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
b@B's password: 

Von nun an können Sie sich von A als a aus bei B als b ohne Passwort anmelden:

a@A:~> ssh b@B

dann funktioniert das ohne Eingabe eines Passwortes

ssh b@B "cd /some/directory;auszuführendes Programm &"

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top