2017-08-02 2 views
0

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 
+0

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

+0

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. –

+0

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

Antwort

0

Sie sollten in der Lage sein, eine expect für das Echo der Steuerzeichen zu verwenden, um Sie zu der Fernbedienung (oder eine andere Zeichenfolge nicht von Ihrem tail -f Befehl erzeugt wird) senden . Zum Beispiel dieses einfache ssh Beispiel funktioniert für mich (die -d ist für debug):

#!/usr/bin/expect -d 
log_user 0 
spawn ssh localhost 
expect " $ " 
send "tail -f /var/log/messages\n" 
log_user 1 
trap { send "\003" } SIGINT 
set timeout -1 
expect "\003" 
expect "$ " 
send "date\r" 
expect "$ " 

Wenn ich dies ausführen, stdin Umleitung im Hintergrund der Schale auf null, ich Strg-C eingeben und er endet sauber .

Verwandte Themen