0

它运行“某种恶魔”。

事实上,我的引导文件如下所示:

<?
$command = "php -f httpdocs/shell/run.php -- -job search/updater::run";
while(true) {
  passthru($command);
}

不幸的是,在 passthru 之后发生的事情涉及一些严重错误的东西,并且有时图书馆会冻结。我使用 tick 函数进行了调试,结果发现这是在等待while(!feof外部 http 资源......

但是,我想调度该过程,并且 while 循环完成的所有内容都触及文件。

当时间戳过时时,我想终止该进程并重新启动它。

但是 passthru 是阻塞的,所以它不会在那个脚本中到达那里。

我需要以某种方式将它分派到后台并有一个循环持续监视它是否仍在运行或文件修改时间戳是否过时并杀死旧进程并启动一个新进程,或者只是启动一个新进程。

我该怎么做,或者有更好/更简单的解决方案吗?

4

2 回答 2

1

不久前,我在命令行脚本上进行了失速检测。听起来有些事情需要发生......

1) 在您正在运行的命令中为 http:// 请求添加超时

2)您可以使用 while() 语句对其进行监控,您必须使用以下内容:

$stillRunning = true;
while ($stillRunning) {
    exec('ps -ef | grep httpdocs/shell/run.php', $processes); //will get all process which contain the path to the file

    //loop through all processes to determine if it's still running.  If so, grab the process ID and kill it'

    exec('kill '.$processId);

    //if it's still there, this will do the job
    if ($this->_ifProcessExists($processId)) {
        exec('kill -9 '.$processId);
    }

    sleep(2);
}

这是我为检测失速以满足我们的需求而构建的类...

<?php
/**
 * GMC Management Class
 * 
 */

class GMC {

    private $executablePath = '/usr/local/PNetT/PNetTCNetClient',
            $outPath = '/usr/local/PNetT/tmpData/SOB/',
            $workflowPath = '',
            $graphicPath = '',
            $logRecipient = 'my@email.com',
            $stalledThreshold = 10, //in seconds
            $originalProcesses = array(),
            $processes = array(),
            $log = array();

    public function __construct () {
        $this->workflowPath = $this->outPath.'workflows/';
        $this->graphicPath = $this->outPath.'graphics/';
    }

    /**
     * Adds an image to the GMC graphics directory
     * 
     * @param string $imgPath The absolute path of the image to add
     */
    public function addImage ($imgPath) {
        exec('cp '.$imgPath.' '.$this->graphicPath);
    }

    /**
     * Determines if a process is stalled
     */
    public function isStalled ($processes = false) {
        if ($processes === false) {
            $processes = $this->_getProcesses();
            $this->originalProcesses = $processes;
        }

        foreach ($processes as $process) {
            if (array_key_exists('duration', $process) && $process['duration'] <= (time() - $this->stalledThreshold)) {
                $this->_addLog("detected #".$process['processId']." as a stalled process");
                return true;
            }
        }

        return false;
    }

    /**
     * Fixes GMC's being stalled
     * Will also report the document that caused the stall
     */
    public function fixStalled () {
        $this->_restart();

        $this->reportLog();
    }

    /**
     * Sends the log to the development team for review
     */
    public function reportLog () {
        $body = "Here's a report how GMC was handled during this last stall:

Oldest process:\n
        ID | COMMAND\n";

        $oldest = $this->_getOldestProcess();
        $body .= "        ".$oldest['processId']." | ".$oldest['command']."\n";

        $body .= "
Logs:\n";

        foreach ($this->log as $log) {
            $body .= "        ".$log."\n";
        }

        $body .= "
Processes:\n
        ID | COMMAND\n";

        foreach ($this->processes as $process) {
            $body .= "        ".$process['processId']." | ".$process['command']."\n";
        }

        mail($this->logRecipient, 'GMC Stalled Report', $body);
    }

    /**
     * Restarts GMC
     * Must be conducted after GMC's stalled processes have been killed
     */
    private function _restart () {
        //kill all GMC processes
        foreach ($this->_getProcesses(true) as $process) {
            $this->_killProcess($process['processId']);
        }

        //restart GMC
        exec('bash /usr/local/PNetT/pnet.sh');

        $this->_addLog("GMC has been restarted");
    }

    /**
     * Restarts GMC
     * Must be conducted after GMC's stalled processes have been killed
     */
    private function _getOldestProcess () {
        $oldest = array(
            'timestamp' => 0,
            'processId' => 0
        );
        foreach ($this->_getProcesses() as $process) {
            if ($process['user'] == 'wwwuser' && $process['duration'] > $oldest['timestamp']) {
                $oldest = array(
                    'timestamp' => $process['duration'],
                    'processId' => $process['processId']
                );
            }
        }

        return $this->processes[$oldest['processId']];
    }

    /**
     * Get a list of all GMC processes
     */
    private function _getProcesses ($newList = false) {
        if ($newList == true || count($this->processes) == 0) {
            //exec('ps -ef | grep GMC', $processes);
            //sample processes for testing, above command is for live usage
            $processes = array(
                'ps -ef | grep GMC',
                'wwwuser   1767 31199  0 12:40 ?        00:00:00 /scripts/GMC/PNetT-5.1-SP1/PNetTCNetClient.bin -o /usr/local/PNetT/tmpData/SOB/workflows/master_ppo_sob_3col.wfd -e PDF -f /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069 Solution PPO 1500-15-20 MOCKUP_temp.pdf -useincluded * -difDataInput1 /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069 Solution PPO 1500-15-20 MOCKUP.txt -difDataInput2 /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069 Solution PPO 1500-15-20 MOCKUP-table.txt',
                'wwwuser   2364  1207  0 12:41 ?        00:00:00 /scripts/GMC/PNetT-5.1-SP1/PNetTCNetClient.bin -o /usr/local/PNetT/tmpData/SOB/workflows/master_ppo_sob_3col.wfd -e PDF -f /usr/local/PNetT/tmpData/SOB/Master PPO-LP2045 mock up_temp.pdf -useincluded * -difDataInput1 /usr/local/PNetT/tmpData/SOB/Master PPO-LP2045 mock up.txt -difDataInput2 /usr/local/PNetT/tmpData/SOB/Master PPO-LP2045 mock up-table.txt',
                'wwwuser   2465  2378  0 12:42 ?        00:00:00 /scripts/GMC/PNetT-5.1-SP1/PNetTCNetClient.bin -o /usr/local/PNetT/tmpData/SOB/workflows/master_ppo_sob_3col.wfd -e PDF -f /usr/local/PNetT/tmpData/SOB/Master PPO-PBARR Test 12-20_temp.pdf -useincluded * -difDataInput1 /usr/local/PNetT/tmpData/SOB/Master PPO-PBARR Test 12-20.txt -difDataInput2 /usr/local/PNetT/tmpData/SOB/Master PPO-PBARR Test 12-20-table.txt',
                'wwwuser  19370  7900  0 13:17 ?        00:00:00 /scripts/GMC/PNetT-5.1-SP1/PNetTCNetClient.bin -o /usr/local/PNetT/tmpData/SOB/workflows/master_ppo_sob_3col.wfd -e PDF -f /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069_temp.pdf -useincluded * -difDataInput1 /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069.txt -difDataInput2 /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069-table.txt',
                'root     19948 19508  0 13:18 pts/6    00:00:00 grep GMC',
                'wwwuser  26685 17061  0 12:25 ?        00:00:00 /scripts/GMC/PNetT-5.1-SP1/PNetTCNetClient.bin -o /usr/local/PNetT/tmpData/SOB/workflows/diff_report.wfd -e PDF -f /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069 Solution PPO 1500-15-20 MOCKUP_differences.pdf -useincluded * -difDataInput1 /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069 Solution PPO 1500-15-20 MOCKUP-report.txt -difDataInput2 /usr/local/PNetT/tmpData/SOB/Master PPO-LP2069 Solution PPO 1500-15-20 MOCKUP-table-report.txt',
                'root     32017     1 89 May03 ?        12-18:02:22 /scripts/GMC/PNetT-5.1-SP1/PNetTNetServer.bin -tempdir /usr/local/GMC/PNetT-5.1-SP1/tmpData -D'
            );

            $this->processes = array();
            foreach ($processes as $idx => $process) {
                if ($idx > 1) {
                    $pieces = preg_split("/\s+/", $process, 8);

                    //skip the grep filter process
                    if ($pieces[7] != 'grep GMC') {
                        $this->processes[$pieces[1]] = array(
                            'user' => $pieces[0],
                            'processId' => $pieces[1],
                            'duration' => strtotime($pieces[4]),
                            'command' => $pieces[7]
                        );
                    }
                }
            }
        }

        return $this->processes;
    }

    /**
     * Kills a process
     * 
     * @param int $processId The process to be killed
     */
    private function _killProcess ($processId) {
        //nicely
        exec('kill '.$processId);

        //if it's still there, this will do the job
        if ($this->_ifProcessExists($processId)) {
            exec('kill -9 '.$processId);

            $this->_addLog("process #".$processId." wasn't nicely killed, I had to force it");
        } else {
            $this->_addLog("process #".$processId." was nicely killed");
        }
    }

    /**
     * Determines if a process is still running
     * 
     * @param int $processId The process to be checked
     */
    private function _ifProcessExists ($processId) {
        exec('ps '.$processId, $return);

        return count($return) > 1;
    }

    /**
     * Adds a message to the log
     */
    private function _addLog ($message) {
        $this->log[] = $message;
    }
}

?>
于 2012-10-05T12:41:33.657 回答
0

事实上,解决问题比解决问题要好。就我而言,我正在处理第 3 方代码。然而 phps 滴答处理功能使我能够查明正确的代码部分,并且问题就在 php.net 主页上作为一个大警告以及解决方案。

它与超时无关,而是与此函数在损坏的套接字上的行为有关。

警告 如果 fsockopen() 打开的连接没有被服务器关闭,feof() 将挂起。要解决此问题,请参见以下示例:

Example #1 使用 feof() 处理超时

返回 feof($fp); }

/* 假设 $fp 之前被 fsockopen() 打开 */

$开始=空;$timeout = ini_get('default_socket_timeout');

while(!safe_feof($fp, $start) && (microtime(true) - $start) < $timeout) { /* 句柄 */ } ?>

于 2012-10-09T15:41:53.813 回答