PHP的命令行模式
自从PHP4.3.0开始,PHP提供了CLI(Command Line Interface)命令行接口,CLI SAPI模块主要用于PHP外壳应用的开发。
区别于CGI(Common Gateway Interface),CLI有很多不同的特性:
- 与 CGI SAPI 不同,CLI输出没有任何头信息
- 在运行时,CLI不会把工作目录改为脚本的当前目录
- 出错时CLI输出纯文本的错误信息(非 HTML 格式)
- CLI SAPI 强制覆盖了 php.ini 中的某些设置,因为这些设置在命令行没有意义,下面设置在CLI强制覆盖
- html_errors: false,取消HTML错误信息
- implicit_flush: true,print和echo的输出会立即写到输出端,而不做任何缓冲,可使用
output buffering
实现输出缓冲 - max_execution_time: 0,命令行运行的php脚本可能等待输入等,运行时间可能很长
- register_argc_argv: true,总是可以在命令行模式下访问命令行参数
- CLI可以独立于Web Server运行
PHP获取命令行参数的方法
访问全局变量$argv
, $argc
在PHP的命令行模式下,可在脚本中直接访问$argv
, $argc
两个全局变量:
- $argv: 命令行实际参数的数组
- $argc: 命令行参数的个数
比如现在有一个arg_test.php
的文件:
<?php
var_dump(argc);
var_dump(argv);
在命令行以下面的命令启动:php arg_test.php -t 800 a set
,输出如下:
int(5)
array(5) {
[0]=>
string(12) "arg_test.php"
[1]=>
string(2) "-t"
[2]=>
string(3) "800"
[3]=>
string(1) "a"
[4]=>
string(4) "bset"
}
一个空格区分一个参数,包括当前的脚本名称,都会放在$argv
中,当时这种方式不便于处理-t
这样的参数,需要自己进行解析。
PHPgetopt
参数处理函数
getopt
函数是PHP自带专门用来处理复杂命令行参数的内置函数。原型如下:
getopt ( string options [, arraylongopts [, int &$optind ]] ) : array
关于getopt()
的说明如下:
- options: 该字符串中的每个字符会被当做选项字符,匹配以单个连字符(-)传入到脚本的选项,比如
x
识别-x
选项,只允许a-z,A-Z,0-9
- longopts: 选项数组,每个数组元素会被作为选项字符串,匹配了以两个连字符(–)传入到脚本的选项,比如
opt
识别--opt
- optind(>=PHP7.1.0): 如果存在该参数,那么参数解析停止的索引将写入该变量
options字符串可能包含一下元素:
- 单独的字符(不接受值)
- 后面跟随冒号的字符(此选项需要值)
- 后面跟随两个冒号的字符(此选项的值可选)
选项的值是字符串后的第一个参数,值和选项之间可以没有前置空格,选项值中不可以包含空格。
getopt()
示例和用法
基本用法示例,PHP文件arg_test.php
如下:
<?php
options = getopt('a:b:cde');
var_dump(options);
以下面的命令启动:
php arg_test.php -aav -c -d -b bv -f
则输出为:
array(4) {
["a"]=>
string(2) "av"
["c"]=>
bool(false)
["d"]=>
bool(false)
["b"]=>
string(2) "bv"
}
可以注意到使用getopt(options)
时的几个点:
options
中的参数顺序和命令行的参数顺序不用相同- 选项和值之间是否有空格都能区分值
options
中单独的字符,返回的参数列表的key
是选项,value
是false
options
中没有指定的选项,及时命令行传入,也不会返回
长选项示例,arg_test.php
:
<?php
// Script arg_test.php
shortopts = "";shortopts .= "f:"; // Required value
shortopts .= "v::"; // Optional valueshortopts .= "abc"; // These options do not accept values
longopts = array(
"required:", // Required value
"optional::", // Optional value
"option", // No value
"opt", // No value
);options = getopt(shortopts,longopts);
var_dump($options);
以下面命令启动:
php arg_test.php -f "value for f" -v -a --required value --optional="optional value" --option
输出为:
array(6) {
["f"]=>
string(11) "value for f"
["v"]=>
bool(false)
["a"]=>
bool(false)
["required"]=>
string(5) "value"
["optional"]=>
string(14) "optional value"
["option"]=>
bool(false)
}
同一个选项可以传递多次,并且可以合并不同的选项:
<?php
// Script arg_test.php
options = getopt("abc");
var_dump(options);
?>
以下面的命令启动:
php arg_test.php -aaac
输出结果为:
array(2) {
["a"]=>
array(3) {
[0]=>
bool(false)
[1]=>
bool(false)
[2]=>
bool(false)
}
["c"]=>
bool(false)
}
最后是使用optind
的例子,注意optind
选项需要PHP7.1以上才支持:
<?php
// Script arg_test.php
optind = null; // 需要预先定义optind
opts = getopt('a:b:', [],optind);
var_dump(optind);pos_args = array_slice(argv,optind);
var_dump($pos_args);
以下面的命令启动:
php arg_test.php -a 1 -b 2 -- test
输出如下:
int(6)
array(1) {
[0]=>
string(4) "test"
}
注意上面的命令:php arg_test.php -a 1 -b 2 -- test
中一共有6个参数,--
和test
是两个参数。
命令行输入和输出
有的时候,我们需要在PHP脚本中检测用户的输入,以及输出一些提示信息给用户。这就需要用到PHP定义的标准输入输出流:
- STDIN: 一个已打开的指向
stdin
的流 - STDOUT: 一个已打开的指向
stdout
的流 - STDERR: 一个已打开的指向
stderr
的流
可以像操作文件句柄一样操作这些标准流,而且不需要手动关闭,PHP会自行关闭。可以发现PHP对这三个常量的定义如下:
- define(‘STDIN’, fopen(‘php://stdin’, ‘r’));
- define(‘STDOUT’, fopen(‘php://stdout’, ‘w’));
- define(‘STDERR’, fopen(‘php://stderr’, ‘w’));
显然这三个常量已经是打开的文件句柄,可以直接进行操作,下面是一个实例:
<?php
// 像写入文件一样,将内容显示到控制台
fwrite(STDOUT, 'please input a number between 1 and 10: ');
input = fgets(STDIN); // 从控制台读取输入continue = true;
// 轮询输入,知道正确为止
while (continue) {
if (input < 1 || input>10) {
// 输出到错误流
fwrite(STDERR, 'you input number is wrong: ' .input);
} else {
fwrite(STDOUT, 'you input number is correct: ' . input);continue = false;
}
$input = fgets(STDIN); // 从控制台读取输入
}
交互过程如下,其中输出到STDERR的内容会标红显示:
please input a number between 1 and 10: 12
you input number is wrong: 12
34
you input number is wrong: 34
9
you input number is correct: 9
Process finished with exit code 0
PHP CLI的可行参数
PHP的命令行模式另外还提供了很多参数来控制CLI的行为,这些参数必须紧跟在php命令后面。
# 指定php.ini配置文件运行
php -c ./custom-php.ini my_script.php
下面列出几个常用的参数,详细的参数可参考官网文档。
选项名称 | 长名称 | 说明 |
---|---|---|
-a | –interactive | 交互式运行 PHP |
-c | –php-ini | 指定一个放置 php.ini 文件的目录,或者直接指定一个自定义的 INI 文件 |
-n | –no-php-ini | 完全忽略 php.ini |
-d | –define | 设置任何可以在 php.ini 文件中设置的配置选项的值: -d configuration_directive[=value] |
-e | –profile-info | 激活扩展信息模式,被用于调试/测试 |
-f | –file | 解析并运行 -f 选项给定的文件名。该参数可选,可以省略,仅指明需要运行的文件名即可 |
-m | –modules | 使用该参数,PHP 将打印出内置以及已加载的 PHP 及 Zend 模块 |
-r | –run | 使用该参数可以在命令行内运行单行 PHP 代码 |
-B | –process-begin | 在处理 stdin 之前先执行 PHP 代码 |
-R | –process-code | 对每个输入行都执行 PHP 代码,此模式下有两个特殊变量:$argn (当前行内容)和$argi (当前行号) |
-F | –process-file | 对每个输入行都执行 PHP 文件 |
-E | –process-end | 在处理完输入后执行的 PHP 代码 |
-v | –version | 将 PHP,PHP SAPI 和 Zend 的版本信息写入标准输出 |
-s | –syntax-highlight | 显示有语法高亮色彩的源代码 |
-z | –zend-extension | 加载 Zend 扩展库。如果仅给定一个文件名 |