回答:
この機能を自動化し、迷惑や潜在的なバグを自分でやることを防ぎ、舞台裏で群れを使用することで古いロックの問題を回避するプログラムがいくつかあります(タッチだけを使用している場合はリスクです) 。私が使ってきたlockrun
し、lckdo
過去に、今がありますflock
素晴らしいです(utilの-linuxの新しめのバージョンで)(1)。使い方はとても簡単です。
* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job
flock -n file command
とのflock -n file -c command
?
-c
、「裸の」(非ながら、(manページあたりのように)シェルを介して指定されたコマンドを実行します-c
)フォームはただexec
与えられたコマンドがね。シェルを介して何かを入力すると、シェルのようなこと(;
またはで区切られた複数のコマンドを実行するなど&&
)を行うことができますが、信頼できない入力を使用している場合はシェル拡張攻撃も可能になります。
frequent_cron_job
毎分実行されていることを表示しようとする(仮想の)コマンドへの引数でした。有用なものは何も追加せず、混乱を引き起こしました(長年にわたって誰もいない場合はあなたのものです)ので、私はそれを削除しました。
シェルでの最良の方法は、flock(1)を使用することです
(
flock -x -w 5 99
## Do your stuff here
) 99>/path/to/my.lock
99
と>
それがある99> /...
前の実行が完了するまでスクリプトを待機させるかどうかを指定していません。「ジョブが互いに「積み重なる」ことを望まない」ということは、すでに実行されている場合はスクリプトを終了することを意味していると思います。
そのため、lckdoなどに依存したくない場合は、次のようにできます。
PIDFILE=/tmp/`basename $0`.pid
if [ -f $PIDFILE ]; then
if ps -p `cat $PIDFILE` > /dev/null 2>&1; then
echo "$0 already running!"
exit
fi
fi
echo $$ > $PIDFILE
trap 'rm -f "$PIDFILE" >/dev/null 2>&1' EXIT HUP KILL INT QUIT TERM
# do the work
これは、あなたが間違ったことをしていることの表れかもしれません。ジョブがそれだけ頻繁に頻繁に実行される場合は、クローンを解除してデーモン形式のプログラムにすることを検討する必要があります。
run-oneコマンドを使用することをお勧めします -ロックを処理するよりもはるかに簡単です。ドキュメントから:
run-oneは、一意の引数セットを持つコマンドの一意のインスタンスを1つだけ実行するラッパースクリプトです。これは、一度に複数のコピーを実行したくない場合に、cronジョブでしばしば役立ちます。
run-this-oneはrun-oneとまったく同じです。ただし、pgrepとkillを使用して、ユーザーが所有し、ターゲットコマンドと引数に一致する実行中のプロセスを見つけて強制終了します。run-this-oneは、一致するすべてのプロセスが停止するまで、一致するプロセスを強制終了しようとしてブロックすることに注意してください。
run-one-constantlyはrun-oneとまったく同じように動作しますが、COMMANDが終了するたびに「COMMAND [ARGS]」が再生成されます(ゼロまたは非ゼロ)。
keep-one-runningはrun-one-constantlyのエイリアスです。
run-one-until-successは、COMMANDが正常に終了する(つまりゼロを終了する)まで "COMMAND [ARGS]"を再生成することを除いて、run-one-constantlyとまったく同じように動作します。
run-one-until-failureはrun-one-constantlyとまったく同じように動作しますが、COMMANDが失敗して終了する(つまり、ゼロ以外で終了する)まで「COMMAND [ARGS]」が再生成されます。
systemdがリリースされたので、Linuxシステムには別のスケジューリングメカニズムがあります。
systemd.timer
中/etc/systemd/system/myjob.service
または~/.config/systemd/user/myjob.service
:
[Service]
ExecStart=/usr/local/bin/myjob
中/etc/systemd/system/myjob.timer
または~/.config/systemd/user/myjob.timer
:
[Timer]
OnCalendar=minutely
[Install]
WantedBy=timers.target
タイマーが次にアクティブになったときにサービスユニットがすでにアクティブになっている場合、サービスの別のインスタンスは開始されません。
起動時にジョブを開始し、各実行が終了してから1分後にジョブを開始する代替方法:
[Timer]
OnBootSec=1m
OnUnitInactiveSec=1m
[Install]
WantedBy=timers.target
重複したcronが実行されているなどの問題を解決するために1つのjarを作成しました。これは、javaまたはシェルcronです。Duplicates.CloseSessions( "Demo.jar")にcron名を渡すだけで、現在のcronを除き、このcronの既存のpidを検索して削除できます。このようなことをするメソッドを実装しました。文字列proname = ManagementFactory.getRuntimeMXBean()。getName(); 文字列pid = proname.split( "@")[0]; System.out.println( "現在のPID:" + pid);
Process proc = Runtime.getRuntime().exec(new String[]{"bash","-c"," ps aux | grep "+cronname+" | awk '{print $2}' "});
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String s = null;
String killid="";
while ((s = stdInput.readLine()) != null ) {
if(s.equals(pid)==false)
{
killid=killid+s+" ";
}
}
そして、再びシェルコマンドでkillid文字列を殺します
@Philip Reynoldsの回答は、ロックを取得せずに5秒間待機した後、コードの実行を開始します。次のFlockが機能していないようです @Philip Reynoldsの回答を修正しました
(
flock -w 5 -x 99 || exit 1
## Do your stuff here
) 99>/path/to/my.lock
そのため、コードが同時に実行されることはありません。代わりに、5秒待機した後、それまでにロックを取得しなかった場合、プロセスは1で終了します。