【PHP】exec()から非同期な別プロセスを起動する方法【Windows・Linux両方】

PHPにはexec関数があります。

これを使って他スクリプトを起動する時…

  • 別のPHPスクリプトを起動したい
  • ただし独立した別プロセスで動かしたい
  • つまり非同期的に実行したかった

こういう感じで使う方法を探していました。

これには一部OS固有の方法が必要になります。
それも含めて具体的コード例をまとめました。

そもそもexec関数は何なのか?デフォルトの挙動

公式では次のように説明されています。

▼ php.netでのexec関数の解説

exec(string $command, array &$output = null, int &$result_code = null): string|false

exec() は指定されたコマンド command を実行します。戻り値 : コマンド結果の最後の行を返します。コマンドを実行し、 一切干渉を受けずに直接コマンドから全てのデータを受けとる必要が あるならば、passthru() 関数を使ってください。失敗時に false を返します。

引用元 : https://www.php.net/manual/ja/function.exec.php

▼ こんな感じで使える

たったこれだけですが・・・

問題は結果が返るまで待つことです。

普通の用途なら問題ないけど、Cronジョブで重い処理を別プロセスで実行したい場合、exec関数をそのまま使うのはメインプロセスで全部やるのと変わりません。

つまり「exec関数は無条件では別プロセスにならない」ということです。でも戻り値を気にしないなら、別プロセスとして起動することも可能です。

exec関数で非同期な別プロセスを作るコード例

ポイントは次の2点

  • 実行されるスクリプトの出力を捨てる
  • OS(Win/Linux)ごとに少し工夫が必要

これを考慮すれば別プロセスが起動できます。

例えば次のようなコードがその例です。

▼ exec()で別プロセス起動のコード例

重要なのは実行されるスクリプトの出力を廃棄することです。ファイルに書き出すという意味ではなく、データそのものを虚無に返しています。

そのためにLinuxでは /dev/null という特別なデバイスファイルがあり、Windowsでは nul というのが用意されてます( null ではなく nul なのが紛らわしい...)

  • Linux : /dev/null に捨てる
  • Windows : nul に捨てる

Macの場合も恐らく /dev/null のはずです。

ちなみにLinuxの処理にある >dev/null 2>&1 & は標準出力・エラー出力を破棄・バックグラウンド実行(&)するという意味です。

関連 - PHPプロセスの多重起動の防止について

少しだけ関係があるので蛇足で紹介

複数プロセスの多重起動禁止についてです。

▼ 例えばこういうケース

  • あるスクリプトをCronなどで定期実行
  • その間は同一スクリプトの起動を禁止
  • 複数プロセスを存在させたくない

今回のように別プロセスを動かしたり、Cronジョブからスクリプトを定期実行する場合、プロセスを多重起動させたくないこともあるはずです。

そういう時は ▼次記事 でも解説したように、flockによる排他的ロックを使えば複数プロセス起動を阻止できます(Windows・Linux両方対応 プラットフォーム関係なし)

こういう知恵が必要になる時も極まれにあります。

良ければ参考までにご覧ください。

まとめ - バックグラウンド処理とかで活用できるかも

ここまでの方法は次の場面で役立つかも

  • サーバーでCronジョブなど動かす
  • その時、重い処理は別プロセスで実行
  • 例えばメール送信・ファイル操作など

とはいえ滅多に使うことはないはずです。

こういう方法もあると学んだので記事にしました。

以上、PHPのexec()で別プロセス起動でした。

PHP

Shareこの記事をシェアしよう!

Commentsこの記事についたコメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください