Cервер &CronSrv


  1. Назначение и краткое описание

  2. Какая польза от &CronSrv?

  3. Состав и конфигурирование

  4. Cron-задания, режимы, секции

  5. Cron-команды, утилиты, формат

  6. Cron-примеры скриптов

  7. "Защитник" CronGuard, или "Ванька-Встанька"

Пример CRON скрипта
[ConfigFileList]
ConfigFile = ~~\Resource\DaqSite\CronServer\CronSrv.cfg
[&CronSrv.StartupScript]
@cron.tab DailyMorning 0 8
@cron.job DailyMorning @Speak Good morning, it's 8:00.
@cron.tab DailyEvening 45-60/5 16 * * Mon-Thu
@cron.job DailyEvening @run -hide msg.exe * /time:5 "Go home. Have a nice evening."
@cron.tab EveryWeekend 45-60/3 15 * * Fri
@cron.job EveryWeekend @run -hide msg.exe * /time:5 "Go home. Have a nice weekend."
@Cron.tab DimDns *
@Cron.job DimDns @IfNotProcessExists dns.exe @Speak Run DNS.EXE, if one not running.
@Cron.job DimDns @IfNotProcessExists dns.exe @Run -hide CronDimDns.bat -d
@Cron.tab Defrag 0 12 * * Fri
@Cron.job Defrag @IfNotProcessExists defrag.exe @Speak Defragment disks every Friday 12:00.
@Cron.job Defrag @IfNotProcessExists defrag.exe @Run -hide CronDefrag.bat
[]

К началу

Назначение и краткое описание

Сервер &CronSrv предназначен для выполнения заданий "по расписанию" в составе измерительных систем пакета CRW-DAQ.
Название Cron взято от греческого Кронос - Κρόνος - бог Времени из древнегреческих мифов.

Довольно частой проблемой в практике автоматизации измерительных систем является необходимость выполнения тех или иных заданий (последовательности действий) по расписанию, например, периодических или по календарным событиям. Например, в ряде случаев требуется периодически (допустим, раз в неделю) запускать дефрагментацию дисков или резервное копирование файлов. Эта задача особенно актуальна для систем длительного круглосуточного действия, которые должны сами, без участия оператора, полностью обслуживать систему, например, архивировать файлы данных, чистить диски от старых файлов и так далее.

Для решения подобных задач можно, разумеется, использовать тот или иной планировщик (штатный Windows Scheduler, программу nnCron и т.д.). Однако это получается крайне неудобно, так как, во-первых, эти планировщики слабо связаны с основным измерительным пакетом и не синхронизованы с ним, а во-вторых, описание конфигурации "расползается" по разным местам, часто трудно доступным, вместо того, чтобы сосредоточиться в одном каталоге измерительной системы. Кроме того, задания &CronSrv исполняются с правами пользователя, под которым запущена и измерительная система (обычно этот пользователь имеет права администратора), поэтому не возникнет проблем с правами и учетными записями пользователя.

Сервер Cron позволит упорядочить и унифицировать описание таких задач и облегчить их сопровождение. Он позволяет описывать в едином формате момент наступления как периодических, так и уникальных (календарных) событий, а также организовывать запуск обработчиков событий, или, по принятой терминологии, заданий. Эти задания можно использовать также и для обработки асинхронных событий, которые вызываются из других программ как готовые подпрограммы с помощью механизма сообщений (DevMsg, DevSend, DevPost, DevSendMsg, DevPostMsg). Кроме того, сервер содержит большое число готовых к исполнению команд, которые можно вызывать как готовые подпрограммы для асинхронного вызова из других программ, также с помощью механизма сообщений. Например, вызов браузера для просмотра справочного файла можно выполнить так:
  if DevPostMsg('&CronSrv @Browse ..\Help\index.htm'+EOL)=0 then writeln('Не могу запустить Help!');
 

Сервер &CronSrv может работать в двух режимах - в календарном (время привязано к календарю) и в импульсном (генерируются периодические события). Эти режимы в совокупности закрывают огромное число задач, связанных с временем, планированием работы установки и организацией тех или иных циклов ее работы.

При использовании сервера &CronSrv не надо забывать, что он имеет ряд ограничений. В текущей версии размер задания - не более 16 kByte, а число заданий - не более 1024. Кроме того, сервер отслеживает наступление событий, только пока работает DAQ-система, поэтому при временных остановках DAQ-системы события, которые наступили во время ее остановки и простоя, будут пропущены (что, в общем-то, естественно). Предполагается, что основным "потребителем" функций сервера &CronSrv станут длительно работающие системы и установки, для которых характерен непрерывный режим работы в течение длительного времени, где эта проблема не стоит.

Другим "потребителем" функций сервера станут стартовые задания, помещаемые в секцию [&CronSrv.StartupScript]. Например, все функции стартовой настройки окон GUI можно будет помещать в эту секцию. Большое число команд сервера позволит унифицировать стартовые скрипты, сведя наибольшую часть стартовых действий в одну секцию [&CronSrv.StartupScript]. Это позволит также за счет унификации сократить объем кода прикладных систем, которые смогут использовать стандартный набор команд для часто востребуемых действий.

Наличие завершающей секции [&CronSrv.FinallyScript] позволяет выполнять некоторые действия по завершению работы системы. Например, можно при завершении работы DAQ-системы также завершить работу каких-то внешних процессов или запустить резервное копирование данных.

К началу

Польза от использования &CronSrv

Использование &CronSrv может принести пользу в следующих случаях:
  1. &CronSrv позволяет унифицировать (стандартизовать) все задачи, связанные со временем и календарем.
  2. &CronSrv позволяет работать в двух режимах - режиме календарных событий (CronTab) и в режиме генерации периодических событий - импульсов (Pulse).
  3. &CronSrv позволяет отделить календарь (планировщик) от исполнительной части.
    Например, прикладная программа может создать обработчик некоторого сообщения, и затем создать задание для &CronSrv, которое посылает нужное сообщение в нужное время.
  4. &CronSrv позволяет создавать "умные" системы, которые сами себя обслуживают: дефрагментируют и чистят диски, делают резервные копии данных, завершают работу в заранее заданное время, напоминают оператору о наступлении заданных моментов времени и т.д. Набор полезных стандартных утилит позволяет облегчить решение обычно стоящих задач - дефрагментация, резервное копирование данных, очистка дисков от устаревших файлов данных, сжатие и архивирование данных.
  5. &CronSrv позволяет контролировать запланированные задания, а также задавать "на лету" новые задания (через сообщения и через консоль &CronSrv). Это повышает гибкость работы установок и позволяет оперативно (без программирования и без остановки измерений) планировать работу установок. Например, если стало известно, что в 03:00 ночи отключат электричество, то на 02:45 можно запланировать автоматическое завершение работы системы - не прерывая работы установки.
  6. Задания &CronSrv позволяют группировать некоторые последовательности действий и затем вызывать их как асинхронно (путем посылки сообщений), так и по расписанию. Фактически задания &CronSrv - это готовые к исполнению подпрограммы, которые можно конструировать "на лету", не прерывая измерений.
  7. Наличие стартовой секции [&CronSrv.StartupScript] и завершающей секции [&CronSrv.FinallyScript] позволяет сосредоточить основные стартовые и завершающие действия в одном месте. Большое количество готовых команд позволяет создавать (без программирования на уровне Daq Pascal) довольно содержательные стартовые и завершающие скрипты, например, задающие размеры и внешний вид окон GUI, вызывающие или завершающие те или иные внешние программы, посылающие при старте сообщения другим устройствам и т.д. Прикладные программы могут теперь не создавать своих стартовых секций, а помещать свои стартовые команды в секцию [&CronSrv.StartupScript]. Все нужные стартовые действия в других устройствах могут быть выполнены путем посылки сообщений (@DevMsg, @DevSend, @DevPost, @DevSendMsg, @DevPostMsg) из стартовой секции [&CronSrv.StartupScript].
  8. &CronSrv позволяет сократить объем прикладного программирования, так как позволяют использовать большой набор готовых команд &CronSrv, не создавая собственных аналогов в каждой из новых систем.
Теперь стоит сказать о том, чего &CronSrv не может:
  1. &CronSrv не предназначен для организации быстрых и частых событий. В календарном режиме CronTab оперирует временами от минуты и более. В режиме Pulser время задается в миллисекундах, но возможны задержки порядка 20-30 ms за счет использования очереди и сообщений.
  2. &CronSrv не предназначен для организации событий с очень точной привязкой по времени. Точность привязки событий по времени составляет порядка 20-30 ms.

К началу

Состав и конфигурирование &CronSrv

Сервер &CronSrv расположен в каталоге Resource\DaqSite\CronServer\, и включает файлы: Для включения сервера &CronSrv в конфигуращию надо его объявить и сконфигурировать. В большинстве случаев подойдет стандартный конфигурационный файл, для включения которого будет достаточно написать:
    [ConfigFileList]
    ConfigFile = ~~\Resource\DaqSite\CronServer\CronSrv.cfg
    []
 
Если стандартный конфигурационный файл почему-то не подходит, можно переопределить отдельные параметры в секции [&CronSrv] в основном конфигурационнм файле, например:
    [&CronSrv]
    DevicePolling = 10, tpTimeCritical
    StdInFifo     = 1024
    StdOutFifo    = 1024
 
Можно также отказаться от стандартного конфигурационного файла, а вместо него включить и отредактировать такой фрагмент:
    [DeviceList]
    &CronSrv = device software program
    [&CronSrv]
    Comment       = CRON server to launch jobs at specified time
    InquiryPeriod = 1
    DevicePolling = 10, tpHighest
    ProgramGuard  = ~~\Resource\DaqSite\CronServer\CronGrd.exe
    ProgramSource = ~~\Resource\DaqSite\CronServer\CronSrv.pas
    StartupScript = [&CronSrv.StartupScript]
    FinallyScript = [&CronSrv.FinallyScript]
    StopTimeOut   = 5000
    StdInFifo     = 512
    StdOutFifo    = 512
    OpenConsole   = 2
    DebugFlags    = 3
    SilentEval    = 0
    StartingOrder = -4096
    StoppingOrder = +4096
    []
 

Сервер &CronSrv, кроме своей основной секции [&CronSrv], имеет также две другие стандартные секции: стартовую секцию [&CronSrv.StartupSection] и завершающую секцию [&CronSrv.FinallySection].

Стартовая секция [&CronSrv.StartupSection] выполняется при старте сервера и помещает приведенные в ней команды в консоль ввода StdIn устройства &CronSrv для дальнейшей обработки в стандартном цикле опроса. Исполнение команд происходит абсолютно так же, как если бы все эти команды были введены вручную в консольном окне или посланы через сообщения. Стартовая секция, за счет большого числа доступных команд, дает возможность стандартным образом выполнять инициализирующие действия, например, задавать при старте системы параметры окон или запускать те или иные внешние программы.

Завершающая секция [&CronSrv.FinallySection] выполняется при остановке сервера и помещает приведенные в ней команды в консоль ввода StdIn устройства &CronSrv, чтобы немедленно после этого их исполнить. Исполнение этой секции имеет ряд особенностей. Во-первых, поскольку обычно завершающая секция исполняется при завершении работы DAQ-системы, то не следует рассчитывать на то, что посланные в секции сообщения будут получены другими устройствами и исполнены, так как эти устройства могут быть уже остановлены к моменту исполнения секции завершения. По этой причине посылать сообщения не рекомендуется - это не будет надежно работать. Отсроченные команды, основанные на посылке сообщений "самому себе", в завершающей секции также могут быть проигнорированы, по той же причине. Тем не менее, достаточно большое число непосредственно исполняемых команд, например, команды @winshow, @winhide, @windraw, @winselect, @showmaintoolbar, @showmainstatusbar, @showmaindaqcontrol, @eval, @run, @ifprocessexists, @iffileexists, @ifdirexists, ifcomputername, @fileopendialog и другие по-прежнему доступны для исполнения.
Другой особенностью является то, что на исполнение завершающих команд отводится ограниченное время, заданное параметром StopTimeOut, в миллисекундах. Если этот параметр равен нулю, исполнение завершающей секции вообще отменяется. Команды, которые сервер не успел выполнить за отведенное время, игнорируются.

После этого следует описать задания, которые будет выполнять сервер &CronSrv.

Стандартный путь описания заданий - помещение в стартовую секцию [&CronSrv.StartupScript] сервера соответствующего набора команд, наиболее важные среди которых - создание задания @cron.tab и добавление команды к заданию @cron.job. Команда @cron.tab определяет имя задания и время его наступления по расписанию. Команда @cron.pul позволяет включить режим периодических событий (Pulser). Команды @cron.job добавляют к созданному заданию исполняемые команды. Команда @cron.run позволяет запускать созданное задание досрочно, например, для тестирования или для обработки асинхронных событий, генерируемых с помощью сообщений. Команда @cron.del позволяет удалять задания из списка заданий. Команда @cron.enb позволяет запретить или разрешить задание, если по каким-то причинам исполнение задания по расписанию должно быть временно приостановлено. Например (см также тут):
    [&CronSrv.StartupScript]
    ;--- Каждое утро в 8:00 ударять в гонг и говорить приветствие
    @Cron.tab DailyMorning 0 8
    @Cron.job DaylyMorning @Voice Gong
    @Cron.job DailyMorning @Speak Доброе утро, сейчас 8:00.

    ;--- Каждую пятницу в 16:00 ударять в гонг и желать приятного отдыха
    @Cron.tab EveryWeekend 0 16 * * Fri
    @Cron.job EveryWeekend @Voice Gong
    @Cron.job EveryWeekend @Speak Рабочая неделя кончилась! Приятного отдыха!

    ;--- Каждую секунду посылать сообщение @Update устройству &GUI
    @Cron.tab EverySecond 0 0 0
    @Cron.pul EverySecond 1000
    @Cron.job EverySecond @DevPostMsg &GUI @Update
    []
 
Cекция [&CronSrv.StartupScript] является стандартным, но не единственным способом создания заданий. Задания могут генерироваться командами, поступающими от других программ с помощью сообщений. Например:
    if DevSend(RefFind('Device &CronSrv'),
              '@Cron.tab EveryEvening 0 17'+EOL+
              '@Cron.job EveryEvening @Speak Добрый вечер, сейчас 17:00.'+EOL)>0
     then writeln('Ok') else writeln('Could not send!');
 

Наконец, задания могут создаваться и запускаться в консоли [&CronSrv] вручную. Это обстоятельства позволяет "на ходу" смотреть и менять план работы системы, создавать и запускать задания в любое время, тестировать или запускать досрочно запланированные задания. Хотя это и не совсем тривиальные действия, но они дают возможность планировать работу системы, не прерывая измерений, что является довольно ценным качеством.

К началу

Задания &CronSrv

Центральным понятием &CronSrv является задание.

Задание (англ. job) является поименованной (имеющей уникальное имя) последовательностью действий, в конкретном случае &CronSrv - последовательностью команд. Задание также имеет расписание - описание моментов времени, когда оно должно исполняться, а также флаг разрешения и запрещения. В настоящей версии &CronSrv текст задания не должен превышать 16 kByte, а число заданий - не более 1024.

Каждое задание может работать в двух режимах - календарном (время в расписании задается в терминах календаря) и импульсном (задается период повторения событий и счетчик). Каждый из режимов удобен для своего круга задач.

Задания создаются командой @cron.tab, которая определяет имя задания (оно должно быть уникальным в рамках данной конфигурации) и время его наступления по календарному расписанию в Cron-формате. С помощью команды @cron.pul задание может использоваться в импульсном режиме (Pulser), когда генерируются периодические события с заданным периодом, начиная с текущего момента. С помощью команды @cron.job к созданному заданию добавляют исполняемые команды. Исполнение задания состоит в том, что заданные команды помещаются в консоль ввода StdIn сервера &CronSrv и начинают последовательно исполняться. Исполнение задания может инициироваться как по расписанию (если задание разрешено), так и по команде @cron.run, которая позволяет запускать созданное задание досрочно. Это нужно, например, для тестирования задания или для обработки асинхронных событий, генерируемых с помощью сообщений. Если задание больше не нужно, команда @cron.del позволяет удалять задания из списка заданий. Команда @cron.enb позволяет запретить или разрешить задание, если по каким-то причинам исполнение задания по расписанию должно быть временно приостановлено. Наконец, текущий список заданий можно посмотреть командой @cron.see.

Задания могут описываться как статически (при загрузке системы, в секции [&CronSrv.StartupScript]), так и динамически, по командам от других программ, которые могут использовать сервер &CronSrv для организации периодических или календарных событий в своих целях, добавляя задания по мере необходимости.

К началу

Два режима работы заданий &CronSrv

Задания сервера &CronSrv могут работать в двух режимах:
  1. Календартный или CronTab - время наступления заданий задается в терминах календарного времени (заданного в Cron-формате) с помощью команды @cron.tab и "привязано" к календарю. Это режим удобен для организации "человеческих" событий, происходящих сравнительно редко и обычно связанных с календарем, например, конец рабочего дня, полдень и т.д. Например:
          @cron.tab DailyMorning 0 8                     - Создать календарное задание "каждый день в 8:00"
          @cron.job DailyMorning @Speak Доброе утро!     - При выполнении говорить: Доброе Утро!
          
  2. Импульсный или Pulser - время наступления заданий определяется в терминах линейного времени с помощью команды @cron.pul. Эта команда задает, начиная с текущего момента, период импульсов (заданный в миллисекундах) и счетчик (число событий, которые надо сгенерировать). Этот режим удобен для организации "машинных" событий, происходящих периодически и обычно связанных с линейным временем. Например:
          @cron.tab EverySecond 0 0 0                    - Создать задание, но не календарное
          @cron.pul EverySecond 1000                     - Стартовать Pulser с периодом 1000 ms, без счетчика
          @cron.job EverySecond @DevPostMsg &GUI @Update     - При выполнении посылать команду @Update устройству &GUI
          @cron.tab Three_Times 0 0 0                    - Создать задание, но не календарное
          @cron.pul Three_Times 10000 3                  - Стартовать Pulser с периодом 10000 ms, выполнять только 3 раза
          @cron.job Three_Times @DevPostMsg &GUI @Refresh    - При выполнении посылать команду @Refresh устройству &GUI
          
Следует заметить, что два указанных режима не являются альтернативными и могут использоваться совместно, если это требуется для решения задачи. Для этого достаточно применить обе команды (@cron.tab, @cron.pul) - и исполнение заданий будет инициироваться обоими условиями.

К началу

Команды &CronSrv

Сервер &CronSrv имеет (кроме стандартного набора) следующий набор команд:

К началу

CRON-утилиты

Для решения типичных задач обслуживания систем с помощью команды @Run к серверу &CronSrv прилагается несколько утилит:

К началу

CRON-формат

Сервер &CronSrv использует Cron-формат для описания времени наступления календарных событий. Cron-формат - это простой, но мощный и гибкий способ описания времени и периодичности действий в терминах календарного времени. Он используется в аргументах команды @cron.tab. Прототипом Cron-формата был традиционный, унаследованный из мира Unix, формат программы Cron, который состоит из пяти полей, разделенных пробелами:
    <Минуты> <Часы> <Дни_месяца> <Месяцы> <Дни_недели>
 
Сервер &CronSrv может работать и с традиционным, и с "улучшенным" вариантом Cron-формата, который отличается от традиционного шестым добавленным полем - <Годы>:
    <Минуты> <Часы> <Дни_месяца> <Месяцы> <Дни_недели> <Годы>
 
Отличием "улучшенного" варианта является также наличие символов - заменителей, которые можно использовать для обозначения минут, часов, дней, месяцев, дней недели и лет для специальных моментов времени:

Вот схема формата:

    1 2 3 4 5 6    Номер поля                        1 2 3 4 5 6    Field index
    * * * * * *                                      * * * * * *
    | | | | | |                                      | | | | | | 
    | | | | | +--- Годы       (диапазон: 1-9999)     | | | | | +--- Years      (range: 1-9999)
    | | | | +----- Дни недели (диапазон: 1-7)        | | | | +----- Week days  (range: 1-7)
    | | | +------- Месяцы     (диапазон: 1-12)       | | | +------- Month      (range: 1-12)
    | | +--------- Дни месяца (диапазон: 1-31)       | | +--------- Month days (range: 1-31)
    | +----------- Часы       (диапазон: 0-23)       | +----------- Hours      (range: 0-23)
    +------------- Минуты     (диапазон: 0-59)       +------------- Minutes    (range: 0-59)
 
Для формирования полей можно использовать следующие правила: При задании графика событий следует учитывать, что, если в момент создания задания календарное условие уже выполнено, то данное событие НЕ ИСПОЛНЯЕТСЯ, пока не наступит следующее событие, удовлетворяющее этому условию. Например, если задать условие [ * ] (выполнять каждую минуту), то соответствующее задание будет вызвано только после смены текущей минуты, хотя формально условие выполняется для любого момента времени. Или, например, задание [ @ @ ] (выполнять каждый день в текущее время суток) будет выполнено только через сутки, хотя в текущий момент условие уже выполнено. Это правило позволяет избежать преждевременного исполнения заданий. В конце концов, никто не мешает исполнить задание немедленно, вызвав команду @cron.run, если это так необходимо.

Примеры:

Cron-формула Расшифровка
* Каждую минуту.
* * * * * * Каждую минуту.
0 8 Каждое утро в 08:00.
0 8 * * Mon-Fri Каждое утро в 08:00 по рабочим дням.
0 8 */2 Каждое утро в 08:00 по четным дням месяца.
0 8 1/2 Каждое утро в 08:00 по нечетным дням месяца.
0 8 * Mar-May Каждое утро в 08:00 весной (март,апрель,май).
45-59/3 16 * * Пн-Чт Каждые 3 минуты начиная с 16:45 до 17:00, с понедельника по четверг. Например, напоминание о конце рабочего дня.
45-59/3 15 * * Fri Каждые 3 минуты начиная с 15:45 до 16:00, в пятницу. Например, напоминание о конце рабочей недели.
0 0 * * Sun В полночь каждое воскресенье.
59 23 31 Dec За минуту до конца года.
59 23 31 Dec Fri За минуту до конца года, если последний день года - пятница.
0-30/3,30-59/5 * * * Mon Каждую третью минуту в течение первых 30 минут каждого часа, затем каждую пятую минуту до конца каждого часа, в понедельник.
0 0 1 В полночь, первого числа каждого месяца.
0 9 1-7 * Mon Первый понедельник каждого месяца, в 9 утра.
0 12 * * * @ Каждый полдень текущего года.
0 ? Каждый день в начале часа, когда стартовал &CronSrv.
0 # Каждый день в начале часа, соответствующего TimeBase.

К началу

Примеры Cron-скрипов

Здесь приводятся типовые примеры скриптов для сервера &CronSrv, в качестве прототипиров, предназначенных для создания собственных скриптов.

;---Включить сервер &CronSrv в конфигурацию.
[ConfigFileList]
ConfigFile = ~~\Resource\DaqSite\CronServer\CronSrv.cfg
[]
 
;--- Стартовая секция сервера  &CronSrv. Выполняется при запуске сервера.
;--- Здесь можно поместить создание заданий, установку размеров окон и т.д.
[&CronSrv.StartupScript]

; Задать "тихий" режим вычислений
@SilentEval 1

;--- Задать режим консольного вывода для отладки
;--- Вывести в консоль справку по командам &CronSrv
@DebugFlags 15
@Help
 
;--- Каждое утро в 8:00 ударять в гонг и говорить приветствие
@Cron.tab DailyMorning 0 8
@Cron.job DaylyMorning @Voice Gong
@Cron.job DailyMorning @Speak Доброе утро, сейчас 8:00.

;--- Выполнить задание один раз, разместив в конце задания
;--- асинхронную (!) команду его удаления после исполнения
;--- Выдать на 15 секунд окно с текстом "RunOnce - это .."
;--- Потом запустить утилиту ..\Utility\RunOnce.bat, старт
;--- выполнять в каталоге ~~\Temp. Обращу внимание - чтобы
;--- эта утилита была доступна,надо указать в секции [DAQ]
;--- путь поиска SearchPath = ..\Utility,или можно вызвать
;--- как %CRW_DAQ_CONFIG_DATA_PATH%\..\Utility\RunOnce.bat
@Cron.tab RunOnce *
@Cron.job RunOnce @Run -hide msg.exe * /time:15 "RunOnce - это задание, выполняемое один раз, после старта."
@Cron.job RunOnce @Run -hide -cd Temp cmd /c RunOnce.bat
@Cron.job RunOnce @Async @Cron.del RunOnce

;--- Каждую минуту проверять наличие процесса DNS.EXE. Если он не запущен, стартовать DNS в
;--- отладочном режиме (-d), отчеты смотри в Common Files\CRW-DAQ\Resource\DimSite\dim\bin\
;--- Использовать стандартную утилиту CronDimDns.bat, отчеты смотреть в ~~\Temp\CronDimDns\
@Cron.tab DimDns *
@Cron.job DimDns @IfNotProcessExists dns.exe @Run -hide CronDimDns.bat -d

;--- В полдень каждую пятницу запускать дефрагментацию дисков, если она сейчас не запущена
;--- Использовать стандартную утилиту CronDefrag.bat, отчеты смотреть в ~~\Temp\CronDefrag\
@Cron.tab Defrag 0 12 * * Fri
@Cron.job Defrag @IfNotProcessExists defrag.exe @Run -hide CronDefrag.bat

;--- В полночь каждое воскресение запускать очистку каталогов, если она сейчас не запущена
;--- Использовать стандартную утилиту CronPurger.bat, отчеты смотреть в ~~\Temp\CronPurger\
;--- В данном примере оставлять файлы *.log в каталоге ..\Data со сроком давности не более
;--- 5 дней, а также не более 1024*1024*64 kB = 65 GB файлов *.DAT в каталоге ..\..\CRON_DATA
;--- Для имен каталогов действуют обычные правила DAQ - относительные имена вычисляются от
;--- файла конфигурации, работают также ссылки ~\ и ~~\
@Cron.tab Purger 0 0 * * Sun
@Cron.job Purger @IfNotProcessExists purger.exe @Run -hide CronPurger.bat -5 ..\Data *.log 1024*1024*64 ..\..\CRON_DATA *.DAT

;--- В полдень каждое воскресение запускать резервирование файлов, если оно еще не запущено
;--- Использовать стандартную утилиту CronBackup.bat, отчеты смотреть в ~~\Temp\CronBackup\
;--- В данном примере копировать файлы *.log из каталога ..\Data в каталог ..\..\BackupLog, 
;--- а также файлы *.dat из каталога ..\Data в каталог ..\..\BackupDat
;--- Для имен каталогов действуют обычные правила DAQ - относительные имена вычисляются от
;--- файла конфигурации, работают также ссылки ~\ и ~~\
@Cron.tab Backup 0 12 * * Sun
@Cron.job Backup @IfNotProcessExists xcopy.exe @Run -hide CronBackup.bat ..\Data *.log ..\..\BackupLog ..\Data *.dat ..\..\BackupDat

;--- В полночь каждую пятницу запускать упаковку файлов данных, если она сейчас не запущена
;--- Использовать стандартную утилиту CronPacker.bat, отчеты смотреть в ~~\Temp\CronPacker\
;--- В данном примере - упаковать файлы *.log в каталоге ..\Data со стандартными опциями (-)
;--- а также упаковать файлы *.DAT в каталоге ..\..\CRON_DATA с заданными явно опциями
;--- Для имен каталогов действуют обычные правила DAQ - относительные имена вычисляются от
;--- файла конфигурации, работают также ссылки ~\ и ~~\
@Cron.tab Packer 0 0 * * Fri
@Cron.job Packer @IfNotProcessExists gzip.exe @Run -hide -lower CronPacker.bat - ..\Data *.log -rvfN9 ..\..\CRON_DATA *.DAT

;--- Создать задание, но не календарное (указать недопустимое время 0 0 0)
;--- Стартовать Pulser с периодом 10000 ms, без счетчика. Каждые 10 секунд
;--- он будет выдавать в консоль статистику использования процессора CPU,%
@cron.tab Every10Sec 0 0 0
@cron.pul Every10Sec 10000                    - 
@cron.job Every10Sec @cron.cpu

;--- Создать задание, но не календарное (указать недопустимое время 0 0 0)
;--- Стартовать Pulser с периодом 15000 ms, со счетчиком повторения 10 раз
;--- Каждые 15 секунд 10 раз будет выдан звук done1
@cron.tab TenTimes 0 0 0
@cron.pul TenTimes 15000 10
@cron.job TenTimes @Voice done1

;--- Задание по дефрагментации системного диска и диска расположения Crw32.exe, которое никогда не выполняется
;--- по расписанию, так как указано недопустимое время, но которое можно использовать как готовую подпрограмму
;--- Поскольку действия не тривиальные и не могут быть сделаны одной командной строкой, то создается временный
;--- командный файл ~~\Temp\Defrag\Defrag.bat, в него записывается нужный набор команд, и затем он исполняется
@Cron.tab SysDefrag 0 0 0 0 0 0
@Cron.job SysDefrag @IfNotDirExists ~~\Temp\Defrag @MkDir ~~\Temp\Defrag
@Cron.job SysDefrag @IfFileExists ~~\Temp\Defrag\Defrag.bat @FileErase ~~\Temp\Defrag\Defrag.bat
@Cron.job SysDefrag @FileWriteln ~~\Temp\Defrag\Defrag.bat ..\..\Resource\Tools\Purger\Purger.exe -raw 512 *.log
@Cron.job SysDefrag @FileWriteln ~~\Temp\Defrag\Defrag.bat set log=%Date:~6,4%%Date:~3,2%%Date:~0,2%-Defrag.log
@Cron.job SysDefrag @FileWriteln ~~\Temp\Defrag\Defrag.bat for %%D in (%SystemDrive% %cd:~0,2%) do (
@Cron.job SysDefrag @FileWriteln ~~\Temp\Defrag\Defrag.bat  @echo. >> %log% && @echo. >> %log%
@Cron.job SysDefrag @FileWriteln ~~\Temp\Defrag\Defrag.bat  @echo %Date%-%Time% - defrag.exe %%D -f -v >> %log%
@Cron.job SysDefrag @FileWriteln ~~\Temp\Defrag\Defrag.bat  defrag.exe %%D -f -v >> %log%
@Cron.job SysDefrag @FileWriteln ~~\Temp\Defrag\Defrag.bat )
@Cron.job SysDefrag @IfFileExists ~~\Temp\Defrag\Defrag.bat @IfNotProcessExists defrag.exe @Run -hide -cd Temp\Defrag cmd /c Defrag.bat
 
;--- В полдень каждое воскресенье запускать дефрагментацию системного диска,
;--- если она еще не запущена; выдавать отчет в каталог Crw32exe\Temp\Defrag
@Cron.tab Defrag 0 12 * * Sun
@Cron.job Defrag @IfNotProcessExists defrag.exe @Cron.run SysDefrag

;--- Посмотреть список созданных заданий
@cron.see
[]

;--- Завершающая секция сервера  &CronSrv. Выполняется при остановке сервера.
[&CronSrv.FinallyScript]

;--- Показать ToolBar, StatusBar, окно DAQ-СИСТЕМА
@ShowMainToolBar 1
@ShowMainStatusBar 1
@ShowMainDaqControl 1

;--- Показать окно ГЛАВНАЯ КОНСОЛЬ и задать его положение
@WinShow ГЛАВНАЯ КОНСОЛЬ
@WinDraw ГЛАВНАЯ КОНСОЛЬ|Left=367|Top=0|Width=600|Height=317
@WinSelect ГЛАВНАЯ КОНСОЛЬ
[]

К началу

"Защитник" CronGuard, или "Ванька-Встанька"

Cервер &CronSrv может заставить программу работать в "непотопляемом" режиме, в котором она перезапускается (или запускает другую программу) в случае своей "смерти". Работает это так.

Пишем "завещание" программе "охраны" CronGrd.exe. Что-то вроде "в случае моей смерти прошу выполнить мое последнее желание". То есть задаем командами параметры "охраны":

После выполнения команды старта "охраны" запускается процесс - "охранник" CronGrd.exe. Он начинает "патрулировать", то есть следить, не "умер" ли его "хозяин" - основной процесс Crw32.exe. Если он "умер", то "охранник" выполняет "завещание", т.е. запускает указанную ему "посмертную" программу в указанном каталоге с указанными параметрами, после чего завершает работу. Если "хозяин" умер и "завещание" исполнено - "служба" закончена.

В качестве "завещания" ("посмертной" программы) можно указать перезапуск пакета ( например, указав ~~\CrwGo.exe ) и передать ему имя текущего основного конфигурационного файла, чтобы "посмертно" произошел перезапуск текущей конфигурации.

При указании каталога @Guard.HomeDir и имени программы @Guard.AppName, а также параметров командной строки @Guard.CmdLine допустимо использовать относительные ссылки: как это принято в DAQ.

При указании параметров командной стоки допустимо также использовать символы - заместители: Использование этих заместителей позволяет перезапускать пакет с теми же аргументами, с какими запущен пакет. Это особенно удобно для организации систем, автоматически запускаемых из "Автозагрузки" или с использованием специального ярлыка, где все нужные параметры уже прописаны.

Чтобы сделать "непотопляемую" систему контроля, мало перезапустить измерительную конфигурацию. Надо также позаботиться о том, чтобы она автоматически стартовала после загрузки ([DAQ] AutoStart = 1 ). Кроме того, программа в этом случае должна сохранять свои критические параметры на жестком диске, например, в .INI - файле, чтобы при старте продолжить прерванную работу в правильном состоянии.

Кроме того, надо вставить ярлык на запуск конфигурации в "Автозагрузку", чтобы при аварийном перезапуске операционной системы измерительная конфигурация также автоматически перезапускалась. Это предотвратит остановку контроля при сбое по питанию, например.

Построенная таким образом система контроля будет подобна русской игрушке - "Ваньке-Встаньке", который после любого "падения" все равно встает в нужное положение.

Пример:
[&CronSrv.StartupScript]
@Guard.HomeDir=~~\                  ; Запускать в своем рабочем каталоге
@Guard.AppName=~~\CrwGo.exe         ; Запускать самого себя - перезапуск пакета
@Guard.CmdLine=/Icon=1 .\!DEMO.CFG  ; Запускать указанный конфигурационный файл
@Guard.CmdLine=%1 %2 %3 %4 %5 %6 %7 ; Другой вариант - взять аргументы, с которыми запущена основная программа
@Guard.Period=15000                 ; Патрулировать каждые 15 сек
@Guard.Display=0                    ; Запускать CrwGo скрытно
@Guard.Start                        ; Начать охрану
[]
[&CronSrv.FinallyScript]
@Guard.Stop                         ; Необходимо снять охрану, иначе будет перезапуск
[]

К началу