Ich versuche, ein Skript erwartet von bash in der folgenden Art und Weise zu nennen:Erwarten - Direkte Ausgabe von Remote-Befehl an den lokalen Datei
#!/bin/bash
mkfifo foobar
expectScript > foobar &
# other stuff that does stuff with foobar
Was expectScript tun muss, ist in einen Remote-Host ssh. Von dort muss es in einen anderen entfernten Host ssh. Dann muss der Benutzer auf root umgestellt werden (Root-Login ist nicht erlaubt). Dann muss ein Befehl ausgegeben werden (z. B. tail -f/var/log/messages), der letztendlich in foobar geschrieben werden muss. Nichts anderes kann in Foobar geschrieben werden, z.B. Kennwortaufforderungen oder Eingabeaufforderungen. Nur die Ausgabe des Befehls kann in foobar geschrieben werden. Ich habe den Login-Teil des Skripts gut funktioniert. Worum ich mich bemühe, ist, wie man es so macht, dass die Ausgabe in foobar geschrieben wird, und zwar so, dass SIGINT den Befehl abbricht. Hier
ist, was ich habe:
#!/usr/bin/expect --
set HOST1_USER myuser
set HOST2_USER myotheruser
set HOST1_PASSWORD mypassword
set HOST2_PASSWORD myotherpassword
set ROOT_PASSWORD anotherpassword
set HOST1 192.168.0.5
# HOST2 is only reachable from HOST1
set HOST2 192.168.1.12
global until_interrupt
set until_interrupt 0
set HOST1_PROMPT "CL-\\d.*#"
set HOST2_PROMPT "\\\$ $"
set ROOT_PROMPT "# $"
log_user 0
spawn ssh [email protected]$HOST1
# ssh keys are exchanged with HOST1, so there is no need for password here
expect -re "$HOST1_PROMPT" {
send "ssh [email protected]$HOST2\n"
expect {
-re ".*ssword.*" { send "$HOST2_PASSWORD\n" }
-re ".*Are you sure you want to continue connecting.*" {send "yes\n"; exp_continue}
}
}
expect -re "$HOST2_PROMPT" { send "su\n" }
expect -re ".*ssword.*" { send "ROOT_PASSWORD\n" }
log_user 1
# nothing up to this point should have been sent to stdout
# now I want the output of the tail command to be sent to stdout
expect -re "$ROOT_PROMPT" { send "tail -f /var/log/messages\n" }
# I want to wait here until SIGINT is sent. There may be a better way than the traps below.
# Set a trap to watch for SIGINT
trap {
set until_interrupt sigint_detected
} SIGINT
while { $until_interrupt == 0 } {
#wait until sigint
}
send "\003"
# I think that is SIGINT, and that I'm sending it because I caught the first one in the trap.
trap {
exit
} SIGINT
set timeout 30
expect -re "$ROOT_PROMPT" { send "exit\n" }
expect -re "$HOST2_PROMPT" { send "exit\n" }
expect -re "$HOST1_PROMPT" { send "exit\n" }
# Fully exited
Die meisten dieses 'expect'-Skripts können einfach durch Verwendung der Public-Key-Authentifizierung und der in' ssh' eingebauten Tunneling-Unterstützung eliminiert werden. – chepner
Danke chepner, aber nicht viel kann beseitigt werden, weil ich auf HOST2 den Befehl als root ausführen muss (sudo wird nicht funktionieren), und HOST2 erlaubt es root nicht, sich über ssh anzumelden. Daher ist es notwendig, sich zuerst als Nicht-Root-Benutzer anzumelden und dann als Root. Ich habe die Lösung auf Hosts implementiert, wo Public-Key-Authentifizierung funktioniert, und es ist viel einfacher. Aber für diesen speziellen Server sehe ich nicht, wie es funktionieren könnte. –
Wenn Sie das Root-Passwort haben, können Sie * konfigurieren * 'sudo' zu arbeiten. Und nichts hindert Sie daran, die richtigen Benutzer-IDs und Host-Namen in Ihrer lokalen 'ssh'-Konfigurationsdatei zu setzen. – chepner