3

我看到了一个 PHP 代码,它使用 shell 命令来确定这个进程现在是否正在运行,但我把它弄丢了。你能给我一个提示如何做到这一点吗?

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

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

PS 这个想法是创建一个守护进程,而不会将无休止的 PHP 进程置于后台。

4

3 回答 3

3

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

于 2012-05-28T11:48:13.123 回答
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可能有助于确保在执行停止时删除锁定文件。可以是日期或 Unix 时间戳,如果它明显太旧(但可能就足够了),$lockstring它可能对移除锁很有用。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;
}

不过,这只适用于本地锁文件。

于 2012-05-28T12:30:50.617 回答
2

独占文件锁定方法比“检查文件是否存在”方法更好,因为如果脚本在您删除文件之前崩溃,那么锁定仍然存在。

这是文件锁定的代码:

//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);

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

于 2013-04-07T05:39:49.737 回答