164

作成したデーモンの一種のウォッチドッグとしてcronジョブを設定しようとしています。デーモンがエラーになって失敗した場合、cronジョブで定期的に再起動する必要があります...これがどれほど可能かはわかりませんが、いくつかのcronチュートリアルを読んだところ、私が何をするかを見つけることができませんでした。探しています...

私のデーモンはシェルスクリプトから開始されるので、cronジョブを実行する方法を探しているのは、そのジョブの前回の実行がまだ実行されていない場合のみです。

私はこの投稿を見つけました。これは、ロックファイルを使用して実行しようとしていることの解決策を提供しましたが、それを実行するためのより良い方法があるかどうかはわかりません...

4

16 に答える 16

170

を使用しflockます。それは新しい。それは良いです。

これで、自分でコードを書く必要はありません。ここで他の理由をチェックしてください:https ://serverfault.com/a/82863

/usr/bin/flock -n /tmp/my.lockfile /usr/local/bin/my_script
于 2015-10-29T13:51:24.360 に答える
124

私が書いた印刷スプーラープログラムに対してこれを行います。これは単なるシェルスクリプトです。

#!/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分ごとに実行され、非常に効果的です。何らかの理由でプロセスが実行されていない場合は、特別な情報をメールで送ってもらいます。

于 2010-03-02T21:00:02.470 に答える
63

他の人が述べているように、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}"
于 2011-09-17T08:04:53.660 に答える
46

run-oneについて誰も言及していないのは驚くべきことです。私はこれで私の問題を解決しました。

 apt-get install run-one

run-one次に、crontabスクリプトの前に追加します

*/20 * * * * * run-one python /script/to/run/awesome.py

このaskubuntuSEの答えをチェックしてください。詳細情報へのリンクもあります。

于 2016-08-09T01:00:51.690 に答える
25

cronを介してそれを行おうとしないでください。cronにスクリプトを実行させてから、プログラムが実行されているかどうかをスクリプトに判断させ、必要に応じて開始します(これを行うには、Ruby、Python、またはお気に入りのスクリプト言語を使用できます)。

于 2010-03-02T20:59:14.280 に答える
10

crontabで直接ワンライナーとして実行することもできます。

* * * * * [ `ps -ef|grep -v grep|grep <command>` -eq 0 ] && <command>
于 2012-08-14T13:43:00.333 に答える
7

私がphpスクリプトを実行しているときにそれを行う方法は次のとおりです。

crontab:

* * * * * 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)は1より大きくなります。

したがって、php cronを実行している場合は、上記のコードをphpコードの先頭に追加すると、1回だけ実行されます。

于 2016-08-26T06:51:14.883 に答える
6

Earlzの回答のフォローアップとして、開始時に$ PID.runningファイルを作成し、終了時に削除するラッパースクリプトが必要です。ラッパースクリプトは、実行するスクリプトを呼び出します。ターゲットスクリプトが失敗したりエラーが発生したりした場合に備えて、ラッパーが必要です。pidファイルが削除されます。

于 2010-03-02T21:01:37.413 に答える
4

lockruncronジョブのラッパースクリプトを作成する必要はありません 。http://www.unixwiz.net/tools/lockrun.html

于 2014-10-20T17:36:52.957 に答える
3

monitなどの既存のツールを使用することをお勧めします。これにより、プロセスが監視および自動再起動されます。ここで利用可能なより多くの情報があります。ほとんどのディストリビューションで簡単に利用できるはずです。

于 2010-03-02T21:02:28.150 に答える
3
# 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
}

更新..群れを使用するより良い方法:

/usr/bin/flock -n /tmp/your-app.lock /path/your-app args 
于 2017-03-21T13:39:09.237 に答える
2

これは私を決して失敗させませんでした:

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}

cronジョブ

* * * * * /path/to/one.sh <command>
于 2016-10-09T14:02:16.313 に答える
1

rsandenの回答の改善として、次のことをお勧めします(コメントとして投稿しますが、十分な評判がありません...):

#!/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の終了ステータスのみに依存します。

于 2014-02-20T21:11:33.087 に答える
1

単純なカスタムphpで十分です。シェルスクリプトと混同する必要はありません。

実行していない場合は、php/home/mypath/example.phpを実行するとします。

次に、次のカスタムphpスクリプトを使用して同じ作業を行います。

次の/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'
于 2016-04-10T17:42:15.257 に答える
1

ドキュメント:https ://www.timkay.com/solo/

soloは、プログラムが一度に複数のコピーを実行するのを防ぐ非常に単純なスクリプト(10行)です。cronを使用すると、前のジョブが終了する前にジョブが実行されないようにするのに役立ちます。

* * * * * solo -port=3801 ./job.pl blah blah
于 2020-04-16T03:13:31.310 に答える
0

そのルートに行く場合は、grepを介してパイプされるpsではなくpgrep(使用可能な場合)を使用することを検討してください。個人的には、フォームのスクリプトから多くのマイレージを取得していますが

while(1){
  call script_that_must_run
  sleep 5
}

これは失敗する可能性がありますが、cronジョブ多くの場合重要なものに最適な方法です。ちょうど別の選択肢。

于 2013-05-05T02:28:12.403 に答える