Могу ли я выполнять работу cron чаще, чем каждую минуту?

Можно ли запускать задание cron каждые 30 секунд без команды sleep?

10 ответов

Решение

Если ваша задача должна выполняться так часто, cron - неправильный инструмент. Помимо того, что он просто не будет запускать задания так часто, вы также рискуете столкнуться с серьезными проблемами, если задание выполняется дольше, чем интервал между запусками. Перепишите свою задачу так, чтобы она демонизировалась и выполнялась постоянно, а затем, при необходимости, запустите ее из cron (при этом убедитесь, что она не перезапустится, если она уже запущена).

Кандидат на самое творческое злоупотребление командой Linux:

nohup watch -n 30 --precise yourprog >/dev/null &

Если yourprog состоит из:

date +%M.%S.%N >> yourprog.out

затем yourprog.out может выглядеть так:

50.51.857291267
51.21.840818353
51.51.840910204
52.21.840513307
52.51.842455224
53.21.841195858
53.51.841407587
54.21.840629676

показывая довольно хороший уровень точности.

Вот объяснение частей команды:

  • nohup - Это сохраняет команду, которая следует за этим, watch в этом случае от выхода при выходе из терминала.
  • watch - Эта программа запускает команду несколько раз. Обычно первый экран вывода команды отображается каждый раз watch запускает команду
  • -n 30 - Интервал, с которым запускается команда. В этом случае это каждые тридцать секунд.
  • --precise - без этой опции, watch запускает команду через интервал секунд. При этом каждый запуск команды начинается с интервала, если это возможно. Если эта опция не была указана в примере, время будет позже и позже более чем на 30 секунд каждый раз из-за времени, необходимого для запуска и выполнения команды (yourprog).
  • yourprog - программа или командная строка для watch выполнить. Если командная строка содержит символы, специальные для оболочки (например, пробел или точка с запятой), ее необходимо заключить в кавычки.
  • >/dev/null - Больше чем перенаправляет вывод команды, выполняемой watch в файл, /dev/null, Этот файл отбрасывает любые данные, записанные в него. Это предотвращает запись вывода на экран или, так как nohup используется, это предотвращает отправку вывода в файл с именем nohup.out,
  • & - watch Команда запускается в фоновом режиме, а управление возвращается в терминал или родительский процесс.

Обратите внимание, что nohup, перенаправление вывода и & оператор фонового управления не является специфичным для watch,

Вот объяснение примера yourprog сценарий:

  • date - Выводит текущую дату и / или время. Это может также установить их.
  • +%M.%S.%N - Это определяет формат вывода для date использовать. %M текущая минута, %S текущая секунда и %N текущая наносекунда.
  • >> yourprog.out - Это перенаправляет вывод date команда в файл с именем yourprog.out, Двойное значение больше, чем приводит к тому, что вывод добавляется в файл при каждом вызове, а не перезаписывается предыдущее содержимое.

Редактировать:

Возможно, еще одна вещь, которой можно злоупотреблять (или, возможно, это законное использование), это системные таймеры.

Смотрите systemd/Timers как замену cron и Cron против системных таймеров.

Я постараюсь опубликовать пример в ближайшее время.

* * * * * /path/to/program
* * * * * sleep 30; /path/to/program

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

#!/bin/sh

if ln -s "pid=$$" /var/pid/myscript.pid; then
  trap "rm /var/pid/myscript.pid" 0 1 2 3 15
else
  echo "Already running, or stale lockfile." >&2
  exit 1
fi

Конечно, это все еще оставляет очень маленькую возможность для сбоя, поэтому поищите в Google лучшее решение, подходящее для вашей среды.

Cron предназначен для того, чтобы просыпаться каждую минуту, поэтому невозможно сделать это без какого-либо взлома, например, сна, как вы упоминали.

Вы можете сделать это с помощью стороннего программного обеспечения.

Опция, которая хорошо сработала для меня - это часто встречающийся

Это позволяет с точностью до миллисекунды и дает вам возможность отложить следующее выполнение до завершения текущего.

мое самое простое и любимое решение для этой задачи:

Запись cron:
* * * * * flock -w0 /path/to/script /path/to/script

сценарий:
while true;do echo doing something; sleep 10s;done

ленивая альтернатива:)

* * * * * flock -w0 /path/to/log watch -n 10 echo doing >> /path/to/log

или же

* * * * * flock -w0 /path/to/log watch -n 10 /path/to/script

профи

  • использование flock Команда избегает запуска скрипта несколькими экземплярами одновременно. Это может быть очень важно в большинстве случаев.
  • flock а также watch Команды доступны в большинстве установок Linux

минусы

  • Остановка такого рода "Сервис" нужно два шага
    • закомментируйте запись cron
    • убить сценарий или watch команда

У меня есть пара проблем:

(1) иногда система загружается и не может начать все точно с 30-секундной точки, тогда возможно, что в то же время, когда вы выполняете одно задание, другое задание будет всплывать, и тогда у вас будет 2 (или более) задания, выполняющих одно и то же вещь. В зависимости от сценария, здесь могут быть некоторые существенные помехи. Таким образом, кодирование в таком сценарии должно содержать некоторый код, чтобы гарантировать, что одновременно выполняется только один экземпляр данного сценария.

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

Таким образом, как сказал один из авторов, в этом случае я бы серьезно подумал о том, чтобы запустить демона, работающего с дополнительными процессами, чтобы он продолжал работать, если он имеет решающее значение для ваших операций.

Не точный ответ на ваш вопрос, но я думаю, что некоторым он может быть полезен. Если вы хотите запускать команду каждую секунду, вы можете сделать это так. Каждую минуту он проходит через 60 секунд, запускает сценарий во вспомогательной оболочке и засыпает на 1 секунду. Вам необходимо убедиться, что вы создали файл блокировки (или аналогичный механизм) и прервали script.pl соответственно (если вы не хотите запускать его несколько раз параллельно).

* * * * * for((i=0; i<60; i++)); do /usr/bin/perl script.pl & sleep 1; done;

Одна простая стратегия для ОС Linux — создать службу SystemD, например/etc/systemd/system/myservice.service:

      [Install]
WantedBy=multi-user.target

[Unit]
Description=Bmon
StartLimitIntervalSec=30
StartLimitBurst=2

[Service]
ExecStart=/usr/bin/bash /home/janie/myservice.sh
Restart=always

Затем вmyservice.sh:

      #!/usr/bin/bash
while true
do
  /home/janie/run_every_10_sec
  sleep 10
done

Это завершит запуск команды/home/janie/run_every_10_secкаждые 10 секунд.

Включитьmyservice.service, бегатьsudo systemctl enable myservice.

Решение, если это для вашего собственного сценария или если вы можете обернуть его:

  1. Получить и запомнить время начала.
  2. Если файл блокировки, к которому вы будете обращаться позже, присутствует, и сценарий не работает в течение 60 секунд, подождите секунду и проверьте снова. (например, во время / сна)*
  3. Если файл блокировки все еще присутствует по истечении 60 секунд, выйдите с предупреждением об устаревшей блокировке.
  4. Сенсорный файл блокировки.
  5. Пока скрипт не работал в течение 60 секунд, зациклите текущую задачу с желаемой продолжительностью сна.
  6. Удалить файл блокировки.
  7. Добавьте как мелко крона.
  8. Боб твой дядя.

Меньше головной боли, чем создание и мониторинг демона.

* Если вы используете PHP, помните clearstatcache().

Другие вопросы по тегам