我有一个cron脚本,每10分钟执行一次PHP脚本.该脚本检查队列并处理队列中的数据.有时队列有足够的数据可以持续超过10分钟的处理,从而产生了两个脚本试图访问相同数据的可能性.我希望能够检测脚本是否已经运行以防止启动脚本的多个副本.我想过创建一个数据库标志,说明脚本正在处理,但如果脚本崩溃,它会使它处于正状态.有没有一种简单的方法可以判断PHP脚本是否已经使用PHP或shell脚本运行?
Mar*_*ery 35
您只需使用锁定文件即可.PHP的flock()函数为Unix 的函数提供了一个简单的包装器flock,它提供了对文件的建议锁.
如果您没有明确地释放它们,操作系统将在持有它们的进程终止时自动释放这些锁,即使它异常终止.
您还可以遵循松散的Unix惯例,即将锁定文件设置为"PID文件" - 也就是说,在获取文件锁定后,让脚本将其PID写入其中.即使你从未在脚本中读过这个内容,如果你的脚本挂起或发疯并且你想找到它的PID以便手动杀死它,它将会很方便.
这是一个复制/粘贴就绪的实现:
#!/usr/bin/php
<?php
$lock_file = fopen('path/to/yourlock.pid', 'c');
$got_lock = flock($lock_file, LOCK_EX | LOCK_NB, $wouldblock);
if ($lock_file === false || (!$got_lock && !$wouldblock)) {
throw new Exception(
"Unexpected error opening or locking lock file. Perhaps you " .
"don't have permission to write to the lock file or its " .
"containing directory?"
);
}
else if (!$got_lock && $wouldblock) {
exit("Another instance is already running; terminating.\n");
}
// Lock acquired; let's write our PID to the lock file for the convenience
// of humans who may wish to terminate the script.
ftruncate($lock_file, 0);
fwrite($lock_file, getmypid() . "\n");
/*
The main body of your script goes here.
*/
echo "Hello, world!";
// All done; we blank the PID file and explicitly release the lock
// (although this should be unnecessary) before terminating.
ftruncate($lock_file, 0);
flock($lock_file, LOCK_UN);
Run Code Online (Sandbox Code Playgroud)
只需将锁定文件的路径设置为您喜欢的位置即可.
小智 6
如果您正在运行Linux,这应该在您的脚本顶部工作:
$running = exec("ps aux|grep ". basename(__FILE__) ."|grep -v grep|wc -l");
if($running > 1) {
exit;
}
Run Code Online (Sandbox Code Playgroud)