Код состояния выхода для скрипта Expect, вызванного из Bash

Я сделал сценарий 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 вернет ненулевое значение, если вход в систему будет неудачным из-за неправильного пароля в сценарии ожидания, но это не сработало. Любые предложения будут высоко ценится.


person Sharjeel    schedule 19.08.2009    source источник


Ответы (5)


Для проверки ошибок в сценарии ожидания есть достойный пример по адресу 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
person glenn jackman    schedule 20.08.2009

Вам следует серьезно взглянуть на Fabric.

person iElectric    schedule 19.08.2009
comment
Честно говоря, я бы не решился переходить на что-то кроме Expect. В течение многих лет Expect был одним из лучших инструментов для автоматизации системных задач, которые не должны быть автоматизированы. Он делает ряд вещей, с которыми другие подобные инструменты действительно не могут сравниться (например, его способность почти идеально имитировать tty/user). Это не значит, что Fabric не очень хорош, поскольку я ничего о нем не знаю... Просто у Expect есть очень большие башмаки, которые нужно заполнить. - person RHSeeger; 21.08.2009
comment
Я предлагал это только потому, что Fabric как раз и создан для таких задач. Никакого вреда! - person iElectric; 25.08.2009

Секция:

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

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

    expect  {
        "assword:" {
            send "$SPASS\r"
            exp_continue
        }
        -re "$prompt"
    }
person Donal Fellows    schedule 02.10.2010

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

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

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

person Douglas Leeder    schedule 21.07.2010

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

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

Статус выхода — это статус 0 для истинного и 1 или любой другой для ложного

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

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

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

person Community    schedule 20.08.2009
comment
Если вы читали мой вопрос, я сказал, что уже пробовал это ($?), но это не сработало. - person Sharjeel; 20.08.2009