從版本 4.3.0 開始,PHP 提供了一種新類型的 SAPI(Server Application Programming Interface,服務端應用編程端口)支持,名爲 CLI,意爲 Command Line Interface,即命令行接口。顧名思義,該 SAPI 模塊主要用做 PHP 的開發外殼應用。CLI SAPI 和其它 SAPI 模塊相比有不少的不一樣之處,咱們將在本章中詳細闡述。值得一提的是,CLI 和 CGI 是不一樣的 SAPI,儘管它們之間有不少共同的行爲。php
CLI SAPI 最早是隨 PHP 4.2.0 版本發佈的,但仍舊只是一個實驗性的版本,並須要在運行 ./configure 時加上 --enable-cli 參數。從 PHP 4.3.0 版本開始,CLI SAPI 成爲了正式模塊,--enable-cli 參數會被默認得設置爲 on,您也能夠用參數 --disable-cli 來屏蔽。html
從 PHP 4.3.0開始,CLI/CGI 二進制執行文件的文件名、位置和是否存在會根據 PHP 在您系統上的安裝而不一樣。在默認狀況下,當運行 make 時,CGI 和 CLI 都會被編譯而且分別放置在您 PHP 源文件目錄的 sapi/cgi/php和 sapi/cli/php 下。您能夠注意到兩個文件都被命名爲了 php。在 make install 的過程當中會發生什麼取決於您的配置行。若是在配置的時候選擇了一個 SAPI 模塊,如 apxs,或者使用了 --disable-cgi 參數,則在 make install 的過程當中,CLI 將被拷貝到 {PREFIX}/bin/php,除非 CGI 已經被放置在了那個位置。所以,例如,若是在您的配置行中有 --with--apxs ,則在 make install 的過程當中,CLI 將被拷貝到 {PREFIX}/bin/php。若是您但願撤銷 CGI 執行文件的安裝,請在 make install 以後運行 make install-cli。或者,您也能夠在您的配置行中加上 --disable-cgi 參數。mysql
注: 因爲 --enable-cli 和 --enable-cgi 同時默認有效,所以,您沒必要再配置行中加上 --enable-cli 來使得 CLI 在 make install 過程當中被拷貝到 {PREFIX}/bin/php。sql
在 PHP 4.2.0 到 PHP 4.2.3 之間的 Windows 發行包中,CLI 的文件名爲 php-cli.exe,相同文件夾下的 php.exe 爲 CGI。從 PHP 4.3.0 版本開始,Windows 的發行包中 CLI 的執行文件爲 php.exe,被放置在一個單獨的名爲 cli 的文件夾下,即 cli/php.exe。編程
這是哪一個 SAPI?: 在命令外殼下,運行 php -v 便能得知該 php 是 CGI 仍是 CLI。請參考函數 php_sapi_name() 以及常量 PHP_SAPI。api
注: 在 PHP 4.3.2 中加入了 UNIX 的 man 頁面。能夠在你的命令外殼下鍵入 man php 來查看。數組
如下爲 CLI SAPI 和其它 SAPI 模塊相比的顯著區別:bash
-
與 CGI SAPI 不一樣,其輸出沒有任何頭信息。服務器
儘管 CGI SAPI 提供了取消 HTTP 頭信息的方法,但在 CLI SAPI 中並不存在相似的方法以開啓 HTTP 頭信息的輸出。session
CLI 默認以安靜模式開始,但爲了保證兼容性, -q 參數使得您可使用舊的 CGI 腳本。
在運行時,不會把工做目錄改成腳本的當前目錄。(您可使用 -C 參數來兼容 CGI 模式)。
出錯時輸出純文本的錯誤信息(非 HTML 格式)。
-
CLI SAPI 強制更改了 php.ini 中的某些設置,由於這些設置在外殼環境下是沒有意義的。
表格 23-1. 被更改的 php.ini 設置選項
設置選項 |
CLI SAPI 默認值 |
備註 |
html_errors |
FALSE |
無心義的 HTML 標記符會使得出錯信息很凌亂,因此在外殼下閱讀報錯信息是十分困難的。所以將該選項的默認值改成 FALSE。 |
implicit_flush |
TRUE |
在命令行模式下,全部來自 print() 和 echo() 的輸出將被當即寫到輸出端,而不做任何地緩衝操做。若是您但願延緩或控制標準輸出,您仍然可使用 output buffering 設置項。 |
max_execution_time |
0 (無限值) |
鑑於在外殼環境下使用 PHP 的無窮的可能性,最大運行時間被設置爲了無限值。爲 WEB 開發的應用程序可能只需運行幾秒鐘時間,而外殼應用程序的運行時間可能會長的多。 |
register_argc_argv |
TRUE |
因爲該設置爲 TRUE,您將老是能夠在 CLI SAPI 中訪問到 argc(傳送給應用程序參數的個數)和 argv(包含有實際參數的數組)。 對於 PHP 4.3.0,在使用 CLI SAPI 時,PHP 變量 $argc 和 $argv 已被註冊而且設定了對應的值。而在這以前的版本,這兩個變量在 CGI 或者 模塊 版本中的創建依賴於將 PHP 的設置選項 register_globals 設爲 on。除了版本和 register_globals 設定之外,您能夠隨時經過調用 $_SERVER 或者 $HTTP_SERVER_VARS來訪問它們。例如:$_SERVER['argv'] |
注: 這些設置沒法在設置文件 php.ini 或任何指定的其它文件中被初始化爲其它值。這些默認值被限制在全部其它的設置文件被解析後改變。不過,它們的值能夠在程序運行的過程當中被改變(儘管對於該運行過程來講,這些設置項是沒有意義的)。
-
爲了減輕外殼環境下的工做,咱們定義了以下常量:
表格 23-2. CLI 專用常量
常量名稱 |
描 述 |
STDIN |
一個已打開的指向 stdin 的流。您能夠用以下方法來調用:
$stdin = fopen('php://stdin', 'r'); |
|
STDOUT |
一個已打開的指向 stdout 的流。您能夠用以下方式來調用:
$stdout = fopen('php://stdout', 'w'); |
|
STDERR |
一個已打開的指向 stderr 的流。您能夠用以下方式來調用:
$stderr = fopen('php://stderr', 'w'); |
|
有了以上常量,您就無需本身創建指向諸如 stderr 的流,只需簡單的使用這些常量來代替流指向:
php -r 'fwrite(STDERR, "stderr\n");' |
您無需本身來關閉這些流,PHP 會自動完成這些操做。
-
CLI SAPI 不會將當前目錄改成已運行的腳本所在的目錄。
如下範例顯示了本模塊與 CGI SAPI 模塊之間的不一樣:
<?php /* Our simple test application named test.php*/ echo getcwd(), "\n"; ?> |
在使用 CGI 版本時,其輸出爲
$ pwd
/tmp
$ php-cgi -f another_directory/test.php
/tmp/another_directory |
咱們明顯能夠看到 PHP 將當前目錄改爲了剛剛運行過的腳本所在的目錄。
使用 CLI SAPI 模式,咱們獲得:
$ pwd
/tmp
$ php -q another_directory/test.php
/tmp |
這使得咱們在利用 PHP 編寫外殼工具時得到了很大的便利。
注: 您能夠在命令行運行時給 CGI SAPI 加上 -C 參數,使其支持 CLI SAPI 的功能。
如下是 PHP 二進制文件(即 php.exe 程序)提供的命令行模式的選項參數,您隨時能夠經過 PHP -h 命令來查詢這些參數。
Usage: php [options] [-f] <file> [args...]
php [options] -r <code> [args...]
php [options] [-- args...]
-s Display colour syntax highlighted source.
-w Display source with stripped comments and whitespace.
-f <file> Parse <file>.
-v Version number
-c <path>|<file> Look for php.ini file in this directory
-a Run interactively
-d foo[=bar] Define INI entry foo with value 'bar'
-e Generate extended information for debugger/profiler
-z <file> Load Zend extension <file>.
-l Syntax check only (lint)
-m Show compiled in modules
-i PHP information
-r <code> Run PHP <code> without using script tags <?..?>
-h This help
args... Arguments passed to script. Use -- args when first argument
starts with - or script is read from stdin |
CLI SAPI 模塊有如下三種不一樣的方法來獲取您要運行的 PHP 代碼:
-
讓 PHP 運行指定文件。
php my_script.php
php -f my_script.php |
以上兩種方法(使用或不使用 -f 參數)都可以運行給定的 my_script.php 文件。您能夠選擇任何文件來運行,您指定的 PHP 腳本並不是必需要以 .php 爲擴展名,它們能夠有任意的文件名和擴展名。
-
在命令行直接運行 PHP 代碼。
php -r 'print_r(get_defined_constants());' |
在使用這種方法時,請您注意外殼變量的替代及引號的使用。
注: 請仔細閱讀以上範例,在運行代碼時沒有開始和結束的標記符!加上 -r 參數後,這些標記符是不須要的,加上它們會致使語法錯誤。
-
經過標準輸入(stdin)提供須要運行的 PHP 代碼。
以上用法給咱們提供了很是強大的功能,使得咱們能夠以下範例所示,動態地生成 PHP 代碼並經過命令行運行這些代碼:
$ some_application | some_filter | php | sort -u >final_output.txt |
以上三種運行代碼的方法不能同時使用。
和全部的外殼應用程序同樣,PHP 的二進制文件(php.exe 文件)及其運行的 PHP 腳本可以接受一系列的參數。PHP 沒有限制傳送給腳本程序的參數的個數(外殼程序對命令行的字符數有限制,但您一般都不會超過該限制)。傳遞給您腳本的參數可在全局變量 $argv 中獲取。該數組中下標爲零的成員爲腳本的名稱(當 PHP 代碼來自標準輸入獲直接用 -r 參數以命令行方式運行時,該名稱爲「-」)。另外,全局變量 $argc 存有 $argv 數組中成員變量的個數(而非傳送給腳本程序的參數的個數)。
只要您傳送給您腳本的參數不是以 - 符號開頭,您就無需過多的注意什麼。向您的腳本傳送以 - 開頭的參數會致使錯誤,由於 PHP 會認爲應該由它自身來處理這些參數。您能夠用參數列表分隔符 -- 來解決這個問題。在 PHP解析完參數後,該符號後全部的參數將會被原樣傳送給您的腳本程序。
# 如下命令將不會運行 PHP 代碼,而只顯示 PHP 命令行模式的使用說明:
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]
# 如下命令將會把「-h」參數傳送給腳本程序,PHP 不會顯示命令行模式的使用說明:
$ php -r 'var_dump($argv);' -- -h
array(2) {
[0]=>
string(1) "-"
[1]=>
string(2) "-h"
} |
除此以外,咱們還有另外一個方法將 PHP 用於外殼腳本。您能夠在寫一個腳本,並在第一行以 #!/usr/bin/php 開頭,在其後加上以 PHP 開始和結尾標記符包含的正常的 PHP 代碼,而後爲該文件設置正確的運行屬性。該方法可使得該文件可以像外殼腳本或 PERL 腳本同樣被直接執行。
#!/usr/bin/php <?php var_dump($argv); ?> |
假設改文件名爲 test 並被放置在當前目錄下,咱們能夠作以下操做:
$ chmod 755 test
$ ./test -h -- foo
array(4) {
[0]=>
string(6) "./test"
[1]=>
string(2) "-h"
[2]=>
string(2) "--"
[3]=>
string(3) "foo"
} |
正如您所看到的,在您向該腳本傳送以 - 開頭的參數時,腳本仍然可以正常運行。
表格 23-3. 命令行選項
選項名稱 |
描 述 |
-s |
顯示有語法高亮色彩的源文件。 該參數使用內建機制來解析文件併爲其生成一個 HTML 高亮版本並將結果寫到標準輸出。請注意該過程所作的只是生成了一個 <code> [...] </code> 的 HTML 標記符塊,並不包含任何的 HTML 頭。
|
-w |
顯示除去了註釋和空格的源代碼。
|
-f |
解析並運行給定的文件名。該參數爲可選參數且能夠不加,僅指明須要運行的文件名便可。 |
-v |
將 PHP、PHP SAPI 及 Zend 的版本信息寫入的標準輸出。例如:
$ php -v
PHP 4.3.0-dev (cli), Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies |
|
-c |
用該參數,您能夠指定一個放置 php.ini 文件的目錄,或者直接指定一個自定義的 INI 文件,其文件名能夠不是 php.ini。例如:
$ php -c /custom/directory/ my_script.php
$ php -c /custom/directory/custom-file.ini my_script.php |
|
-a |
交互地運行 PHP。 |
-d |
用該參數能夠自行設置 php.ini 文件中設置變量的值,其語法爲:
-d configuration_directive[=value] |
範例:
# Ommiting the value part will set the given configuration directive to "1"
$ php -d max_execution_time
-r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"
# Passing an empty value part will set the configuration directive to ""
php -d max_execution_time=
-r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""
# The configuration directive will be set to anything passed after the '=' character
$ php -d max_execution_time=20
-r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(2) "20"
$ php
-d max_execution_time=doesntmakesense
-r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(15) "doesntmakesense" |
|
-e |
爲調試器等生成擴展信息。 |
-z |
加載 Zend 擴展庫。若是僅給定一個文件名,PHP 將試圖從您系統擴展庫的默認路徑(在 Linux 系統下,該路徑一般由 /etc/ld.so.conf 指定)加載該擴展庫。若是您用一個絕對路徑指定文件名,則系統的擴展庫默認路徑將不會被使用。若是用相對路徑指定的文件名,PHP 則僅試圖加載相對於當前目錄的擴展庫。 |
-l |
該參數提供了對指定 PHP 代碼進行語法檢查的方便的方法。若是成功,則向標準輸出寫入 No syntax errors detected in <filename> 字符串,而且外殼返回值爲 0。若是失敗,則 Errors parsing <filename> 以及內部解析器錯誤信息會一塊兒被寫入到標準輸出,同時外殼返回值將別設置爲 255。 該參數將沒法檢查致命錯誤(如未定義函數),若是您但願檢測之名錯誤,請使用 -f 參數。
|
-m |
使用該參數,PHP 將打印出內置以及已加載的 PHP 及 Zend 模塊:
$ php -m
[PHP Modules]
xml
tokenizer
standard
session
posix
pcre
overload
mysql
mbstring
ctype
[Zend Modules] |
|
-i |
該命令行參數會調用 phpinfo() 函數,並打印出結果。若是 PHP 沒有正常工做,咱們建議您執行 php -i 命令來查看在信息表格以前或者對應的地方是否有任何錯誤信息輸出。請注意輸出的內容爲 HTML 格式,所以輸出的信息篇幅較大。 |
-r |
使用該參數能夠在命令行運行 PHP 代碼。您無需加上 PHP 的起始和結束標識符(<?php 和 ?>),不然將會致使語法解析錯誤。
注: 使用這種形式的 PHP 時,應個別注意避免和外殼環境進行的命令行參數替換相沖突。
顯示語法解析錯誤的範例
$ php -r "$foo = get_defined_constants();"
Command line code(1) : Parse error - parse error, unexpected '=' |
這裏的問題在於即時使用了雙引號 ",sh/bash 仍然實行了參數替換。因爲 $foo 沒有被定義,被替換後它所在的位置變成了空字符,所以在運行時,實際被 PHP 讀取的代碼爲:
$ php -r " = get_defined_constants();" |
正確的方法是使用單引號 '。在用單引號引用的字符串中,變量不會被 sh/bash 還原成其原值。
$ php -r '$foo = get_defined_constants(); var_dump($foo);'
array(370) {
["E_ERROR"]=>
int(1)
["E_WARNING"]=>
int(2)
["E_PARSE"]=>
int(4)
["E_NOTICE"]=>
int(8)
["E_CORE_ERROR"]=>
[...] |
若是您使用的外殼不是 sh/bash,您可能會碰到其它的問題。請報告您碰到的 bug,或者發郵件到 phpdoc@lists.php.net。
當您試圖將外殼的環境變量引入到馬或者用反斜線來轉義字符時也可能碰到各類各樣的問題,請您在使用時注意!
注: -r 在 CLI SAPI 中有效,在 CGI SAPI 中無效。
|
-h |
使用該參數,您能夠獲得完整的命令行參數的列表及這些參數做用的簡單描述。 |
PHP 的命令行模式能使得 PHP 腳本能徹底獨立於 WEB 服務器單獨運行。若是您使用 Unix 系統,您須要在您的 PHP 腳本的最前面加上一行特殊的代碼,使得它可以被執行,這樣系統就能知道用什麼樣的程序要運行該腳本。在 Windows 平臺下您能夠將 php.exe 和 .php 文件的雙擊屬性相關聯,您也能夠編寫一個批處理文件來用 PHP 執行腳本。爲 Unix 系統增長的第一行代碼不會影響該腳本在 Windows 下的運行,所以您也能夠用該方法編寫跨平臺的腳本程序。如下是一個簡單的PHP 命令行程序的範例。
例子 23-1. 試圖以命令行方式運行的 PHP 腳本(script.php)
#!/usr/bin/php <?php
if ($argc != 2 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) { ?>
This is a command line PHP script with one option.
Usage: <?php echo $argv[0]; ?> <option>
<option> can be some word you would like to print out. With the --help, -help, -h, or -? options, you can get this help.
<?php } else { echo $argv[1]; } ?> |
|
在以上腳本中,咱們用第一行特殊的代碼來指明該文件應該由 PHP 來執行。咱們在這裏使用 CLI 的版本,所以不會有 HTTP 頭信息輸出。在您用 PHP 編寫命令行應用程序時,您可使用兩個參數:$argc 和 $argv。前面一個的值是比參數個數大 1 的整數(運行的腳本自己的名稱也被看成一個參數)。第二個時包含有參數的數組,其第一個元素爲腳本的名稱,下標爲數字 0($argv[0])。
在以上程序中咱們檢查了參數的個數是大於 1 個仍是小於 1 個。即時參數是 --help、-help、-h 或 -?,咱們仍然打印出幫助信息,並同時動態輸出腳本的名稱。若是還收到了其它參數,咱們也把它們顯示出來。
若是您但願在 Unix 下運行以上腳本,您須要使得它成爲可執行腳本,而後簡單的運行 script.php echothis 或 script.php -h。在 Windows 下,您能夠爲此編寫一個批處理文件:
例子 23-2. 運行 PHP 命令行腳本的批處理文件(script.bat)
@c:\php\cli\php.exe script.php %1 %2 %3 %4 |
|
假設您將上述程序命名爲 script.php,且您的 CLI php.exe 文件放置在 c:\php\cli\php.exe,該批處理文件會幫助您將附加的參數傳給腳本程序: script.bat echothis 或 script.bat -h。