2016-09-07 4 views
-1

После того, как следующий скрипт считывает файл инвентаризации и завершает команды из файла тестовых команд, функция foreach ищет дополнительную информацию из файла инвентаризации для обработки и ошибок, а не для завершения.Использование Expect как выйти из функции foreach после 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 

получает ошибку после последнего хоста входа/выхода:

>$ 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

Я не знаю, почему это вопрос perl. – mob

ответ

1

Согласно TCL вики, команда чтения будет читать все до тех пор, пока не встретится конец файла. Это включает в себя последнюю строку новой строки. Чтобы отказаться от последней строки новой строки, вам необходимо добавить -nonewline

Для получения более подробной информации, пожалуйста, обратитесь к http://wiki.tcl.tk/1182.

Предположим, у нас есть файл inventory_2ps с двумя строками имени хоста. "Host1" и "host2"

$ cat inventory_2ps 
host1 
host2 

Если вручную запустить команду открытым TCL, мы получаем следующее

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

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

исправить:

Попробуйте изменить следующие строки

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

и

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

к

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

и

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

соответственно.

+0

Не могли бы вы объяснить свое мышление здесь? –

+0

@alex, совершенно. И поскольку содержимое файла заканчивается символом новой строки, при разбиении на строки новой строки результирующий список заканчивается пустым элементом. –

1

Вам необходимо убедиться, что ваш код игнорирует пустые значения в ваших входных данных, потому что они бесполезны в вашем случае. Вы можете сделать это, добавив некоторую тривиальную фильтрацию в начале каждого foreach цикла:

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

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

Я часто хотел бы использовать немного более сложную фильтрацию (как показано ниже), а затем я могу поместить комментарии в моих файлах конфигурация. Это очень хорошо на практике!

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

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

Совершенно независимо от этого, а также убедитесь, что вы включили пространство между текстом split и набора символов расщепляется. Это может быть артефактом вашего представления здесь и не присутствовать в вашем живом коде, но это имеет значение совсем немного, поскольку Tcl чувствителен к разнице.