これらのコマンドはすべて、指定したコマンドまたはスクリプトを実行する子プロセスを生成し、各子プロセスは標準出力 (stdout) に書き込まれるコマンド出力をキャプチャします。
shell_exec()
shell_exec() コマンドラインは、実際にはバックティック (`) 演算子のバリエーションにすぎません。シェルまたは Perl スクリプトを作成したことがある場合は、バックティック演算子内で他のコマンドの出力をキャプチャできることをご存知でしょう。たとえば、リスト 1 は、バッククォートを使用して、現在のディレクトリ内の各テキスト (.txt) の単語数を取得する方法を示しています。
リスト 1. バッククォートを使用して単語の数を数える
コードをコピーします コードは次のとおりです。
#! /bin/sh
number_of_words=`wc -w *.txt`
echo $number_of_words
#result は次のようになります:
#165 readme.txt 388 件の結果.txt 588 summary .txt
#and so on....
PHP スクリプトでは、リスト 2 に示すように、shell_exec() でこの単純なコマンドを実行すると、目的の結果が得られます。ここでは、同じディレクトリにいくつかのテキストファイルが存在すると仮定します。
リスト 2. shell_exec() で同じコマンドを実行する
コードをコピーします コードは次のとおりです:
$results =shell_exec('wc -w *.txt');
echo $results;
図 1 では、得られる結果はシェル スクリプトから得られる結果と同じです。これは、shell_exec() を使用すると、シェルを通じて外部プログラムを実行し、結果を文字列として返すことができるためです。
図 1.shell_exec() 経由でシェル コマンドを実行した結果
以下に示すように、末尾のアポストロフィ演算子を使用するだけでも同じ結果が得られることに注意してください。
リスト 3. 末尾のアポストロフィ演算子のみを使用する
コードをコピーします コードは次のとおりです。 ?php $results = `wc -w *.txt`;
echo $results;
?>
リスト 4 は、より単純なメソッドを示しています。
リスト 4. より単純なメソッド
コードをコピーします
コードは次のとおりです。 echo `wc -w *.txt`;
?>
UNIX コマンド ラインとシェル スクリプトを使用して多くのことができることを知っておくことが重要です。たとえば、パイプを使用してコマンドを接続できます。演算子を使用してその中にシェル スクリプトを作成し、そのシェル スクリプトを呼び出すこともできます (必要に応じてパラメータありまたはパラメータなし)。
たとえば、そのディレクトリ内の最初の 5 つのテキスト ファイルの単語だけをカウントしたい場合は、垂直バー (|) を使用して wc コマンドと head コマンドを接続できます。あるいは、以下に示すように、出力を pre タグ内に配置して、Web ブラウザーでより美しくレンダリングすることもできます。
リスト 5. より複雑なシェル コマンド
コードをコピー
コードは次のとおりです。 ?php $results =shell_exec('wc -w *.txt | head -5'); echo ""
"; ?>
図 2 は、リスト 5 のスクリプトを実行した結果を示しています。
図 2. より複雑なシェル コマンドを実行したshell_exec() の結果
この記事の後半では、PHP を使用してこれらのスクリプトに引数を渡す方法を学習します。これをシェル コマンドを実行する方法と考えることができますが、表示できるのは標準出力のみであることに注意してください。コマンドまたはスクリプトでエラーが発生した場合、パイプ経由で標準エラー (stderr) を stdout に追加しない限り、標準エラー (stderr) は表示されません。
passthru()
passthru() を使用すると、外部プログラムを実行し、結果を画面に表示できます。ブラウザに表示される結果を確認するために echo や return を使用する必要はありません。オプションのパラメーターを追加できます。これは、外部プログラムから返されたコードを保持する変数 (成功を表す 0 など) であり、デバッグのためのより優れたメカニズムを提供します。
リスト 6 では、 passthru() コマンドを使用して、前のセクションで実行した単語カウント スクリプトを実行します。ご覧のとおり、リターン コードを含む $returnval 変数も追加しました。
リスト 6. passthru() コマンドを使用して単語カウント スクリプトを実行します
コードをコピーします
コードは次のとおりです。
passthru('wc -w *.txt | head -5',$returnval); echo "
".$returnval; 🎜>?>
何かを返すために echo を使用する必要がないことに注意してください。以下に示すように、結果は画面に直接表示されます。
図 3. リターン コードを伴う passthru() コマンドの実行結果
リスト 7 では、スクリプトのヘッダーの 5 の前にあるダッシュ (-) を削除することにより、小さなエラーが導入されました。
リスト 7. 単語カウント スクリプトにバグを導入します
コードをコピーします コードは次のとおりです。
//以下にエラーを紹介します (head コマンドから - を削除します)
passthru('wc -w *.txt | head 5',$returnval
echo); "
".$returnval;
?>
スクリプトは期待どおりに実行されないことに注意してください。図 4 に示すように、空白の画面、水平線、および戻り値 1 が表示されます。このリターン コードは通常、何らかのエラーが発生したことを示します。リターンコードをテストできれば、バグの発見と修正がはるかに簡単になります。
図 4. passthru() 使用時のエラー コードの表示
exec()
exec() コマンドは、出力を返す点を除いて、shell_exec() と似ています。最後の行に追加し、オプションでコマンドの完全な出力とエラー コードを配列に入力します。リスト 8 は、データ配列内のデータをキャプチャせずに exec() を実行した場合に何が起こるかを示しています。
リスト 8. データ配列内のデータをキャプチャせずに exec() を実行する
コードをコピーします コードは次のとおりです:
$results = exec('wc -w *.txt | head -5');
echo $results;
# 最後の行または結果だけを出力します。例:
#3847 myfile.txt
?>
結果を配列にキャプチャするには、配列の名前を 2 番目の引数として exec() に追加します。リスト 9 では、$data を配列の名前として使用して、このステップを実行しました。
リスト 9. exec() からのデータ配列の結果のキャプチャ
コードをコピーします コードは次のとおりです:
php
$results = exec('wc -w *.txt | head -5',$data);
print_r($data); array:
# Array ([0]=> 555 text1.txt [1] => 283 text2.txt)
?>
で結果を取得した後配列で何らかの処理を行うことができます。たとえば、最初のスペースで分割したり、分割された値をデータベース テーブルに保存したり、各行に特定の書式設定やタグを適用したりできます。
system()
リスト 10 に示すように、system() コマンドはハイブリッドです。 passthru() と同様に、外部プログラムから受け取ったものを直接出力します。また、exec() のように最後の行を返し、戻りコードを利用できるようにします。
リスト 10. system() コマンド
コードをコピーします コードは次のとおりです。
>< ?php
system('wc -w *.txt | head -5');
#出力します:
#123 file1.txt 332 file2.txt 444 file3.txt
#and so on
?>
いくつかの例
これらの PHP コマンドの使用方法は理解できましたが、まだいくつか疑問があるかもしれません。たとえば、いつどのコマンドを使用すればよいでしょうか?すべてはあなたのニーズ次第です。
私は主に、すべてに exec() コマンドとデータ配列を使用します。または、特に結果を気にしない場合は、より単純なコマンドに shell_exec() を使用します。シェル スクリプトを返すだけの場合は、 passthru() を使用します。さまざまな機会に異なる機能を使用することがよくありますが、それらが交換可能な場合もあります。すべては私の気分と、何を達成しようとしているかによって決まります。
もう 1 つの質問は、「彼らの強みは何ですか?」ということです。まったく手がかりがない場合、またはシェル コマンドを使用するのに最適なプロジェクトはあるものの、その使用方法がわからない場合は、ここで洞察を提供します。
さまざまなバックアップまたはファイル転送機能を提供するアプリケーションを作成している場合は、shell_exec() またはここで提供されている他のコマンドの 1 つを使用して、rsync がサポートされているシェル スクリプトを実行することを選択できます。必要な rsync コマンドを組み込むシェル スクリプトを作成し、 passthru() を使用してユーザーのコマンドまたは cron ジョブに基づいてスクリプトを実行できます。
たとえば、アプリケーションで適切な権限 (管理者権限など) を持つユーザーが、あるサーバーから別のサーバーに 50 個の PDF ファイルを送信したいと考えています。次に、ユーザーはアプリケーション内の正しい場所に移動し、「転送」をクリックし、送信する必要がある PDF を選択して、「送信」をクリックする必要があります。その過程で、フォームには、次に示すように return オプション変数を使用して passthru() 経由で rsync スクリプトを実行する PHP スクリプトが含まれる必要があります。
リスト 11. passthru() 経由で rsync スクリプトを実行するサンプル PHP スクリプト
コードをコピーします
コードは次のとおりです。
passthru('xfer_rsync.sh',$returnvalue);
if ($returnvalue != 0){
//問題があります! //ここにエラー コードを追加します
}else{
//問題ありません
//他のページにリダイレクトします
}
?>
ifアプリケーションでは、プロセスまたはファイル、またはそれらのプロセスまたはファイルに関するデータをリストする必要があります。この記事でまとめたコマンドのいずれかを使用すると、これを簡単に行うことができます。たとえば、単純な grep コマンドは、特定の検索条件に一致するファイルを見つけるのに役立ちます。これを exec() コマンドとともに使用すると、結果が配列に保存され、HTML テーブルまたはフォームを構築できるようになり、さらに他のコマンドを実行できるようになります。
これまで、ユーザーが生成したイベントについて説明してきました。ユーザーがボタンを押すかリンクをクリックするたびに、PHP は対応するスクリプトを実行します。スタンドアロンの PHP スクリプトを cron または他のスケジューラとともに使用して、興味深い効果を実現することもできます。たとえば、バックアップ スクリプトがある場合は、cron 経由で実行することも、PHP スクリプトにパッケージ化して実行することもできます。なぜこれを行うのでしょうか?これは冗長だと思いませんか?それは当てはまりません。このように考える必要があります。exec() または passthru() を介してバックアップ スクリプトを実行し、戻りコードに基づいて何らかの動作を実行できます。エラーが発生した場合は、エラー ログまたはデータベースにログを記録したり、警告電子メールを送信したりできます。スクリプトが成功した場合は、生の出力をデータベースにダンプできます (たとえば、rsync には冗長モードがあり、後で問題を診断するのに役立ちます)。
------------------------------------------ ---------- ------------------------------------
セキュリティ
しましょうここでセキュリティについて簡単に説明します。 性別: ユーザー入力を受け入れて情報をシェルに渡す場合は、ユーザー入力をフィルタリングすることをお勧めします。 sudo (スーパーユーザーとして実行) や rm (削除) など、有害で禁止されていると思われるコマンドを削除します。実際には、おそらくユーザーにオープンリクエストを送信させるのではなく、リストから選択させることを望んでいるでしょう。
たとえば、ファイルのリストを引数として受け取る転送プログラムを実行する場合は、一連のチェックボックスを使用してすべてのファイルをリストする必要があります。ユーザーは、[送信] をクリックしてファイルを選択および選択解除し、rsync シェル スクリプトをアクティブにすることができます。ユーザーは自分でファイルを入力したり、正規表現を使用したりすることはできません。
------------------------------------------ ---------- ------------------------------------
結論
この記事では、PHP コマンドを使用してシェル スクリプトやその他のコマンドを実行する基本について説明しました。これらの PHP コマンドには、shell_exec()、exec()、passthru()、および system() が含まれます。次に、学んだことを自分のアプリケーションで実践する必要があります。