Próbuję ustawić pracę cron jako swego rodzaju stróża dla demona, którego stworzyłem. Jeśli demon wystąpi i zawiedzie, chcę, aby zadanie crona okresowo go restartowało ... Nie jestem pewien, jak to jest możliwe, ale przeczytałem kilka samouczków crona i nie mogłem znaleźć niczego, co zrobiłoby to, co ja Szukam ...
Mój demon uruchamia się ze skryptu powłoki, więc tak naprawdę szukam sposobu na uruchomienie zadania cron TYLKO, jeśli poprzednie uruchomienie tego zadania nadal nie działa.
Znalazłem ten post , który zapewnił rozwiązanie tego, co próbuję zrobić za pomocą plików blokujących, nie jestem pewien, czy istnieje lepszy sposób na zrobienie tego ...
grep -v grep | grep doctype.php
możesz zrobićgrep [d]octype.php
.&
skrypt był uruchamiany przez crona.Użyj
flock
. Jest nowe. To jest lepsze.Teraz nie musisz samodzielnie pisać kodu. Sprawdź więcej powodów tutaj: https://serverfault.com/a/82863
/usr/bin/flock -n /tmp/my.lockfile /usr/local/bin/my_script
źródło
setlock
,s6-setlock
,chpst
, Irunlock
w swoich trybach non-blocking są alternatywy, które są dostępne na więcej niż tylko Linux. unix.stackexchange.com/a/475580/5132Jak stwierdzili inni, pisanie i sprawdzanie pliku PID jest dobrym rozwiązaniem. Oto moja implementacja 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}"
źródło
>
" kontra ">>
". Przepraszam za to.[ -e "${PIDFILE}" ]
”. Jeśli tak nie jest, uruchomi program w tle, zapisze swój PID do pliku („echo $! > "${PIDFILE}"
”) i zakończ. Jeśli zamiast tego plik PID istnieje, skrypt sprawdzi Twoje własne procesy („ps -u $(whoami) -opid=
”) i sprawdzi, czy używasz jednego z tym samym PID („grep -P "^\s*$(cat ${PIDFILE})$"
”). Jeśli nie, skrypt rozpocznie program jak poprzednio, nadpisz plik PID nowym PID i zakończ. Nie widzę powodu do modyfikowania skryptu; czy ty?Zaskakujące jest to, że nikt nie wspomniał o run-one . Rozwiązałem ten problem.
następnie dodaj
run-one
przed skryptem crontabSprawdź tę odpowiedź askubuntu SE. Znajdziesz tam również link do szczegółowych informacji.
źródło
Nie próbuj tego robić przez cron. Niech cron uruchomi skrypt bez względu na wszystko, a następnie niech skrypt zdecyduje, czy program jest uruchomiony i uruchom go, jeśli to konieczne (pamiętaj, że możesz do tego użyć Ruby, Python lub ulubionego języka skryptowego)
źródło
Możesz to również zrobić jako jednolinijkowy bezpośrednio w swojej tabeli crontab:
* * * * * [ `ps -ef|grep -v grep|grep <command>` -eq 0 ] && <command>
źródło
ps -ef|grep [c]ommand
-eq 0] && <polecenie>, gdzie zawijanie pierwszej litery polecenia w nawiasach wyklucza je z wyników grep.[ "$(ps -ef|grep [c]ommand|wc -l)" -eq 0 ] && <command>
[ $(grep something | wc -l) -eq 0 ]
to naprawdę okrężny sposób pisania! grep -q something
. Więc chcesz po prostups -ef | grep '[c]ommand' || command
grep -c
Sposób, w jaki to robię, gdy uruchamiam skrypty php, to:
Crontab:
Kod php:
<?php if (shell_exec('ps aux | grep ' . __FILE__ . ' | wc -l') > 1) { exit('already running...'); } // do stuff
To polecenie wyszukuje na liście procesów systemowych bieżącą nazwę pliku php, jeśli istnieje, licznik linii (wc -l) będzie większy niż jeden, ponieważ samo polecenie wyszukiwania zawiera nazwę pliku
więc jeśli korzystasz z php cronów, dodaj powyższy kod na początku swojego kodu php i uruchomi się tylko raz.
źródło
W następstwie odpowiedzi Earlz, potrzebujesz skryptu opakowującego, który tworzy plik $ PID.running po uruchomieniu i usuwa po jego zakończeniu. Skrypt opakowania wywołuje skrypt, który chcesz uruchomić. Opakowanie jest niezbędne na wypadek awarii lub błędu skryptu docelowego, plik pid zostanie usunięty.
źródło
Dzięki temu
lockrun
nie musisz pisać skryptu opakowującego dla swojego zadania cron. http://www.unixwiz.net/tools/lockrun.htmlźródło
Polecam użycie istniejącego narzędzia, takiego jak monit , będzie ono monitorować i automatycznie restartować procesy. Więcej informacji można znaleźć tutaj . Powinien być łatwo dostępny w większości dystrybucji.
źródło
Ten nigdy mnie nie zawiódł:
one.sh :
LFILE=/tmp/one-`echo "$@" | 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} $@ rm -f ${LFILE}
praca cron :
* * * * * /path/to/one.sh <command>
źródło
# 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 }
UPDATE ... lepszy sposób przy użyciu flocka:
źródło
Sugerowałbym następujące ulepszenie odpowiedzi rsandena (opublikowałbym jako komentarz, ale nie mam wystarczającej reputacji ...):
#!/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
Pozwala to uniknąć możliwych fałszywych dopasowań (i narzutu greppingu) i blokuje wyjście i polega tylko na statusie wyjścia ps.
źródło
ps
polecenie dopasuje PID dla innych użytkowników w systemie, nie tylko dla Twojego. Dodanie „-u
” dops
polecenia zmienia sposób działania statusu wyjścia.Wystarczy prosty niestandardowy php do osiągnięcia. Nie trzeba mylić ze skryptem powłoki.
załóżmy, że chcesz uruchomić php /home/mypath/example.php, jeśli nie jest uruchomiony
Następnie użyj następującego niestandardowego skryptu php, aby wykonać to samo zadanie.
utwórz następujący /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); } ?>
Następnie w swoim cronie dodaj następujące
* * * * * php /home/mypath/forever.php 'php /home/mypath/example.php'
źródło
Rozważ użycie pgrep (jeśli jest dostępne) zamiast ps piped przez grep, jeśli zamierzasz iść tą drogą. Chociaż osobiście mam dużo kilometrów ze skryptów formularza
while(1){ call script_that_must_run sleep 5 }
Chociaż może to zawieść, a zadania cron są często najlepszym sposobem na podstawowe rzeczy. Po prostu inna alternatywa.
źródło
Dokumenty: https://www.timkay.com/solo/
Przykład
źródło