x
ロックファイルを開くときは、フラグを使用する必要があります。
<?php
$lock = '/tmp/myscript.lock';
$f = fopen($lock, 'x');
if ($f === false) {
die("\nCan't acquire lock\n");
} else {
// Do processing
while (true) {
echo "Working\n";
sleep(2);
}
fclose($f);
unlink($lock);
}
PHPマニュアルからの注意
' x ' - 書き込み専用に作成して開きます。ファイルポインタをファイルの先頭に置きます。ファイルが既に存在する場合、fopen() 呼び出しは FALSE を返し、レベル E_WARNING のエラーを生成して失敗します。ファイルが存在しない場合は、作成してみてください。これは、基礎となる open(2) システムコールに O_EXCL|O_CREAT フラグを指定することと同じです。
そして、ここにmanページO_EXCL
からの説明があります:
O_EXCL - O_CREAT と O_EXCL が設定されている場合、ファイルが存在する場合、open() は失敗します。ファイルが存在するかどうかのチェックと、存在しない場合のファイルの作成は、O_EXCL と O_CREAT が設定された同じディレクトリで同じファイル名を指定して open() を実行する他のスレッドに関してアトミックである必要があります。O_EXCL と O_CREAT が設定され、パス名がシンボリック リンクの場合、シンボリック リンクの内容に関係なく、open() は失敗し、errno を [EEXIST] に設定します。O_EXCL が設定され、O_CREAT が設定されていない場合、結果は未定義です。
更新:
より信頼性の高いアプローチ - ロックを取得し、ワーカー スクリプトを実行してロックを解放するメイン スクリプトを実行します。
<?php
// File: main.php
$lock = '/tmp/myscript.lock';
$f = fopen($lock, 'x');
if ($f === false) {
die("\nCan't acquire lock\n");
} else {
// Spawn worker which does processing (redirect stderr to stdout)
$worker = './worker 2>&1';
$output = array();
$retval = 0;
exec($worker, $output, $retval);
echo "Worker exited with code: $retval\n";
echo "Output:\n";
echo implode("\n", $output) . "\n";
// Cleanup the lock
fclose($f);
unlink($lock);
}
ここに労働者が行きます。その中で偽の致命的なエラーを発生させましょう:
#!/usr/bin/env php
<?php
// File: worker (must be executable +x)
for ($i = 0; $i < 3; $i++) {
echo "Processing $i\n";
if ($i == 2) {
// Fake fatal error
trigger_error("Oh, fatal error!", E_USER_ERROR);
}
sleep(1);
}
これが私が得た出力です:
galymzhan@atom:~$ php main.php
Worker exited with code: 255
Output:
Processing 0
Processing 1
Processing 2
PHP Fatal error: Oh, fatal error! in /home/galymzhan/worker on line 8
PHP Stack trace:
PHP 1. {main}() /home/galymzhan/worker:0
PHP 2. trigger_error() /home/galymzhan/worker:8
重要な点は、ロック ファイルが適切にクリーンアップされるmain.php
ため、問題なく再実行できることです。