(PHP) 外部コマンド実行関数の使い方まとめ・違いなど【shell_exec(), passthru() 】

(PHP) 外部コマンド実行関数の使い方まとめ・違いなど【shell_exec(), passthru() 】

 

 

本記事では、PHPから外部コマンドを実行する関数の使い方を紹介する。

 

PHPから外部コマンドを実行する方法一覧

まずPHPから外部コマンドを実行する関数は以下の6つがある

 

PHPから外部コマンドを実行する関数一覧

exec()
コマンド実行結果を指定した変数へ返す(配列で取得)

shell_exec()
コマンド実行結果を全て取得(スカラーで取得)

passthru()
コマンド実行結果を直接標準出力へ出力。戻り値はナシ。指定した変数へUnixコマンド実行結果が帰る

passthru()関数はexec()関数と同様にコマンドを実行する。 Unix コマンドからの出力がバイナリデータであり、 ブラウザーへ直接返す必要がある場合 passthru()を 使用する必要がある。

system()
コマンド実行結果のうち最後の一行だけ取得

popen()
プロセスへのファイルポインタをオープンする

proc_open()
プロセスへの入出力用ファイルポインタを開く

 

よく使うのは exec() 、shell_exec(), で、他には
passthru()もバイナリの結果を標準出力(画面)に出力するときに使用する

なので本記事では、exec() 、shell_exec()、passthru()について、
PHPから外部コマンドを実行しその結果を取得する方法を紹介していく。

 

exec関数の使い方




まずはexec関数から外部コマンドを実行しその結果を取得する方法を紹介していく。

以下の例では、「ls -l」コマンド(指定したディレクトリに存在するファイルやディレクトリを一覧で取得する)を実行してみる。

サンプルとして、以下のような test_dir ディレクトリを作成した

>ls -l test_dir

-rw-r--r--  1 root  staff  0 Nov 20 13:07 example.sh
-rw-r--r--  1 root  staff  0 Nov 20 13:07 sample.php
-rw-r--r--  1 root  staff  0 Nov 20 13:05 test.txt

 

exec関数の書式

exec(コマンド, アウトプット配列, 実行結果ステータス);

exec関数に指定できる引数は3つあり、使い方が想像しづらいと思うので、一つ一つサンプルプログラムを通して説明していく。

 

サンプルプログラム①

では実際にexec関数に、「ls -l test_dir」というコマンドを指定して結果を出力してみる。

<?php

$cmd = 'ls -l test_dir';
echo exec($cmd);

?>

実行結果:

-rw-r--r--  1 root  staff  0 Nov 20 13:05 test.txt

まずは引数の一つ目だけを指定した例。
外部コマンドの結果を取得することができたが、最後の一行しか表示されていない。

これはexec関数は第二引数のアウトプットを指定しないと、実行結果の最後の行しか返さないからだ。

 

サンプルプログラム② 出力結果をすべて取得する

exec関数で外部コマンドの全ての出力結果を取得するには、前述したように第二引数にアウトプット用の配列を指定する必要がある。

以下に第二引数を指定して、出力結果を全て取得する方法を記述する。

<?php 

$cmd = 'ls -l test_dir';
exec($cmd, $output);
print_r($output);

?>

実行結果:

Array
(
    [0] => total 0
    [1] => -rw-r--r--  1 root  staff  0 Nov 20 13:07 example.sh
    [2] => -rw-r--r--  1 root  staff  0 Nov 20 13:07 sample.php
    [3] => -rw-r--r--  1 root  staff  0 Nov 20 13:05 test.txt
)

 

第二引数に指定したアウトプット用の配列の結果をprint_r()してみた。
出力結果の行毎に、配列として要素に格納されているのが分かるだろう。

上記のように第二引数を指定すれば、出力結果をすべて1行ごとに配列に格納することが可能だ。

 

サンプルプログラム③ ステータスを取得する

exec関数によるコマンドが正常に終了したかを確認する場合は、第三引数のステータスを指定する。ステータスはLinuxのコマンド同様に、正常終了の場合0失敗の場合0以外となる。

以下に第三引数を指定して、実行結果のステータスを取得する方法を記述する。

サンプルプログラム(正常終了):

<?php

$cmd = 'ls -l test_dir';
exec($cmd, $output, $result);
echo '実行結果:'.$result; 

?>

実行結果(正常終了):

実行結果:0

 

コマンドが正常に終了したため、0が出力された。
次に失敗する例を試してみる

サンプルプログラム(失敗):

<?php 

$cmd = 'ls -l test_dirrrrrrrrrrrrrrrrr';  存在しないディレクトリを指定
exec($cmd, $output, $result);
echo '実行結果:'.$result;

?>

実行結果(失敗):

ls: test_dirrrrrrrrrrrrrrrrr: No such file or directory
実行結果:1

 

存在しないディレクトリを指定したので、実行結果は1(失敗)となった。

このようにexecコマンドは第三引数を指定すれば、コマンドの成功有無をステータスで判断できる

 

サンプルプログラム④ 配列に値を追加する

exec関数は、既に値が設定されている配列を第二引数に指定した場合、execコマンドによる実行結果がその配列の要素の最後から追加される。

サンプルプログラム:

<?php 

$output = ["test1", "test2", "test3"];
$cmd = 'ls test_dir';
exec($cmd, $output, $result);
print_r($output); 

?>

実行結果:

Array
(
    [0] => test1
    [1] => test2
    [2] => test3
    [3] => example.sh
    [4] => sample.php
    [5] => test.txt
)

 

このように配列の要素の最後に、lsコマンドの結果が追加されていることが分かる。

 

shell_exec関数の使い方




次にshell_exec関数から外部コマンドを実行しその結果を取得する方法を紹介していく。

shell_exec関数は、exec関数と同じく外部コマンドを実行し、出力結果を返す関数だ。

 

shell_exec関数の書式。

shell_exec( $コマンド )

引数:

引数は一つとなっており、実行する外部コマンドのみを指定する。
要はexec関数の簡易版とでも言えば良いだろう。

返り値:
実行されたコマンドの出力を返す。
実行時にエラーが発生、または何も出力しなかった場合はNULLを返す。

execコマンドと異なる点は以下となる

execコマンドと異なる点
  • 第二引数に結果を格納するための配列が指定できない。
  • 第三引数にステータスを指定できないため、実行に失敗したかどうかを判断することができない。

 

なので、exec関数とshell_exec関数の使い分けとしては、

  • 単純に外部コマンドを実行するだけならshell_exec関数。
  • 出力結果を配列で格納したり、実行時のステータスが知りたい場合はexec関数。

と、使い分けると良いだろう。

 

以下はshell_exec関数の簡単なサンプル。

サンプルプログラム:

<?php

$output = shell_exec('ls -l test_dir');
echo $output; 

?>

実行結果:

total 0
-rw-r--r--  1 root  staff  0 Nov 20 13:07 example.sh
-rw-r--r--  1 root  staff  0 Nov 20 13:07 sample.php
-rw-r--r--  1 root  staff  0 Nov 20 13:05 test.txt

 

標準エラーを取得するには

shell_exec も exec も、結果を取得するのは標準出力(STDOUT)だけだ。
標準エラー(STDERR)を取得するにはコマンドの最後に「2>&1」を追加するとよい。

例:

$command = 'ls -l';
$output = shell_exec("{$command}  2>&1");
print_r($output);

 

passthru関数の使い方

次にpassthru関数から外部コマンドを実行しその結果を取得する方法を紹介していく。

passthru関数もこれまで同様、外部コマンドを実行し、出力結果を返す関数だ。

<?php

passthru ('ls -l test_dir');

?>

実行結果:

total 0
-rw-r--r--  1 root  staff  0 Nov 20 13:07 example.sh
-rw-r--r--  1 root  staff  0 Nov 20 13:07 sample.php
-rw-r--r--  1 root  staff  0 Nov 20 13:05 test.txt

 

外部コマンド実行結果をバイナリで受け取る

passthru()関数を使うと、実行結果がバイナリでもそのまま受け取ることが可能だ。

<?php

passthru ('cat img.png');

?>

実行結果:

?PNG
IHDR??/??gAMA??
               ?a cHRMz&?????u0?`:?p??Q<xeXIfMMJ(?iZ``???tY?* pHYs???+iTXtXML:com.adobe.xmp<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 6.0.0">
   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
      <rdf:Description rdf:about=""
            xmlns:tiff="http://ns.adobe.com/tiff/1.0/"
            xmlns:exif="http://ns.adobe.com/exif/1.0/">
         <tiff:YResolution>96</tiff:YResolution>
         <tiff:ResolutionUnit>2</tiff:ResolutionUnit>
         <tiff:XResolution>96</tiff:XResolution>
         <tiff:Orientation>1</tiff:Orientation>
         <exif:PixelXDimension>1000</exif:PixelXDimension>
         <exif:ColorSpace>1</exif:ColorSpace>
         <exif:PixelYDimension>641</exif:PixelYDimension>
      </rdf:Description>
   </rdf:RDF>
</x:xmpmeta>
??߯???U(??7????oăʪ?~3듕xߧ??7??'Oւ   ?]???kg    P A    ?@H?+??@@@H??G?%QQ???F C??
                                                                      P?
?6@@@t   T@??;?M@@@@??   ? A??N`@@@ A?3   ?@H?+??@@@H??
                                                           P?
?6@@@t   T@??;?M@@@@??   ? A??N`@@@ A?3   ?@H?+??@@@H??
                                                           P?
?6@@@t   T@??;?M@@@@??   ? A??N`@@@ A?3   ?@H?+??@@@H??
                                                           P?

以下略

 

上記のように、バイナリの結果を受けとってそのまま出力することが可能だ。

 

まとめ

今回はPHPで外部コマンドを実行する、PHPをコマンドラインから実行するということについて解説した。

外部コマンドを実行するexec関数、shell_exec関数、passthru関数は、

  • コマンドプロンプトやターミナルから実行するコマンドをそのまま使用できる。
  • Linuxやコマンドプロンプトなどの外部コマンドや外部プログラムを実行することができる。

 

 

(PHP) ob_start()で、標準出力をバッファリングする

(PHP)「self::」と「$this」の違い【使い分け方なども紹介】

(PHP) spl_autoload_registerの使い方と解説

 

 

記事が気に入った方はシェアをお願いします!

コメントを残す

メールアドレスが公開されることはありません。