min117の日記

初期desireもち。趣味Mac,メインFedora,仕事xp。

PHP からbashコマンドをノンブロッキング(非同期処理)で実行する

PHPソースコード内でLinuxのシェル(bash)を呼びたいことがよくある。例えば

A.ラジオを録音するためのこんな画面(recRADIO5.html)を開発していて

f:id:min117:20180303232249p:plain

B.「録音開始」を押したら録音画面(recRADIO5.php)に推移

f:id:min117:20180303232600p:plain

C. 録音ファイルをいつでもどこでも聞くことができる

f:id:min117:20180303232552p:plain

を実装しようとしているが、B.のとき画面が固まって困る

より具体的には、B.でphpからLinuxシェル(bash)コマンドを呼んでいるのだが

f:id:min117:20180303233105p:plain

そのbashコマンドの実行結果が返ってくるまで、PHPが画面を固まらせてしまっている

解消法がわからなくてホトホト苦労したが、やっとやり方がわかった。

 

 

PHP からbashコマンドをノンブロッキング(非同期処理)で実行する方法

① bashコマンドの末尾にアンパサンド(&マーク)を付けてバックグラウンド実行する

② bashコマンドの出力は >> /dev/nullに捨てる

③ bashコマンドは必ずsudo実行する。でないと >> /dev/null に書き込めない!

 → phpがsudoコマンドを呼び出せる権限を持っているか(httpd.confまわりの)確認必要。

④ bashコマンドは、頭にshをつけて別シェルで実行する!でないとなぜかブロッキングかかる

⑤ php内から実行するbashコマンドは一旦 $command変数に格納してから shell_exec("$command"); としたほうがよい。

 → shell_exec()引数内に直接コマンドを書くとなぜかブロッキングかかる  

 

ソース文字列はこんな感じ。

// ./folder1/folder2/rec_radiko2_2/rec_radiko2.sh JOAK 1 id_desu@gmail.com pass_desu /media/MUSIC JOAK > /dev/null 2>&1 &

// ./folder1/folder2/rec_radiko2_2/rec_radiko2.sh ' . "$myCH" . ' ' . "$myMIN" . ' ' . 'id_desu@gmail.com pass_desu /media/MUSIC' . ' ' . "$myCH" . ' > /dev/null 2>&1 &

$command = 'sh /folder1/folder2/rec_radiko2_2/rec_radiko2.sh ' . "$myCH" . ' ' . "$myMIN" . ' ' . 'id_desu@gmail.com pass_desu /media/MUSIC' . ' ' . "$myCH" . ' > /dev/null 2>&1 &';

順番にみていくと、まずは行末が大事

$myCH" . ' > /dev/null 2>&1 &';

となっている。アンパサンド(&マーク)を使ってbashコマンドをバックグラウンド実行しているということだ(上記①)。

qiita.com

さらにまだ行末が大事

$myCH" . ' > /dev/null 2>&1 &';

となっていて、出力をnullデバイスに捨てているのだが(上記②)、そのためにはnullデバイスを使える権限が必要なわけで、つまりsudoで実行しなければいけない(上記③)。今回はなぜかsudoなしで成功したが、うまくいかないときは「bashコマンド先頭にsudoをつける」をとりあえずやってみるのが良さそう。

最後は行頭に目をやると、

$command = 'sh /folder1/folder2/rec_radiko2_2/rec_radiko2.sh '

となっていて、ラジコ録音スクリプト(rec_radiko2.sh)を、別のシェルで実行させるために頭にshを持ってきているのが分かる(上記④)。

シェルコマンドの実行方法はこの本にまとまっている。

f:id:min117:20180304000354j:plain

Linuxシェルコマンドでは他の追随を許さない最良の本だと思う。 改訂第3版が最新だけど、改訂新版でもほぼ同じだから、中古でもなんでもいいから1冊は持っておくといいと思う。

 

いやはや、今回はやりたいことの情報がGoogleですら取れなくて苦労した。

PHP ノンブロッキング bash で検索しても、全くそれらしい情報に当たらないし。

PHP バックグラウンド実行 bash で検索して、やっとこのへんが参考になった。

takuya-1st.hatenablog.jp

PHPでの非同期処理はnode.jsが常道らしいが、

qiita.com

単にbashコマンドを実行したいだけなのにnodeサーバを立てること自体がだるいので、今回は参考程度にしておいた。