Итак, у меня есть хрон, который мне нужно запускать каждые 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?
У вас есть */30
в указателе минут - это означает каждую минуту, но с шагом в 30 (другими словами, каждые полчаса). Поскольку cron
не переходит к субминутным разрешениям, вам нужно будет найти другой способ.
Одна возможность, хотя и немного клочья, состоит в том, чтобы иметь два задания, одно смещение на 30 секунд:
* * * * * /path/to/executable param1 param2
* * * * * ( sleep 30 ; /path/to/executable param1 param2 )
Оба задания cron запускаются каждую минуту, но последняя будет ждать полминуты перед выполнением "мяса" задания, /path/to/executable
.
* * * * * ( /path/to/executable param1 param2; sleep 30 ; /path/to/executable param1 param2 )
Вы не можете. 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'\''
Гранулярность Cron находится в минутах и не предназначена для пробуждения каждые x
секунд, чтобы что-то запускать. Запустите свою повторяющуюся задачу в цикле, и она будет делать то, что вам нужно:
#!/bin/env bash
while [ true ]; do
sleep 30
# do what you need to here
done
Нет необходимости в двух входах 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'\''"
Вы можете проверить мой ответ на этот похожий вопрос
В основном, я включил там сценарий bash под названием "runEvery.sh", который вы можете запускать cron каждые 1 минуту и передавать в качестве аргументов настоящую команду, которую вы хотите запустить, и частоту в секундах, в которой вы хотите ее запустить.
что-то вроде этого
* * * * * ~/bin/runEvery.sh 5 myScript.sh
Задача Cron не может использоваться для планирования задания в секундах. i.e Вы не можете планировать выполнение задания cron каждые 5 секунд. Альтернативой является запись оболочки script, которая использует в ней команду sleep 5
.
Создайте оболочку script every-5-seconds.sh, используя bash while, как показано ниже.
$ cat every-5-seconds.sh
#!/bin/bash
while true
do
/home/ramesh/backup.sh
sleep 5
done
Теперь запустите эту оболочку script в фоновом режиме, используя nohup
, как показано ниже. Это приведет к выполнению script даже после выхода из сеанса. Это выполнит вашу оболочку backup.sh script каждые 5 секунд.
$ nohup ./every-5-seconds.sh &
backup.sh
требуется 1,5 секунды, он будет выполняться каждые 6,5 секунд. Есть способы избежать этого, например sleep $((5 - $(date +%s) % 5))
в /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 секунд
Используйте часы:
$ watch --interval .30 script_to_run_every_30_sec.sh
$ watch --interval .10 php some_file.php
я использовать что-то вроде $ watch --interval .10 php some_file.php
? или watch
работают только с .sh файлами?
Задача Crontab может использоваться для планирования задания в минутах/часах/днях, но не в секундах. Альтернатива:
Создайте script для выполнения каждые 30 секунд:
#!/bin/bash
# 30sec.sh
for COUNT in `seq 29` ; do
cp /application/tmp/* /home/test
sleep 30
done
Используйте crontab -e
и crontab для выполнения этого script:
* * * * * /home/test/30sec.sh > /dev/null
Использовать fcron (http://fcron.free.fr/) - дает вам детализацию в секундах и пути лучше и богаче функций, чем cron (vixie-cron) и стабильный тоже. Я делал такие глупые вещи, как около 60 php-скриптов, работающих на одной машине, в очень глупых настройках, и он все еще выполнял свою работу!
Спасибо за все хорошие ответы. Чтобы сделать это простым, мне понравилось смешанное решение, с контролем над crontab и временным разделением на скрипт. Так вот что я сделал, чтобы запустить скрипт каждые 20 секунд (три раза в минуту). Линия Crontab:
* * * * 1-6 ./a/b/checkAgendaScript >> /home/a/b/cronlogs/checkAgenda.log
Автор сценария:
cd /home/a/b/checkAgenda
java -jar checkAgenda.jar
sleep 20
java -jar checkAgenda.jar
sleep 20
java -jar checkAgenda.jar
Если вы используете новейшую ОС Linux с SystemD, вы можете использовать SystemD Timer для запуска своего скрипта на любом уровне детализации, который вы хотите (теоретически до наносекунд), и - если хотите - гораздо более гибкие правила запуска, чем когда-либо допускал Cron, Не требуется 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 может планировать следующий прогон, чтобы он совпал с другими событиями, ему нужно было бы разбудить процессор реже. 1 1ms
в приведенном выше примере не является идеальным - я обычно устанавливаю точность до 1
(1 секунду) в моих запланированных заданиях на подминутное время, но это будет означать, что если вы посмотрите на журнал с сообщениями "Hello World", видеть, что он часто задерживается на 1 секунду. Если вы в порядке с этим, я предлагаю установить точность до 1 секунды или более. Как вы могли заметить, этот таймер не очень хорошо имитирует Cron - в том смысле, что команда не запускается в начале каждого периода настенных часов (т.е. Она не начинается на 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]
.
Более подробные сведения можно найти по адресу:
man systemd.timer
man systemd.time
man systemd.service
man system.exec
В настоящее время я использую метод ниже. Работает без проблем.
* * * * * /bin/bash -c ' for i in {1..X}; do YOUR_COMMANDS ; sleep Y ; done '
Если вы хотите запускать каждые N секунд, тогда X будет 60/N, а Y будет N.
Спасибо.
написать один скрипт оболочки. создать файл.sh
nano every30second.sh
и писать сценарий
#!/bin/bash
For (( i=1; i <= 2; i++ ))
do
write Command here
sleep 30
done
затем установите cron для этого скрипта crontab -e
(* * * * */home/username/every30second.sh)
этот cron вызывает.sh файл каждые 1 мин и в.sh файле команду запускается 2 раза за 1 мин.
если вы хотите запустить скрипт в течение 5 секунд, замените 30 на 5 и измените для цикла следующим образом: For (( i=1; я <= 12; i++ ))
когда вы выбираете для любой секунды, затем вычисляете 60/ваш второй и записываете в цикл For
У меня была аналогичная задача, и я использовал следующий подход:
nohup watch -n30 "kill -3 NODE_PID" &
Мне нужно было периодически убивать -3 (чтобы получить трассировку стека программы) каждые 30 секунд в течение нескольких часов.
nohup ... &
Это здесь, чтобы быть уверенным, что я не потеряю выполнение часов, если я потеряю оболочку (проблема с сетью, авария окон и т.д.).
Выполнить в цикле оболочки, например:
#!/bin/sh
counter=1
while true ; do
echo $counter
counter=$((counter+1))
if [[ "$counter" -eq 60 ]]; then
counter=0
fi
wget -q http://localhost/tool/heartbeat/ -O - > /dev/null 2>&1 &
sleep 1
done
60
должно быть 30
, вы можете переместить эту wget
внутри , if
заявление, в противном случае он выполняется каждый второй. В любом случае, я не уверен, насколько это лучше, чем просто один sleep 30
. Если бы вы отслеживали фактическое время UNIX, а не счетчик, это имело бы значение.