添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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 的文件:

    var_dump( argc); var_dump( argv);

    在命令行以下面的命令启动: php arg_test.php -t 800 a set ,输出如下:

    int(5)
    array(5) {
      string(12) "arg_test.php"
      string(2) "-t"
      string(3) "800"
      string(1) "a"
      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如下:

    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是选项,valuefalse
  • options中没有指定的选项,及时命令行传入,也不会返回
  • 长选项示例,arg_test.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)
    

    同一个选项可以传递多次,并且可以合并不同的选项:

    // Script arg_test.php options = getopt("abc"); var_dump(options);

    以下面的命令启动:

    php arg_test.php -aaac
    

    输出结果为:

    array(2) {
      ["a"]=>
      array(3) {
        bool(false)
        bool(false)
        bool(false)
      ["c"]=>
      bool(false)
    

    最后是使用optind的例子,注意optind选项需要PHP7.1以上才支持:

    // 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) {
      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’));
  • 显然这三个常量已经是打开的文件句柄,可以直接进行操作,下面是一个实例:

    // 像写入文件一样,将内容显示到控制台 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
    you input number is wrong: 34
    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
    

    下面列出几个常用的参数,详细的参数可参考官网文档