PHP 命令列?是的,您可以!
將 PHP 用於一般目的的指令碼並將命令列介面用於 PHP 調試
瞭解如何通過命令列調試 PHP 代碼,以及體驗 PHP 本身作為 shell 指令碼語言的強大之處。
?
CLI PHP 的優點
多年以來,我一直都在應用不確定的工程師職責定義。我個人認為,工程師就是使用工具來實現與該工具最初開發目的無關的功能。雖然這種想法並不總是正確,但當您認真考慮它時,將發現大多數創新和發明確實來自於通過以前從未考慮過的方法使用工具。
?
想象一下我是多麼驚訝,然後,我忽然想到一個主意:使用我的老朋友 PHP,作為命令列工具,它對於 Web 頁面來說一直都非常可靠。我絕對不是這樣做的第一人,但是這對我來說的確是全新的想法。
?
當然,只是可以 在命令列中使用 PHP 當然不是這樣做的最佳理由。但是,您在第一次開始以這種方式用 PHP 進行實驗時可能很快就會發現幾個令人興奮的驚喜。首先,調試現有指令碼將變得前所未有地簡單。由主要輸出和極少邏輯組成的 PHP 程式都將變得令人難以置信地簡單。除此之外,您還可以使用所有 PHP 知識來完成以前從未想過使用 PHP 完成的任務。事實上,確實沒有任何事能阻止您使用 PHP 作為幾乎所有給定編程項目的全能王。
?
產生興趣了?很好,讓我們開始著手並看看您可以在命令列中使用 PHP 來完成哪些任務。
?
安裝
安裝十分簡單扼要,它甚至可能都不需要特別安裝任何內容。開始時先在命令列中嘗試一個簡單的 PHP 指令碼。您可以使用現有 PHP 指令碼,也可以嘗試使用以下代碼。本例是基於 Linux? 的,但是類似的原理也適用於其他系統。
?
首先,確認 PHP 可執行檔的位置 ―― 對於大多數 Linux 系統,幾乎肯定是 /usr/bin/php。如果不確定其位置,請在命令列中鍵入 which php 並查看響應內容。
?
其次,鍵入以下代碼,確保將 /usr/bin/php 替換為 PHP 可執行檔的實際路徑。
#!/usr/bin/php -qHello 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 指令碼,並且輸出就是可能已經猜測到的結果。我不會詳細說明該指令碼的工作原理,但是使用過 shell 指令碼和 PHP 的人應當十分熟悉指令碼的大部分內容。由於這第一個指令碼現在的運行沒有出現任何問題(我們希望如此!),因此我們將略微偏離真正的命令列介面 (CLI) 應用程式,看一看為什麼在命令列中使用 PHP 對於所有 PHP 程式員來說都是最佳選擇的好理由:調試。
?
PHP 調試
可能只有我有這種體驗,但是我經常發現調試 CLI 程式會演變成一場噩夢,尤其是處理嵌入了 HTML 的指令碼,例如 Microsoft? Active Server Pages (ASP) 或 PHP。通常很難判斷特定錯誤訊息所表達的精確含義,使用者輸入可能很難再次產生,並且整件事通常會使您頭痛的希望拔光頭髮。
?
不幸的是,雖然 足夠聰明的程式員可以找到 CLI 能夠有所協助的方法(例如,通過從檔案讀取輸入或通過一個通道的另一個程式),但是大部分問題都不會由於使用命令列而顯著減弱。不過,CLI 確實使一件事變得更加簡單:找到錯誤訊息,以便可以在第一位置讀取這些錯誤訊息。
?
為了查看使用命令列調試的值,讓我們從下面所示的非常非常糟糕的 PHP 檔案開始。
#!/usr/bin/php -qDon<'t>code?
雖然第一眼看到代碼時,就發現這個指令碼中的一些錯誤十分明顯,但是代碼在 網頁瀏覽器中提供了無用調試資訊的極好樣本。尤其是,不會發生這種情況:在 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 2Content-type: text/htmlX-Powered-By: PHP/4.3.11?
更棒了!錯誤訊息已與其他資料分離,並且在做出更改後可以輕鬆地重新查看頁面。在這種情況下,很清楚它在行中某個位置需要 '('。while 語句看似適合用在這裡,因此添加一組新括弧,得到以下原始碼。
#!/usr/bin/php -qDon<'t>code?
現在,再次運行代碼將得到以下輸出:
?
清單 1. 再次運行結果
Content-type: text/htmlX-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 -qOutput #1.
?
這將得到:
Output #1.Output #2.Output #3.
?
註:PHP 標記外的新行已被輸出,但是 echo 命令或 print 命令中沒有暗含的新行。事實上,命令提示字元重新出現在 Output #2.Output #3. 所在的行中。PHP 擁有的任何其他列印函數將會像此函數一樣運行正常,任何寫迴文件的函數也是一樣的。
#!/usr/bin/php -q
?
以上代碼將把 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
?
這段代碼的工作原理應當很像 cat,迴轉提供給它的所有輸入。但是,這時它還不能接受參數。
?
第一個 PHP shell 指令碼
很好 ―― 從這裡開始事情會變得非常有趣。運用到目前為止學到的簡單知識,您可以建立簡單而有用的 shell 指令碼。在文字編輯器中鍵入以下代碼。
?
清單 2. randomize-lines
#!/usr/bin/php -q
?
現在,只需一些快速檢查即可運行這個指令碼:
- 確保 hashbang(第一行,以
#! 開頭)被設為先前描述的 PHP 可執行檔的位置 - 儲存檔案
- 使用
chmod 添加可執行許可權 - 運行程式
註:randomize-lines 將完全執行所期望的操作:它打亂鍵入的輸入內容行並將它們以不同的順序返回回來。這項功能可以頗具價值地填補 shell 指令碼庫中的空白。
?
作為此指令碼的應用程式樣本,您可以使用它為音樂或視頻播放器動態產生全部隨機播放列表。例如,要打亂 XMMS 播放清單,請嘗試:
./randomize-lines < .xmms/xmms.m3u > tempmv temp .xmms/xmms.m3u
?
現在,再升一級。
?
命令列參數
實際命令列程式使用參數。同樣,就像 C 語言和其他類似語言一樣,您可以為此目的而使用 argv 和 argc。特別是,argv 是程式的參數數組,第一個參數是程式本身。使用這個函數,構建根據給定參數從檔案或使用者輸入讀取資料的程式就不難了。例如,請查看以下代碼。
?
清單 3. randomize-lines-w-args
#!/usr/bin/php -q
?
現在您擁有這樣一個程式:完全啟動並執行 CLI PHP 程式,它可以接受使用者輸入,也可以接受檔案清單並隨機排列每個檔案的相關內容。
?
結束語
工欲善其事,必先利其器;但是記住:最佳工具通常都不是您期望使用的那一個工具。請給 PHP 一個機會,在命令列介面中使用它,您就會發現它已經成為您的 shell 指令碼工具新寵。最糟糕的情況是:它可以省去一些 Web 服務器麻煩。
?
參考資料
學習
- 您可以參閱本文在 developerWorks 全球網站上的 英文原文 。
- 閱讀 “PHP by example” 發現 PHP 用於構建複雜且功能強大的 Web 相關程式的簡單方法。
- PHP Freaks 討論了如何在 CLI 上使用 PHP。
- PHP CLI 擁有它自己的 Web 網站。誰知道?
- PHP.net 是 PHP 開發人員的資源。
- 查閱 “PHP 推薦讀物列表”。
- 瀏覽 developerWorks 上所有的 PHP 文章 和 PHP 教程。
- 查閱 IBM developerWorks 的 PHP 項目資源中心 擴充 PHP 技巧。
- 要收聽針對軟體開發人員的有趣訪談和討論,一定要訪問 developerWorks podcast。
- 隨時關注 developerWorks 的 技術事件和網路廣播。
- 查閱最近將在全球舉辦的面向 IBM 開放源碼開發人員的研討會、交易展覽、網路廣播和其他 活動。
- 訪問 developerWorks 開源軟體技術專區,獲得豐富的 how-to 資訊、工具和項目更新,協助您用開放源碼技術進行開發,並與 IBM 產品結合使用。
- 訪問 Safari 線上書店 瀏覽開放源碼技術的各種參考資料。
獲得產品和技術
- 使用 IBM 試用軟體 構建您的下一個開發項目,這些軟體可以通過下載或從 DVD 中獲得。
討論
- 參與 developerWorks blog,加入 developerWorks 社區。
- 參與 developerWorks PHP 開發人員論壇。
來源:http://www.ibm.com/developerworks/cn/opensource/os-php-command/
?
?
?
?
?
?
?
?
?