Планировщик
Время действия
Большей частью Eserv занят непосредственным выполнением запросов подключившихся к нему клиентов — то ли это приём почты от почтовой программы или сервера по протоколу SMTP, то ли доставка файла с далёкого web-сервера. Однако у хорошего сервера всегда найдётся достаточно дел, которые следует выполнять "за кадром", в свободное от обработки запросов время — чтобы в нужный момент представить пользователю уже готовый результат. К таким делам относятся опрос внешних почтовых ящиков POP3, окончательная отправка почты во "внешний мир", взаимодействие с серверами новостей. Если используется встроенная антивирусная проверка, необходимо достаточно регулярно побуждать антивирус к перезагрузке вирусной базы. Несколько реже, но тоже достаточно регулярно, требуется удалять с диска устаревшие рабочие файлы, файлы журналов, давно не используемые файлы из кэша HTTP-прокси. Далее, как говорится, везде…Разумеется, все эти задачи можно возложить и на системный планировщик (или на любой из множества доступных аналогов UNIX-утилиты CRON, выполняющей аналогичные функции), однако особенности почтовых и новостных заданий (для которых требуется генерация уникальных имён файлов) потянули за собой именно встроенный планировщик. К тому же, раз "всё в одном флаконе", то отдавать столь существенную часть работы "на сторону" просто неприлично.
Настройки Планировщика
Единственным параметром настройки Планировщика является список заданий. Планировщик примерно раз в минуту просматривает этот список в поисках заданий, которые необходимо выполнить именно в этот конкретный момент. Найденные задания активизируются. Их результатом может быть запуск внешних приложений — такие задания выполняются параллельно с Eserv и не отнимают у Планировщика много времени — либо выполнение каких-либо внутренних команд Eserv — такие задания теоретически могут задержать работу Планировщика весьма надолго, из-за чего часть заданий может быть просто не выполнена.Если в процессе анализа или выполнения задания Планировщик обнаруживает ошибку, он прекращает просмотр списка — некоторые задания могут быть пропущены и по этой причине.
Каждое перечисленное в списке задание описывается с помощью следующего набора свойств.
Имя задания
Речь идёт об имени описывающего задание объекта. Имена должны быть уникальны — во-первых, потому, что так проще отслеживать в журнале запуски заданий, а во-вторых — потому, что любое задание можно в любое время активизировать вручную, использовав web-интерфейс (разумеется, для этого придётся написать свою HTML-страницу или отредактировать имеющуюся в каталоге wwwroot\dial страницу poll.html, изначально предназначенную для запуска настроенных по умолчанию почтовых заданий), а для этого необходимо указать имя задания.
Активно
Если этот флажок выставлен, задание может быть выполнено автоматически. Если флажок не выставлен, то задание может быть запущено только вручную. Манипулируя этой настройкой, можно временно отключить ненужное задание, не удаляя его насовсем.
Режим
^^^^Режим и ниже описанный План являются взаимозависимыми параметрами — формат записи параметра План зависит от выбранного режима выполнения задания. Режим может быть следующим:
#||
||Каждый час|Задание выполняется ежечасно в указанную в Плане минуту;||
||Ежедневно|Задание выполняется ежедневно, при этом План определяет час и минуту выполнения;||
||Ежемесячно|Задание выполняется раз в месяц, а План определяет число, час и минуту выполнения. Естественно, если задать 31 число, то задание выполнится не в каждый месяц;||
||С интервалом|Наиболее удобный режим для запуска почтовых заданий. Задания запускаются через заданный Планом интервал — точнее, в моменты времени, кратные интервалу;||
||По расписанию|Усложнённая разновидность режима Ежедневно — в этом случае в Плане можно задать несколько моментов времени для запуска задания;||
||Правило|В этом режиме момент запуска задания заранее не определён — задание активизируется, если выполняется записанное в План условие. Это условие составляется из специальных "волшебных слов" — некоторые наиболее употребительные из них приведены ниже;||
||Почтовый робот|Этот режим упоминается в главе, посвящённой Почтовому серверу. В этом режиме задание запускается при помещении письма в почтовый ящик пользователя, имеющего то же имя, что и задание;||
||Событие|Информация об этом режиме отсутствует.||
||#
План
^^^^План в сочетании с параметром Режим определяет конкретные моменты запуска заданий. Для разных режимов используются различные форматы записи:
#||
||Каждый час|Одна или две цифры, определяющие конкретную минуту часа — например: 5;||
||Ежедневно|Используется формат ЧЧ:ММ (час:минута) — например: 3:20;||
||Ежемесячно|Используется формат ДД.ЧЧ:ММ (число.час:минута) — например: 15.3:20;||
||С интервалом|Используется формат ЧЧ:ММ (час:минута), но задаётся не момент времени, а интервал между запусками заданий. Если совсем точно — задание запускается в моменты времени, кратные указанному интервалу. Например, если интервал составляет 1:10, то задание будет запущено в 0:00, 1:10, 2:20, 3:30, 4:40, 5:50, 7:00 и так далее;||
||По расписанию|Серия значений в формате ЧЧ:ММ (час:минута) через пробел — например: 3:15 16:20 21:0;||
||Правило|Условие, составленное из специальных "волшебных слов". Подробнее настройка правил будет рассмотрена ниже;||
||Почтовый робот|Для этого режима план не имеет смысла. Во избежание неприятностей рекомендуется записать какое-либо безопасное значение, например, 18:00;||
||Событие|Информация об этом режиме отсутствует.||
||#
КоманднаяСтрока
Командная строка задаёт выполняемые действия. Это может быть запуск различных внешних приложений, возможно, сразу нескольких, или выполнение каких-то внутренних функций Eserv. Более подробно правила составления командной строки описаны чуть ниже.
Сервер
Если в командной строке задания требуется указать имя или IP-адрес сервера (таковы, например, задания на приём-отправку почты и новостей), необходимое значение можно задать с помощью этого параметра, а в командной строке в соответствующем месте просто сослаться на него с помощью макропеременной %Server%. Такой подход позволяет легко клонировать задания — командная строка при этом остаётся неизменной.
Имя
Если в командной строке задания требуется указать имя пользователя (таковы, например, задания на приём почты и новостей, иногда указание имени пользователя требуется и для отправки почты), необходимое значение можно задать с помощью этого параметра, а в командной строке в соответствующем месте просто сослаться на него с помощью макропеременной %Login%. Такой подход позволяет легко клонировать задания — командная строка при этом остаётся неизменной.
Пароль
Если в командной строке задания требуется указать пароль пользователя (таковы, например, задания на приём почты и новостей, иногда указание имени пользователя требуется и для отправки почты), необходимое значение можно задать с помощью этого параметра, а в командной строке в соответствующем месте просто сослаться на него с помощью макропеременной %Password%. Такой подход позволяет легко клонировать задания — командная строка при этом остаётся неизменной. К тому же при этом несколько повышается защищённость настроек, поскольку параметр хранится в зашифрованном виде.
Командная строка
Командная строка задаёт выполняемые действия. Это может быть запуск различных внешних приложений, возможно, сразу нескольких, или выполнение каких-то внутренних функций Eserv.
В первом случае записывается почти обычная командная строка запуска приложения. Типичный пример — запуск задания очистки каталога временных файлов Eserv:
agents\purger.exe -rd 40 temp\*.*
Обратите внимание, что при запуске заданий текущим является каталог запуска самого Eserv, поэтому путь к файлам приложений можно задавать и относительным. Доступны также определённые к моменту запуска Eserv пути поиска, задаваемые системной переменной окружения PATH.
Если необходимо одним заданием запустить несколько приложений, их командные строки разделяются символом амперсанда & — как это сделано в стандартном задании POP3RECV, где запускаются почтовые агенты pop3recv.exe и Erobot.exe (приведённый ниже фрагмент представляет собой одну длинную строку):
agents\pop3recv.exe -d -o temp\%~TempFile%.eml -s %Server% -u %Login% -w %Password% &agents\Erobot.exe -c agents\pop3toss.cfg -o temp\%~TempFile%.toss -i temp\%~PrevTempFile%.eml
Правда, необходимо учитывать, что приложения в этом случае выполняются не последовательно друг за другом, а параллельно — командная строка определяет только то, что приложение pop3recv.exe будет запущено несколько раньше, чем erobot.exe. Если нужна строго последовательная работа приложений, командные строки их вызова придётся перенести в командный файл, а задание настроить на запуск командного файла. Тут следует обратить особое внимание на ещё два важных момента. Во-первых, действительно ли такой режим возможен — приложения оконного типа и даже некоторые консольные (то есть, работающие с командной строкой и вроде бы ориентированные на использование в командных файлах) устроены так, что возвращают управление командному файлу немедленно после запуска и далее работают самостоятельно. Во-вторых, командный файл не является исполняемым в прямом смысле слова — это набор инструкций для командного процессора, который и надлежит запускать в этом случае:
command.com /c file.bat
Это пример запуска командного файла при работе в среде Windows 95, 98 или ME. Если используется Windows NT, 2000 или XP, то запускать следует другой командный процессор, специально ориентированный на особенности используемой системы:
cmd.exe /c file.bat
Командный файл полезен и в том случае, когда командная строка получается слишком длинной. Дело в том, что существует ограничение на длину строки конфигурационного файла Eserv.ini — строки длиннее 256 символов приводят к ошибке загрузки. Поскольку задание со всеми параметрами записывается в одну строку, то собственно командная строка вряд ли может быть длиннее 200 символов. Если этого мало — выручит командный файл. Впрочем, с таким же успехом (и даже с некоторым выигрышем в быстродействии) можно организовать запуск нужных приложений с помощью модуля расширения Eserv, также называемого плагином или "штепселем" (как изначально и переводилось на русский язык иностранное plug-in).
Для вызова внутренних функций Eserv предусмотрено ключевое слово Internal:, после которого через пробел надлежит записать вызываемую функцию и её параметры, если таковые имеются. Не следует смешивать в одной строке запуск внешних приложений и вызов внутренних функций, а также вызывать более одной внутренней функции. При необходимости нужную последовательность вызовов можно оформить в модуль расширения и вызывать как единую внутреннюю функцию. Следующие функции могут быть вызваны из командной строки задания безо всяких ограничений:
#||
||CALL_DIAL|Увеличивает на единицу внутренний счётчик дозвона Eserv. Если при этом соединение не установлено, запускается дозвон.||
||CALL_HANGUP|Уменьшает на единицу внутренний счётчик дозвона Eserv. Если счётчик уменьшается до нуля, активное модемное соединение разрывается.||
||ESERV_HANGUP|Немедленно разрывает активное модемное соединение.||
||TurnOnConnection: имя|Включает флажок Активно в параметрах указанного модемного соединения.||
||TurnOffConnection: имя|Выключает флажок Активно в параметрах указанного модемного соединения. Состояние связи при этом не изменяется — если соединение было активным, оно продолжает использоваться до тех пор, пока не будет каким-либо образом разорвано.||
||AVreload_db|Инициирует перезагрузку баз активного антивируса.||
||MSGID-LIST 0!|Очищает список обработанных Тоссером писем. Имеет смысл при включённом контроле дубликатов писем. Подробнее об этом режиме можно прочитать в главе, посвящённой Почтовому серверу Eserv.||
||#
Для обеспечения должной функциональности в командной строке могут использоваться специальные макропараметры, вместо которых при обработке задания подставляются необходимые значения. В контексте Планировщика доступны следующие параметры:
#||
||%TempFile%|Генерирует уникальную строку символов, которую можно использовать для формирования уникального имени файла. Этот макропараметр изначально предназначен для использования в заданиях на получение и отправку почты и новостей.||
||%PrevTempFile%|Возвращает строку символов, сформированную предыдущим вызовом макроса %TempFile%. Этот макропараметр изначально предназначен для использования в заданиях на получение почты и новостей. Смысл его существования заключается в подстановке одной и той же строки в две различных позиции командной строки — сначала строка генерируется макросом %TempFile%, и на её основе формируется имя выходного файла специализированного агента, затем посредством макроса %PrevTempFile% эта же строка формирует точно такое же имя файла, но уже в качестве входного файла универсального агента Erobot. Пример правильного использования макроса можно посмотреть выше.||
||%Server%|Возвращает значение свойства Сервер.||
||%Login%|Возвращает значение свойства *Имя.||
||%Password%|Возвращает значение свойства Пароль.||
||%MailFileName%|Этот макропараметр имеет смысл для заданий типа Почтовый робот и возвращает путь к файлу обрабатываемого письма.||
||#
Типичная ошибка, которую обычно допускают при написании вызываемых в качестве заданий командных файлов, состоит в механическом переносе командных строк со всеми макропеременными из командной строки задания в файл. Между тем, макропараметры имеют смысл только в контексте Eserv, командный процессор системы воспримет такие записи как обращения к несуществующим переменным окружения, и результат будет весьма далёк от ожидаемого. Вызов макросов следует оставить в командной строке самого задания, а подставляемые значения передавать в командный файл в качестве параметров. Если преобразовывать по этим правилам приведённую выше строку задания на получение почты, то получится примерно следующее: cmd.exe /c runmail.bat %~TempFile% %Server% %Login% %Password%
Командный файл runmail.bat будет иметь следующий вид: agents\pop3recv.exe -d -o temp\%1.eml -s %2 -u %3 -w %4---agents\Erobot.exe -c agents\pop3toss.cfg -o temp\%1.toss -i temp\%1.eml
Обратите внимание — здесь нет нужды в применении макроса %PrevTempFile%, поскольку единожды сгенерированная макросом %TempFile% уникальная строка после передачи в командный файл может использоваться сколько угодно раз.
Запись правил
Программирование планировщика Eserv не представляет большой сложности, если принять в качестве объективной реальности тот стиль программирования, который диктует язык Форт — именно на нём целиком и полностью написан Eserv. Более подробно особенности языка рассмотрены в главе, посвящённой созданию модулей расширения (плагинов). Для размещения результатов вычислений Форт использует специальный стек. Форт-слова (так в этом языке называют операторы) извлекают необходимые им параметры из этого стека и помещают результат обратно в стек. Фактически это реализация так называемой польской обратной (или бесскобочной) записи — лет десять-пятнадцать назад подобный механизм встречался в некоторых особо продвинутых программируемых калькуляторах. В таких системах для сложения двух чисел требуется сначала ввести оба числа, а уже затем символ операции. Планировщик программируется по этому принципу.Условие запуска задания записывается в виде комбинации элементарных правил. Каждое правило на самом деле представляет собой вызов определённого в Eserv Форт-слова, помещающего в стек одно логическое значение:
#||
||ONLINE?|Истинно при наличии активного модемного соединения;||
||CheckOutMail|Истинно при наличии исходящей почты (в каталоге mail\out);||
||CheckOutNews|Истинно при наличии исходящих новостей (в каталоге news\out);||
||IntervalExp: чч:мм|Истинно, если показания системных часов кратны заданному интервалу времени. Например, если интервал составляет 1:10, то условие будет истинно в 0:00, 1:10, 2:20, 3:30, 4:40, 5:50, 7:00 и так далее;||
||Time: чч:мм|Истинно, если системные часы показывают заданное время;||
||DayOfWeek: н-к|Истинно, если день недели находится в заданных пределах
(0 — воскресенье, 6 — суббота);||
||TimeInterval: чч:мм-чч:мм|Истинно, если показания системных часов находятся в заданном интервале.||
||#
Результаты, возвращаемые правилами, комбинируются между собой с помощью трёх основных операторов булевой алгебры:
#||
||AND|логическое И||
||OR|логическое ИЛИ||
||0=|логическое НЕ||
||#
Операторы объединения (AND, OR) снимают со стека два значения и записывают в стек одно значение — полученный результат. Оператор отрицания "выворачивает наизнанку" последнее записанное в стек значение. Окончательный результат определяет, запустится задание или нет — задание запускается только в случае истинности результата.
Пример: задание необходимо запустить при наличии исходящей почты, при установленном модемном соединении и обязательно в ночное время — с 23:00 до 6:00. Для таких условий записывается следующее правило:
~TimeInterval: 23:00-24:00 ~TimeInterval: 00:00-06:00 OR ~CheckOutMail AND ONLINE? AND можно написать и так:
~CheckOutMail ONLINE? AND ~TimeInterval: 23:00-24:00 ~TimeInterval: 00:00-06:00 OR AND
Кажется, никто не проверял, как отреагирует Eserv, если ему указать полный интервал 23:00-06:00 — может, и правильно. Пример хорош тем, что демонстрирует управление порядком вычислений без использования скобок. А один умный человек предложил такой вариант:
~CheckOutMail ONLINE? AND ~TimeInterval: 06:00-23:00 0= AND что переводится на человеческий язык следующим образом: запустить при наличии исходящей почты, при установленном модемном соединении и не в период с 6:00 до 23:00.
Типичный пример: запуск задания раз в пятнадцать минут при наличии модемного соединения и раз в три часа при отсутствии оного. Это реализуется следующим правилом:
~IntervalExp: 00:15 ONLINE? AND ~IntervalExp: 03:00 ONLINE? 0= AND OR
На самом деле его можно упростить — на том основании, что три часа есть интервал, кратный пятнадцати минутам. Поэтому условие можно переформулировать так: раз в пятнадцать минут при наличии модемного соединения и раз в три часа безусловно. Получается такое правило:
~IntervalExp: 00:15 ONLINE? AND ~IntervalExp: 03:00 OR
При написании правил обратите особое внимание на правильность записи слов — Форт является регистрозависимым языком, и слово IntervalExp: (именно так, с двоеточием, оно тоже является неотъемлемой частью слова) не эквивалентно Intervalexp:. Второе слово, скорее всего, вообще не определено. К краху Eserv его появление в большинстве случаев не приведёт, но работа Планировщика будет нарушена, и это скажется на всех заданиях. Второй существенный момент: правило должно оставить на стеке ровно одно значение. Если по ошибке оставлено более одного значения или ни одного (бывает и так), это тоже приводит к сбоям в работе Планировщика, а в его журнале (это файл ммддSCH.log в подкаталоге log) появляются строчки, содержащие записи вида D:4 (число указывает, сколько лишних байт находится в стеке; одно значение соответствует 4 байтам; если число отрицательное, то со стека снято больше значений, чем в нём находилось) — при наличии таких строк ищите ошибки в записи правил.
Обратите внимание ещё раз — задание со всеми параметрами, включая План, записывается в конфигурационный файл Eserv.ini в виде одной строки, длина которой не должна превышать 256 символов. Если она получается слишком длинной, придётся писать собственные командные файлы или модули расширения.
Вернуться к содержанию