あまり知られてはいませんがphpのプログラム内にはLinuxやコマンドプロンプトで使用するようなコマンドを、実行することができる関数が存在しています。
今回はphpのプログラム内から外部コマンドの実行が可能となるphpのexecについてご紹介します。
あまり使われない関数ですが、使えると意外と便利なんですよ。
目次
phpのexec関数は外部コマンドを実行する関数
冒頭でも記載しましたが、phpのプログラムにはWindowsのコマンドプロンプトなど外部コマンドを実行することができるexec関数が用意されています。
windowsのコマンドプロンプト以外にも、MacやLinuxのターミナルからのコマンドなども実行することができます。
PHPをコマンドラインで実行する方法について詳しく解説!exec関数の書き方
exec関数は以下のような書き方になります。
1 |
string exec(string $コマンド [, array &$アウトプット [, int &$ステータス ]]) |
第一引数には実行するコマンド・プログラム名を指定します。
第二引数は指定した場合、コマンドの出力結果を行ごとに指定した配列に格納します。
第三引数では、指定した変数に実行したコマンドのステータスが取得できます。
プログラム内部からただ外部コマンドを実行させるだけでなく、実行結果の取得までできるようになっています。
【PHP】$argv を使ってコマンドラインの引数を取得する方法exec関数を使えば出力結果の取得やステータスの取得も可能
exec関数を使えば第二引数・第三引数で出力結果やステータスの取得をすることが可能です。
まずはサンプルとして以下の指定したディレクトリに在るファイルまたはディレクトリを一覧で取得するコマンド「ls-l」を実行してみます。
windowsで同じようなプログラムを実行する場合は、「ls-l」のコマンド部分を「dir」に変更しないといけないので注意です。
1 2 |
$command = 'ls - 1 /opt'; echo exec($command); |
実行結果は以下のようになります。
1 |
drwxr-xr-x 5 root wheel 170 March 15 10:14 standalone |
複数行在るはずの実行結果が最後の一行しか表示されていません。これは第二引数に実行結果を入れるための配列を指定していないからです。
ここからはexec関数の第二引数・第三引数について詳しく紹介します。
第二引数に配列指定で出力結果を全て取得
前項のプログラムだと外部コマンドを実行はできるものの、出力結果全てを表示させることができません。
そこで以下のように出力結果全てを入れるためのアウトプット用配列を第二引数に指定します。
1 2 3 |
$command = 'ls - 1 /usr'; exec($command, $output); print_r($output); |
このようにアウトプット用の配列を第二引数に指定することで、実行結果が以下のように表示されます。
1 2 3 4 5 6 7 |
Array ( [0] => total 8 [1] => lrwxr-xr-x 1 root wheel 8 March 25 2014 X11 -> /output/X11 [2] => drwxr 1066 root wheel 36244 May 8 12:39 bin etc... ) |
最後の一行しか表示されていなかった出力結果が全て表示されています。
これで外部コマンドの実行を失敗した場合も、原因を突き止めやすくなりますね。
配列に値を追加することができる
第二引数に空の変数を入れれば実行結果が配列として代入されるのですが、実はここに既に値が設定されている配列を指定することもできます。
既に値が入っている配列を指定すると、その後ろに出力結果が追加されます。
1 2 3 4 |
$output = ['alpha', 'beta', 'gamma']; $command = 'ls'; exec($command, $output, $result); print_r($output); |
上記のようなプログラムを実行すると以下のような結果が表示されます。
1 2 3 4 5 6 7 8 9 |
Array ( [0] => alpha [1] => beta [2] => gamma [3] => main.php [4] => main.css [5] => movie.mp4 ) |
元から入っていた配列の後ろに追加されるように、指定したフォルダ内のファイル名が入っています。
第三引数のステータスを指定してコマンドの正常終了を確認
第三引数に変数を入れてその中身を見ることで、コマンドが正常終了しているか確認することができます。
exec関数でのコマンド実行後、第三引数の中身を表示して0なら正常終了しており、それ以外なら失敗していることになります。
以下のようなサンプルプログラムを実行してみます。
1 2 3 |
$command = 'ls - 1 /usr'; exec($command, $output, $result); echo '結果:'.$result; |
上記の場合ディレクトリが存在していれば0、存在していなければ0以外が表示されます。
コマンドの実行と同時にデバッグもやりやすい関数になっていますね。
【PHP】error_reportingを利用したエラー出力の設定方法を徹底解説コマンドが見つからなかったり実行権限が無いとエラーがでる
前項では第三引数に変数を指定することで、コマンドが正常に実行されているか確認できることを紹介しています。
実際にexec関数を実行して、第三引数に0が返ってきていれば問題ありませんが、それ以外だったら困りますよね。
特に第三引数に0以外の数字が入ってくる原因として多いのが、コマンドが見つからない・コマンドの実行権限がないといった2つです。
ここからはその2つに関して1つずつ対処方法をご紹介します。
コマンドが見つからない
存在しないコマンドを実行した場合、第三引数にはエラーに関連した数字が返ってきます。
例えば以下のようなプログラムを実行してみます。
1 2 3 |
$command = 'l /usr'; exec($command, $output, $result); echo '結果:'.$result; |
この場合以下のような結果が表示されます。
1 2 |
sh: l: コマンドがみつかりません 結果:127 |
コマンドとして「l」は存在しないのでエラーとして「127」がステータスとして返ってきていますね。
指定したコマンドが間違っていないか、コマンドにパスが通っているかなど確認するのがおすすめです。
コマンドの実行権限がない
存在しているコマンドであっても、コマンドの実行権限がない場合はエラーが第三引数に返ってきます。
例えば以下のようなプログラムをrootユーザではないユーザで実行するとエラーになります。
1 2 3 |
$command = 'ls /root'; exec($command, $output, $result); echo '結果:'.$result; |
rootユーザ以外が実行すると以下のような結果が表示されます。
1 2 |
ls: cannot open directory /root: 許可がありません 結果:2 |
この場合は、コマンド自体はsudoで実行すれば解決します。
sudoとは指定したコマンドをroot権限で実行することができますが、普通に実行すると実行ユーザのパス入力を求められます。
sudoコマンドの「-S」オプションを使えば、パスを端末入力ではなく標準入力から読み込むことが可能です。
以下のように記述することで実行ユーザのパスが正しければ、コマンドがきちんと実行されます。
1 2 3 |
$command = "echo 'pass' | sudo -S ls /root"; exec($command, $output, $result); echo '結果:'.$result; |
実行すると以下のような結果になります。
1 |
結果:0 |
「pass」の中身にはユーザの正しいパスワードを代入しておきます。
$command内の「|」はパイプと呼ばれるもので、複数コマンドを繋げる役割をしています。
上記では「echo ‘pass’」で出力したパスを「sudo -S ls/root」に渡しています。こうすることで途中でパスワードを入力せずにコマンドの実行ができます。
まとめ
今回はphpプログラム内から外部コマンドの実行をすることができるexec関数をご紹介しました。
出力結果を取得できたり、エラーが出ていないかの確認も可能です。
exec関数を使う場面そのものは少ないですが、使えれば便利ではあるので是非使い方を覚えていってくださいね。