2014-06-22 5 views
0

У меня есть сценарий Bash, который включает в себя сценарий ожидания/TCL EOF в отдельной функции. Сценарий ожидания выйдет с 0-4 возможными кодами выхода в зависимости от того, что определяет сценарий ожидания/TCL с удаленного устройства, и в операторе if ... elif ... else я пишу конкретную строку переменной в зависимости от этого кода выхода (в рамках функции ожидания/TCL). Затем управление передается обратно в сценарий Bash, где содержит блок case, содержащий строку, содержащуюся в указанной переменной.Сценарий Broken expect/TCL

Проблема, с которой я столкнулся, заключается в том, что моя функция Bash, которая содержит сценарий expect/TCL, не улавливает код выхода 3 (ну, как и я, я вижу, что запись в файле журнала правильно записывается в файл журнала, но если я эхо значение кода выхода, которое оно фактически улавливает ноль, когда ситуация должна быть 3), и поэтому мой оператор case не переключается точно.

Вы можете найти ошибку?

(Я нарезал сценарий прямо до этих частей, чтобы сохранить пост кратким и конкретным, поэтому просто предположим, что окружающий код работает нормально).

function myTclFunc() 
{ 
    /usr/bin/expect<<EOF 
    proc log_msg {msg {to_stdout no}} { 
     set log_line "[timestamp -format {[%d/%m/%Y @ %T]}] \$msg" 
     set fh [open ~/mylogfile.log a] 
     puts \$fh \$log_line 
     close \$fh 
     if {\$to_stdout} {puts \$log_line} 
    } 

    ;#exp_internal 1 
    set timeout 5 
    set send_human {.1 .3 1 .05 2} 

    spawn ssh -o "StrictHostKeyChecking no" "[USER]@$1" 

    expect { 
     "password: " { send -h "[MY_PASSWD]\r" } 
     timeout { log_msg "A RELEVANT STRING TO LOG $1/$2"; exit 1 } 
    } 

    set timeout 3 
    sleep 1 ; 
    send -h "[COMMAND A]\r" ; 
    expect { 
     timeout { exit 1 } 
     -re {\m\d{1,}(\.\d{1,}){3}\M} 
    } 
    if { ! [regexp {192\.[0-9]{1,3}\.{2}[0-9]{1,3}} $expect_out(0,string)]} { 
     send -h "[COMMAND B]\r" ; 
    } 
    expect { 
     "[STRING 1]" { 
      send -h "[COMMAND C]\r" ; 
      log_msg "Problem F on $1/$2" ; 
      exit 3 
     } 
     "[STRING 2]" { 
      send -h "[COMMAND D]\r" ; 
      sleep 1 ; 
      send -h "[COMMAND E]\r" ; 
      send -h "\r" ; 
      puts "\r" 
      ;#exit 0 
     } 
    } 
    expect eof 
EOF 
    if [[ $? -eq 0 ]]; then 
     passBack="GOOD"; 
    elif [[ $? -eq 3 ]]; then 
     passBack="BAD"; 
    else 
     passBack="TIMEOUT"; 
    fi; 
} 

[...snipped code...] 
myTclFunc $myVar $1 

case "$passBack" in 
GOOD) 
    echo "" 
    exit 0 
    ;; 
BAD) 
    echo "" 
    exit 4 
    ;; 
CHECK) 
    echo "" 
    exit 3 
    ;; 
esac; 
[...snipped code...] 

ответ

0

Смесь Shell и Tcl может быть немного сложной в разы. В частности, вы хотите доставить \ в механизм регулярных выражений в нескольких местах, внутри документа здесь с некорректным разделительным словом. К счастью, вы в противном случае ставите RE внутри брекетов, поэтому просто запутывает, а не супер-запутанный!

Соответствующая часть документации Баша говорит:

Здесь Документы

Этого типа перенаправление инструктирует оболочку не читать входной сигнал от источника тока до строки, содержащей только слова (с нет завершающих пробелов). Все строки, считываемые до этой точки, затем используются в качестве стандартного ввода для команды.

Формат здесь-документов не является:

<<[-]word 
     here-document 
    delimiter 

Нет расширения параметров, подстановки команд, арифметическое расширение, или расширение путь осуществляется на слова. Если указаны любые символы в слова, то разделитель является результатом удаления цитаты на слове, а строки в этом документе не будут расширены. Если слово не закодировано, все строки этого документа подвергаются расширению параметров, подстановке команд и арифметическому расширению. В последнем случае последовательность символов \ < новой строки > игнорируется, и \ должны использоваться процитировать символы \, $ и `.

Если оператор перенаправления < < -, то все ведущие символы табуляции удаляется из входных линий и линии, содержащей разделителя.Это позволяет здесь-документы в сценариях оболочки быть отступом естественным образом.

Поскольку вы используете версию без кавычек, вы хотите удвоить обратную косую черту, которую должен интерпретировать интерпретатор Tcl. В вашем случае это только те, что содержатся в регулярных выражениях. Таким образом, вы хотите, чтобы это (со всем выше и ниже без изменений, я думаю):

expect { 
     timeout { exit 1 } 
     -re {\\m\\d{1,}(\\.\\d{1,}){3}\\M} 
    } 
    if { ! [regexp {192\\.[0-9]{1,3}\\.{2}[0-9]{1,3}} $expect_out(0,string)]} { 
     send -h "[COMMAND B]\\r" ; 
    } 

О, и вы также должны \\r (как описано выше) на протяжении всего сценария вместо \r.


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

При упаковке всего обратно вместе может понадобиться bash's printf %q. Это будет генерировать что-то трудно читать, но это упаковка операция после того, как все ...


А по отношению к кодам ошибок? Проблема там проще; сам тест - [[ $? -eq 0 ]] - устанавливает код ошибки. Вы должны сохранить его в правильной переменной, а затем проверить на это.

Здесь, проверить эти сводились случаи:

bash-3.2$ (exit 2); if [[ $? -eq 0 ]]; then echo ok; elif [[ $? -eq 2 ]]; then echo good; else echo bad; fi 
bad 
bash-3.2$ (exit 2); echo $?; if [[ $? -eq 0 ]]; then echo ok; elif [[ $? -eq 2 ]]; then echo good; else echo bad; fi 
2 
ok 
bash-3.2$ (exit 2); code=$?; echo $code; if [[ $code -eq 0 ]]; then echo ok; elif [[ $code -eq 2 ]]; then echo good; else echo bad; fi 
2 
good 

Первый из них примерно то, что вы делаете прямо сейчас, вторая показывает, насколько неочевидными он может получить - промежуточный echo изменяет результат - и третий показывает, как с этим справиться (хранение значения в code здесь, но название на самом деле не все, что особенное).

+0

Полезно, хотя, к сожалению, я все еще вижу проблему, при которой код выхода 3 не попадает. –

+0

@ дядя-junky Hah; там есть классическая проблема. Вы все еще нуждаетесь в других проблемах ... –

+0

А, я вижу. Я удивлен, что моя книга Oreilly «Shell Scripting» не включает это ... Спасибо, я буду проверять. –