Вопрос или проблема
Я использую bash-скрипт для входа на telnet-сервер и выполнения нескольких команд. Он выглядит так:
login_and_run.sh
#!/bin/bash
unset TELNET_USER_NAME_STRING
unset TELNET_PASSWORD_STRING
unset TELNET_USER_NAME
unset TELNET_PASSWORD
TELNET_USER_NAME_STRING=`cat SAP_output`
TELNET_PASSWORD_STRING="Пароль:"
TELNET_USER_NAME="UserNam3\r"
TELNET_PASSWORD="Passw0rd\r"
# Ожидание начинается здесь
expect <<- DONE
spawn telnet localhost 50008
expect '$TELNET_USER_NAME_STRING'
send "$TELNET_USER_NAME"
sleep 3
expect "$TELNET_PASSWORD_STRING"
send "$TELNET_PASSWORD"
sleep 3
spawn ls
expect eof
DONE
где
SAP_output:
Попытка ::1...
Попытка 127.0.0.1...
Соединено с localhost.
Символ выхода - '^]'.
***********************************************
**********************************************
****###*******####*****#######**************
**##***##****##**##****##****##************
***##*******##****##***##****##**********
*****##*****########***######***********
******##****##****##***##*************
**##***##**##******##**##************
****###****##******##**##**********
**********************************
********************************
Администрирование Telnet
SAP Java EE Application Server v7.50
Имя пользователя:
telnet входит, я получаю баннер, но на этом все останавливается (похоже, что строки не совпадают). Будет ли безопаснее использовать подстановочные знаки вместо точного ответа (и сопоставлять только ” Имя пользователя: “)?
Разобрался:
TELNET_USER_NAME_STRING='*имя:*'
TELNET_PASSWORD_STRING='*пароль:*'
TELNET_USER_NAME='UserNam3\r'
TELNET_PASSWORD='Passw0rd\r'
# Ожидание начинается здесь
expect <<- DONE
spawn telnet localhost 50008
expect '$TELNET_USER_NAME_STRING'
send "$TELNET_USER_NAME"
expect '$TELNET_PASSWORD_STRING'
send "$TELNET_PASSWORD"
# Проверить, вошли ли мы
expect eof
DONE
Используйте подстановочные знаки вместо полного баннера и замените символ новой строки ‘\r’ на ‘нажать’ enter.
Правка:
Это гораздо более элегантный ответ.
Ответ или решение
Ваша проблема с несовпадением строки ответа сервера, связанная с использованием скрипта на Bash и Expect для автоматизации процесса входа на сервер Telnet, решена правильно, и давайте подробнее рассмотрим, как вы подошли к решению и какие обучающие моменты можно выделить.
Проблема
Ваш начальный скрипт пытался ожидать точного совпадения строки, выводимой Telnet-сервером, что, в большинстве случаев, может быть ненадежным, особенно когда вывод может содержать различные изменения (например, в зависимости от версии сервера или конфигурации). Для этого вы использовали:
expect '$TELNET_USER_NAME_STRING'
Однако из-за того, что вывод сервера может варьироваться, точное совпадение строк часто оказывается сложной задачей.
Решение
Вы предложили использовать подстановочные символы *
, чтобы делать ожидания более гибкими и надежными. Изменение включает использование:
TELNET_USER_NAME_STRING='*name:*'
Таким образом, вместо того чтобы ожидать точное совпадение всей строки, вы теперь просто ожидаете, что в выводе будет содержаться подстрока, которая соответствует шаблону, что значительно снижает вероятность ошибок из-за несовпадения.
Рекомендации по улучшению скрипта
-
Избегайте использования
sleep
:
Вместо того, чтобы использовать командыsleep
, которые могут вызывать неопределенности и замедлять выполнение скрипта, лучше использоватьexpect
для более точного ожидания ответов сервера. Это обеспечит большую гибкость и надежность. -
Улучшение читаемости кода:
Вы можете добавить комментарии к критическим частям скрипта, чтобы улучшить его читаемость и понимание, что именно вы ожидаете от каждой строки. -
Логирование:
Добавьте функции логирования, чтобы отслеживать хода выполнения скрипта. Это поможет в диагностике ошибок и улучшении вашего مستقبلного кода. -
Безопасность паролей:
Избегайте жесткой кодировки паролей в скриптах. Более безопасным подходом может быть использование переменных окружения или файлов конфигурации, доступ к которым ограничен.
Пример улучшенного скрипта
Вот пример улучшенного скрипта с учетом вышеизложенного:
#!/bin/bash
unset TELNET_USER_NAME_STRING
unset TELNET_PASSWORD_STRING
unset TELNET_USER_NAME
unset TELNET_PASSWORD
TELNET_USER_NAME_STRING='*name:*'
TELNET_PASSWORD_STRING='*assword:*'
TELNET_USER_NAME='UserNam3\r'
TELNET_PASSWORD='Passw0rd\r'
# Начало скрипта Expect
expect <<- DONE
spawn telnet localhost 50008
expect "$TELNET_USER_NAME_STRING"
send "$TELNET_USER_NAME"
expect "$TELNET_PASSWORD_STRING"
send "$TELNET_PASSWORD"
expect eof
DONE
Заключение
Использование подстановочных символов вместо точных совпадений – это отличная практика, которая позволяет сделать скрипт более устойчивым к изменениям в выводе Telnet-сервера. Также стоит обратить внимание на другие аспекты, такие как безопасность и читаемость кода, что в конечном итоге приведет к созданию более надежных и безопасных сценариев автоматизации.