php - 确保Linux上只有一个正在运行的PHP进程

标签 php linux cron

我有一个每分钟从 cron 运行的 php 脚本。但有时它的工作时间超过 1 分钟。 我的问题是:确保当前只有一个进程在运行的最佳方法是什么?

我使用这段代码:

$output = shell_exec('ps aux | grep some_script.php | grep -v grep');   //get all processes containing "some_script.php" and exclude current grep process
$trimmed = rtrim($output, PHP_EOL); //trim newline symbol in the end
$processes = explode(PHP_EOL, $trimmed);    //get the array of lines (i.e. processes)
$procCnt = count($processes);   //get number of lines
if ($procCnt > 2) {
  echo "busy\n";
  exit();       //exit if number of processes more than 2 (see explaination below)
}

如果有一个 some_script 进程从 cron 运行,shell_exec 会返回类似这样的内容:

apache     13593  0.0  0.0   9228  1068 ?        Ss   18:20   0:00 /bin/bash -c php -f /srv/www/robot/some_script.php 2>&1
apache     13602  0.0  0.0 290640 10544 ?        S    18:20   0:00 php -f /srv/www/robot/some_script.php

所以如果我有超过 2 行的输出,我调用 exit()

我想问:我走的路对吗?或者有更好的方法吗?

任何帮助将不胜感激

最佳答案

以这种方式检查会创建一个竞争条件,其中两个进程可以同时检索列表,然后都决定退出。根据您尝试执行的操作,这可能是问题,也可能不是问题。

一个可能更好的选择是创建某种锁。我使用的一个简单的目录是仅在进程运行时存在的目录 - mkdir是原子的,它要么成功(没有其他进程在运行)要么失败(另一个进程已经创建了它)。只需确保在完成后将其删除:

if (!mkdir("lock_dir")) {
   echo "busy\n";
   exit();
}
register_shutdown_function(function() {
   rmdir("lock_dir");
});

或者更好,它看起来像 flock是出于类似的目的而制作的。这是手册中的示例:

<?php

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

if (flock($fp, LOCK_EX)) {  // acquire an exclusive lock
    ftruncate($fp, 0);      // truncate file
    fwrite($fp, "Write something here\n");
    fflush($fp);            // flush output before releasing the lock
    flock($fp, LOCK_UN);    // release the lock
} else {
    echo "Couldn't get the lock!";
}

fclose($fp);

?>

只需锁定脚本的运行时,类似于我的第一个示例。

关于php - 确保Linux上只有一个正在运行的PHP进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20525023/

相关文章:

node.js - 如何在 Node.js 中管理 Cron 作业

git pull 的 Cron 作业

php - 单个表单提交的 if 语句中单个字段的多个更新查询

linux - bash 脚本似乎无法执行 linux 命令

php - CentOS 5 上用于 PHP 5.3 的 PECL OAuth

linux - Windows是否可以进行无密码身份验证

python - 如何用文件B中的第n行替换文件A中第n个出现的字符?

curl - 如何使 crontab 与 URL 中的curl 和& 符号一起使用?

php - 如何避免在mysql数据库中出现负值

php - 查询异常期间失去与 MySQL 服务器的连接