Код состояния выхода для сценария Expect, вызванного из Bash - PullRequest
2 голосов
/ 19 августа 2009

Я создал Bash-скрипт, который использует ожидаемый скрипт для автоматизации входа в ssh. Скрипт подключается к нескольким серверам и запускает некоторые команды. Сценарий bash запрашивает учетные данные для входа один раз.

Я хочу включить функцию, в которой сценарий завершается, если не удается войти в систему для первого сервера, чтобы избежать проверки сценария для следующих серверов, что приводит к блокировке учетной записи пользователя. Блокировка учетной записи происходит в течение 3 последовательных сбоев входа в систему, и число серверов, к которым пытается подключиться скрипт, превышает 3.

Это фрагмент скрипта bash, который вызывает ожидаемый скрипт.

countu=0
for servername in $(cat $linux_host_list)
do
./script.expect $LUSERNAME $LPASS $servername Linux >> linux_log_file.txt & < /dev/null
let countl=countl+1
done

и вот фрагмент ожидаемого сценария (script.expect)

#!/usr/bin/expect -f
set timeout 30
set username [lindex $argv 0]
set SPASS [lindex $argv 1]
set servername [lindex $argv 2]
set case [lindex $argv 3]
set prompt "(%|#|\\$|%\]) $"
switch $case {
    Linux {
        log_user 0
        spawn ssh -o StrictHostKeyChecking=no $username@$servername
        expect  {
            "assword:" {
                send "$SPASS\r"
                expect -re "$prompt"
            }
            expect -re "$prompt"
        }
        send "sudo su -\r"
        expect {
            "assword:" { send "$SPASS\r" }
        }
        expect -re "$prompt"
        log_user 1
        send "opcagt -status ; opctemplate -l ; cat watch.cf 2> /dev/null\r"
        expect -re "$prompt"
        log_user 0
        send "exit\r"
        expect -re "$prompt"
        log_user 1
    }

Я попытался получить выходные данные команды bash ($?), предполагая, что команда bash вернет ненулевое значение, если произойдет сбой входа в систему из-за неверного пароля в ожидаемом сценарии, но это не сработало. Любые предложения будут высоко оценены.

Ответы [ 5 ]

2 голосов
/ 20 августа 2009

Для проверки ошибок в ожидаемом скрипте есть хороший пример на http://systeminetwork.com/article/handle-errors-expect-scripts

Что вы должны сделать, это что-то вроде этого:

proc do_exit {msg} {
    puts stderr $msg
    exit 1
}

switch -exact -- $case {
    Linux {
        spawn ssh ...
        expect {
            -re {assword: $} {
                send -- "$SPASS\r"
                exp_continue 
                # remain in this expect block and look for the next matching pattern
            }
            "some message about incorrect password" {
                do_exit "incorrect password"
            }
            timeout {do_exit "timed out waiting for prompt"}
            default {do_exit "something else happened"}
            -re $prompt
        }
        # ... rest of your script
    }
}

Полагаю, вам не нужно знать о состоянии завершения серии команд "opcagt ..." (вы просто хотите просмотреть содержимое файла watch.cf. нужно получить оболочку, чтобы сказать вам:

send -- "opcagt -status 2>&1 || echo "non-zero return from opcagt: $?"
expect {
    "non-zero return" { handle error and exit? }
    -re $prompt
}
# ... continue
1 голос
/ 03 октября 2010

Раздел:

    expect  {
        "assword:" {
            send "$SPASS\r"
            expect -re "$prompt"
        }
        expect -re "$prompt"
    }

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

    expect  {
        "assword:" {
            send "$SPASS\r"
            exp_continue
        }
        -re "$prompt"
    }
1 голос
/ 19 августа 2009

Вы должны серьезно взглянуть на Ткань .

0 голосов
/ 21 июля 2010

Вы запускаете ожидаемые сценарии в фоновом режиме (&), поэтому вы не можете получить результаты первого, прежде чем продолжить.

Как написан ваш ожидаемый скрипт, он получит 30-секундный тайм-аут во втором запросе пароля, если первый пароль окажется неудачным. Вместо этого вы могли бы сделать альтернативу expect, чтобы увидеть, получаете ли вы еще одно приглашение assword и немедленно завершить работу.

Затем измените сценарий оболочки, чтобы не помещать ожидаемые вызовы в фоновом режиме, вместо этого перехватите вывод с помощью $? и протестируйте его.

0 голосов
/ 20 августа 2009

Я не сильно разбираюсь в написании сценариев и все такое, поэтому я не могу написать точные шаги или сценарий, чтобы доказать, что я имел в виду - любезно извините

Ну, я читал, что в bash предусмотрена вещь, называемая выходом

Состояние выхода - это состояние 0 для истины и 1 или чего-либо еще для ложных

Это можно увидеть, выполнив команду, а затем проверив ее состояние выхода, набрав «echo $?»

То, что я предлагаю, - это когда вы пытаетесь подключиться по ssh к одному серверу, и аутентификация не проходит, должен быть статус выхода чего-то отличного от 0

Получение здесь цикла if-then-else и проверка состояния на 0 для выполнения скрипта и любого другого значения для полного выхода из скрипта с подходящим сообщением об ошибке

...