somemo programming etc.

プログラマ、雑記、プログラミング関係はLinkから、数式はこっちでまとめていることが多い

【php】Web画面からのシステムコマンドを非同期で起動

よく使うので忘れないようにメモ

その前にまずはOS判断について
OS判断をする理由は非同期で実行する際の関数が違うからです。
ここでのOSはLinux系とWindows系の2種類とします。

判別は、phpの定数「PHP_OS」が用意されているのでそれを使えば簡単にできます。
この定数の値が
"WIN32" または "WINNT"のときにwindowsの処理を行うようにします。
また、実行するファイルのパスに含まれるディレクトリの区切り文字が違います。
しかし、上記の判定によって変えなくとも定数「DIRECTORY_SEPARATOR」が用意されています。
長いので、フレームワークによってはさらに定義されてDSなどになっていることもありました。

Linux系でのコマンド:
 exec: http://www.php.net/manual/ja/function.exec.php
 または、
 system: http://www.php.net/manual/ja/function.system.php
を使用します。

それぞれの第1引数にコマンドを渡し実行する。
exec("php 実行ファイル名 2>&1/dev/null &");
これで「同期」しながらの実行は完了です。
出力の設定はご自由に。

Windwosでは、exec・systemを用いて非同期実行できません。

下記の関数を用いて実行します。
 popen: http://php.net/manual/ja/function.popen.php
 または、
 proc_open: http://www.php.net/manual/ja/function.proc-open.php

popen: command で指定したコマンドのフォークによってできたプロセスへのパイプをオープンします。
⇒フォーク(fork): http://ja.wikipedia.org/wiki/Fork

要するに、現在のプロセスとは独立した新たなプロセスを作成するようです。
proc_openは、popenより詳細な設定ができるようです。
今回は、popenを用いて実行してみました。

$fp = popen("start 実行ファイル名", 'r');
pclose($fp);

startをつけることで非同期として実行します。

サンプル

html部分
<html>
<head>非同期テスト<head>
<title>非同期テスト</title>
<body>
    <form action="async.php" method="post">
        <input type="submit" name="submit" value="submit" />
    </form>
<body>
async.php(リクエスト応答部分)
<?php
$fp = popen("start php background.php", 'r');
pclose($fp);

echo date('Y/m/d H:i:s');
background.php(非同期実行部分)
<?php
for ($i = 0; $i < 30000000; $i++) {
    ;
}
file_put_contents(date('Ymd_His') . '.txt', '');
リクエストに対するレスポンスとして日付の表示し、 非同期部分でループ処理後に、日付ファイルの出力をしています。 30000000回ループで3秒くらいかかったので、非同期であることを実感できました