PHP命令行模式提供了一种在终端中执行PHP脚本的方式,它与其他SAPI(Server Application Programming Interface)模块有一些区别。在本文中,我们将介绍如何确定当前使用的是哪个SAPI,并讨论与其他SAPI模块的区别、选项、用法、I/O流、交互式shell、内置Web服务器和INI配置相关的内容。
一、判断SAPI
CLI SAPI 模块主要用作 PHP 的开发外壳应用。CLI SAPI 和其它 SAPI 模块相比有很多的不同之处。尽管 CLI 和 CGI 有很多共同的行为,但它们是不同的 SAPI。
CLI SAPI 模块会通过默认的 –enable-cli 参数设置启用, 也可以在运行 ./configure 时用参数 –disable-cli 来屏蔽。
CLI/CGI 二进制执行文件的文件名、位置和是否存在会根据 PHP 在系统上的安装而不同。在默认情况下,当运行 make 时,CGI 和 CLI 都会被编译并且分别放置在 PHP 源文件目录的 sapi/cgi/php-cgi 和 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 参数。
注意:由于 –enable-cli 和 –enable-cgi 同时默认有效,因此,不必再配置行中加上 –enable-cli 来使得 CLI 在 make install 过程中被拷贝到 {PREFIX}/bin/php。
在 Windows 发行包中,CLI 在主目录中的二进制文件名为 php.exe。CGI 版本的文件名为 php-cgi.exe。 如果 PHP 配置使用了 –enable-cli-win32,还会有一个额外的 php-win.exe 随包发布。 它相当于 CLI 版本,但是 php-win 不输出任何内容,便不提供控制台(不会弹出“DOS 窗口”)。
二、SAPI模块区别
以下为 CLI SAPI 和其它 SAPI 模块相比的显著区别:
1、与 CGI SAPI 不同,其输出没有任何头信息。
尽管 CGI SAPI 提供了取消 HTTP 头信息的方法,但在 CLI SAPI 中并不存在类似的方法以开启 HTTP 头信息的输出。
CLI 默认以安静模式开始,但为了保证兼容性,-q 和 –no-header 参数为了向后兼容仍然保留,使得可以使用旧的 CGI 脚本。
在运行时,不会把工作目录改为脚本的当前目录(可以使用 -C 和 –no-chdir 参数来兼容 CGI 模式)。出错时输出纯文本的错误信息(非 HTML 格式)。
2、CLI SAPI 强制覆盖了 php.ini 中的某些设置,因为这些设置在外壳环境下是没有意义的。
设置选项 | 默认值 | 备注 |
---|---|---|
html_errors | false |
无意义的 HTML 标记符会使得出错信息很凌乱,所以在外壳下阅读报错信息是十分困难的。因此将该选项的默认值改为 false 。 |
implicit_flush | true |
在命令行模式下,所有来自 print 和 echo 的输出将被立即写到输出端,而不作任何地缓冲操作。如果希望延缓或控制标准输出,仍然可以使用 output buffering 设置项。 |
max_execution_time | 0(无限值) | 鉴于在外壳环境下使用 PHP 的无穷的可能性,最大运行时间被设置为了无限值。为 web 开发的应用程序可能只需运行几秒钟时间,而外壳应用程序的运行时间可能会长的多。 |
register_argc_argv | true |
由于该设置为 在使用CLISAP时,PHP 变量 |
output_buffering | false |
虽然 php.ini 设置已经硬编码为 |
max_input_time | false |
PHP CLI 不支持 GET、POST、文件上传。 |
3、为了减轻外壳环境下的工作,我们为 I/O 流 定义了一系列常量。
4、CLI SAPI 不会将当前目录改为已运行的脚本所在的目录。
以下范例显示了本模块与 CGI SAPI 模块之间的不同:
<?php // 名为 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 编写外壳工具时获得了很大的便利。
三、选项
PHP 二进制文件可以随时通过执行带 -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 and execute <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 <addr>:<port> Run with built-in web server. -t <docroot> Specify document root <docroot> for built-in web server. -s Output HTML syntax highlighted source. -v Version number -w Output 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 --ini Show configuration file names --rf <name> Show information about function <name>. --rc <name> Show information about class <name>. --re <name> Show information about extension <name>. --rz <name> Show information about Zend extension <name>. --ri <name> Show configuration for extension <name>.
命令行选项:
选项 | 长选项 | 说明 |
---|---|---|
-a | –interactive |
运行交互式 PHP。 |
-b | –bindpath |
外部 FASTCGI 服务器模式绑定路径(仅 CGI可用)。 |
-C | –no-chdir |
不改变脚本的目录(仅 CGI 可用)。 |
-q | –no-header |
安静模式。禁止输出 HTTP 头(仅CGI可用)。 |
-T | –timing |
测量脚本重复 count 次的执行时间(仅 CGI可用)。 |
-c | –php-ini |
在指定目录查找 php.ini 或者自定义 $ php -c /custom/directory/ my_script.php $ php -c /custom/directory/custom-file.ini my_script.php 如果未指定此选项,php.ini 将在默认位置搜索。 |
-n | –no-php-ini |
完全忽略 php.ini。 |
-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 代码进行语法检查的便捷方法。 成功时将会在标准输出中写入 此选项不能发现像是函数未定义之类的核心错误(fatal errors)。可以使用 -f 测试核心错误(fatal errors)。 注意: 此选项不能和 -r 一起使用。 |
-m | –modules |
示例 #1 打印内置(且已加载的) PHP 和 Zend 模块 $ php -m [PHP Modules] xml tokenizer standard session posix pcre overload mysql mbstring ctype [Zend Modules] |
-r | –run |
允许在命令行内直接执行单行 PHP 代码。 不需要加上 PHP 开始和结束标识符( 注意: 使用这种形式的 PHP 时,应注意避免和 shell 环境进行的命令行参数替换相冲突。 示例 #2 当使用双引号时会造成语法错误 $ php -r "$foo = get_defined_constants();" PHP Parse error: syntax error, unexpected '=' in Command line code on line 1 Parse error: syntax error, unexpected '=' in Command line code on line 1 这里的问题是在使用双引号 $ php -r " = get_defined_constants();" 正确的方式是使用单引号 示例 #3 使用单引号防止 shell 变量替换 $ 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"]=> [...] 如果使用的 shell 不是 sh/bash,可能会碰到更多的问题 —— 如果有的话,请向 » https://github.com/php/php-src/issues 报告 bug。试图在命令行中使用( shell/PHP )变量或者使用反斜杠转义时需要格外小心,因为很容易遇到问题。勿谓言之不预! 注意: 可以在CLISAPI<中使用 -r,但不能在 CGISAPI中使用。 注意: 此选项仅适用于非常基本的代码,因此在此模式下会忽略某些配置指令(如 auto_prepend_file 和 auto_append_file)。 |
-B | –process-begin |
处理 stdin 之前需要执行的 PHP 代码。 |
-R | –process-code |
对每个输入行都执行的 PHP 代码。 此模式下有两个特殊变量: $argn 和 $argi。 $argn 将包含 PHP 正在处理的行, $argi 将包含正在处理的行号。 |
-F | –process-file |
对每个输入行都执行的 PHP 文件。 |
-E | –process-end |
在处理完输入后执行的 PHP 代码。 示例 #4 使用 -B 、 -R 、 -E 选项统计项目总行数。 $ find my_proj | php -B '$l=0;' -R '$l += count(@file($argn));' -E 'echo "Total Lines: $l\n";' Total Lines: 37328 |
-S | –server |
启动 内置 web 服务器. |
-t | –docroot | 为内置 web 服务器指定文档根目录。 |
-s | –syntax-highlight 和 –syntax-highlighting |
为源代码添加语法高亮显示。 此选项将使用内部机制解析文件并将生成的 HTML 高亮版本写入到标准输出。 注意它所做的只是生成一块 注意: 此选项不能和 -r 一起使用。 |
-v | –version |
示例 #5 使用 -v 获取 SAPI 的名称以及 PHP 和 Zend 的版本号 $ php -v PHP 5.3.1 (cli) (built: Dec 11 2009 19:55:07) Copyright (c) 1997-2009 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies |
-w | –strip |
显示忽略注释和空格后的源代码。 注意: 此选项不能和 -r 一起使用。 |
-z | –zend-extension |
加载 Zend 扩展。如果仅指定了文件名,PHP 将尝试从当前系统默认函数库中尝试加载此扩展 (例如在 Linux 上通常是 /etc/ld.so.conf)。 传递绝对路径的文件名将不会使用系统库搜索路径。如果用相对路径指定的文件名,则 PHP 仅试图在当前目录的相对目录加载扩展库。 |
–ini |
展示配置文件名和扫描目录。 示例 #6 $ php --ini Configuration File (php.ini) Path: /usr/dev/php/5.2/lib Loaded Configuration File: /usr/dev/php/5.2/lib/php.ini Scan for additional .ini files in: (none) Additional .ini files parsed: (none) |
|
–rf | –rfunction |
展示指定函数或者类方法的有关信息(例如参数名称和数量)。 如果 PHP 在编译时启用 Reflection 支持,该选项才可以使用。 示例 #7 基础 $ php --rf var_dump Function [ <internal> public function var_dump ] { - Parameters [2] { Parameter #0 [ <required> $var ] Parameter #1 [ <optional> $... ] } } |
–rc | –rclass |
展示指定类的有关信息(常量、属性和方法的列表)。 如果 PHP 在编译时启用 Reflection 支持,该选项才可以使用。 示例 #8 $ php --rc Directory Class [ <internal:standard> class Directory ] { - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [0] { } - Methods [3] { Method [ <internal> public method close ] { } Method [ <internal> public method rewind ] { } Method [ <internal> public method read ] { } } } |
–re | –rextension |
展示指定扩展的有关信息(php.ini 选项、定义函数、常量和类的列表)。 如果 PHP 在编译时启用 Reflection 支持,该选项才可以使用。 示例 #9 $ php --re json Extension [ <persistent> extension #19 json version 1.2.1 ] { - Functions { Function [ <internal> function json_encode ] { } Function [ <internal> function json_decode ] { } } } |
–rz | –rzendextension |
展示指定 Zend 扩展的配置信息(也可以通过 phpinfo()返回相同信息)。 |
–ri | –rextinfo |
展示指定扩展的配置信息(也可以通过 phpinfo()返回相同信息)。 使用 “main” 作为扩展名可以获取到核心配置信息。 示例 #10 $ php --ri date date date/time support => enabled "Olson" Timezone Database Version => 2009.20 Timezone Database => internal Default timezone => Europe/Oslo Directive => Local Value => Master Value date.timezone => Europe/Oslo => Europe/Oslo date.default_latitude => 59.930972 => 59.930972 date.default_longitude => 10.776699 => 10.776699 date.sunset_zenith => 90.583333 => 90.583333 date.sunrise_zenith => 90.583333 => 90.583333 |
四、用法
参考《PHP命令行模式用法》。
五、I/O流
CLI SAPI 为 I/O 流定义了一些常量,以使命令行变量编程更容易一些。
常量 | 描述 |
---|---|
STDIN |
已经打开的 <?php 如果想从 <?php |
STDOUT |
已经打开的 <?php |
STDERR |
已经打开的 <?php |
综上所述,则无需打开 stderr 流,只需使用常量代替流资源:
php -r 'fwrite(STDERR, "stderr\n");'
无须显式关闭这些流,因为它们会在脚本结束时由 PHP 自动关闭。
六、交互式shell
参考《PHP交互式shell》。
七、内置Web Server
参考《PHP内置Web Server》。
八、INI配置
CLI SAPI 配置选项:
名字 | 默认 | 可修改范围 | 更新日志 |
---|---|---|---|
cli_server.color | “0” | INI_ALL |
这是配置指令的简短说明。
cli_server.color boolean
控制内置Web Server的终端输出有无颜色。