PHP スクリプトを定期的に実行する必要がある最初に思いつくのは、crond コマンドでこの機能を実装することです。しかし、クロンの処刑中に奇妙なことが判明した。 crondでの設定は以下の通りです。
*/1 * * * * root /usr/bin/flock -xn /tmp/test.lock -c '/usr/bin/php /home/hailong/test.php > /tmp/test.tt 2>&1'
スクリプトは初回のみ正常に実行され、再度実行されることはありません。 /tmp/test.lock ファイルを削除すると、PHP スクリプトは再び正常に実行できるようになります。一度実行すると再度正常に実行することはできません。
余談:
ご覧のとおり、設定ファイルの最後に 2>&1 が追加されています。なぜ 2>&1 を追加するのでしょうか?ブログ投稿「エコーによるプロセスクラッシュ」をチェックしてください
さらに、注意深い友人なら、flock コマンドを使用したことにも気づくでしょう。 flock コマンドは、スクリプトが同時に繰り返し実行されるのを防ぐために使用されます。 crond スクリプトの同時実行および繰り返し実行を制御するその他の方法については、「Crond スクリプト実行における同時実行競合の解決」を参照してください。
crond 設定から flock を削除します。以下の通り:
*/1 * * * * root /usr/bin/php /home/hailong/test.php > /tmp/test.tt 2>&1
スクリプトが正常に実行できることがわかりました。それはフロックの問題に違いない。 flock は成熟した Linux コマンドなので、問題が発生する可能性はほとんどありません。最も可能性として考えられるのは、PHP コードの一部が flock と競合していることです。 PHP コードは次のとおりです。
<?php$f = popen("/home/exfilter restart", "r");while(!feof($f)) { $content = fgets($f, 1024); if (strpos($content, "start success") !== false) { break; }}pclose($f);file_put_contents("/tmp/test.log", date("Y-m-d H:i:s"));?>
前にも言いましたが、初回のみ flock のロック ファイルが存在しないため、正常に実行できます。ロックファイルが存在すると正常に実行されなくなります。 PHP プログラムの実行後、flock はファイルのロックを解放しません。 /tmp/test.lock ファイルがどのファイルによって占有されているかを見てみましょう。
[hailong@vhost ~]$ sudo /usr/sbin/lsof | grep test.lockexfilter 29821 root 3r REG 202,1 0 90439710 /tmp/test.lock[hailong@vhost ~]$ ps aux | grep 29821root 29821 0.1 0.2 175224 22596 ? Ssl 07:46 0:00 /home/exfilter -d56667 30068 0.0 0.0 69460 852 pts/0 S+ 07:49 0:00 grep 29821
test.lock ファイルが、PHP プログラムの Popen 関数によって開始されたプロセスによって占有されていることがわかります。デーモンプロセスが起動されるため、プロセスは終了せず、常にロックが占有されます。
flock コマンドを有効にして、代わりに他の方法を使用してください。その他の方法については、ブログ投稿「Crond スクリプト実行における同時実行競合の問題の解決」を参照してください。
Linux システム上のファイル ロックは、主に勧告ロックと必須ロックに分けられます。 Linux で使用されるファイル ロックのほとんどは協調ロックであり、強制ロックを使用する場合は、システムが強制ロックをサポートしているかどうかも確認する必要があります
協調ロックでは、ロックが機能する前にユーザー プロセスがファイル ロックを積極的に適用する必要があります。たとえば、プロセス A がファイルに協調ロックを追加した場合、プロセス B がロックを適用せずにファイルに直接書き込む場合にも可能です。
強制ロックはオペレーティング システム カーネルによって保証されています。ユーザープロセスが独自に申請する必要はありません。
flock コマンドは協調ロックを使用します。
メインプロセスがファイルロックを取得すると、フォークされた子プロセスもファイルロックを取得します。
元のリンク: crond で flock コマンドを使用する場合の落とし穴、転載する場合は出典を明示してください。