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 标志。
这是手册页O_EXCL
的解释:
O_EXCL - 如果设置了 O_CREAT 和 O_EXCL,如果文件存在,则 open() 将失败。检查文件是否存在以及如果文件不存在则创建文件对于执行 open() 的其他线程在同一目录中命名相同的文件名并设置了 O_EXCL 和 O_CREAT应该是原子的。如果设置了 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
再次运行而不会出现问题。