Запуск задания cron, только если он еще не запущен
Итак, я пытаюсь настроить работу cron как своего рода сторожевого таймера для созданного мной демона. Если демон демонтируется и терпит неудачу, я хочу, чтобы задание cron периодически перезапускало его... Я не уверен, насколько это возможно, но я прочитал пару учебников cron и не смог найти ничего, что могло бы сделать то, что я Я ищу...
Мой демон запускается из оболочки script, поэтому я действительно ищу способ запуска задания cron ТОЛЬКО, если предыдущий запуск этого задания еще не запущен.
Я нашел этот пост, который предоставил решение для того, что я пытаюсь сделать, используя файлы блокировки, а не я не уверен, есть ли лучше способ сделать это...
Спасибо за вашу помощь.
Ответы
Ответ 1
Я делаю это для программы диспетчера очереди печати, которую я написал, это всего лишь оболочка script:
#!/bin/sh
if ps -ef | grep -v grep | grep doctype.php ; then
exit 0
else
/home/user/bin/doctype.php >> /home/user/bin/spooler.log &
#mailing program
/home/user/bin/simplemail.php "Print spooler was not running... Restarted."
exit 0
fi
Он работает каждые две минуты и довольно эффективен. У меня есть электронная почта со специальной информацией, если по какой-то причине процесс не запущен.
Ответ 2
Используйте flock
. Это новое. Это лучше.
Теперь вам не нужно писать код самостоятельно. Здесь вы можете найти дополнительные причины: https://serverfault.com/a/82863
/usr/bin/flock -n /tmp/my.lockfile /usr/local/bin/my_script
Ответ 3
Как заявили другие, написание и проверка PID файла является хорошим решением. Здесь моя реализация bash:
#!/bin/bash
mkdir -p "$HOME/tmp"
PIDFILE="$HOME/tmp/myprogram.pid"
if [ -e "${PIDFILE}" ] && (ps -u $(whoami) -opid= |
grep -P "^\s*$(cat ${PIDFILE})$" &> /dev/null); then
echo "Already running."
exit 99
fi
/path/to/myprogram > $HOME/tmp/myprogram.log &
echo $! > "${PIDFILE}"
chmod 644 "${PIDFILE}"
Ответ 4
Не пытайтесь делать это через cron. Имейте cron запустите script независимо от того, что, а затем пусть script решит, запущена ли программа, и запустите ее, если это необходимо (обратите внимание, что вы можете использовать Ruby или Python или ваш любимый язык сценариев для этого)
Ответ 5
Удивительно, что никто не упомянул про run-one. Я решил мою проблему с этим.
apt-get install run-one
затем добавьте run-one
перед вашим скриптом crontab
*/20 * * * * * run-one python /script/to/run/awesome.py
Посмотрите этот ответ askubuntu SE. Вы можете найти ссылку на подробную информацию там же.
Ответ 6
Вы также можете сделать это как однострочный непосредственно в своем crontab:
* * * * * [ `ps -ef|grep -v grep|grep <command>` -eq 0 ] && <command>
Ответ 7
В ответ на ответ Earlz вам понадобится обертка script, которая создает файл $PID.running при запуске и удаляет, когда закончится. Обертка script вызывает script, который вы хотите запустить. Обертка необходима, если целевой script выходит из строя или ошибки, файл pid удаляется..
Ответ 8
То, как я это делаю, когда я запускаю php-скрипты:
Кронтаб:
* * * * * php /path/to/php/script.php &
Код php:
<?php
if (shell_exec('ps aux | grep ' . __FILE__ . ' | wc -l') > 1) {
exit('already running...');
}
// do stuff
Эта команда выполняет поиск в списке системных процессов для текущего имени файла php
если он существует, счетчик строк (wc -l) будет больше, чем один, поскольку сама команда поиска, содержащая имя файла
поэтому, если вы запустите php crons, добавьте вышеприведенный код в начало вашего php-кода, и он будет запускаться только один раз.
Ответ 9
Я бы рекомендовал использовать существующий инструмент, например monit, он будет отслеживать и автоматически перезапускать процессы. Существует более подробная информация здесь. Он должен быть легко доступен в большинстве дистрибутивов.
Ответ 10
С lockrun
вам не нужно писать обертку script для вашего задания cron. http://www.unixwiz.net/tools/lockrun.html
Ответ 11
Этот один никогда не подводил меня:
one.sh
LFILE=/tmp/one-`echo "[email protected]" | md5sum | cut -d\ -f1`.pid
if [ -e ${LFILE} ] && kill -0 `cat ${LFILE}`; then
exit
fi
trap "rm -f ${LFILE}; exit" INT TERM EXIT
echo $$ > ${LFILE}
[email protected]
rm -f ${LFILE}
работа cron:
* * * * * /path/to/one.sh <command>
Ответ 12
Я бы предложил следующее как улучшение rsanden answer (я бы опубликовал комментарий, но не имел достаточной репутации...):
#!/usr/bin/env bash
PIDFILE="$HOME/tmp/myprogram.pid"
if [ -e "${PIDFILE}" ] && (ps -p $(cat ${PIDFILE}) > /dev/null); then
echo "Already running."
exit 99
fi
/path/to/myprogram
Это позволяет избежать возможных ложных совпадений (и накладных расходов на grepping), и он подавляет вывод и полагается только на статус выхода ps.
Ответ 13
Простой пользовательский php достаточно для достижения. Не нужно путать с оболочкой script.
позволяет предположить, что вы хотите запустить php/home/mypath/example.php, если не запускаете
Затем используйте следующий пользовательский php script для выполнения того же задания.
создайте следующие /home/mypath/forever.php
<?php
$cmd = $argv[1];
$grep = "ps -ef | grep '".$cmd."'";
exec($grep,$out);
if(count($out)<5){
$cmd .= ' > /dev/null 2>/dev/null &';
exec($cmd,$out);
print_r($out);
}
?>
Затем в вашем cron добавьте следующее
* * * * * php /home/mypath/forever.php 'php /home/mypath/example.php'
Ответ 14
# one instance only (works unless your cmd has 'grep' in it)
ALREADY_RUNNING_EXIT_STATUS=0
bn=`basename $0`
proc=`ps -ef | grep -v grep | grep "$bn" | grep -v " $$ "`
[ $? -eq 0 ] && {
pid=`echo $proc | awk '{print $2}'`
echo "$bn already running with pid $pid"
exit $ALREADY_RUNNING_EXIT_STATUS
}
Ответ 15
Рассмотрите возможность использования pgrep (если доступно), а не ps через grep, если вы собираетесь идти по этому маршруту. Хотя, лично, у меня много пробега из сценариев формы
while(1){
call script_that_must_run
sleep 5
}
Хотя это может потерпеть неудачу, и рабочие задания cron часто являются лучшим способом для основных вещей. Еще одна альтернатива.