【PHP8.x】passthru関数の使い方

passthru関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

passthru関数は、外部プログラムを実行し、その出力を直接ブラウザに出力する関数です。PHPスクリプトからシェルコマンドなどの外部コマンドを実行する必要がある場合に利用されます。

この関数は、コマンドを引数として受け取り、そのコマンドをOSのシェルを通して実行します。実行されたコマンドの標準出力は、バイナリデータを含めて、そのままクライアントのブラウザに送信されます。passthru関数は、コマンドの実行結果を文字列として返すのではなく、直接出力ストリームに書き込む点がexec関数やsystem関数と異なります。

passthru関数は、主に外部プログラムが生成する生の出力データを、PHPスクリプトを介してクライアントに配信する場合に便利です。例えば、画像処理プログラムや動画エンコーダなどの出力を直接ブラウザに表示する場合などが考えられます。

セキュリティ上の注意点として、passthru関数に渡すコマンドは、慎重に扱う必要があります。ユーザーからの入力に基づいてコマンドを組み立てる場合、コマンドインジェクション攻撃のリスクが高まります。入力値の検証やエスケープ処理を徹底し、安全なコマンド実行を心がける必要があります。

また、safe_modeが有効な場合、passthru関数の利用は制限されることがあります。disable_functionsディレクティブでpassthru関数が無効化されている場合もあります。これらの設定を確認し、利用環境に合わせて適切に対応する必要があります。

構文(syntax)

1passthru ( string $command , int &$return_var = null ) : void

引数(parameters)

string $command, ?int &$result_code = null

  • string $command: 実行するコマンドを指定する文字列
  • ?int &$result_code: コマンドの終了コードを受け取るための変数への参照。指定しない場合はNULLになる

戻り値(return)

void

passthru関数は、外部コマンドの実行結果を標準出力に直接出力し、コマンドの終了ステータスを返しますが、PHPの関数としては直接的な戻り値はありません。

サンプルコード

PHP passthru でファイル操作を行う

1<?php
2
3/**
4 * passthru関数を使用してファイルを作成し、その内容を表示、そして削除するデモンストレーションを行います。
5 * 外部コマンドの生の出力を直接PHPの出力バッファに流し込み、コマンドの終了ステータスを取得します。
6 *
7 * 注意: このコードはLinux/macOS環境のコマンドを想定しています。
8 * Windows環境で実行する場合、echo, cat, rmコマンドをdel, typeなどに適宜変更する必要があります。
9 */
10function demonstrate_passthru_with_file_operations(): void
11{
12    // 一時ファイル名を生成
13    $tempFile = 'temp_passthru_test_file.txt';
14    $fileContent = "Hello from PHP passthru!\nThis is a test file content.";
15
16    echo "--- Creating file: '{$tempFile}' ---\n";
17    // echo コマンドでファイルを作成し内容を書き込む
18    // escapeshellarg() で引数を適切にエスケープし、コマンドインジェクションを防ぎます。
19    $commandCreate = "echo " . escapeshellarg($fileContent) . " > " . escapeshellarg($tempFile);
20    passthru($commandCreate, $resultCodeCreate);
21    echo "Command: '{$commandCreate}' executed. Result code: {$resultCodeCreate}\n";
22    if ($resultCodeCreate === 0) {
23        echo "File created successfully.\n\n";
24
25        echo "--- Displaying file content: '{$tempFile}' ---\n";
26        // cat コマンドでファイルの内容を表示
27        // passthruは外部コマンドの出力を直接ブラウザに出力します。
28        $commandCat = "cat " . escapeshellarg($tempFile);
29        passthru($commandCat, $resultCodeCat);
30        echo "\nCommand: '{$commandCat}' executed. Result code: {$resultCodeCat}\n";
31        if ($resultCodeCat === 0) {
32            echo "File content displayed successfully.\n\n";
33        } else {
34            echo "Failed to display file content.\n\n";
35        }
36
37        echo "--- Deleting file: '{$tempFile}' ---\n";
38        // rm コマンドでファイルを削除
39        $commandDelete = "rm " . escapeshellarg($tempFile);
40        passthru($commandDelete, $resultCodeDelete);
41        echo "Command: '{$commandDelete}' executed. Result code: {$resultCodeDelete}\n";
42        if ($resultCodeDelete === 0) {
43            echo "File deleted successfully.\n\n";
44        } else {
45            echo "Failed to delete file.\n\n";
46        }
47    } else {
48        echo "Failed to create file. Please check permissions or command syntax.\n\n";
49    }
50}
51
52// 関数を実行して、passthruの動作を確認
53demonstrate_passthru_with_file_operations();

passthru関数は、PHPから外部のシェルコマンドを実行し、そのコマンドが標準出力に書き出す内容を、PHPの出力バッファへ直接流し込む機能を提供します。これにより、コマンドの生の出力をそのままWebブラウザなどに表示できます。

最初の引数$commandには、実行したいシェルコマンドを文字列で指定します。セキュリティ上の理由から、ユーザー入力など外部からの値を含めるコマンド引数は、escapeshellarg()関数で適切にエスケープすることが非常に重要です。オプションの第二引数&$result_codeは参照渡しで、実行したコマンドの終了ステータス(成功なら通常0)を受け取る整数型の変数です。この値を確認することで、コマンドが正常に終了したかどうかの判断ができます。passthru関数自体の戻り値はvoidであり、PHP側には何も値を返しません。

サンプルコードでは、このpassthru関数を用いて、一時ファイルを操作する一連のデモンストレーションを行っています。具体的には、まずechoコマンドを使って指定した内容を持つ一時ファイルを「作成」し、次にcatコマンドでそのファイルの内容を「表示」します。passthruの特性により、catコマンドの出力が直接PHPの出力として表示されます。最後にrmコマンドで一時ファイルを「削除」しています。それぞれのコマンド実行後には$result_codeを確認し、コマンドが正常に実行されたかを判断しています。このコードはLinux/macOS環境のコマンドを前提としており、Windows環境で実行する場合は、echo, cat, rmコマンドを適宜変更する必要があります。

passthru関数は、外部コマンドの生出力を直接Webサーバーの出力バッファに流すため、デバッグ情報の表示やストリーミング処理に適しています。サンプルコードのように、ユーザーからの入力値をコマンドに渡す際は、必ずescapeshellarg()escapeshellcmd()関数で適切にエスケープし、コマンドインジェクションを防ぐことが極めて重要です。OSによって利用できるコマンド名が異なる点にも注意が必要です。また、第2引数のresult_codeでコマンドの終了ステータスを確認し、処理の成否を判断する習慣をつけましょう。ファイル操作時には、PHPが動作するユーザーのファイルアクセス権限も適切に設定する必要があります。

PHP: passthru と shell_exec の違いを理解する

1<?php
2
3/**
4 * passthru() と shell_exec() の主な違いを示すサンプルコードです。
5 *
6 * passthru():
7 * - コマンドの出力を直接標準出力(ブラウザやコンソール)に流します。
8 * - 戻り値は void です。
9 * - 第2引数でコマンドの終了ステータス(エラーコード)を取得できます。
10 *
11 * shell_exec():
12 * - コマンドの出力を文字列として返し、プログラム内でその文字列を操作できます。
13 * - 戻り値はコマンドの出力文字列です。
14 * - コマンドの終了ステータスを直接取得することはできません。
15 */
16function demonstratePassthruVsShellExec(): void
17{
18    echo "--- passthru() の使用例 ---" . PHP_EOL;
19    $commandPassthru = "echo 'Hello from passthru! The current directory is:' && ls -ld .";
20    $resultCodePassthru = null; // PHP 8 の ?int 型に合わせ、null で初期化可能
21
22    echo "passthru() でコマンドを実行中: '$commandPassthru'" . PHP_EOL;
23    // passthru() はコマンドの出力を直接出力します。
24    // 第2引数 $resultCodePassthru にコマンドの終了コードが設定されます。
25    passthru($commandPassthru, $resultCodePassthru);
26    echo "passthru() 実行後の終了コード: " . ($resultCodePassthru ?? '取得できませんでした') . PHP_EOL;
27
28    echo PHP_EOL . "--- shell_exec() の使用例 ---" . PHP_EOL;
29    $commandShellExec = "echo 'Hello from shell_exec! The current date is:' && date";
30
31    echo "shell_exec() でコマンドを実行中: '$commandShellExec'" . PHP_EOL;
32    // shell_exec() はコマンドの出力を文字列として返します。
33    // 出力を表示するには、別途 echo などが必要です。
34    $outputShellExec = shell_exec($commandShellExec);
35
36    echo "shell_exec() が返した出力:\n";
37    echo $outputShellExec ?? "[出力なし]" . PHP_EOL;
38    // shell_exec() はコマンドの終了コードを直接取得できません。
39    // 終了コードが必要な場合は、`exec()` や `system()` 関数を使用するか、
40    // コマンド自身が出力を介して終了コードを伝えるように設計する必要があります。
41
42    echo PHP_EOL . "--- 結論 ---" . PHP_EOL;
43    echo "passthru() は出力を直接表示し、終了コードも取得できるため、" . PHP_EOL;
44    echo "大きなファイルを処理したり、リアルタイムの出力を必要とする場合に適しています。" . PHP_EOL;
45    echo "shell_exec() は出力を文字列として取得し、プログラムで加工できるため、" . PHP_EOL;
46    echo "コマンドの出力をPHPスクリプト内で利用・解析する場合に適しています。" . PHP_EOL;
47}
48
49// 関数を実行して、passthru() と shell_exec() の動作を確認します。
50demonstratePassthruVsShellExec();
51
52?>

PHP 8で利用できるpassthru関数は、外部のコマンドを実行し、その出力を直接標準出力(ウェブページやコンソールなど)に流すための機能です。引数として、実行したいコマンドを文字列$commandで指定します。オプションの引数&$result_codeには、コマンドの実行が成功したか、またはエラーで終了したかを示す数値(終了ステータス)が格納されます。この関数の戻り値はvoidであり、関数自体は何も返しません。

この関数は、コマンドの実行結果をリアルタイムで表示したい場合や、PHPスクリプトが大きな出力を直接ユーザーに見せたい場合に特に適しています。例えば、lsコマンドでファイル一覧を表示したり、catコマンドでファイルの内容を表示したりする際に、その結果をそのままブラウザやターミナルに表示できます。

サンプルコードでは、passthruecholsコマンドの出力を直接表示し、その終了コードも$resultCodePassthru変数に格納していることがわかります。

これに対し、shell_exec関数も外部コマンドを実行しますが、その出力は文字列としてPHPスクリプトに返されます。そのため、shell_execはコマンドの出力をPHPプログラム内で加工したり、変数に格納して利用したい場合に適しています。しかし、shell_execではコマンドの終了ステータスを直接取得することはできません。

結論として、出力を直接表示し、かつ終了ステータスも取得したい場合はpassthruを、出力をPHPスクリプトで細かく制御したい場合はshell_execを選択すると良いでしょう。

これらの関数は外部コマンドを実行するため、ユーザーからの入力を直接コマンドに含める場合、OSコマンドインジェクションの危険性があります。必ずescapeshellarg()escapeshellcmd()で適切にエスケープ処理を行ってください。

passthru()はコマンドの出力を直接標準出力へ流し、終了コードも取得できます。リアルタイム表示や大容量出力に適しますが、PHPスクリプト内で出力内容を加工することはできません。

一方、shell_exec()はコマンドの出力を文字列として取得し、PHP内で柔軟に加工できます。しかし、大量の出力はメモリを消費する可能性があり、コマンドの終了コードを直接取得することはできません。

どちらの関数も、コマンドが意図通りに実行されたかを確認するため、戻り値や終了コードを用いた適切なエラーチェックが不可欠です。

関連コンテンツ

【PHP8.x】passthru関数の使い方 | いっしー@Webエンジニア