Запуск cron каждые 30 секунд - PullRequest
248 голосов
/ 08 марта 2012

Хорошо, у меня есть cron, который мне нужно запускать каждые 30 секунд.

Вот что у меня есть:

*/30 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''

Он работает, но работает ли он каждые 30 минут30 секунд?

Кроме того, я читал, что cron, возможно, не лучший инструмент для использования, если я запускаю его так часто.Есть ли другой лучший инструмент, который я могу использовать или установить на Ubuntu 11.04, который будет лучшим вариантом?Есть ли способ исправить вышеуказанный cron?

Ответы [ 16 ]

638 голосов
/ 08 марта 2012

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

Одна из возможностей, хотя и немного сложная, состоит в том, чтобы иметь два задания, одно смещение на 30 секунд:

* * * * * /path/to/executable param1 param2
* * * * * ( sleep 30 ; /path/to/executable param1 param2 )

Обе cron работы фактически выполняются каждую минуту, но последняя будет ждать полминуты, прежде чем выполнять «мясо» задания, /path/to/executable.

58 голосов
/ 08 марта 2012

Вы не можете. Cron имеет зернистость 60 секунд.

* * * * * cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''
* * * * * sleep 30 && cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''
35 голосов
/ 08 марта 2012

Степень детализации Cron указана в минутах, а не был предназначен для пробуждения каждые x секунд, чтобы что-то запустить.Запустите повторяющееся задание в цикле, и оно должно сделать то, что вам нужно:

#!/bin/env bash
while [ true ]; do
 sleep 30
 # do what you need to here
done
22 голосов
/ 20 марта 2015

Нет необходимости в двух записях cron, вы можете поместить их в один с помощью:

* * * * * /bin/bash -l -c "/path/to/executable; sleep 30 ; /path/to/executable"

, так что в вашем случае:

* * * * * /bin/bash -l -c "cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'' ; sleep 30 ; cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''"

11 голосов
/ 16 июня 2013

Вы можете проверить мой ответ на этот похожий вопрос

По сути, я включил туда bash-скрипт с именем "runEvery.sh", который вы можете запускать с помощью cron каждую 1 минуту и ​​передавать в качестве аргументов реальную команду, которую вы хотите запустить, и частоту, с которой вы хотите запускать это.

как то так

* * * * * ~/bin/runEvery.sh 5 myScript.sh

9 голосов
/ 15 октября 2014

Задание Cron нельзя использовать для планирования задания с интервалом в секунды. Т.е. вы не можете запланировать запуск задания cron каждые 5 секунд. Альтернативой является написание сценария оболочки, в котором используется команда sleep 5.

Создайте скрипт оболочки каждые 5-seconds.sh, используя цикл bash while, как показано ниже.

$ cat every-5-seconds.sh
#!/bin/bash
while true
do
 /home/ramesh/backup.sh
 sleep 5
done

Теперь выполните этот сценарий оболочки в фоновом режиме, используя nohup, как показано ниже. Это продолжит выполнение сценария даже после выхода из сеанса. Это будет запускать скрипт оболочки backup.sh каждые 5 секунд.

$ nohup ./every-5-seconds.sh &
8 голосов
/ 30 ноября 2018

Если вы используете новейшую ОС Linux с SystemD, вы можете использовать модуль таймера SystemD для запуска скрипта на любом уровне детализации, который вы пожелаете (теоретически до наносекунд), и - если вы хотите - гораздо более гибкие правила запуска, чем Крон когда-либо позволял. Нет sleep требуется кладж

Требуется немного больше, чтобы установить, чем одна строка в файле cron, но если вам нужно что-то лучше, чем «Каждую минуту», это стоит усилий.

Модель таймера SystemD в основном такова - таймеры - это единицы, которые запускают сервисные единицы, когда таймер истекает .

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

Вот простой пример, который регистрирует «Hello World» каждые 10 секунд:

/etc/systemd/system/helloworld.service

[Unit]
Description=Say Hello
[Service]
ExecStart=/usr/bin/logger -i Hello World

/etc/systemd/system/helloworld.timer

[Unit]
Description=Say Hello every 10 seconds
[Timer]
OnBootSec=10
OnUnitActiveSec=10
AccuracySec=1ms
[Install]
WantedBy=timers.target

После настройки этих устройств (в /etc/systemd/system, как описано выше, для общесистемной настройки или в ~/.config/systemd/user для настройки, специфичной для пользователя), вам необходимо включить таймер (но не службу). запустив systemctl enable helloworld.timer. Если вы хотите немедленно запустить таймер (вместо ожидания его запуска после перезагрузки), также запустите systemctl start helloworld.timer.

Используемые здесь поля раздела [Timer]:

  • OnBootSec - запускать службу через много секунд после каждой загрузки.
  • OnUnitActiveSec - запустить службу через много секунд после последнего запуска службы. Это то, что заставляет таймер повторяться и вести себя как задание cron.
  • AccuracySec - устанавливает точность таймера. Таймеры точны настолько, насколько это поле установлено, и по умолчанию используется 1 минута (эмулирует cron). Основная причина не требовать максимальной точности заключается в повышении энергопотребления - если SystemD может запланировать следующий запуск так, чтобы он совпадал с другими событиями, он должен реже разбудить ЦП. 1ms в приведенном выше примере не является идеальным - я обычно устанавливаю точность на 1 (1 секунду) в моих подпрограммах, выполняемых менее минуты, но это будет означать, что если вы посмотрите на журнал, показывающий сообщения «Hello World» Вы бы увидели, что это часто поздно на 1 секунду. Если вы согласны с этим, я предлагаю установить точность в 1 секунду или более.

Как вы, возможно, заметили, этот таймер не очень хорошо имитирует Крона - в том смысле, что команда не запускается в начале каждого периода настенных часов (то есть не запускается на 10-й секунде часы, потом 20 и тд). Вместо этого просто происходит, когда таймер истекает. Если система загрузилась в 12:05:37, то в следующий раз команда будет запущена в 12:05:47, затем в 12:05:57 и т. Д. Если вас интересует фактическая точность настенных часов, вы можете хотите заменить поля OnBootSec и OnUnitActiveSec и вместо этого установить правило OnCalendar с нужным вам расписанием (которое, насколько я понимаю, не может быть быстрее 1 секунды при использовании формата календаря). Приведенный выше пример также можно записать в виде:

OnCalendar=*-*-* *:*:00,10,20,30,40,50

Последнее примечание: как вы, наверное, догадались, юнит helloworld.timer запускает юнит helloworld.service, потому что они имеют одинаковое имя (за исключением суффикса типа юнита). Это значение по умолчанию, но вы можете переопределить его, установив поле Unit для раздела [Timer].

Более подробную информацию можно найти по адресу:

7 голосов
/ 27 октября 2016

Используйте часы:

$ watch --interval .30 script_to_run_every_30_sec.sh
6 голосов
/ 24 февраля 2018

в директории /etc/cron.d/

new создать файл excute_per_30s

* * * * * yourusername  /bin/date >> /home/yourusername/temp/date.txt
* * * * * yourusername sleep 30; /bin/date >> /home/yourusername/temp/date.txt

будет запускать cron каждые 30 секунд

5 голосов
/ 07 марта 2015

Использовать fcron (http://fcron.free.fr/) - дает вам детализацию в считанные секунды и делает ее лучше и более функциональной, чем cron (vixie-cron) и стабильной. Я использовал для создания глупых вещей, таких как запуск около 60 сценариев php одна машина в очень дурацких настройках и она все же сделала свое дело!

...