php.exe和php-win.exe和php-cgi.exe的區別

PHP 的命令行模式

從版本 4.3.0 開始,PHP 提供了一種新類型的 SAPI(Server Application Programming Interface,服務端應用編程端口)支持,名爲 CLI,意爲 Command Line Interface,即命令行接口。顧名思義,該 SAPI 模塊主要用作 PHP 的開發外殼應用。CLI SAPI 和其它 SAPI模塊相比有很多的不同之處,我們將在本章中詳細闡述。值得一提的是,CLI 和 CGI 是不同的 SAPI,儘管它們之間有很多共同的行爲。

CLI SAPI 最先是隨 PHP 4.2.0 版本發佈的,但仍舊只是一個實驗性的版本,並需要在運行./configure 時加上 --enable-cli 參數。從 PHP 4.3.0 版本開始,CLI SAPI 成爲了正式模塊,--enable-cli 參數會被默認得設置爲 on,也可以用參數 --disable-cli 來屏蔽。

從 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 參數。

Note:

由於 --enable-cli 和 --enable-cgi 同時默認有效,因此,不必再配置行中加上 --enable-cli 來使得 CLI 在 make install 過程中被拷貝到 {PREFIX}/bin/php

在 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。在 PHP 5 中,CLI 存在於主文件夾中,名爲 php.exe,而 CGI 版本名爲 php-cgi.exe

從 PHP 5 起,一個名爲 php-win.exe 的新文件隨包發佈。它相當於 CLI 版本,但是 php-win 不輸出任何內容,便不提供控制檯(不會彈出“DOS 窗口”)。這種方式類似於 php-gtk。需要使用 --enable-cli-win32 選項來配置它。

Note如何得知自己使用的是哪個 SAPI?

在命令行下,運行 php -v 便能得知該 php 是 CGI 還是 CLI。請參考函數php_sapi_name() 以及常量 PHP_SAPI

Note:

在 PHP 4.3.2 中加入了 Unix 的 man 頁面。可以在命令行中鍵入 man php 來查看。

以下爲 CLI SAPI 和其它 SAPI 模塊相比的顯著區別:

  • 與 CGI SAPI 不同,其輸出沒有任何頭信息。

    儘管 CGI SAPI 提供了取消 HTTP 頭信息的方法,但在 CLI SAPI 中並不存在類似的方法以開啓 HTTP 頭信息的輸出。

    CLI 默認以安靜模式開始,但爲了保證兼容性,-q 和 --no-header 參數爲了向後兼容仍然保留,使得可以使用舊的 CGI 腳本。

    在運行時,不會把工作目錄改爲腳本的當前目錄(可以使用 -C 和 --no-chdir 參數來兼容 CGI 模式)。

    出錯時輸出純文本的錯誤信息(非 HTML 格式)。

  • CLI SAPI 強制覆蓋了 php.ini 中的某些設置,因爲這些設置在外殼環境下是沒有意義的。

    覆蓋 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']

    Note:

    這些設置無法在設置文件 php.ini 或任何指定的其它文件中被初始化爲其它值。這些默認值被限制在所有其它的設置文件被解析後改變。不過,它們的值可以在程序運行的過程中被改變(儘管對於該運行過程來說,這些設置項是沒有意義的)。

  • 爲了減輕外殼環境下的工作,我們定義瞭如下常量:

    CLI 專用常量
    常量名稱 描 述
    STDIN 一個已打開的指向 stdin 的流。可以用如下方法來調用: <?php

    $stdin 
    fopen('php://stdin''r');

    ?> 
    如果想從 stdin 讀取一行內容,可以使用 <?php
    $line 
    trim(fgets(STDIN)); // 從 STDIN 讀取一行
    fscanf(STDIN"%d "$number); // 從 STDIN 讀取數字
    ?>
    STDOUT 一個已打開的指向 stdout 的流。可以用如下方式來調用: <?php

    $stdout 
    fopen('php://stdout''w');

    ?>
    STDERR 一個已打開的指向 stderr 的流。可以用如下方式來調用: <?php

    $stderr 
    fopen('php://stderr''w');

    ?>

    有了以上常量,就無需自己建立指向諸如 stderr 的流,只需簡單的使用這些常量來代替流指向:

    php -r 'fwrite(STDERR, "stderr
    ");'
    無需自己來關閉這些流,PHP 會自動完成這些操作。

  • CLI SAPI 不會將當前目錄改爲已運行的腳本所在的目錄。

    以下範例顯示了本模塊與 CGI SAPI 模塊之間的不同: <?php
    // 名爲 test.php 的簡單測試程序
    echo getcwd(), " ";
    ?>

    在使用 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 編寫外殼工具時獲得了很大的便利。

    Note:

    可以在命令行運行時給該 CGI SAPI 加上 -C 參數,使其支持 CLI SAPI 的功能。

以下是 PHP 二進制文件(即 php.exe 程序)提供的命令行模式的選項參數,隨時可以運行帶-h 參數的 PHP 命令來查詢這些參數。

Usage: php [options] [-f] <file> [--] [args...]
       php [options] -r <code> [--] [args...]
       php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
       php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
       php [options] -- [args...]
       php [options] -a

  -a               Run interactively
  -c <path>|<file> Look for php.ini file in this directory
  -n               No php.ini file will be used
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -f <file>        Parse <file>.
  -h               This help
  -i               PHP information
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -r <code>        Run PHP <code> without using script tags <?..?>
  -B <begin_code>  Run PHP <begin_code> before processing input lines
  -R <code>        Run PHP <code> for every input line
  -F <file>        Parse and execute <file> for every input line
  -E <end_code>    Run PHP <end_code> after processing all input lines
  -H               Hide any passed arguments from external tools.
  -s               Display colour syntax highlighted source.
  -v               Version number
  -w               Display source with stripped comments and whitespace.
  -z <file>        Load Zend extension <file>.

  args...          Arguments passed to script. Use -- args when first argument
                   starts with - or script is read from stdin

CLI SAPI 模塊有以下三種不同的方法來獲取要運行的 PHP 代碼:

  1. 讓 PHP 運行指定文件。

    php my_script.php
    
    php -f my_script.php
    

    以上兩種方法(使用或不使用 -f 參數)都能夠運行給定的 my_script.php 文件。可以選擇任何文件來運行,指定的 PHP 腳本並非必須要以 .php 爲擴展名,它們可以有任意的文件名和擴展名。

  2. 在命令行直接運行 PHP 代碼。

    php -r 'print_r(get_defined_constants());'
    

    在使用這種方法時,請注意外殼變量的替代及引號的使用。

    Note:

    請仔細閱讀以上範例,在運行代碼時沒有開始和結束的標記符!加上 -r 參數後,這些標記符是不需要的,加上它們會導致語法錯誤。

  3. 通過標準輸入(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 代碼,然後爲該文件設置正確的運行屬性(例如:chmod +x test)。該方法可以使得該文件能夠像外殼腳本或 PERL 腳本一樣被直接執行。 #!/usr/bin/php
<?php
    var_dump
($argv);
?>

假設改文件名爲 test 並被放置在當前目錄下,可以做如下操作:

$ chmod +x test
$ ./test -h -- foo
array(4) {
  [0]=>
  string(6) "./test"
  [1]=>
  string(2) "-h"
  [2]=>
  string(2) "--"
  [3]=>
  string(3) "foo"
}

正如所看到的,在向該腳本傳送以 - 開頭的參數時,腳本仍然能夠正常運行。

PHP 4.3.3 以來有效的長選項:

命令行選項
選項名稱 長名稱 說明
-a --interactive

交互式運行 PHP。如果編譯 PHP 時加入了 Readline 擴展(Windows 下不可用),那將會得到一個很好的外殼,包括一個自動完成的功能(例如可以在鍵入變量名的時候,按下 TAB 鍵,PHP 會自動完成該變量名)以及命令歷史記錄,可以用上下鍵來訪問。歷史記錄存在 ~/.php_history 文件中。

Note:

通過 auto_prepend_file 和 auto_append_file 包含的文件在此模式下會被解析,但有些限制,例如函數必須在被調用之前定義。

-c --php-ini

用該參數,可以指定一個放置 php.ini 文件的目錄,或者直接指定一個自定義的 INI 文件(其文件名可以不是 php.ini),例如:

$ php -c /custom/directory/ my_script.php

$ php -c /custom/directory/custom-file.ini my_script.php
如果不指定此選項,PHP 將在默認位置搜索文件。

-n --no-php-ini

完全忽略 php.ini。此參數在 PHP 4.3.0 以後有效。

-d --define

用該參數可以自行設置任何可以在 php.ini 文件中設置的配置選項的值,其語法爲:

-d configuration_directive[=value]

例子(因版面原因而折行顯示):

# 取值部分被省略,將會把配置選項設爲 "1"
$ php -d max_execution_time
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"

# 取值部分爲空白,將會把配置選項設爲 ""
php -d max_execution_time=
        -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""

# 配置選項將被設置成爲任何 '=' 字符之後的值
$  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 --profile-info

激活擴展信息模式,被用於調試/測試。

-f --file

解析並運行 -f 選項給定的文件名。該參數爲可選參數,可以省略,僅指明需要運行的文件名即可。

-h and -? --help and --usage 使用該參數,可以得到完整的命令行參數的列表及這些參數作用的簡單描述。
-i --info 該命令行參數會調用 phpinfo() 函數並顯示出結果。如果 PHP 沒有正常工作,建議執行 php -i 命令來查看在信息表格之前或者對應的地方是否有任何錯誤信息輸出。請注意當使用 CGI 摸索時,輸出的內容爲 HTML 格式,因此輸出的信息篇幅較大。
-l --syntax-check

該參數提供了對指定 PHP 代碼進行語法檢查的方便的方法。如果成功,則向標準輸出寫入 No syntax errors detected in <filename> 字符串,並且外殼返回值爲 0。如果失敗,則輸出 Errors parsing <filename> 以及內部解析器錯誤信息到標準輸出,同時外殼返回值將別設置爲 255

該參數將無法檢查致命錯誤(如未定義函數),如果也希望檢測致命錯誤,請使用 -f 參數。

Note:

該參數不能和 -r 一同使用。

-m --modules

使用該參數,PHP 將打印出內置以及已加載的 PHP 及 Zend 模塊:

$ php -m
[PHP Modules]
xml
tokenizer
standard
session
posix
pcre
overload
mysql
mbstring
ctype

[Zend Modules]

-r --run

使用該參數可以在命令行內運行單行 PHP 代碼。無需加上 PHP 的起始和結束標識符(<?php 和 ?>),否則將會導致語法解析錯誤。

Note:

使用這種形式的 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 向 » http://bugs.php.net/ 報告。注意,當試圖將 shell 變量用到代碼中或者使用反斜線時仍然很容易碰到問題。

Note:

-r 在 CLI SAPI 中有效,在 CGI SAPI 中無效。

Note:

此選項只用於非常基本的用途。因此一些配置指令(例如 auto_prepend_file 和 auto_append_file)在此模式下被忽略。

-B --process-begin

在處理 stdin 之前先執行 PHP 代碼。PHP 5 新加。

-R --process-code

對每個輸入行都執行 PHP 代碼。PHP 5 新加。

此模式下有兩個特殊變量:$argn 和 $argi$argn 包含 PHP 當前處理的行內容,而$argi 則包含該行號。

-F --process-file

對每個輸入行都執行 PHP 文件。PHP 5 新加。

-E --process-end

在處理完輸入後執行的 PHP 代碼。PHP 5 新加。

使用 -B ,-R 和 -E 選項來計算一個項目總行數的例子。

$ find my_proj | php -B '$l=0;' -R '$l += count(@file($argn));' -E 'echo "Total Lines: $l
";'
Total Lines: 37328

-s --syntax-highlight and --syntax-highlight

顯示有語法高亮色彩的源代碼。

該參數使用內建機制來解析文件併爲其生成一個 HTML 高亮版本並將結果寫到標準輸出。請注意該過程所做的只是生成了一個 <code> [...] </code> 的 HTML 標記的塊,並不包含任何的 HTML 頭。

Note:

該選項不能和 -r 參數同時使用。

-v --version

將 PHP,PHP SAPI 和 Zend 的版本信息寫入標準輸出。例如:

$ php -v
PHP 4.3.0 (cli), Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies

-w --strip

顯示除去了註釋和多餘空白的源代碼。

Note:

該選項不能和 -r 參數同時使用。

-z --zend-extension

加載 Zend 擴展庫。如果僅給定一個文件名,PHP 將試圖從當前系統擴展庫的默認路徑(在 Linux 系統下,該路徑通常由 /etc/ld.so.conf 指定)加載該擴展庫。如果用一個絕對路徑指定文件名,則不會使用系統的擴展庫默認路徑。如果用相對路徑指定的文件名,則 PHP 僅試圖在當前目錄的相對目錄加載擴展庫。

PHP 的命令行模式能使得 PHP 腳本能完全獨立於 web 服務器單獨運行。如果使用 Unix 系統,需要在 PHP 腳本的最前面加上一行特殊的代碼,使得它能夠被執行,這樣系統就能知道用哪個程序去運行該腳本。在 Windows 平臺下可以將 php.exe 和 .php 文件的雙擊屬性相關聯,也可以編寫一個批處理文件來用 PHP 執行腳本。爲 Unix 系統增加的第一行代碼不會影響該腳本在 Windows 下的運行,因此也可以用該方法編寫跨平臺的腳本程序。以下是一個簡單的 PHP 命令行程序的範例。

Example #1 試圖以命令行方式運行的 PHP 腳本(script.php)

#!/usr/bin/php
<?php

if ($argc != || 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 下,可以爲此編寫一個批處理文件:

Example #2 運行 PHP 命令行腳本的批處理文件(script.bat)

@C:phpphp.exe script.php %1 %2 %3 %

假設將上述程序命名爲 script.php,且 CLI 版的 php.exe 文件放置在 c:phpcliphp.exe,該批處理文件會幫助將附加的參數傳給腳本程序:script.bat echothis 或 script.bat -h

請參閱 Readline 擴展模塊的有關文檔,以獲取更多的函數的信息。這些函數可以幫助完善 PHP 命令行應用程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章