PHP
shell

PHPスクリプトをシェルのバックグラウンド実行で動かす方法

More than 3 years have passed since last update.

はじめに

シェルコマンドでは、各コマンドを&でつなぐことでバックグラウンド実行を行うことが出来ます。
これを使って複数のコマンドの同時実行などが可能です。
便利ですよね。

ただ、この方法でphpのスクリプトをバックグラウンド実行しようとしても出来ずにハマったのでその解決法をメモ。

バックグラウンド起動成功例

sleep 10を2回起動しているにもかかわらず、totalの実行時間は10秒で済んでいる

~% date;echo 'Start jobs!'; sleep 10 & sleep 10 & wait;date
Thu Jan 8 12:58:40 JST 2015
Start jobs!
[5] 27000
[6] 27001
[5] done sleep 10
[6] done sleep 10
Thu Jan 8 12:58:50 JST 2015

ただし、PHPで記載されたスクリプトなど、一部のコマンドに関してはバックグラウンド実行を行うことが出来ません。

バックグラウンド起動をしていない場合は成功する

~% php -r 'echo "hoge\n";'
~% hoge

バックグラウンド起動をさせようとした場合は標準入出力が失敗し、以下のエラーがでてsuspendする

~% php -r 'echo "hoge\n";' &
~% [5] + suspended (tty output) php -r 'echo "hoge\n";'

解決法1 < /dev/nullをつける

とりあえず手元で簡単に行ないたい場合はこちらのやり方で大丈夫なようです。
一番簡単な例

~% php -r 'echo "hoge\n";' < /dev/null&
[7] 27068
~% hoge

[7] done php -r 'echo "hoge\n";' < /dev/null

複数同時起動させる例1
→成功

~% php -r 'echo "hoge\n";' < /dev/null& php -r 'echo "fuga\n";' < /dev/null&;
[7] 27119
[8] 27120
~% hoge
fuga
[8] done php -r 'echo "fuga\n";' < /dev/null
~%
[7] done php -r 'echo "hoge\n";' < /dev/null

複数同時起動させる例2
→成功 各PHPスクリプトにsleep(10)を入れているにもかかわらず、全体で10秒で完了している

~% date; php -r 'sleep (10); echo "hoge\n";' < /dev/null& php -r 'sleep (10); echo "fuga\n";' < /dev/null&; wait; date;
Thu Jan 8 13:22:22 JST 2015
[7] 27124
[8] 27125
fuga
hoge
[8] done php -r 'sleep (10); echo "fuga\n";' < /dev/null
[7] done php -r 'sleep (10); echo "hoge\n";' < /dev/null
Thu Jan 8 13:22:32 JST 2015

解決法2 シェルスクリプトファイルを記載してそちらを実行する

上記のワンライナーを以下のシェルスクリプトに書き換えます。
おすすめはこちらです。
この時、< /dev/nullは不要です。

BGSample.sh
#!/bin/sh
date;
php -r 'sleep(10); echo "fuga\n";' &
php -r 'sleep(10); echo "hoge\n";' &
wait;
date;

実行結果

~% sh ./BGSample.sh
Thu Jan 8 13:26:30 JST 2015
fuga
hoge
Thu Jan 8 13:26:40 JST 2015

こちらも大丈夫でした。実行時間が10秒ですので、各phpのスクリプトが並列で実行されていることがわかりますし、出力もわかりやすいですね。