SSH, einen Befehl bei der Anmeldung ausführen und dann eingeloggt bleiben?

29

Ich habe es mit expect versucht, aber es hat nicht funktioniert: es hat die Verbindung am Ende geschlossen.

Können wir ein Skript über ssh ausführen, das sich auf entfernten Rechnern anmeldet, einen Befehl ausführt und die Verbindung nicht trennt?

Also ssh auf einer Maschine, cd in ein solches und ein solches Verzeichnis und dann einen Befehl ausführen und eingeloggt bleiben.

-Jonathan

(Ich nehme an, ich habe verwendet)

#!/usr/bin/expect -f
set password [lrange $argv 0 0]
spawn ssh root@marlboro "cd /tmp; ls -altr | tail"
expect "?assword:*"
send -- "$password\r"
send -- "\r"
interact
Jonathan
quelle
9
Bin es nur ich oder "automatisieren" Sie die Kennwortauthentifizierung auf diese Weise, anstatt Pubkeys oder andere vernünftige Methoden zu verwenden?
Grawity

Antworten:

25

Fügen Sie ein ; /bin/bashan das Ende Ihrer Befehlszeile auf der Remote-Seite? Das ist:

spawn ssh -t root@marlboro "cd /tmp; ls -altr | tail; /bin/bash -i"

Noch besser ist es, die .bashrc-Datei von root so zu ändern, dass sie ungefähr so ​​lautet:

PROMPT_COMMAND="cd /tmp && ls -altr | tail ; unset PROMPT_COMMAND"

:)

Bill Weiss
quelle
2
Möglicherweise möchten Sie -izu dieser Bash hinzufügen .
Teddy
Ja, ich nehme an :)
Bill Weiss
Wenn ich das tue, bricht die Tab-Vervollständigung in der neuen Shell ab (auch mit "-i") - eine Idee, warum / wie man das behebt?
Coderer
1
Ich habe meine neue Antwort hier getestet, es funktioniert großartig. Ein bisschen rau, aber es funktioniert.
Bill Weiss
7
Versuchen Sie ssh -t, eine Pty zuzuweisen.
Bis auf weiteres angehalten.
4

Wenn Sie in Python damit einverstanden sind, hat pexpect ein Beispiel, das fast genau das tut, wonach Sie fragen:

import pexpect
child = pexpect.spawn ('ftp ftp.openbsd.org')
child.expect ('Name .*: ')
child.sendline ('anonymous')
child.expect ('Password:')
child.sendline ('[email protected]')
child.expect ('ftp> ')
child.sendline ('ls /pub/OpenBSD/')
child.expect ('ftp> ')
print child.before   # Print the result of the ls command.
child.interact()     # Give control of the child to the user.

Um dies mit ssh anstelle von ftp zu tun, möchten Sie einen Code, der dem folgenden ähnelt (die Beispieldateien in pexpect enthalten viel mehr Details und Informationen, aber hier sind die Grundlagen):

import pexpect
child = pexpect.spawn ('ssh root@marlboro')
child.expect ('Password:')
child.sendline ('password')
child.expect ('prompt# ')
child.sendline ('cd /tmp')
child.expect ('prompt# ')
child.sendline ('ls -altr | tail')
child.expect ('prompt# ')
print child.before, child.after   # Print the result of the ls command.
child.interact()     # Give control of the child to the user.

Versteht mich nicht falsch, ich LIEBE es zu erwarten (besonders Autoexpect), aber Python ist für mich einfach sooo viel einfacher zu lernen.

Jed Daniels
quelle
Auch ich gehe von erwarten zu erwarten. Python ist jetzt viel allgegenwärtiger.
JM Becker
4

Der wahrscheinlich einfachste und sauberste Weg, um in einen Server zu ssh, eine interaktive Shell zu erzeugen und Befehle in dieser Shell auszuführen, besteht darin, eine benutzerdefinierte rc-Datei für bash zu erstellen.

Geben Sie in Ihrer benutzerdefinierten bashrc-Datei auf dem Server zuerst die Standarddatei ein und fügen Sie dann Ihre benutzerdefinierten Befehle hinzu, z

~ / .bashrc_custom:

. ~/.bashrc
cd dir/
workon virtualenvproject

Sie können dann Ihre SSH-Sitzung wie folgt starten:

$ ssh -t server "/bin/bash --rcfile ~/.bashrc_custom -i"

Die -tOption erzwingt eine Pseudotty-Zuweisung, sodass Dinge wie die Tab-Vervollständigung funktionieren.

Die --rcfileOption gibt an, welche RC-Datei anstelle der Standarddatei geladen werden soll. Wichtig: Um erkannt zu werden, müssen Sie in der Befehlszeile vor den Optionen mit einem einzelnen Zeichen "Argumente mit zwei Strichen" eingeben.

Das -iArgument zu / bin / bash dient dazu, eine interaktive Shell aufzurufen.

Danilo Bargen
quelle
eigentlich nicht. Was kann ich tun, wenn ich für jede Verbindung unterschiedliche Befehle ausführen möchte?
Eugen Konkov
1

Wenn jemand Informationen darüber haben möchte, was im Hintergrund passiert, sollten Sie sich das sshd-Handbuch ansehen:

Wenn sich ein Benutzer erfolgreich anmeldet, führt sshd Folgendes aus:

  1. Befindet sich die Anmeldung auf einem tty und wurde kein Befehl angegeben, werden die letzte Anmeldezeit und / etc / motd ausgegeben (sofern dies nicht in der Konfigurationsdatei oder durch ~ / .hushlogin verhindert wird; siehe Abschnitt DATEIEN).
  2. Wenn der Login auf einem Tag liegt, wird die Login-Zeit aufgezeichnet.
  3. Überprüft / etc / nologin und / var / run / nologin; Wenn einer vorhanden ist, wird der Inhalt gedruckt und beendet (außer root).
  4. Änderungen werden mit normalen Benutzerrechten ausgeführt.
  5. Richtet die Basisumgebung ein.
  6. Liest die Datei ~ / .ssh / environment, falls vorhanden, und Benutzer können ihre Umgebung ändern. Siehe die PermitUserEnvironment-Option in sshd_config (5).
  7. Änderungen im Home-Verzeichnis des Benutzers.
  8. Wenn ~ / .ssh / rc vorhanden ist, wird es ausgeführt. Wenn / etc / ssh / sshrc vorhanden ist, wird es ausgeführt. Andernfalls wird xauth (1) ausgeführt. Die RC-Dateien erhalten das X11-Authentifizierungsprotokoll und das Cookie in der Standardeingabe. Siehe SSHRC weiter unten.
  9. Führt die Shell oder den Befehl des Benutzers aus .

https://www.freebsd.org/cgi/man.cgi?sshd(8)#LOGIN_PROCESS

Gerry
quelle
0

Sie sollten es generell vermeiden, ssh auf diese Art und Weise zu verwenden, da es seinen Zweck verfehlt.
Mach ein

ssh-add -l | grep "file_of_your_rsa_priv_key_here"

um zu sehen, ob Ihr Schlüssel im Pool der aktiven ssh-Sitzung aufgeführt ist, oder fügen Sie ihn selbst hinzu (mit ssh-add).

Kounavi
quelle