8

CLI(cmd、bashなど)を介してプログラムを実行するために使用されるユーティリティ機能があります。STDOUTSTDERRおよびの 3 つの項目の配列を返しますEXIT CODE

これまでのところ、問題なくうまく機能しています。実際、私が抱えている問題は機能を妨げるものではありませんが、パフォーマンスが心配です。

問題は、場合によっては、PHP が同じコマンドを複数回 (私の場合は 3 回) 実行することです。

/**
 * Executes a program and waits for it to finish, taking pipes into account.
 * @param string $cmd Command line to execute, including any arguments.
 * @param string $input Data for standard input.
 * @param boolean $log Whether to log execution failures or not (defaults to true).
 * @return array Array of "stdout", "stderr" and "return".
 */
public static function execute($cmd,$stdin=null,$log=true){
    //static $once=true; if(!$once)die; $once=false;
    $proc=proc_open($cmd, array(
        0=>array('pipe','r'),
        1=>array('pipe','w'),
        2=>array('pipe','w')   ), $pipes);
    fwrite($pipes[0],$stdin);                fclose($pipes[0]);
    $stdout=stream_get_contents($pipes[1]);  fclose($pipes[1]);
    $stderr=stream_get_contents($pipes[2]);  fclose($pipes[2]);
    $return=proc_close($proc);
    if($return!=0 && $log)
        xlog('Error: Program execution returned failure.',$stdout,$stderr,$return);
    return array( 'stdout'=>$stdout, 'stderr'=>$stderr, 'return'=>$return );
}

コメント行 (9 行目) に注意してください。それはテスト用でした。これを有効にして、ターゲット プログラムが 1 回だけ実行されるようにしました (コードが何らかの形で同じ関数を呼び出している可能性があると考えていました)。しかし、その行を有効にしても、プログラムは複数回実行されました。

現状では、同じプログラムを (別の機会に) 実行しているコード内の 2 つの場所があります。コマンドラインはどちらも同じです。

ただし、プログラムが 1 回実行される場合と、PHP がプログラムを 3 回実行する場合があります。

Process Explorer でこの動作を監視して確認しています。Windows 7 x64 を使用しています。プログラムは PHP と同様に 32 ビットです。

編集:問題のプログラムはカスタム開発されており、新しいプロセスを開きません。

4

3 に答える 3

1

一度だけ実行されることをテストするコードに欠陥があるように見えます。

2 つの php プロセスを実行している場合、それらは静的変数を共有しません。そのため、同時リクエストにより、これが複数回実行される可能性があります。

$once次に、関数の最後で false に設定する必要があります。そうしないと、dieに到達しません。

関数が 2 回呼び出されているかどうかを確認するために、ログを追加してみてください。

外部アプリケーションを実行するだけのユニット/ストレス テストをいくつか作成します。複数のプロセスが表示される場合は、php コードではなく、アプリに何か問題があります。

于 2011-05-15T21:45:54.480 に答える
0

I know this may not be the best option, but this is what I did. Though this was on Linux, but I'm sure there is way to port this to Windows.

What I did, was run pgrep and check if there already existed a command like this and if it did simply exit. As you said you are running same command (with exact parameters), so just check if there already is a command running and act respectively.

I used this command:

$pid = shell_exec('pgrep -cfx "/* My command */"');
if ($pid > 1) return -1;
于 2011-05-17T06:08:05.237 に答える
0

とても奇妙です。そして、完全なコードなしでは理解するのは非常に困難です。

サーバーが同じページを何度も呼び出すことにストレスを感じている場合は、おそらく CPU のラウンド ロビン プロセスに関連している可能性が高いでしょう。同時にこのメソッドへの別の要求があるため、PHP には static 変数を false に設定する時間がありません。その他の可能性は、PHP が静的な値を適切に分離できず、このメソッドへの別の要求が、PHP が値を同期するまで別のメモリ位置を読み取る可能性があることです。

于 2011-05-17T05:26:15.857 に答える