Вопрос или проблема
Ниже представлен образец скрипта, который мы выполняем ежедневно для получения информации с сервера. В последние несколько дней некоторые данные сервера отсутствуют в выходных данных, которые сохраняются в локальном файле VS-HV-Report_2017.txt
.
Возможно ли получить статус ошибки при выполнении скрипта, если он не может подключиться к серверу? Чтобы у нас была черная строка или статус ошибки вместо выходных данных?
#!/usr/bin/expect
set timeout 5
#find /path/to/files -type f -mtime +10 -delete
set date [exec date "+%d-%B-%Y"]
spawn sh -c "yes | cp -ifr .ssh/VS-HV-config .ssh/config"
spawn sh -c "> VS-HV-Report_2017.txt"
#cat ./info.py
spawn sh -c "ssh L1n \"./info.py | sed 's/total.*//g'\" >> VS-HV-Report_2017.txt"
expect "Enter passphrase for key '/root/.ssh/id_rsa':"
send "passwd\r"
spawn sh -c "ssh L2n \"./info.py | sed 's/total.*//g'\" >> VS-HV-Report_2017.txt"
expect "Enter passphrase for key '/root/.ssh/id_rsa':"
send "passwd\r"
spawn sh -c "ssh L3n \"./info.py | sed 's/total.*//g'\" >> VS-HV-Report_2017.txt"
expect "Enter passphrase for key '/root/.ssh/id_rsa':"
send "passwd\r"
set timeout 5
#spawn sh -c "./format-VS-HV.sh > format-allinement-output.csv"
#spawn sh -c \"./format-VS-HV.sh\" > format-allinement-output.csv
exec ./format-VS-HV.sh > /root/format-allinement-output/format-allinement-output-$date.csv
Ваш код представляет собой любопытную смесь TCL и оболочки и, вероятно, должен быть написан только на одном из них. С TCL он мог бы выглядеть примерно так:
#!/usr/bin/expect
set timeout 5
# TCL имеет функции времени, нет необходимости вызывать `date`...
set epoch [clock seconds]
set outfile "VS-HV-Report_[clock format $epoch -format "%Y"].txt"
set date [clock format $epoch -format "%d-%B-%Y"]
# "yes | cp -i ..." очень странно; зачем интерактивный флаг, а затем
# игнорировать его с помощью "yes |" из неинтерактивного кода?
#spawn sh -c "yes | cp -ifr .ssh/VS-HV-config .ssh/config"
exec cp -f .ssh/VS-HV-config .ssh/config
# TCL может выполнять I/O, давайте используем это вместо разветвления процессов sh...
#spawn sh -c "> VS-HV-Report_2017.txt"
set outfh [open $outfile w+]
# и цикл TCL вместо дублирования кода запуска для хоста...
set hostlist {L1n L2n L3n}
foreach host $hostlist {
set done_auth 0
# Запуск sh для запуска ssh довольно сложен; давайте просто
# вызовем ssh напрямую (и поймаем любые ошибки...)
#spawn sh -c "ssh L1n \"./info.py | sed 's/total.*//g'\" >> VS-HV-Report_2017.txt"
if { [catch {spawn ssh $host {./info.py | sed 's/total.*//g'}} msg] } {
puts $outfh "SSHFAIL $host $msg"
continue
}
while 1 {
expect {
-re {Enter passphrase for key '[^']+': } {
# поскольку в цикле (потому что EOF или таймаут могут произойти
# в любом месте) нужно аутентифицироваться только один раз в том случае, если удаленная
# сторона не ведет себя хорошо
if {$done_auth == 0} {
send "hasapass\r"
set done_auth 1
}
}
# помните ли вы о таймауте? для него есть хук.
timeout {
puts $outfh "TIMEOUT $host $timeout"
break
}
# выведите любые "данные сервера", возвращенные в выходной
# файл (match_max может быть актуален при чтении, если есть
# много данных) когда соединение закрывается
eof {
puts $outfh $expect_out(buffer)
break
}
}
}
}
close $outfh
exec ./format-VS-HV.sh > /root/format-allinement-output/format-allinement-output-$date.csv
Ответ или решение
В качестве эксперта в области информационных технологий, я хотел бы обсудить, как можно обрабатывать ошибки и получать статус выполнения при использовании скриптов на языке Expect, особенно в ситуациях, когда необходимо иметь возможность установить, выполнена ли команда подключения к серверу успешно. Рассмотрим модификацию вашего скрипта, чтобы обеспечить обработку ошибок в случае недоступности сервера.
Задача
В вашем оригинальном скрипте используется команда spawn
для подключения к нескольким серверам и выполнения скрипта info.py
. Однако в случае, если соединение с сервером не удается установить, необходимо добавить функционал для записи ошибки в выходной файл и отображения информации о неудачном подключении.
Обработка ошибок
Для полноценной обработки ошибок, мы можем использовать конструкцию catch
в языке Expect, чтобы отловить ошибки во время выполнения команд и затем записать информацию об этом в выходной файл. Ниже представлена доработанная версия вашего скрипта:
#!/usr/bin/expect
set timeout 5
set epoch [clock seconds]
set outfile "VS-HV-Report_[clock format $epoch -format "%Y"].txt"
set date [clock format $epoch -format "%d-%B-%Y"]
set outfh [open $outfile w+]
# Список хостов
set hostlist {L1n L2n L3n}
foreach host $hostlist {
set done_auth 0
# Используем catch для отлова ошибок при подключении к серверу
if { [catch {spawn ssh $host "./info.py | sed 's/total.*//g'"} msg] } {
puts $outfh "SSH_FAIL: Не удалось подключиться к $host - $msg"
continue ; # переходим к следующему хосту
}
# Цикл ожидания для обработки авторизации и вывода
while 1 {
expect {
-re {Enter passphrase for key '[^']+':} {
if { $done_auth == 0 } {
send "passwd\r" ; # Замените "passwd" на ваш пароль
set done_auth 1
}
}
timeout {
puts $outfh "TIMEOUT: Не удалось подключиться к $host"
break;
}
eof {
puts $outfh $expect_out(buffer) ; # Записываем вывод
break;
}
}
}
}
close $outfh
# Форматируем вывод
exec ./format-VS-HV.sh > /root/format-allinement-output/format-allinement-output-$date.csv
Пояснения
-
Использование
catch
: Это позволяет нам отследить ошибки, если командаspawn ssh
не смогла подключиться к серверу. В случае ошибки мы записываем соответствующее сообщение в выходной файл. -
Проверка состояния соединения: Обработка различных событий, таких как
timeout
иeof
, помогает гарантировать, что мы всегда получаем вывод или информацию об ошибке. -
Обработка паролей: Не забудьте заменить
"passwd"
на правильный пароль, если используется автоматизация ввода пароля. Убедитесь, что использование паролей сохраняет безопасность ваших данных. -
Форматирование даты: Дата формируется на основе текущего времени, что упрощает ведение журналов и делает ваши отчеты более организованными.
Заключение
Используя предложенные правки, ваш скрипт сможет надежно обрабатывать ошибки подключения к серверам, записывая соответствующую информацию в выходной файл. Такой подход не только улучшает читаемость кода, но и повышает его устойчивость. Если вам требуется больше деталей относительно отдельных аспектов работы скрипта, пожалуйста, дайте знать, и я с удовольствием помогу.