Ssh veranlassen, einen Befehl im Hintergrund auf dem Zielcomputer auszuführen


304

Dies ist eine Folgefrage zu Wie verwenden Sie ssh in einem Shell-Skript? Frage. Wie kann ich den Befehl ssh zurückgeben, wenn ich einen Befehl auf dem Remotecomputer ausführen möchte, der im Hintergrund auf diesem Computer ausgeführt wird? Wenn ich versuche, nur das kaufmännische Und (&) am Ende des Befehls einzufügen, hängt es einfach. Die genaue Form des Befehls sieht folgendermaßen 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 ich SSH- Schlüssel eingerichtet habe, sodass kein Kennwort erforderlich ist.

Antworten:


315

Ich hatte dieses Problem in einem Programm, das ich vor einem Jahr geschrieben habe - es stellt sich heraus, dass die Antwort ziemlich kompliziert ist. Sie müssen sowohl nohup als auch die Ausgabeumleitung verwenden, wie im Wikipedia-Artikel über nohup erläutert , der hier zur Vereinfachung kopiert wurde.

Das Nicht-Hupen von Jobs im Hintergrund ist beispielsweise nützlich, wenn Sie über SSH angemeldet sind, da Jobs im Hintergrund dazu führen können, dass die Shell aufgrund einer Race-Bedingung beim Abmelden hängen bleibt [2]. Dieses Problem kann auch behoben werden, indem alle drei E / A-Streams umgeleitet werden:

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

1
Diese Dateien werden im aktuellen Verzeichnis erstellt. Die Grenze ist also die Menge an freiem Speicherplatz auf der Partition. Natürlich können Sie auch zu umleiten /dev/null.
Frank Kusters

2
Irgendwelche Ideen zum Hintergrund des Prozesses, nachdem er nach Aufforderungen gefragt hat? (wie ein gpg - entschlüsseln, das fertig ist, nach dem Passwort zu fragen)
isaaclw

Der Versuch, einen Resque-Arbeiter im Hintergrund mit nohup zu starten, aber es funktioniert nicht .. :(
Infant Dev

1
Können Sie bitte erklären, was das < /dev/nullbedeutet? Vielen Dank.
Qian Chen

1
Ebenfalls aus dem Wikipedia-Artikel zu nohup: "Beachten Sie auch, dass eine schließende SSH-Sitzung nicht immer ein HUP-Signal an abhängige Prozesse sendet. Dies hängt unter anderem davon ab, ob ein Pseudo-Terminal zugewiesen wurde oder nicht." Obwohl das Nohup nicht immer benötigt wird, sind Sie langfristig besser damit als ohne.
Jax

254

Dies war für mich der sauberste Weg, dies 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


7
-nwird nicht benötigt wie -fimpliziert-n
blissini

6
ssh -fLässt den SSH-Prozess verbunden, nur im Hintergrund. Mit den Lösungen / dev / null kann ssh schnell getrennt werden, was möglicherweise vorzuziehen ist.
Beni Cherniavsky-Paskin

Diese Lösung funktioniert auch zum Senden von Befehlen über ssh an ein Syonology NAS
Stefan F

Ich brauche die Ergebnisse von "ls -l", um auf meiner Fernbedienung angezeigt zu werden. Dieser Befehl führt dies nicht aus.
Siddharth

@Siddharth Leiten Sie dann zu einer benannten Datei anstatt zu / dev / null um.
Sherellbc

29

Fd's umleiten

Die Ausgabe muss umgeleitet werden, wobei &>/dev/nullsowohl stderr als auch stdout nach / dev / null umgeleitet werden und ein Synonym für >/dev/null 2>/dev/nulloder ist >/dev/null 2>&1.

Klammern

Der beste Weg ist zu verwenden, sh -c '( ( command ) & )'wo Befehl etwas 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, den Befehl / die Shell mit nice zu starten:

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

8
Ich weiß, dass dies eine sehr alte Antwort von Ihnen ist, aber können Sie einige Kommentare dazu hinzufügen, warum der Weg in Klammern der beste Weg ist, was (wenn überhaupt) das Hinzufügen von Unterschieden nohupausmacht und warum und wann Sie ihn verwenden würden nice? Ich denke, das würde dieser Antwort viel hinzufügen.
Dr. K

Vielleicht, um dies teilweise zu beantworten: Mit nohup müssen Sie das & nicht an den auszuführenden Befehl anhängen.
Cadoiz

21

Wenn Sie die Verbindung nicht offen halten können, können Sie den Bildschirm verwenden , 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: ctrl-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 der Bildschirm innerhalb jeder Sitzung auch mehrere Shells erstellen kann. Ein ähnlicher Effekt kann mit tmux erzielt werden .

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: ctrl-b d

So listen Sie Bildschirmsitzungen auf:

tmux list-sessions

So fügen Sie eine Sitzung erneut hinzu:

tmux attach <session number>

Der Standard-tmux-Steuerschlüssel ' ctrl-b' ist etwas schwierig zu verwenden, aber es gibt einige Beispiele für tmux-Konfigurationen, die mit tmux geliefert werden und die Sie ausprobieren können.


3
wie würde man das verwenden screen?
Quamis

18

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 &\""

Sehr hilfreich. Vielen Dank.
Michael Martinez

8

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

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


2
Dies wäre eine großartige allgemeine Lösung, wenn atBefehlszeilenargumente nach der Zeit und nicht nur aus einer Datei akzeptiert würden .
Tyler Collier

3
Sie können eine Datei mit <<< wie in simulieren: ssh user @ target "at now -f <<< 'my_comnads'"
Nico

6

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"

das scheint für mich zu funktionieren. 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 sie auch verwenden

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

um alle Ausgaben nach / dev / null umzuleiten.


5

Das hat bei mir mal funktioniert:

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

2

Sie können es so machen ...

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

Perfekt, funktioniert mit einer PuTTY SSH-Sitzung. Ich kann beenden und das Skript wird auf dem Computer fortgesetzt. Danke dir.
Satria

1

Wenn ich einen Befehl auf einem Remotecomputer ausführen muss, der kompliziert ist, 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"

0

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

In der Befehlszeile hat Folgendes funktioniert: (Möglicherweise benötigen Sie die "-i keyFile" nicht, wenn Sie sie nicht benötigen, um zum Host zu ssh).

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

Beachten Sie, dass in meiner Befehlszeile nach dem "-c" ein Argument steht, das alle in Anführungszeichen steht. Aber damit es am anderen Ende funktioniert, braucht es immer noch die Anführungszeichen, also musste ich 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 hat ein bisschen Versuch und Irrtum gekostet, um dies zum Laufen zu bringen, aber es scheint jetzt gut zu funktionieren.


0

Es erschien mir sehr praktisch, eine Remote- TMXX-Sitzung mit der folgenden tmux new -d <shell cmd>Syntax durchzuführen :

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

Dadurch wird eine neue Sitzung auf dem elsewhereHost gestartet, und der Befehl ssh auf dem lokalen Computer kehrt fast sofort zur Shell zurück. Sie können dann ssh zum Remote-Host und tmux attachzu dieser Sitzung. Beachten Sie, dass der lokale tmux nicht ausgeführt wird, sondern nur remote!

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

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

0
YOUR-COMMAND &> YOUR-LOG.log &    

Dies sollte den Befehl ausführen und eine Prozess-ID zuweisen. Sie können einfach -f YOUR-LOG.log verfolgen, um die Ergebnisse zu sehen, die darauf geschrieben werden, sobald sie eintreten. Sie können sich jederzeit abmelden und der Vorgang wird fortgesetzt


0

Sie können dies ohne nohup tun:

ssh user@host 'myprogram >out.log 2>err.log &'

-2

Ich denke, das ist was Sie brauchen: Zuerst müssen Sie sshpassauf Ihrem Computer installieren . 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

-3

Befolgen Sie zunächst dieses Verfahren:

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

Verwenden Sie nun ssh, um ein Verzeichnis ~ / .ssh als Benutzer b auf B zu erstellen. (Das Verzeichnis ist möglicherweise bereits vorhanden, was in Ordnung ist.)

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

Fügen Sie zum Schluss den neuen öffentlichen Schlüssel von a an b @ B: .ssh / authorized_keys hinzu und geben Sie das Passwort von b ein letztes Mal 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 bei B als b von A als ohne Passwort anmelden:

a@A:~> ssh b@B

dann funktioniert dies ohne Eingabe eines Passworts

ssh b @ B "cd / some / directory; Programm zum Ausführen &"


1
Die Frage besagt, dass Dagorym die Schlüssel bereits so eingerichtet hat, dass kein Passwort erforderlich ist, aber es hängt noch
Max Nanasy
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.