2019-07-23に更新

PHPで新しいプロセスに処理を引き継ぐ方法

動機

PHPで無限ループ処理をしたかったのですが、サーバーの都合上5分でプロセスがタイムアウトしてしまうので、PHPからコマンドを呼び出して、新しくPHPプロセスを立てて処理を引き継ぐことにしました。

方法

PHPで外部コマンドを実行するには、exec()を使います。

ところで、PHPがインストールされているOSで/home/example.phpを実行するなら、次のようなコマンドを打ちますよね。

php /home/example.php

( ˘ω˘) 。o(つまりこうすれば…)

exec('php /home/example.php');

残念!!

処理中のプロセスを見ると、大量のPHPが。そして、手元には大量のエラー通知メールが…。

ここで、exec()のPHPリファレンスをもう一度よく見てみましょう。

注意:

プログラムがこの関数で始まる場合、 バックグラウンドで処理を続けさせるには、 プログラムの出力をファイルや別の出力ストリームにリダイレクトする必要があります。 そうしないと、プログラムが実行を終えるまで PHP はハングしてしまいます。

https://www.php.net/manual/ja/function.exec.php

つまりexec()からコマンドを実行すると、子プロセスの出力があるまでこのPHPはkillされないということです。これは、exec()が返り値を待っているためでしょう。

しかし厄介なのは、この待機中のプロセスは子プロセスが終了しない限り、あらゆるタイムアウト処理を無視する点です。いつまでもプロセスに残り続け、メモリを食い続けるのです。

これを防ぐためには、以下のようにします。

exec('php /home/example.php > /dev/null &');

>を使うと、左側(ここではphp /home/example.php)の出力を右側(ここでは/dev/null)にリダイレクトします。

/dev/nullは虚無を表すスペシャルファイルで、ここを出力先に指定すると、その出力は破棄されます。

&はコマンドの後ろに付けることで、バックグラウンド実行を示します。これにより、非同期でその処理を扱うことができます。

まとめ

PHPで新しいプロセスを立ててバックグラウンド実行するには次のコマンドを使います。

exec('php /home/example.php > /dev/null &');

重たい処理だけバックグラウンドに逃がしたいときにも使えそうです。

参考

Linuxコマンド(Bash)でバックグラウンド実行する方法のまとめメモ

【php】 exec()関数などでバックグラウンドでコマンドを実行するとき

ツイッターでシェア
みんなに共有、忘れないようにメモ

ウラル

Splatoonの二次創作サイト「スプランプ」の管理人です。サーモンラン研究所やオクトチャット、フェス速報などを作りました。

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント