PHP exec()とsystem()とpassthru()


312

違いは何ですか?

各機能に特定の状況や理由はありますか?はいの場合、それらの状況の例をいくつか挙げていただけますか?

PHP.netによると、これらは外部プログラムの実行に使用されます。参考資料 を見る私が見た例から、明らかな違いは見られません。

単純にスクリプト(bashまたはpython)を実行する場合、どの関数を使用することをお勧めしますか?


16
proc_open()ともありpopen()、どちらも生成されたプロセスをより高度に制御できます。
クリスチャン

回答:


195

目的は少し異なります。

  • exec() システムコマンドを呼び出し、出力を自分で処理するためのものです。
  • system() システムコマンドを実行し、すぐに出力(おそらくテキスト)を表示するためのものです。
  • passthru() 生の戻り値を希望するシステムコマンドを実行するためのものです-おそらく何かバイナリです。

とにかく、私はそれらのどれも使用しないことをお勧めします。これらはすべて、移植性の低いコードを生成します。


147
場合によっては、機能性のために移植性を犠牲にする必要があります。PHPがうまくいかないことがいくつかあります。
フランククルック

30
@Kalium:ステートメントについて詳しく説明してください。漠然としたパーセンテージの統計を述べただけでは納得できません。システムコールを使用してスクリプトを実行しても、アプリケーション全体がバックエンドのスクリプトの束に依存しない限り、まったく問題ないと思います。
コーディングベア2009

46
@Christian izkata@izein:~$ dir -bash: dir: command not found-FreeBSD
Izkata

5
@OZ_非常に高価な計算を行わなければならない状況になりました。そのために利用可能なPHPモジュールはありませんでした。私は自分のCプログラムを作成し、それをpassthru()で呼び出しました。時々、移植性は他のものより重要ではない場合があります。プロジェクトによって異なります。
Paolo

9
また、それはだ誤謬あなたが避けるようPHPが長いなどの携帯型であることを考えるのはexecsystempassthru。PHPコードは、それが実行される環境に依存しています。多くのセキュリティバグは、これを考慮していないためです。ここでは簡単な例です:stackoverflow.com/questions/3003145/...
Pacerier

131

http://php.net/ && Chipmunkninjaから 抜粋

システム()関数

PHPのシステム関数は、実行するコマンドの文字列引数と、そのコマンドに渡す引数を受け取ります。この関数は、指定されたコマンドを実行し、結果のテキストを出力ストリーム(Webサーバー状況でのHTTP出力、またはコマンドラインツールとしてPHPを実行している場合はコンソール)にダンプします。この関数の戻り値は、プログラムからの出力の最後の行です(テキスト出力を出す場合)。

EXEC()関数

システム関数は非常に便利で強力ですが、最大の問題の1つは、プログラムから生成されるすべてのテキストが直接出力ストリームに送られることです。結果のテキストをフォーマットして別の方法で表示したり、まったく表示したくない場合があります。

このため、PHPのexec関数は完全に適応されています。実行されているプログラムによって生成されたすべてのテキストを出力ストリームに自動的にダンプする代わりに、このテキストを関数の2番目のパラメーターで返される配列に入れる機会を提供します。

もしくはshell_exec()関数

これまで実行してきたプログラムのほとんどは、多かれ少なかれ、実際のプログラムでした1。ただし、WindowsおよびUnixのユーザーが動作する環境は、実際にはこれよりもはるかに豊かです。Windowsユーザーには、Windowsコマンドプロンプトプログラムcmd.exeを使用するオプションがあります。このプログラムはコマンドシェルと呼ばれます。

パススルー()関数

PHPが提供する魅力的な関数の1つは、これまでに見たものと似ていますが、パススルー関数です。この関数は、他の関数と同様に、指定したプログラムを実行します。ただし、その後、このプログラムからの未加工の出力が、PHPが現在動作している出力ストリーム(つまり、WebサーバーシナリオのHTTP、またはPHPのコマンドラインバージョンのシェル)にすぐに送信されます。

proc_open()関数とのpopen() 関数

proc_open()はpopen()に似ていますが、プログラムの実行を大幅に制御できます。cmdは、シェルによって実行されるコマンドです。descriptorspecは、キーが記述子番号を表し、値がPHPがその記述子を子プロセスに渡す方法を表すインデックス付き配列です。パイプは、作成されたパイプのPHPの末尾に対応するファイルポインターのインデックス付き配列に設定されます。戻り値はプロセスを表すリソースです。使い終わったら、proc_close()を使用して解放する必要があります。


6
shell_execの実行速度は、他の代替よりも高速です。
Dinesh Saini 2014年

29
回答をChipmunkNinjaから直接コピーしたことを説明する必要があります。
TachyonVortex 2014年

7
@TachyonVortexは幸運にも彼は答えをそのままコピーしました。
Phileo99 2014年

2
ウェイバックマシンにその記事のコピーがあります:web.archive.org/web/20130809032648/http
//chipmunkninja.com/…– bagonyi

2
popenとproc_openはどうですか?
CMCDragonkai 2015

103

以前の回答はすべて少し混乱または不完全であるように思われるため、ここに違いの表を示します...

+----------------+-----------------+----------------+----------------+
|    Command     | Displays Output | Can Get Output | Gets Exit Code |
+----------------+-----------------+----------------+----------------+
| system()       | Yes (as text)   | Last line only | Yes            |
| passthru()     | Yes (raw)       | No             | Yes            |
| exec()         | No              | Yes (array)    | Yes            |
| shell_exec()   | No              | Yes (string)   | No             |
| backticks (``) | No              | Yes (string)   | No             |
+----------------+-----------------+----------------+----------------+
  • 「出力を表示する」とは、ブラウザ(またはコマンドラインから実行している場合はコマンドライン出力)に出力をストリーミングすることを意味します。
  • 「出力を取得できる」とは、コマンドの出力を取得してPHP変数に割り当てることができることを意味します。
  • 「終了コード」は、コマンドによって返される特別な値です(「戻りステータス」とも呼ばれます)。通常、ゼロは成功したことを意味し、他の値は通常エラーコードです。

その他の注意事項:

  • shell_exec()とbackticks演算子は同じことを行います。
  • proc_open()とpopen()もあり、実行中のコマンドでストリームをインタラクティブに読み書きできます。
  • エラーメッセージもキャプチャ/表示する場合は、コマンド文字列に「2>&1」を追加します。
  • escapeshellcmd()を使用して、問題のある文字を含む可能性のあるコマンド引数をエスケープします。
  • $ output変数をexec()に渡して出力を保存する場合、$ outputが空でなければ、新しい出力が追加されます。したがって、最初にunset($ output)する必要があるかもしれません。

どれがphpファイルを実行できますか?
ジョニーなぜ

1
@johnywhyそれ自体なし-php cliなどを明示的に呼び出さない限り。あなたincludeと友達が欲しいと思う
ハーゲンフォン

21

実際には、コマンドが返す可能性のある出力をどのように処理するか、および呼び出し先プログラムが終了するまでPHPスクリプトを待機させるかどうかがすべてです。

  • exec コマンドを実行し、出力を呼び出し元に渡します(またはオプションの変数に返します)。

  • passthruexec()コマンドを実行するという点で関数に似ています。この関数は、Unixコマンドの出力がバイナリデータの代わりに、exec()またはsystem()ブラウザに直接渡す必要がある場合に使用する必要があります。

  • system 外部プログラムを実行し、出力を表示しますが、最終行のみです。

コマンドを実行する必要があり、コマンドからのすべてのデータが干渉を受けることなく直接渡される場合は、 passthru()関数をます。


8

コマンドラインからPHPスクリプトを実行している場合、passthru()大きな利点が1つあります。それはあなたのようなスクリプト/プログラムを実行できるようになりますvimdialogこれらのプログラムは制御を処理し、が完了したときにのみスクリプトに戻ります。

system()またはを使用する場合exec()これらのスクリプト/プログラム実行する、機能しません。

落とし穴:何らかの理由lesspassthru()、PHPでは実行できません。


1
あなたの言っていることが理解できません。CLIと(F)CGI(およびmod_php)の両方からプログラムを実行できます。selinuxなど、システムによって課される制限がある場合があります。しかし、適切に設定されたシステムでは、それらが選択的にオフになります。もちろん共有ホストは別の話ですが、尊敬されるクライアントにも共有環境を提供しないでしょうか?
クリスチャン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.