PHPのexit終了ステータスコードでシェルスクリプトを分岐する

PHP

お疲れ様です。すぺきよです。

業務用に作成したスクリプトが複数あると、一つ一つ手動で呼び出す必要があって手間ですよね。

特に単一責任のルールのもとでスクリプトを作成していると、スクリプトの数がどんどん多くなってきます。

全ての処理をするために一つ一つコマンドラインで実行するのも手間だしミスも誘発します。

そんな時にはシェルスクリプトです。

実行したい一連のコマンドを書けば、一気に実行してくれるので便利です。

ただ、作成したスクリプトによっては、実行結果によって後続の処理を変更したい場合があります。

例えば、通信エラーが出たりで処理に失敗したらその場でエラーメッセージを出力して処理を終了させたい場合などですね。

これをPHPのスクリプトとシェルスクリプトの組み合わせで行うにはどうすればいいのか調べたところ、それそのものの解がありませんでした。

いくつかの情報を組み合わせればできるのですが、あちこち調べるのも手間ですし、ここにまとめます。

この記事を読むとわかること

PHPで記述されたスクリプトの結果によってシェルスクリプトの処理を分岐させる方法の具体的な書き方がわかります。

筆者の環境

この記事記載時の筆者の環境を記載します。

OS

macOS Ventura 13.5.2

PHP

PHP 8.2.9

結論

分岐するには以下のように記述します。

PHP側ではexit関数に終了ステータスコードを指定してコードを切り替えるようにします。

#! /bin/bash

php ./script1.php
script1_result_code=$?

if test $script1_result_code -ne 0
then
    echo "script failed with $script1_result_code"
    exit 1
fi

php ./script2.php

このスクリプトのミソは、コマンドの終了ステータスコードが入る「?」変数を使って後続の処理をif文で切り替えているところです。

コマンドが実行されるたびに変数「?」の内容は書き換えられてしまうので、一度「script1_result_code」という変数にコピーして、後続で利用できるようにもしています。

実際に動作を確認してみる

では、実際にコードを書いて動作を確認してみましょう。

プロジェクトフォルダの準備

端末内の任意の場所にフォルダを一つ作成し、そこをプロジェクトフォルダとしてください。

シェルスクリプトの準備

プロジェクトフォルダ内に、上記結論に記載しているシェルスクリプトを「launch_php_scripts.sh」として保存し、次のコマンドで実行権限を与えます。

chmod 777 launch_php_scripts.sh

実行権限を与えないと、シェルスクリプトは起動できません。

テスト用のPHPを準備

script1.phpを準備

プロジェクトフォルダ内に、script1.phpを作成し、以下のコードを貼り付けてください。

起動確認用のechoを実行してから、exitで終了するだけの簡単なスクリプトです。

<?php
echo "launch script1.\n";
exit(0);

script2.phpを準備

プロジェクトフォルダ内に、script2.phpを作成し、以下のコードを貼り付けてください。

起動確認用のechoを実行するだけの簡単なスクリプトです。

<?php
echo "launch script2.\n";

いろんなパターンで実際に動作を確認してみる

exit(0)のままで実行する

まずは、script1.phpのexit()に指定している数値が0であることを確認してください。

ターミナルなどのコマンドラインでプロジェクトまで移動して、次のコマンドを実行してみましょうてください。

./launch_php_scripts.sh

実行結果として、次のようになると思います。

launch script1.
launch script2.

順番にスクリプトが実行されていますね。

exit(0)以外で実行する

次に、script1.phpのexit()に0以外の数値を指定して実行してみます。

今回は以下のように試しに99を指定して、実行してみましょう。

<?php
echo "launch script1.\n";
exit(99);

実行結果としては次のようになると思います。

launch script1.
script failed with 99

結果が変わり、script2.phpが実行されていないことがわかりますね。

今回は99を指定しましたが、いろいろな数値を試してみてください。

「script failed with **」の**のところにexit関数で与えた数値が入っていることと思います。

PHPの公式によるとexitには0〜254までの数値しか指定できないので注意してください。

exitの値を省略する

exit関数は、引数の値を省略することが可能です。

以下のようにscript1.phpのexit関数に値を指定せずに実行してみましょう。

<?php
echo "launch script1.\n";
exit();

実行結果は以下のようになります。

launch script1.
launch script2.

結果から見るに、exit()と引数を省略すると、ステータスコードは0となるようですね。

exitに文字列を指定する

exit関数のマニュアルを見ると、引数に文字列を指定することもできそうです。

exit(string $status = ?): void

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

以下のように文字列を指定して実行してみるとどうなるか確認してみましょう。

<?php
echo "launch script1.\n";
exit("this is error message.\n");

上記のようにエラーメッセージを出力しているつもりで、実行してみた結果は以下のとおりになります。

launch script1.
this is error message.
launch script2.

あれ、エラーのつもりで文字列を指定したつもりなのに、後続のscript2が実行されてしまっていますね。

さらに、エラー用の文字列は標準出力に出力されてしまっています。

エラーのつもりでexit関数に文字列を指定しても、終了ステータスコードは0になってしまうので注意が必要です。

exitを省略するとどうなるか

PHPはexit関数がなくとも、スクリプトの最後まで実行されると処理が終了します。

以下のようにscript1.phpのexit(0)を省略して実行してみるとどうなるか確認してみましょう。

<?php
echo "launch script1.\n";

実行結果は以下のようになります。

launch script1.
launch script2.

結果から見るに、ステータスコードは0で返ってきているようですね。

exitの代わりにdieを利用する

PHPのコードを終了するために利用するexit関数ですが、代わりにdie関数を使うことも可能です。

以下のようにscript1.phpのexit(0)をdieに変更して実行してみるとどうなるか確認してみましょう。

<?php
echo "launch script1.\n";
die;

実行結果は以下のようになります。

launch script1.
launch script2.

結果から見るに、ステータスコードは0で返ってきているようですね。

die関数の仕様に以下の記載があるので、この動作は仕様通りということになりますね。

この言語構造は、exit() と同等です。

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

最後に

今回はPHPのスクリプトをシェルスクリプトで扱う際に、スクリプトの結果によってどのようにスクリプトを切り替えるかをまとめてみました。

PHPだけでもいろいろできてはかどりますが、シェルスクリプトと組み合わせることでさらにはかどるようになります。

みなさまの良きPHPライフに貢献できれば幸いです。

タイトルとURLをコピーしました