cron、毎分RAMの問題

cron、毎分RAMの問題

私は、WordPress の cron.php ファイルで PHP を実行する cronjob を持っています。これは主に投稿をスケジュールするために使用され、キャッシュを更新する可能性があると考えています。

私は cron ジョブを 1 分ごとに実行しています。頻繁に ps をチェックしたところ、2 つの PHP インスタンスが cron.php を実行しているのがわかりました。1 つのインスタンスを実行するだけで必要なことはすべて実行されるため、これは不要です。RAM をチェックする別のジョブがあり、2 つのインスタンスがそれをトリップすることがあります (常に大量の RAM が使用可能であると予想しており、それを下げることもできますが、そうしたくありません)。1 つのジョブに 1 分以上かかることはまず考えられません (かかる場合もありますが)。

プロセスがすでに存在する場合、ジョブを実行せずに実行するにはどうすればよいですか? PHP コード自体は、データベースに接続/使用しない限りチェックできないと思います。使用できる cron コマンドはありますか? 1 分を超える場合はインスタンスを強制終了したくありません。新しいインスタンスを生成しないだけです。

答え1

ここに簡単な bash スクリプト ソリューションがあります。おそらく cron.php スクリプトでも同じことができます。これは実際に、実行時間が長すぎるプロセスをチェックします。自動化システムの場合、これはおそらく良いアイデアです。

#!/bin/bash

# Exit if process is already running
if test -e /tmp/wordpress-job.pid; then
  # Check if the pid that was stored in /tmp/wordpress-job.pid does exist
  if ps ax -o pid= | grep $(cat /tmp/wordpress-job.pid ) &> /dev/null; then
    exit 0
  fi
fi

# Create the file that marks this process as running
echo $$ > /tmp/wordpress-job.pid

# Some extra security check to prevent the pid file
# to survive.
trap "rm -f /tmp/wordpress-job.pid" EXIT TERM INT HUP 

# Start the long-running process in the background
sleep 3600 & # long-running process

# Sleep some time before trying to kill that process
sleep 300

# Kill job if it takes longer than it should
kill %1

# Delete the file that marks this process as running
rm -f /tmp/wordpress-job.pid

「sleep 3600」を PHP コマンドラインに置き換え、以下の 300 をスクリプトの実行が許可される最大時間に変更する必要があります。

答え2

crontab エントリで以下を実行します:

if mv /var/run/my-php-job.pending /var/run/my-php-job.running 2>/dev/null; then
  echo $$ >|/var/run/my-php-job.running   # optional
  … # run the job
  : >|/var/run/my-php-job.running         # optional
  mv /var/run/my-php-job.running /var/run/my-php-job.pending
fi

これを crontab エントリに入力します@reboot:

rm -f /var/run/my-php-job.running
touch /var/run/my-php-job.pending

ファイル名はロックとして機能します。 の間は.running実行中のジョブがあり、次のジョブは開始されません。 のとき.pending、実行中のジョブが開始され、 に切り替わります.running

.runningオプションの行を含めると、ジョブが停止した場合の調査のために、シェルのプロセス ID がファイルに書き込まれます。ログ ファイルを使用すると、これはほとんど不要になります。

ジョブを実行しているシェルがクラッシュした場合 (これは起こりにくいことですが、誰かが故意にシェルを強制終了した場合やメモリ不足の場合にのみ発生するリスクがあります)、ロック ファイルは で停止します.running(ジョブ自体がクラッシュした場合は問題ありません)。以前のスクリプトの突然の終了を検出することはできますが、非常に困難です。

答え3

並列実行を回避するための特別なユーティリティがあります: util-linux の flock、BSD システムの lockf、NetBSD および INN と cnews パッケージの shlock。

最も可能性の高いケース (Linux) では、次のようなものを呼び出します。

flock -w 60 /somedir/lockfile cron.php

他の回答のレシピは自家製の群れの代替品であり、そのようなツールがない場合にのみ役立ちます。

一方、プログラム内でこのようなロックを直接処理することもできますが、すべての詳細を慎重に繰り返す必要があります。そうしないと、競合状態が発生する可能性があります。

関連情報