汎用スクリプト作成には PHP を使用し、PHP デバッグにはコマンド ライン インターフェイスを使用します
コマンド ラインから PHP コードをデバッグする方法を学び、シェル スクリプト言語としての PHP 自体のパワーを体験してください。
?
CLI PHP の利点
私は何年もの間、エンジニアの責任について不確かな定義を適用してきました。私は個人的に、エンジニアはツールの本来の開発目的とは関係のない機能を実現するためにツールを使用すると考えています。この考えが常に正しいとは限りませんが、よく考えてみると、ほとんどのイノベーションや発明は、これまで考えられなかった方法でツールを使用することから生まれていることがわかります。
?
私の驚きを想像してみてください。そこで、突然アイデアが思いつきました。コマンド ライン ツールとして Web ページにとって常に非常に信頼できる古い友人の PHP を使用してください。これを行うのは私が初めてではありませんが、私にとっては間違いなく新しいアイデアです。
?
もちろん、 コマンドラインから PHP を 使用できるということだけが、そうするための最良の理由ではありません。ただし、この方法で PHP を初めて実験し始めると、すぐにいくつかの興味深い驚きに気づくかもしれません。まず、既存のスクリプトのデバッグがこれまでより簡単になります。大部分が出力と最小限のロジックで構成される PHP プログラムは、驚くほどシンプルになります。さらに、PHP の知識をすべて活用して、これまで PHP で実行することを考えもしなかったタスクを実行できます。実際、ほぼすべてのプログラミング プロジェクトの最終手段として PHP を使用することを妨げるものは何もありません。
?
興味がありますか?わかりました。早速始めて、コマンド ラインから PHP を使用して何ができるかを見てみましょう。
?
インストール
インストールは非常にシンプルかつ簡単で、特に何もインストールする必要がない場合もあります。まず、コマンド ラインで簡単な PHP スクリプトを試してください。既存の PHP スクリプトを使用するか、次のコードを試してください。この例は Linux® に基づいていますが、同様の原則が他のシステムにも当てはまります。
?
まず、PHP 実行可能ファイルの場所を確認します。ほとんどの Linux システムでは、これはほぼ確実に /usr/bin/php になります。その場所がわからない場合は、コマンドラインに which php
と入力して応答を確認してください。
?
次に、次のコードを入力します。/usr/bin/php を PHP 実行可能ファイルへの実際のパスに置き換えてください。
#!/usr/bin/php -q Hello world
?
ファイルを保存し、実行可能権限が設定されていることを確認します。ほとんどのシステムでは、chmod x hello-world
または同様のコードを使用してこれを行うことができます。次に、PHP ファイルを実行し (./hello-world
または必要に応じて php hello-world
を実行)、実行されるかどうかを確認します。実行すると、PHP インストールにはデフォルトでコマンド ライン機能が含まれます。
コードが正しく実行されない場合、作業が少し難しくなる可能性があります。その理由についてはさまざまな可能性が考えられます。 PHP 関連のエラー (「プログラムが見つかりません」などを除く) が発生した場合、問題はコードのタイプミスです。 PHP 実行可能ファイルが見つからない場合は、正しいパスを使用していることを確認してください。 PHP という名前の実行可能ファイルがない場合は、それを取得する必要があります。
?
PHP 実行可能ファイルを入手するには、システムに応じて異なる手順が必要になる場合がありますが、必要なサポートを受けることはそれほど難しくありません。まず、特定のオペレーティング システムまたはディストリビューションのドキュメントを参照してください。
?
現時点で PHP がシステムにインストールされていない場合は、まず PHP をインストールしてから、上記のコードを再度実行してみてください。多くのシステムでは、PHP をインストールするだけで済みます。さらに多くのことを行う必要がある場合は、お気に入りのパッケージ管理ツール (apt-get
や yum
など) を使用して PHP CLI パッケージ (名前は若干異なる場合があります) を取得するだけで問題が解決できる場合があります。
?
PHP パッケージ管理ツールでコマンド ラインが見つからない場合、最悪のシナリオでは、--enable-cli
タグを使用して PHP を再コンパイルできます。実際、これにはわずかに最適化されたシステムが提供されるという利点があり、いずれにしても悪いアイデアではありません。いずれにしても、始めるのはそれほど難しいことではありません。
?
ここまでで、HelloWorld スクリプトが実行されているはずです。出力はご想像のとおりになるでしょう。スクリプトがどのように機能するかについては詳しく説明しませんが、そのほとんどはシェル スクリプトと PHP を使用したことがある人にはよく知られているはずです。この最初のスクリプトは問題なく実行できるようになったので (そう願っています!)、実際のコマンド ライン インターフェイス (CLI) アプリケーションから少し離れて、すべての PHP プログラムでコマンド ラインから PHP が使用される理由を見てみましょう。それが誰にとっても最良の選択である理由は、デバッグです。
?
PHP 调试
可能只有我有这种体验,但是我经常发现调试 CLI 程序会演变成一场噩梦,尤其是处理嵌入了 HTML 的脚本,例如 Microsoft? Active Server Pages (ASP) 或 PHP。通常很难判断特定错误消息所表达的精确含义,用户输入可能很难再次生成,并且整件事通常会使您头痛的希望拔光头发。
?
不幸的是,虽然 足够聪明的程序员可以找到 CLI 能够有所帮助的方法(例如,通过从文件读取输入或通过一个通道的另一个程序),但是大部分问题都不会由于使用命令行而显著减弱。不过,CLI 确实使一件事变得更加简单:找到错误消息,以便可以在第一位置读取这些错误消息。
?
为了查看使用命令行调试的值,让我们从下面所示的非常非常糟糕的 PHP 文件开始。
#!/usr/bin/php -q Don<'t>code<?php while drunk(); ?<
?
虽然第一眼看到代码时,就发现这个脚本中的一些错误十分明显,但是代码在 Web 浏览器中提供了无用调试信息的极好示例。尤其是,不会发生这种情况:在 Apache 中运行此页面只是得到了根本没有输出的结果。如果错误不明显,那么您怎样找到错误原因?
?
解决这个问题的传统方法是查看错误日志。例如,您可能先运行:
tail -f /var/log/httpd/error_log
?
然后再将页面装入运行 Apache 2 的 Linux 系统,这将得到诸如下面的输出:
[client 127.0.0.1] PHP Parse error: parse error, unexpected T_STRING, expecting '(' in /var/www/html/dont-code-drunk.php on line 2
?
不幸的是,您可能同意我的观点,考虑这种不太理想的解决方案。一方面,文件日志位置可能因系统的不同而有所不同。另一方面,您必须浏览不相关事件的日志以查找所需内容,这对于活动的服务器来说很可能是一场噩梦。
?
此时,您可能和我曾经想的一样:一定会有更好的方法。
?
使用 CLI 定位并修正错误
通过直接在 CLI 上运行脚本,可以轻松地分离出代码中存在的问题。运行:
php dont-code-drunk.php
?
结果,可能会得到以下输出:
PHP Parse error: parse error, unexpected T_STRING, expecting '(' in /var/www/html/dont-code-drunk.php on line 2 Content-type: text/html X-Powered-By: PHP/4.3.11
?
更棒了!错误消息已与其他数据分离,并且在做出更改后可以轻松地重新查看页面。在这种情况下,很清楚它在行中某个位置需要 '('
。while
语句看似适合用在这里,因此添加一组新括号,得到以下源代码。
#!/usr/bin/php -q Don<'t>code<?php while (drunk()); ?<
?
现在,再次运行代码将得到以下输出:
?
清单 1. 再次运行结果
Content-type: text/html X-Powered-By: PHP/4.3.11 <'t>codePHP Fatal error: Call to undefined function: drunk() in /var/www/html/dont-code-drunk.php on line 2
?
脚本仍有很多问题,但是您已经取得了一些进展。您已经相对轻松地提取到了所需的错误消息,使您可以快速修正程序中的问题并继续处理下一个问题。
?
全然使用 PHP 的任何人都可以以这种方式充分利用 CLI PHP 进行调试。但是为什么不进一步伸展您自己并开始用 PHP 真正实现 shell 脚本?向前迈进,并且您将会看到将 PHP 用于简单或者不那么简单的 shell 脚本的一些可能性。
?
PHP I/O 通道
为第一个 PHP 脚本制定一个简单的初始目标:创建一个能读入文件并打乱该文件中各行的脚本。如果要打乱 m3u 文件或类似内容,则使用此功能可能很便利。这样做意味着您必须能够从文件或标准输入读取数据并将数据写回终端。
?
这将出现 PHP 中的第一大挑战。PHP 最初不是设计用于与用户直接的键盘输入或文本输出结合使用。了解这一设计是至关重要的,因为如果需要在命令行中执行任何操作,都必须能够与用户来回通信。在诸如 C
之类的传统编程语言中,您将使用 STDIN
、STDOUT
和 STDERR
完成此操作。您可以将 PHP 中的相同通道分别用于输入、标准输出和输出到错误通道。
?
STDOUT:echo、print、STDOUT 和 php://stdout
即 使 PHP 设计用于输出到浏览器而不是输出到 CLI,从 PHP 创建输出也是非常简单的,它几乎不需要花太多时间思考。记住,PHP 标记外的任何内容都将被直接输出到 CLI,这就是上面的 HelloWorld 程序如此简单的原因。这也是为什么先输出上面的 Don<'t>code
后再输出错误消息的原因。您是否用 HTML 标记圈起文字都没有关系;因为不管怎样都会显示这些文字。事实上,您通常需要避免使用 HTML 标记,因为它们都将直接打印给用户。
?
您还可以使用基本函数进行输出。例如,echo
和 print
命令打印到标准输出。
#!/usr/bin/php -q Output #1. <?php echo "Output #2."; print "Output #3."?>
?
这将得到:
Output #1. Output #2.Output #3.
?
注:PHP 标记外的新行已被输出,但是 echo
命令或 print
命令中没有暗含的新行。事实上,命令提示符重新出现在 Output #2.Output #3.
所在的行中。PHP 拥有的任何其他打印函数将会像此函数一样运行正常,任何写回文件的函数也是一样的。
#!/usr/bin/php -q <?php $STDOUT = fopen("php://stdout", "w"); fwrite($STDOUT, "Output #1."); fclose($STDOUT); ?>
?
以上代码将把 php://stdout
作为输出通道显式打开,并且 php://output
通常以与 php://stdout
相同的方法运行。最新版本的 PHP 可以使用 STDOUT
作为常量而不是定义上面使用的变量 $STDOUT
。
?
STDERR:STDERR 和 php://stderr
STDERR
与 STDOUT
十分接近。用于写入此通道的所有技术将镜像 STDOUT
的那些技术,惟一的差别是您将打开 php://stderr
而不是 php://stdout
或 php://error
。
?
STDIN:STDIN 和 php://stdin
STDIN
是从 Web 编程而来的最有趣更改,因为它向您展示了真正的用户输入而不是使用表单或其他基于浏览器的方法。尝试以下命令:
#!/usr/bin/php -q <?php $file = file_get_contents("php://stdin", "r"); echo $file; ?>
?
这段代码的工作原理应当很像 cat
,回转提供给它的所有输入。但是,这时它还不能接受参数。
?
第一个 PHP shell 脚本
很好 ―― 从这里开始事情会变得非常有趣。运用到目前为止学到的简单知识,您可以创建简单而有用的 shell 脚本。在文本编辑器中键入以下代码。
?
清单 2. randomize-lines
#!/usr/bin/php -q <?php $lines = split("\n", file_get_contents("php://stdin", "r")); shuffle($lines); foreach ($lines as $line) { if ($line !== "") { echo "$line\n"; } } ?>
?
现在,只需一些快速检查即可运行这个脚本:
- 确保 hashbang(第一行,以
#!
开头)被设为先前描述的 PHP 可执行文件的位置 - 保存文件
- 使用
chmod
添加可执行权限 - 运行程序
注:randomize-lines 将完全执行所期望的操作:它打乱键入的输入内容行并将它们以不同的顺序返回回来。这项功能可以颇具价值地填补 shell 脚本库中的空白。
?
作为此脚本的应用程序示例,您可以使用它为音乐或视频播放器动态生成随机播放列表。例如,要打乱 XMMS 播放列表,请尝试:
./randomize-lines < .xmms/xmms.m3u > temp mv temp .xmms/xmms.m3u
?
现在,再升一级。
?
命令行参数
实际命令行程序使用参数。同样,就像 C 语言和其他类似语言一样,您可以为此目的而使用 argv
和 argc
。特别是,argv
是程序的参数数组,第一个参数是程序本身。使用这个函数,构建根据给定参数从文件或用户输入读取数据的程序就不难了。例如,请查看以下代码。
?
清单 3. randomize-lines-w-args
#!/usr/bin/php -q <?php array_shift($argv); if (count($argv) == 0) { $argv[0] = "php://stdin"; } foreach ($argv as $file) { $lines = split("\n", file_get_contents($file, "r")); shuffle($lines); foreach ($lines as $line) { if ($line !== "") { echo "$line\n"; } } } ?>
?
现在您拥有这样一个程序:完全运行的 CLI PHP 程序,它可以接受用户输入,也可以接受文件列表并随机排列每个文件的相关内容。
?
结束语
工欲善其事,必先利其器;但是记住:最佳工具通常都不是您期望使用的那一个工具。请给 PHP 一个机会,在命令行接口中使用它,您就会发现它已经成为您的 shell 脚本工具新宠。最糟糕的情况是:它可以省去一些 Web 服务器麻烦。
?
参考資料
学ぶ
- この記事の英語版のオリジナル版は、developerWorks グローバル サイトで読むことができます。
- 「PHP by example」を読んで、複雑で強力な Web 関連プログラムを構築する PHP の簡単な方法を理解してください。
- PHP Freaks では、CLI で PHP を使用する方法について説明します。
- PHP CLI には独自の Web サイトがあります。知るか?
- PHP.net は、PHP 開発者向けのリソースです。
- 「PHP 推奨書籍リスト」をご覧ください。
- developerWorks ですべての PHP 記事と PHP チュートリアルを参照します。
- PHP の拡張に関するヒントについては、IBM developerWorks PHP プロジェクトのリソース・センターを参照してください。
- ソフトウェア開発者向けの興味深いインタビューやディスカッションを聞くには、developerWorks ポッドキャストに必ずアクセスしてください。
- developerWorks の技術イベントや Web キャストに常にアクセスしてください。
- 世界中で開催される IBM オープンソース開発者向けの今後のワークショップ、見本市、Web キャスト、その他のイベントをチェックしてください。
- developerWorks のオープン ソース ソフトウェア テクノロジー ゾーンにアクセスして、オープン ソース テクノロジーを使用した開発や IBM 製品での使用に役立つ豊富なハウツー情報、ツール、プロジェクトの最新情報を入手してください。
- Safari オンライン ブックストアにアクセスして、オープンソース テクノロジに関するさまざまな参考資料を閲覧してください。
製品とテクノロジーを入手
- ダウンロードまたは DVD として入手できる IBM 試用版ソフトウェアを使用して、次の開発プロジェクトを構築します。
話し合う
- developerWorks ブログに参加し、developerWorks コミュニティに参加してください。
- developerWorks PHP 開発者フォーラムに参加してください。
出典: http://www.ibm.com/developerworks/cn/opensource/os-php-command/
?
?
?
?
?
?
?
?
?