如何以单例形式运行php进程

时间:2012-05-28 11:43:33

标签: php shell

我见过一个PHP代码,它使用shell命令来确定此进程是否正在运行,但我已经丢失了。你能给我一个如何做到这一点的提示吗?

想法是创建一个php文件,并使用 php -f 将此文件作为cron作业运行。脚本的执行时间可能是10秒,但也可能是10分钟。我需要让这个cron每分钟运行一次,如果来自流行分钟的cron仍在运行 - 停止新的cron并让另一个完成。

我在shell编程方面不是很好,所以我需要一些帮助。

P.S 这个想法是创建一个守护进程而不在后台放置无休止的PHP进程。

3 个答案:

答案 0 :(得分:3)

您应该尝试获取锁定文件上的独占非阻塞锁定。如果成功,您的进程是唯一正在运行的实例,您应该保持锁定直到您终止。如果你没有成功获得锁,那么已经有另一个正在运行的实例,你应该终止。

答案 1 :(得分:2)

出于多种目的,以下代码是可以的(可能存在竞争条件,但对于微小的cronjob,这可能非常罕见):

if (file_exists($lockfilename)) {
   ... // lock is already taken
} else {
   if ( !file_put_contents($lockfilename, $lockstring)) {
      error("unable to write $lockfilename");
   }
   $lock_taken = true;
   ... // do what you have to do
   if ( !unlink($lockfilename)) {
      warning("unable to unlink $lockfilename");
   }
   $lock_taken = false;
}

全局变量$lock_taken可能有助于确保在执行暂停时删除lockfile。 $lockstring可以是日期或Unix时间戳,如果它显然太旧(但filemtime()就足够了),这可能对删除锁有用。

如果你绝对不能冒险参加比赛,你必须做一些像

这样的事情
if ( !($lockfile = fopen($lockfilename, "x"))) {
   ... // lock is already taken
} else {
   $lock_taken = true;
   ... // write something to lockfile (optional)
   fclose($lockfile);
   ... // do what you have to do
   if ( !unlink($lockfilename)) {
      warning("unable to unlink $lockfilename");
   }
   $lock_taken = false;
}

但这仅适用于本地锁定文件。

答案 2 :(得分:1)

独占文件锁定方法优于“检查文件是否存在”,因为如果脚本在删除文件之前崩溃,则锁定仍然存在。

以下是文件锁定的代码:

//Allow only one instance
$fileHandler = fopen('file_lock.lock', 'w');
$hasLock = flock($fileHandler, LOCK_EX | LOCK_NB);
if (!$hasLock)
    die("Another instance is already running");

//do work

//release lock
flock($fileHandler, LOCK_UN);
fclose($fileHandler);

释放锁定块是可选的,因为系统将在脚本执行后自动释放锁定。