Wie können Sie mit ssh einen Befehl auf dem Remote-Computer ausführen, ohne ihn zu beenden?

29

Normalerweise, wenn Sie einen Befehl an ssh wie folgt übergeben

ssh [email protected] 'some-command.sh'

Sie erhalten eine nicht interaktive Sitzung und ssh wird beendet, sobald der Befehl (oder das Skript oder was auch immer) ausgeführt wird. Wie kann ich eine interaktive Sitzung abrufen und dennoch einen Befehl ausführen, den ich auf meinem lokalen Computer angegeben habe? Zum Beispiel möchte ich in der Lage sein, einen Bildschirm zu öffnen und eine bestimmte Bildschirmsitzung neu zu starten:

ssh [email protected] 'screen -r 12345'

Dies ist jedoch nicht zulässig und gibt den Fehler "Muss mit einem Terminal verbunden sein" zurück. was ich vermute bedeutet im Wesentlichen "muss diesen Befehl von einer interaktiven Shell aufrufen".

Als weiteres Beispiel benutze ich eine Menge Maschinen bei der Arbeit, die oft erfordern, dass ich ein gemeinsames Konto benutze, um Rechte für bestimmte Dinge zu haben (ja, ich weiß: schlechte Idee, aber beschuldige mich nicht, das habe ich nicht eingerichtet Art und Weise), und sie haben in der Regel ksh als Standard-Shell. Ich möchte mich anmelden, zu bash (oder zsh) wechseln und das .bash_profile (oder .zshrc) meines eigenen Kontos beziehen. Dies wäre einfach, wenn ich eine interaktive SSH-Sitzung einrichten und einen Befehl an den Remotecomputer übergeben könnte, der bei der Anmeldung ausgeführt wird.

Ich habe eine sehr kludgey (und ungetestete) Lösung im Sinn, die ich posten werde, aber ich hoffe, dass jemand einen besseren Weg kennt.

UPDATE: Für diejenigen, die das nicht bemerkt haben, plane ich nicht, das alles von Hand zu machen. Wenn ich also auffordere, eine interaktive Sitzung zu eröffnen und dann von Hand zu machen, löst das eigentlich nichts.

2. UPDATE: Um es noch einmal zu klären: Ich versuche (beliebige) Befehle auf dem Server auszuführen (programmgesteuert auf dem Client angegeben), aber dann ist eine interaktive Sitzung geöffnet, die von allen Aktionen dieser programmgesteuerten Befehle betroffen ist.

Bilderstürmer
quelle
echo "command" | ssh user@remote_host
Laggingreflex
2
Haben Sie den Teil der Frage "ohne zu beenden" verpasst? Ich bin mir ziemlich sicher, dass dies nach Beendigung des Befehls beendet wird.
Iconoclast

Antworten:

26

Sie können den folgenden Befehl verwenden, um bash zu starten und Ihr eigenes Profil zu erstellen, wenn Sie ssh ausführen:

ssh  -t hostname "bash --rcfile ~user/.bashrc"
Dogbane
quelle
4
+1. Der -tSchalter behebt auch das Problem des Fragestellers screen.
Patches
3
Kann dies mit beliebigen Befehlen verwendet werden, ohne die Verbindung zu trennen? Wenn ich es versuche ssh -t www.dev "echo 'hi there'", wird die Verbindung sofort geschlossen, nachdem der Befehl ausgeführt wurde.
Iconoclast
11

Aufbauend auf der Antwort von dogbane sieht eine vollständige Lösung folgendermaßen aus:

ssh -t user@server 'cd /a/great/place; bash'

Hier -terzwinge ich die Zuweisung eines Pseudo-Terminals, das für eine interaktive Shell benötigt wird. Dann führe ich zwei Befehle auf dem Server aus: zuerst das, was ich vor dem Öffnen der interaktiven Shell tun wollte (in meinem Fall, indem ich das Verzeichnis in einen bestimmten Ordner ändere), und dann die interaktive Shell selbst. bash erkennt, dass es ein Pseudo-Terminal hat und reagiert interaktiv.

Die einzelnen Anführungszeichen stellen sicher, dass das Ganze als Befehl, der von Ihrer Standard-Shell ausgeführt wird, an den Remote-Server übergeben wird.

Nochmals vielen Dank an Dogbane für den nötigen Hinweis -t. Früher habe ich dieses Problem mit gelöst expect, was definitiv bedeutet, eine Maus mit einer Kanone zu töten. (:

user1179239
quelle
2

Versuchen Sie diese Lösung.

echo "command" | ssh user@remote_host

Die Anmeldung ist interaktiv und Ihr Befehl wird so übergeben, als ob Sie ihn in der interaktiven Befehlszeile eingegeben hätten. Die Sitzung wird beendet, als hätten Sie etwas eingegeben

ssh user@remote_host 'command'
user210540
quelle
3
Wenn die Sitzung nach Abschluss des Befehls beendet wird, wird die Frage nicht beantwortet. Der Sinn des Befehls besteht darin, nach Ausführung des Befehls eine interaktive Sitzung abzuhalten und nicht nur Befehle an Server zu senden ssh.
Iconoclast
Dies ist zumindest gut, um eine Interaktion zu simulieren , in der der Befehl ausgeführt werden kann, ohne -teine eigene Bash-Datei zu verwenden. +1
laggingreflex
0

Verwenden Sie ssh -X, um termIO cmds zu verwenden.

Außerdem können Sie Ihre Befehle wie "ssh 'source ~ / .bashrc && cd && do'" verketten.

Ethrbunny
quelle
aber nachdem die ganze Kette fertig ist, habe ich keine interaktive Sitzung mehr, oder? Es schließt immer noch, oder?
Iconoclast
Und möchten Sie den Begriff derIO-Lösung näher erläutern?
Iconoclast
0

Warum nicht detach auf dem Remote-System installieren und verwenden:

ssh -t [email protected] "/home/user/bin/detach ls"
Dan D.
quelle
Wird dies 'ls' ausführen und mich dann mit einer interaktiven Sitzung verlassen? Was ist, wenn ich anstelle von 'ls' 'source .somefile' ausführe, um einige Aliase und Funktionen abzurufen? Werden sie in meiner interaktiven Sitzung verfügbar sein oder wurde sie in einer anderen Sitzung ausgeführt?
Bilderstürmer
Nein, wegen detach, lshalten nicht die Sitzung geöffnet und trennen , ohne den Druck der Ausgang lsaber es wird immer noch laufen.
Dan D.
Ich versuche (willkürliche) Befehle auf dem Server auszuführen (programmgesteuert auf dem Client angegeben), aber dann ist eine interaktive Sitzung geöffnet, die von allen Aktionen dieser programmgesteuerten Befehle betroffen ist. Wenn ich Sie also richtig verstehe, hilft mir das nicht.
Bilderstürmer
0

Die Antwort von laggingreflex ist nah ... Ich würde es wie folgt ändern:

echo "command\n$(cat -)" | ssh user@remote_host

Leider wird Ihnen die Funktionsweise wahrscheinlich nicht gefallen, da "cat" die Zeilen puffert, die in stdout geschrieben werden ... Wenn wir ein Skript namens "echo-cat" erstellen, das ungefähr so ​​aussieht:

{
  echo "${@}"
 #cat buffers & won't flush to stdout immediately
 #cat -
  IFS='\n'
  while read line
  do
        echo "${line}"
  done
}

Wir erhalten das gleiche Ergebnis ohne Pufferung:

echo-cat "command" | ssh user@remote_host

Damit kommen Sie Ihrem Ziel wahrscheinlich viel näher ...

Rechnung
quelle
0

Das ist klug und ungetestet, aber ich denke, es sollte funktionieren.

Erstellen Sie ein Skript mit dem Namen (zB) remote-starter, das nach einem user @ host-Argument ein Argument in Anführungszeichen setzt:

remote-starter [email protected] 'some-command.sh arg1 arg2'

Dieses Skript sollte zuerst den in Anführungszeichen gesetzten Befehl (ohne Anführungszeichen) in der Datei mit dem Namen (z. B.) .onetimeauf dem Remotecomputer speichern und dann einen regulären ssh-Befehl ausführen, wobei dieses Mal kein Befehl übergeben wird, der auf dem Remotecomputer ausgeführt werden soll. (Wenn Sie ssh [email protected] in einem Skript ausführen, funktioniert es möglicherweise, exec ssh [email protected] auszuführen.)

Damit dies funktioniert, muss der Remotecomputer eine Quelle .onetimeaus seinem .bash_profile oder .zshrc oder was auch immer erstellen. Nach der Ausführung .onetimesollte es gelöscht werden .onetime, sodass die Datei nicht mehr ausgeführt wird, wenn Sie sich regelmäßig anmelden.

Bilderstürmer
quelle