2016-09-07 2 views
-1

Nachdem das folgende Skript die Inventardatei liest und die Befehle aus der Testbefehlsdatei ausführt, sucht die Foreach-Funktion nach weiteren Informationen aus der Inventardatei zur Verarbeitung und Fehlern anstatt zu enden.Verwenden von Expect Wie beende ich foreach-Funktion nach EOF

#!/usr/bin/expect 

set timeout 5 

# Open and read hosts from file 
set fp [open "inventory_2ps"] 
set hosts [split [read $fp]"\n"] 
close $fp 

# Get commands to run in server 
set fh [open "testcommands"] 
set commands [split [read $fh] "\n"] 
close $fh 

# Set login variable 
set user "xxxxxxx"; 
set PW "xxxxxxx"; 

# Spawn server login 
foreach host $hosts { 

    spawn ssh [email protected]$host 
    expect "$ " 

    send "su - xxxxxx\n" 
    expect "Password: " 

    send "$PW\n" 
    expect "$ " 

    send "xxxxxx -nobash\r" 
    expect "> " 

    foreach cmd $commands { 
      send "$cmd\n" 
      expect "> " 

      } 
    expect eof 

erhalten Fehler nach dem letzten Host-Login/Ausfahrt:

>$ spawn ssh [email protected]" 
ssh: Could not resolve hostname ": Name or service not known 
send: spawn id exp10 not open 
    while executing 
"send "su - xxxxxx\n"" 
    ("foreach" body line 6) 
    invoked from within 
"foreach host $hosts { 

    spawn ssh [email protected]$host 
    expect "$ " 
+3

Ich weiß nicht, warum das eine Perlfrage ist. – mob

Antwort

1

Nach TCL Wiki, wird der Lesebefehl alles lesen, bis es EOF trifft. Dies beinhaltet den letzten Zeilenumbruch. Um die letzte neue Zeile zu verwerfen, müssen Sie hinzufügen -nonewline

Weitere Informationen finden Sie unter http://wiki.tcl.tk/1182.

Nehmen wir an, wir haben die inventory_2ps Datei mit 2 Hostnamen Zeilen.

Versuchen Sie, die folgenden Zeilen zu ändern : "host1" und "host2"

$ cat inventory_2ps 
host1 
host2 

Wenn wir manuell den offenen tcl-Befehl ausführen, erhalten wir den folgenden

$ tclsh 
% set fp [open "inventory_2ps"] 
file3 
% puts [read $fp] 
host1 
host2 

% set fp [open "inventory_2ps"] 
file4 
% puts [read -nonewline $fp] 
host1 
host2 
% 

zu beheben

set hosts [split [read $fp]"\n"] 

und

set commands [split [read $fh] "\n"] 

zu

set hosts [split [read -nonewline $fp]] 

und

set commands [split [read -nonewline $fh]] 

sind.

+0

Können Sie Ihr Denken hier ein bisschen erklären? –

+0

@alex, absolut. Und da der Dateiinhalt mit einem Zeilenumbruch endet, endet die Ergebnisliste beim Aufteilen auf Zeilenumbrüche mit einem leeren Element. –

1

Sie müssen sicherstellen, dass Ihr Code leere Werte in Ihren Eingabedaten ignoriert, da sie nicht hilfreich sind in Ihrem Fall. Sie tun dies, indem einige triviale Filterung zu Beginn jeder foreach Schleife ergänzt:

foreach host $hosts { 
    if {[string trim $host] eq ""} then continue 

    spawn ssh [email protected]$host 
    # ... 

ich oft ein wenig komplexer Filterung verwenden möchten (wie unten), wie kann ich Kommentare in meinem Konfigurationsdateien setzen. Das ist in der Praxis sehr schön!

foreach host $hosts { 
    set host [string trim $host] 
    if {$host eq ""} then continue 
    if {[string match "#*" $host]} then continue 

    spawn ssh [email protected]$host 
    # ... 

aus dieser ganz abgesehen, auch sicherstellen, dass Sie ein Leerzeichen zwischen dem Text zu split und der Zeichensatz enthalten durch aufzuspalten. Das könnte ein Artefakt deiner Eingabe sein und nicht in deinem Live-Code vorhanden sein, aber es ist ziemlich wichtig, da Tcl sensibel für den Unterschied ist.