如何检查PHP脚本是否仍在运行?

9

我有一个监听队列的PHP脚本。理论上,它不应该死掉。是否有一些方法可以检查它是否仍在运行?类似于Ruby的God(http://god.rubyforge.org/)对于PHP的解决方案?

God是语言无关的,但最好有一个适用于Windows的解决方案。

13个回答

13
在Linux中运行以下命令ps:
ps -C php -f

您可以在PHP脚本中执行以下操作:

$output = shell_exec('ps -C php -f');
if (strpos($output, "php my_script.php")===false) { 
  shell_exec('php my_script.php  > /dev/null 2>&1 &');
}
上述代码列出所有正在运行的PHP进程,然后检查是否在运行进程列表中有"my_script.php",如果没有,则运行该过程,并且不等待该进程终止就继续执行其原来的操作。

请问您能否解释一下选项的含义? - famas23

13

我遇到了相同的问题,想要检查是否有脚本正在运行。因此我想出了以下方法并将其作为cron作业运行。它将正在运行的进程作为数组获取,并循环每个行并检查文件名。看起来工作得很好。请将#user#替换为您的脚本用户。

exec("ps -U #user# -u #user# u", $output, $result);
foreach ($output AS $line) if(strpos($line, "test.php")) echo "found";

5
只需在脚本后添加第二个命令。当/如果它停止时,第二个命令就会被调用。例如:
php daemon.php 2>&1 | mail -s "Daemon stopped" you@example.org

编辑:

从技术上讲,这会立即调用邮件程序,但仅在php脚本结束时才完成命令。这样做可以捕获php脚本的输出并包含在邮件正文中,这对于调试导致脚本停止的原因非常有用。


不,当php运行时,会执行邮件命令。但是一旦它停止,就会发送EOF,这会导致邮件程序发送邮件。 - Mez

3

简单的Bash脚本

#!/bin/bash
while [true]; do
    if ! pidof -x script.php;
    then
        php script.php &
    fi
done

1
另外,注意你的 CPU 使用率会飙升 :) - Chris Broadfoot
不是很广泛...我经常使用它(好吧,每分钟在cron作业中执行一次)。 - Mez
这里有太多的问题,我简直不敢相信。[true] 是无效的语法,你可以通过等待 PHP 脚本结束来摆脱 if 语句。 - Overv

2

虽然不是针对Windows的,但是……

我有几个长时间运行的PHP脚本,并且还有一个用shell脚本包装的脚本。你可以选择从脚本中返回一个值,该值将在shell脚本中被检查,以便退出、立即重启或睡眠几秒钟-然后重新启动。

这里是一个简单的示例,它只是一直运行PHP脚本,直到手动停止为止。

#!/bin/bash
clear
date
php -f cli-SCRIPT.php
echo "wait a little while ..."; sleep 10
exec $0

"exec $0"重新启动脚本,而不会创建一个稍后需要解开的子进程(同时占用资源)。这个bash脚本包装了一个邮件发送器,所以如果它退出并暂停一下也没问题。


这与我目前正在使用的上帝脚本几乎相同,绝对比忙等待好。 - Smokinn

2

以下是我为解决类似问题所做的工作。如果有其他人需要cron频繁执行参数化的php脚本,但只想让一个执行在任何时候运行,则可以添加以下内容到php脚本的顶部或创建一个共用方法。

$runningScripts = shell_exec('ps -ef |grep '.strtolower($parameter).' |grep '.dirname(__FILE__).' |grep '.basename(__FILE__).' |grep -v grep |wc -l');
if($runningScripts > 1){
    die();
}

1
你可以在你的crontab中写入类似以下内容的命令:
0 3 * * * /usr/bin/php -f /home/test/test.php my_special_cron

你的test.php文件应该像这样:

Your test.php文件应该像这样:

<?php

php_sapi_name() == 'cli' || exit;

if($argv[1]) {
   substr_count(shell_exec('ps -ax'), $argv[1]) < 3 || exit;
}

// your code here

那样你就只会有一个以 "my-special-cron" 为进程关键字的活动计划实例。因此,您可以在同一 PHP 文件中添加更多作业。 test.php system_send_emails sendEmails test.php system_create_orders orderExport

1

受Justin Levene答案的启发并对其进行了改进,因为ps -C在Mac上不起作用,而我需要它。因此,您可以在php脚本中使用它(可能只是在您需要保持守护程序活动之前),在Mac OS X 10.11.4和Ubuntu 14.04中进行了测试:

$daemonPath = "FULL_PATH_TO_DAEMON";
$runningPhpProcessesOfDaemon = (int) shell_exec("ps aux | grep -c '[p]hp ".$daemonPath."'");
if ($runningPhpProcessesOfDaemon === 0) {
    shell_exec('php ' . $daemonPath . ' > /dev/null 2>&1 &');
}

小而有用的细节:为什么要使用grep -c '[p]hp ...'而不是grep -c 'php ...'
因为在计算进程数时,grep -c 'php ...'将被计算为符合我们模式的进程。因此,使用php的第一个字母的正则表达式使我们的命令与我们搜索的模式不同。

0

如果您在直接检查 PHP 脚本方面遇到问题,您可以制作一个微不足道的包装器并进行检查。我对 Windows 脚本不够熟悉,无法在此处介绍如何操作,但在 Bash 中,它看起来像是...

wrapper_for_test_php.sh

#!/bin/bash
php test.php

然后你只需要像检查其他Bash脚本一样检查包装器:pidof -x wrapper_for_test_php.sh


0

一个可能的解决方案是使用套接字函数在端口上进行侦听。您可以使用简单的脚本检查套接字是否仍在侦听。即使像Pingdom这样的监控服务也可以监视其状态。如果它死了,套接字就不再侦听。

有很多解决方案...祝你好运。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接