expect: отправить письмо с помощью telnet

Март 6, 2012 at 11:22 4 комментария

Люблю писать bash-скрипты, хлебом не корми. Но иногда этого мало для полноценной автоматизации.
Простой пример: есть некий хост, который необходимо время от времени проверять на доступность. Если вдруг он перестал отвечать, надо послать alarm администратору. Например, на электронную почту. В локальной сети есть MTA (exim, postfix, sendmail etc), и ему надо как-то втюхать свое письмо.
Но для этого необходимо организовать с ним диалог. Для эмуляции диалога как раз и нужен пакет expect. Он основан на Tcl, так что это тоже понадобится в системе.
Expect по сути состоит из условия expect (строка, ожидающаяся от опрашиваемого процесса) и ответа, который отсылается директивой send. Чтобы понять, как построить скрипт, надо сначала все попробовать в консоли.
Для отправки письма это должно быть как-то так:

jimmi@kakabba:~$ telnet 192.168.11.68 25
Trying 192.168.11.68...
Connected to 192.168.11.68.
Escape character is '^]'.
220 internal.example.com ESMTP Postfix
helo example.com
250 internal.example.com
mail from:<sysadmin@example.com>
250 2.1.0 Ok
rcpt to:<sysadmin@example.com>
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
Subject:ALARM!
Device is unreachable                 
.
250 2.0.0 Ok: queued as 023B9CDAF
quit
221 2.0.0 Bye

Теперь мы знаем, что отвечает почтарь на наши запросы. И можно смело строить скрипт для expect.

#!/usr/bin/expect -f   #внимательно! оболочка не bash
set mail_server "192.168.11.68"       #адрес почтового сервера, с кем диалогизируем                                                                                                                                              
set helo_response "helo example.com"     #приветствуем его                                                                                                                                             
set mail_from "mail from:<sysadmin@example.com>"     #от кого будет письмо                                                                                                                                 
set rcpt_to "rcpt to:<sysadmin@example.com>"       #кому письмо                                                                                                                                   
set subj "ALARM!"                         #тема и далее тело письма                                                                                                                                      
set message_body "Alarm! is disconnected"                                                                                                                                       
                                                                                                                                                                                    
spawn telnet $mail_server 25                  #запускаем процесс, с которым будем общаться                                                                                                                                      
expect "220 internal.example.com ESMTP Postfix" {send "$ehlo_response\r"}    #после ответа процесса, задвигаем туда наши заготовленные ответы с переводом каретки в конце                                                                                                         
expect "250 internal.example.com" {send "$mail_from\r"}                                                                                                                               
expect "250 2.1.0 Ok" {send "$rcpt_to\r"}                                                                                                                                           
expect "250 2.1.5 Ok" {send "data\r"}                                                                                                                                               
expect -re "354(.*)" {         #expect позволяет использовать регэкспы, что удобно, когда ответ процесса может быть немного разный                                                                                                                                                     
send "Subject: $subj\n\n$message_body\r\n.\r"                                                                                                                                   
}                                                                                                                                                                                   
expect -re "250(.*)" {                                                                                                                                                              
send "quit\r"         #безусловное до свидания, чтобы завершить процесс                                                                                                                                                              
}      

Можно запускать это дело как обычный скрипт отдельно. А можно использовать в другом скрипте:

#!/bin/bash
host_access=`ping -c1 $1 | grep 'received' | awk -F',' '{ print $2}' | awk '{ print $1}'` #в качестве параметра в скрипт передается адрес тестируемого хоста. если количество полученных пакетов от ping = 0, то хост недоступен
if [ $host_access == 0 ];
then
  echo "Unreachable"
  ./telnet_mail #адрес скрипта с expect, который пошлет alarm
else
  echo "Connected"
Реклама

Entry filed under: Linux. Tags: , , , , .

dokuwiki: acl (управление доступом) amavis:whitelist моего домена не работает

4 комментария Add your own

  • 1. Анатолий  |  Декабрь 15, 2013 в 13:47

    Как быть c expect если сервер имеет динамический таймстамп типа — ESMTP Exim 4.70 Sun, 15 Dec 2013 12:46:09 +0200
    Помогите плз.

    Ответить
    • 2. kakabba  |  Декабрь 15, 2013 в 20:49

      Я давно этой штукой не занималась, но кажется, там можно использовать регулярные выражение с ключом -re.
      То есть, если я правильно поняла, вы не можете однозначно написать в скрипте предполагаемый ответ сервера. Тогда вместо expect «220 internal.example.com ESMTP Postfix», придется писать что-то в стиле expect -re «ESMTP Exim 4\.70(.*)\n». Конечно, вместо (.*) наверно надо бы описать формат даты.

      Ответить
  • 3. Анатолий  |  Декабрь 15, 2013 в 21:32

    В регулярных выражениях как и в юникс в целом я не очень силён. Я так понимаю запрос должен быть в виде expect -re «220 my.mail.server ESMTP Exim 4\.70(date ‘+%c %z’)\n» {send «$helo_response\r»} ?
    Еще я заметил таймаут около 3 секунд, после приветствия (helo), тоесть ошибка в 2 секунды и expect уже будет с неправильным временем … тоесть дальше не продолжит работу цепочка команд скрипта.

    Ещё как я могу увидеть ход выполнения скрипта. Есть ли возможность отображать ход его исполнения или логировать в файл?

    Заранее спасибо за ответ.

    Ответить
    • 4. kakabba  |  Декабрь 15, 2013 в 21:53

      Я думаю, что можно не морочиться с точностью даты. Нужно просто описать ответ в стиле(пишу, не проверяя, так что может быть двоеточия или еще что-то экранировать): то есть «ESMTP Exim 4\.70 Sun, [0-9]{2} [A-Z][a-z]{3} [0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]:[0-9]{2} \+[0-9]{4}\n». Кажется, это описывает то, что надо.
      Логирование есть, вообще ничего не помню, как настраивать.
      Чуть-чуть гугления дало ответ:
      В начало скрипта добавить строчку
      set ::logfile [open c:/test/log.txt a]:
      там, где хочется логировать:
      puts $::logfile «String I want to log»
      в конец скрипта добавить:
      close $::logfile

      Я сама, кажется, не пробовала(или благополучно забыла), так что отпишитесь, если что-то получится.

      Ответить

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

Trackback this post  |  Subscribe to the comments via RSS Feed



%d такие блоггеры, как: