それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

phpで複数行のシェル呼び出しをバックグラウンドにする

php でシェル呼び出しをバックグラウンドにするには

シェル経由のコマンド実行をバックグラウンド(プロセスの親 にする)には次のとおりに書く。

<?php
shell_exec ( "sleep 100 > /dev/null 2>/dev/null & ");

STDOUT/STDERRをphp から切り離せば、プロセスをバックグラウンド・ジョブにすることが出来る。

複数行ならどうするのか

コマンド1行に対して1つの & が必要なので、複数行呼び出すときは複数回 & をすると大変なことになる。

これはひどい結果になる。

この場合、次々とコマンドを呼び出だすだけになる。

<?php
shell_exec ( "sleep 100 > /dev/null 2>/dev/null & ");
shell_exec ( "sleep 100 > /dev/null 2>/dev/null & ");
shell_exec ( "sleep 100 > /dev/null 2>/dev/null & ");
shell_exec ( "sleep 100 > /dev/null 2>/dev/null & ");

このコマンドが、一時ファイルを作って作業して一時ファイルを消すような処理をしていると、処理中の一時ファイルが先に消されちゃったりする。

複数行に渡るコマンドを実行するには

コマンドを { $cmd } のように 括弧で区切る方法が一番楽

<?php
shell_exec ( "{sleep 100;sleep 100;sleep 100;sleep 100;} > /dev/null 2>/dev/null & ");

これは、気づくのに時間がかかった。シェル呼び出しは 括弧{} でくくってあげると一括りのコマンドとして実行できるんですね

shell_exec で 2&1>/dev/null & をつけると、が sh -c 経由になるので もしやと思ったらビンゴだった。

カッコつきのコマンドのエラーを探すには

括弧をつけると、シェルスクリプトのエラーを探すのが面倒になる。エラーが出た時に追いかけるのが面倒です。

この場合は、エラーと標準出力の書き出し先を明示してあげれば楽ちんになった。

<?php
shell_exec ( "sleep 100 > /tmp/stdout 2>/tmp/stderr & ");

phpの shell_exec 関数は 標準出入力がファイルに流されてて、&がついてたら apache プロセスから切り離すようになるみたいです。

関連資料

takuya-1st.hatenablog.jp

2018-03-04

バックグラウンドでroot は書きすぎなので削るなど