0

「ある種のデーモン」を実行します。

実際、私のブートストラップ ファイルは次のようになります。

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

残念ながら、パススルーの後に起こっていることには、いくつかの非常にバグのあるものが含まれており、ライブラリがフリーズすることがあります。while(!feoftick 関数を使用してデバッグしたところ、外部の http リソースを何らかの形で待機していることが判明しました....

ただし、プロセスをディスパッチしたいと思います。while ループが終了するすべてのものがファイルに触れます。

タイムスタンプが古くなったら、プロセスを強制終了して再起動します。

ただし、パススルーはブロックされているため、そのスクリプトではそこに到達しません。

どういうわけかそれをバックグラウンドにディスパッチし、まだ実行されているか、ファイルの変更タイムスタンプが古くなって古いプロセスを強制終了し、新しいプロセスを開始するか、新しいプロセスを開始するかを継続的に監視するループを用意する必要があります。

どうすればこれを行うことができますか、またはより良い/より簡単な解決策がありますか?

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

実際、問題を回避するよりも、問題を解決する方が適切です。私の場合、サードパーティのコードを扱っていました。ただし、phpsティック処理関数を使用すると、正しいコード部分を特定することができ、問題はphp.netホームページで、解決策とともに大きな警告として正しく表示されていました。

タイムアウトとは関係ありませんが、壊れたソケットでのこの関数の動作とは関係ありません。

警告fsockopen()によって開かれた接続がサーバーによって閉じられなかった場合、feof()はハングします。これを回避するには、以下の例を参照してください。

例1feof()を使用したタイムアウトの処理

feof($ fp);を返します。}

/ * $ fpが以前にfsockopen()によって開かれたと仮定します* /

$ start = NULL; $ timeout = ini_get('default_socket_timeout');

while(!safe_feof($ fp、$ start)&&(microtime(true)-$ start)<$ timeout){/*ハンドル*/}?>

于 2012-10-09T15:41:53.813 に答える