【问题标题】:knowing whether a php script is still running知道 php 脚本是否仍在运行
【发布时间】:2013-01-01 06:02:00
【问题描述】:

我有一堆 php 脚本计划在 CentOS 机器上的 cron 中每隔几分钟运行一次。我希望每个脚本在启动时自行检查它的前一个实例是否仍在运行,如果是则停止。

【问题讨论】:

  • 使用下面提到的锁文件,或者使用数据库,它可以比锁文件做更多的事情,例如存储统计:开始/停止时间,手动cron启动,它也支持锁定。

标签: php cron centos


【解决方案1】:

我这样做是为了管理任务并确保它们一次只运行一个

public function startTask($taskname)
{
    $running = "running";
    $lockfile = $taskname . "RUNNING";
    file_put_contents($lockfile, $running);
}

public function endTask($taskname)
{
    $lockfile = $taskname . "RUNNING";
    unlink($lockfile);
}

public function isTaskRunning($taskname)
{
    $lockfile = $taskname . "RUNNING";
    if (file_exists($lockfile))
    {
        return true;
    }
}

您在开始任务时调用startTask('name'),然后在完成时调用endTask('name')。在你使用的任务的第一行

if (isTaskRunning('name')) {
   die('already running');
}

将这些放在配置类或所有任务文件中包含的东西中

【讨论】:

  • 不错,非常巧妙的解决方案。从现在开始一定会使用它。
  • @VladPreda 又好又简单... :-)
  • 需要取消对 php 的链接权限...仔细选择您的 apache 用户!
  • @Sebas OP 正在使用 CRONTAB 而不是 Web 服务器运行脚本......但我明白你的意思
  • 你说得对,我很傻,这实际上可能就是他以这种方式执行取消链接的原因。
【解决方案2】:

使用锁定文件:

<?php
$lockfile = "/tmp/lock.txt";
$fp = fopen($lockfile, "r+");

if (flock($fp, LOCK_EX)) {  // acquire an exclusive lock
    ftruncate($fp, 0);      // truncate file
    fwrite($fp, sprintf("Started: %s\nPID: %s", date(), getmypid()));

    // perform your tasks here.

    fflush($fp);            // flush output before releasing the lock
    flock($fp, LOCK_UN);    // release the lock
} else {
    echo "Couldn't get the lock!\nCheck $lockfile for more info.";
}

fclose($fp);

【讨论】:

  • 所以你将这段代码复制并粘贴到每个任务中?只是说他们有20个任务?当您想更改临时文件名时会发生什么?
  • @ManseUK 呃...在包含文件中创建一些函数?定义一个对象? 编辑代码以满足他们的需要?我不记得说过“这是你将使用的确切代码sn-p,你永远不能修改它”。这是一个演示功能的基本示例。
【解决方案3】:

或者,如果您使用的是数据库,您可以像这样创建数据库Named Lock

<?php

$process = "myProcess";

$sql = mysql_query("select get_lock('$process', 0)");
$got_lock = (bool)mysql_fetch_array($sql)[0];

// If process is already running exit
if(!$got_lock){
    echo "Process running";
    exit;
}

// Run my process
for($i=0;$i<100000000;$i++){
    echo $i;
}

// Release the lock
mysql_query("select release_lock('$process')");

这种形式的锁定称为named lock,它不会“锁定”数据库,它只是创建一个“命名锁定”,当您调用它时,它会检查名称是否存在。它与table lockrow lock 完全不同,它内置于mysql 中,用于其他应用程序,例如this。

您可以拥有任意数量的锁,一旦应用程序结束,它们就会自动释放,例如您的客户端与 mysql 断开连接:进程完成、php 中断/崩溃、mysql 崩溃(这不是 100% 确定)等。

【讨论】:

  • 因此您可以将列更新为 1,然后再更新为 0...如果为零,则可以运行第二个脚本...
【解决方案4】:

您可以在 PHP 脚本的末尾添加一个简单的回显(可能带有 date()),这将在您的 cron 日志中可见,并显示脚本是否到达末尾(然后完成其任务)

【讨论】:

  • 那如何满足每个脚本自检的OPs请求?
  • 好吧,脚本可以检查日志文件搜索那个'echo at the end'字符串来说明之前的实例是否已经完成。顺便说一句,我赞成你的回答,我觉得它更有条理 ^^'
猜你喜欢
  • 1970-01-01
  • 2010-09-12
  • 1970-01-01
  • 2022-10-11
  • 2012-03-09
  • 2010-11-29
  • 2010-10-11
  • 2023-03-17
相关资源
最近更新 更多