mirror of
https://github.com/php/doc-zh.git
synced 2026-03-23 22:52:08 +01:00
1815 lines
56 KiB
XML
1815 lines
56 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- $Revision$ -->
|
||
<!-- EN-Revision: 74ba8fee2972b6ba4f955392d760dea54e757a95 Maintainer: HonestQiao Status: ready -->
|
||
<!-- CREDITS: HonestQiao, Haohappy, Luffy, mowangjuanzi -->
|
||
<chapter xml:id="features.commandline" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||
<title>PHP 的命令行模式</title>
|
||
|
||
<!--Introduction: {{{-->
|
||
<section xml:id="features.commandline.introduction" annotations="chunk:false">
|
||
<title>简介</title>
|
||
|
||
<para>
|
||
&cli.sapi; 主要是使用 PHP 开发 shell 应用。&cli.sapi; 与本章中解释的其它 <acronym>SAPI</acronym>
|
||
存在相当多的差异。值得一提的是,尽管 &cli; 和 <literal>CGI</literal> 有很多共同的行为,但它们是不同的 <acronym>SAPI</acronym>。
|
||
</para>
|
||
|
||
<para>
|
||
&cli.sapi; 模块会通过默认的 <option
|
||
role="configure">--enable-cli</option> 参数设置启用,
|
||
也可以在运行 <command>./configure</command> 时用参数
|
||
<option role="configure">--disable-cli</option> 来屏蔽。
|
||
</para>
|
||
|
||
<para>
|
||
&cli;/<acronym>CGI</acronym> 二进制执行文件的文件名、位置和是否存在会根据
|
||
PHP 在系统上的安装而不同。在默认情况下,当运行
|
||
<command>make</command> 时,CGI 和 &cli; 都会被编译并且分别放置在
|
||
PHP 源文件目录的 <filename>sapi/cgi/php-cgi</filename> 和
|
||
<filename>sapi/cli/php</filename> 下。可以注意到两个文件都被命名为了
|
||
php。在 <command>make install</command>
|
||
的过程中会发生什么取决于配置行。如果在配置的时候选择了一个
|
||
<acronym>SAPI</acronym> 模块,如 apxs,或者使用了
|
||
<option role="configure">--disable-cgi</option> 参数,则在
|
||
<command>make install</command> 的过程中,&cli; 将被拷贝到
|
||
<filename>{PREFIX}/bin/php</filename>,除非 <acronym>CGI</acronym>
|
||
已经被放置在了那个位置。因此,例如,如果在配置行中有
|
||
<option role="configure">--with-apxs</option>,则在
|
||
<literal>make install</literal> 的过程中,&cli; 将被拷贝到
|
||
<literal>{PREFIX}/bin/php</literal>。如果希望覆盖 <acronym>CGI</acronym>
|
||
执行文件的安装,请在 <command>make install</command>
|
||
之后运行 <command>make install-cli</command>。或者,也可以在配置行中加上
|
||
<option role="configure">--disable-cgi</option> 参数。
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
由于 <option role="configure">--enable-cli</option> 和
|
||
<option role="configure">--enable-cgi</option>
|
||
同时默认有效,因此,不必再配置行中加上
|
||
<option role="configure">--enable-cli</option> 来使得 &cli; 在
|
||
<command>make install</command> 过程中被拷贝到
|
||
<filename>{PREFIX}/bin/php</filename>。
|
||
</para>
|
||
</note>
|
||
|
||
<para>
|
||
在 Windows 发行包中,&cli; 在主目录中的二进制文件名为
|
||
<filename>php.exe</filename>。<acronym>CGI</acronym> 版本的文件名为
|
||
<filename>php-cgi.exe</filename>。
|
||
如果 PHP 配置使用了
|
||
<option role="configure">--enable-cli-win32</option>,还会有一个额外的 <filename>
|
||
php-win.exe</filename> 随包发布。
|
||
它相当于 &cli; 版本,但是 php-win
|
||
不输出任何内容,便不提供控制台(不会弹出“DOS 窗口”)。
|
||
</para>
|
||
|
||
<note>
|
||
<title>如何得知自己使用的是哪个 SAPI?</title>
|
||
<para>
|
||
在命令行下,运行 <command>php -v</command> 便能得知该
|
||
<filename>php</filename> 是 <acronym>CGI</acronym> 还是 &cli;。请参考函数
|
||
<function>php_sapi_name</function> 以及常量 <constant>PHP_SAPI</constant>。
|
||
</para>
|
||
</note>
|
||
|
||
<note>
|
||
<para>
|
||
在命令行中键入
|
||
<command>man php</command> 可以查看 Unix <literal>man</literal> 手册页面。
|
||
</para>
|
||
</note>
|
||
</section>
|
||
<!--}}}-->
|
||
|
||
<!--Differences: {{{-->
|
||
<section xml:id="features.commandline.differences">
|
||
<title>和其它 <acronym>SAPI</acronym> 模块的区别</title>
|
||
|
||
<para>
|
||
以下为 &cli; <acronym>SAPI</acronym> 和其它 <acronym>SAPI</acronym> 模块相比的显著区别:
|
||
<itemizedlist>
|
||
<listitem>
|
||
<para>
|
||
与 <acronym>CGI</acronym> <acronym>SAPI</acronym> 不同,其输出没有任何头信息。
|
||
</para>
|
||
<para>
|
||
尽管 <acronym>CGI</acronym> <acronym>SAPI</acronym> 提供了取消 HTTP 头信息的方法,但在
|
||
&cli.sapi; 中并不存在类似的方法以开启 HTTP 头信息的输出。
|
||
</para>
|
||
<para>
|
||
&cli; 默认以安静模式开始,但为了保证兼容性,<option>-q</option> 和
|
||
<option>--no-header</option> 参数为了向后兼容仍然保留,使得可以使用旧的 <acronym>CGI</acronym> 脚本。
|
||
</para>
|
||
<para>
|
||
在运行时,不会把工作目录改为脚本的当前目录(可以使用
|
||
<option>-C</option> 和 <option>--no-chdir</option> 参数来兼容 CGI 模式)。
|
||
</para>
|
||
<para>
|
||
出错时输出纯文本的错误信息(非 <acronym>HTML</acronym> 格式)。
|
||
</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>
|
||
&cli.sapi; 强制覆盖了 &php.ini;
|
||
中的某些设置,因为这些设置在外壳环境下是没有意义的。
|
||
</para>
|
||
<para>
|
||
<table>
|
||
<title>覆盖 &php.ini; 设置选项</title>
|
||
<tgroup cols="3">
|
||
<thead>
|
||
<row>
|
||
<entry>设置选项</entry>
|
||
<entry>&cli; <acronym>SAPI</acronym> 默认值</entry>
|
||
<entry>备注</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry><link linkend="ini.html-errors">html_errors</link></entry>
|
||
<entry>&false;</entry>
|
||
<entry>
|
||
无意义的 <acronym>HTML</acronym>
|
||
标记符会使得出错信息很凌乱,所以在外壳下阅读报错信息是十分困难的。因此将该选项的默认值改为 &false;。
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><link linkend="ini.implicit-flush">implicit_flush</link></entry>
|
||
<entry>&true;</entry>
|
||
<entry>
|
||
在命令行模式下,所有来自 <link linkend="function.print"><literal>print</literal></link> 和
|
||
<link linkend="function.echo"><literal>echo</literal></link> 的输出将被立即写到输出端,而不作任何地缓冲操作。如果希望延缓或控制标准输出,仍然可以使用
|
||
<link linkend="ref.outcontrol">output buffering</link> 设置项。
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><link linkend="ini.max-execution-time">max_execution_time</link></entry>
|
||
<entry>0(无限值)</entry>
|
||
<entry>
|
||
鉴于在外壳环境下使用 PHP 的无穷的可能性,最大运行时间被设置为了无限值。为
|
||
web 开发的应用程序可能只需运行几秒钟时间,而外壳应用程序的运行时间可能会长的多。
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><link linkend="ini.register-argc-argv">register_argc_argv</link></entry>
|
||
<entry>&true;</entry>
|
||
<entry>
|
||
<para>
|
||
由于该设置为 &true;,将总是可以在 &cli; <acronym>SAPI</acronym>
|
||
中访问到 <emphasis>argc</emphasis>(传送给应用程序参数的个数)和
|
||
<emphasis>argv</emphasis>(包含有实际参数的数组)。
|
||
</para>
|
||
<para>
|
||
在使用 &cli; <acronym>SAPI</acronym> 时,PHP 变量
|
||
<literal>$argc</literal> 和 <literal>$argv</literal>
|
||
已被注册并且设定了对应的值。随时可以通过
|
||
<varname>$_SERVER</varname> 数组
|
||
来访问它们,例如:<varname>$_SERVER['argv']</varname>
|
||
</para>
|
||
<warning>
|
||
<para>
|
||
<varname>$argv</varname> 或 <varname>$_SERVER['argv']</varname>
|
||
的存在并不能表明脚本一定正在从命令行运行,因为当启用 <link linkend="ini.register-argc-argv">register_argc_argv</link>
|
||
时,它们可能在其他上下文中设置。应改为检查 <function>php_sapi_name</function> 返回的值。
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
if (php_sapi_name() === 'cli') {
|
||
echo "This is being run from the command line!\n";
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</warning>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><link linkend="ini.output-buffering">output_buffering</link></entry>
|
||
<entry>&false;</entry>
|
||
<entry>
|
||
<para>
|
||
虽然 &php.ini; 设置已经硬编码为 &false;,
|
||
<link linkend="book.outcontrol">输出缓冲控制</link>函数仍然有效。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><link linkend="ini.max-input-time">max_input_time</link></entry>
|
||
<entry>&false;</entry>
|
||
<entry>
|
||
<para>
|
||
PHP &cli; 不支持 GET、POST、文件上传。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
<note>
|
||
<para>
|
||
这些设置无法在设置文件 &php.ini;
|
||
或任何指定的其它文件中被初始化为其它值。这些默认值被限制在所有其它的设置文件被解析后改变。
|
||
不过,它们的值可以在程序运行的过程中被改变
|
||
(尽管对于该运行过程来说,这些设置项是没有意义的,例如 <link linkend="ini.register-argc-argv">register_argc_argv</link>)。
|
||
</para>
|
||
</note>
|
||
<note>
|
||
<para>
|
||
推荐命令行脚本设置
|
||
<link linkend="ini.ignore-user-abort">ignore_user_abort</link>。
|
||
更多信息参见 <function>ignore_user_abort</function>。
|
||
</para>
|
||
</note>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>
|
||
为了减轻外壳环境下的工作,我们为 <link linkend="features.commandline.io-streams">I/O 流
|
||
</link>定义了一系列常量。
|
||
</para>
|
||
</listitem>
|
||
|
||
<listitem>
|
||
<para>
|
||
&cli.sapi;
|
||
<emphasis role="strong">不会</emphasis>将当前目录改为已运行的脚本所在的目录。
|
||
</para>
|
||
<para>
|
||
以下范例显示了本模块与 <acronym>CGI</acronym>
|
||
<acronym>SAPI</acronym> 模块之间的不同:
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
// 名为 test.php 的简单测试程序
|
||
echo getcwd(), "\n";
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</para>
|
||
<para>
|
||
在使用 <literal>CGI</literal> 版本时,其输出为
|
||
<screen>
|
||
<![CDATA[
|
||
$ pwd
|
||
/tmp
|
||
|
||
$ php-cgi -f another_directory/test.php
|
||
/tmp/another_directory
|
||
]]>
|
||
</screen>
|
||
</para>
|
||
<para>
|
||
明显可以看到 PHP 将当前目录改成了刚刚运行过的脚本所在的目录。
|
||
</para>
|
||
<para>
|
||
使用 &cli.sapi; 模式,得到:
|
||
<screen>
|
||
<![CDATA[
|
||
$ pwd
|
||
/tmp
|
||
|
||
$ php -q another_directory/test.php
|
||
/tmp
|
||
]]>
|
||
</screen>
|
||
这使得在利用 PHP 编写外壳工具时获得了很大的便利。
|
||
</para>
|
||
<note>
|
||
<para>
|
||
可以在命令行运行时给该 <acronym>CGI</acronym> <acronym>SAPI</acronym> 加上
|
||
<option>-C</option> 参数,使其支持 &cli.sapi; 的功能。
|
||
</para>
|
||
</note>
|
||
</listitem>
|
||
</itemizedlist>
|
||
</para>
|
||
</section>
|
||
<!--}}}-->
|
||
|
||
<!--Options: {{{-->
|
||
<section xml:id="features.commandline.options">
|
||
<title>命令行选项</title>
|
||
<titleabbrev>选项</titleabbrev>
|
||
|
||
<para>
|
||
PHP 二进制文件可以随时通过执行带 <option>-h</option> 参数的 PHP 命令获取提供的命令行选项列表:
|
||
<screen>
|
||
<![CDATA[
|
||
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>.
|
||
]]>
|
||
</screen>
|
||
</para>
|
||
|
||
<para>
|
||
<table>
|
||
<title>命令行选项</title>
|
||
<tgroup cols="2">
|
||
<thead>
|
||
<row>
|
||
<entry>选项</entry>
|
||
<entry>长选项</entry>
|
||
<entry>说明</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry>-a</entry>
|
||
<entry>--interactive</entry>
|
||
<entry>
|
||
<para>
|
||
运行交互式 PHP。参阅<link linkend="features.commandline.interactive">交互式 shell</link>
|
||
章节获取更多信息。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-b</entry>
|
||
<entry>--bindpath</entry>
|
||
<entry>
|
||
<para>
|
||
外部 FASTCGI 服务器模式绑定路径(仅 <acronym>CGI</acronym> 可用)。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-C</entry>
|
||
<entry>--no-chdir</entry>
|
||
<entry>
|
||
<para>
|
||
不改变脚本的目录(仅 <acronym>CGI</acronym> 可用)。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-q</entry>
|
||
<entry>--no-header</entry>
|
||
<entry>
|
||
<para>
|
||
安静模式。禁止输出 <acronym>HTTP</acronym>
|
||
头(仅 <acronym>CGI</acronym> 可用)。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-T</entry>
|
||
<entry>--timing</entry>
|
||
<entry>
|
||
<para>
|
||
测量脚本重复 <varname>count</varname> 次的执行时间(仅 <acronym>CGI</acronym> 可用)。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-c</entry>
|
||
<entry>--php-ini</entry>
|
||
<entry>
|
||
<para>
|
||
在指定目录查找 &php.ini; 或者自定义 <literal>INI</literal>
|
||
文件(名称可以不是 &php.ini;),例如:
|
||
</para>
|
||
<para><informalexample>
|
||
<screen>
|
||
<![CDATA[
|
||
$ php -c /custom/directory/ my_script.php
|
||
|
||
$ php -c /custom/directory/custom-file.ini my_script.php
|
||
]]>
|
||
</screen>
|
||
</informalexample></para>
|
||
<para>
|
||
如果未指定此选项,&php.ini; 将在<link linkend="configuration.file">默认位置</link>搜索。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-n</entry>
|
||
<entry>--no-php-ini</entry>
|
||
<entry>
|
||
<para>
|
||
完全忽略 &php.ini;。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-d</entry>
|
||
<entry>--define</entry>
|
||
<entry>
|
||
<para>
|
||
允许设置 &php.ini; 中配置指令的值。语法是:
|
||
<screen>
|
||
<![CDATA[
|
||
-d configuration_directive[=value]
|
||
]]>
|
||
</screen>
|
||
</para>
|
||
<para><example>
|
||
<title>使用 <literal>-d</literal> 设置 INI 配置的示例</title>
|
||
<screen>
|
||
<![CDATA[
|
||
# 忽略值部分,将会设置配置指令为 "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"
|
||
]]>
|
||
</screen>
|
||
</example></para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-e</entry>
|
||
<entry>--profile-info</entry>
|
||
<entry>
|
||
<para>
|
||
激活扩展信息模式,用于调试/分析。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-f</entry>
|
||
<entry>--file</entry>
|
||
<entry>
|
||
<para>
|
||
解析并执行指定文件。 <option>-f</option>
|
||
可选且可以忽略 —— 只需提供需要执行的文件名就足够。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-h and -?</entry>
|
||
<entry>--help and --usage</entry>
|
||
<entry>
|
||
输出命令行选项列表并描述了这些选项的作用。
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-i</entry>
|
||
<entry>--info</entry>
|
||
<entry>
|
||
调用 <function>phpinfo</function> 并输出结果。如果 PHP
|
||
不能正常工作,建议使用命令 <command>php -i</command>
|
||
查看在信息表输出之前或者中间某个位置是否有错误消息。注意当使用
|
||
<acronym>CGI</acronym> 模式时会输出 <acronym>HTML</acronym>,
|
||
这会非常大。
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-l</entry>
|
||
<entry>--syntax-check</entry>
|
||
<entry>
|
||
<para>
|
||
检查语法但不执行指定 PHP 代码。如果未指定文件,则将处理来自标准输入的输入,否则将检查每个文件。成功时,文本
|
||
<literal>No syntax errors detected in <filename></literal> 将写入标准输出。失败时,除了内部解析器错误外,文本
|
||
<literal>Errors parsing <filename></literal> 将写入标准输出。如果在指定文件(或标准输入)中发现任何错误,则将
|
||
shell 返回代码设置为 <literal>-1</literal>,否则将 shell 返回代码设置为 <literal>0</literal>。
|
||
</para>
|
||
<para>
|
||
此选项不会找到需要执行代码的致命错误(如未定义的函数)。
|
||
</para>
|
||
<note>
|
||
<para>
|
||
在 PHP 8.3.0 之前,只能指定一个要检查的文件。
|
||
</para>
|
||
</note>
|
||
<note>
|
||
<para>
|
||
此选项不能和 <option>-r</option> 一起使用。
|
||
</para>
|
||
</note>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-m</entry>
|
||
<entry>--modules</entry>
|
||
<entry>
|
||
<para><example>
|
||
<title>打印内置(且已加载的) PHP 和 Zend 模块</title>
|
||
<screen>
|
||
<![CDATA[
|
||
$ php -m
|
||
[PHP Modules]
|
||
xml
|
||
tokenizer
|
||
standard
|
||
session
|
||
posix
|
||
pcre
|
||
overload
|
||
mysql
|
||
mbstring
|
||
ctype
|
||
|
||
[Zend Modules]
|
||
]]>
|
||
</screen>
|
||
</example></para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-r</entry>
|
||
<entry>--run</entry>
|
||
<entry>
|
||
<para>
|
||
允许在命令行内直接执行单行 PHP 代码。
|
||
<emphasis role="strong">不需要</emphasis>加上 PHP 开始和结束标识符(<literal><?php</literal> 和
|
||
<literal>?></literal>),否则将会造成语法错误。
|
||
</para>
|
||
<note>
|
||
<para>
|
||
使用这种形式的 PHP 时,应注意避免和 shell 环境进行的命令行参数替换相冲突。
|
||
</para>
|
||
<example>
|
||
<title>当使用双引号时会造成语法错误</title>
|
||
<screen>
|
||
<![CDATA[
|
||
$ 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
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
<para>
|
||
这里的问题是在使用双引号 <literal>"</literal> 时 sh/bash 会执行变量替换。
|
||
由于 <varname>$foo</varname> 变量没有被定义,因此它将替换为空字符,
|
||
从而导致传递给 PHP 执行的代码实际上会变成:
|
||
</para>
|
||
<informalexample>
|
||
<screen>
|
||
<![CDATA[
|
||
$ php -r " = get_defined_constants();"
|
||
]]>
|
||
</screen>
|
||
</informalexample>
|
||
|
||
<para>
|
||
正确的方式是使用单引号 <literal>'</literal>
|
||
。使用单引号时 sh/bash 不会进行变量替换。
|
||
</para>
|
||
<example>
|
||
<title>使用单引号防止 shell 变量替换</title>
|
||
<screen>
|
||
<![CDATA[
|
||
$ 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"]=>
|
||
[...]
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
<para>
|
||
如果使用的 shell 不是 sh/bash,可能会碰到更多的问题 ——
|
||
如果有的话,请向 <link xlink:href="&url.php.bugs;">&url.php.bugs;</link>
|
||
报告 bug。试图在命令行中使用( shell/PHP
|
||
)变量或者使用反斜杠转义时需要格外小心,因为很容易遇到问题。勿谓言之不预!
|
||
</para>
|
||
</note>
|
||
<note>
|
||
<para>
|
||
可以在 &cli.sapi; 中使用
|
||
<option>-r</option>,但不能在 <emphasis>CGI</emphasis> <acronym>SAPI</acronym> 中使用。
|
||
</para>
|
||
</note>
|
||
<note>
|
||
<para>
|
||
此选项仅适用于非常基本的代码,因此在此模式下会忽略某些配置指令(如 <link
|
||
linkend="ini.auto-prepend-file">auto_prepend_file</link> 和 <link
|
||
linkend="ini.auto-append-file">auto_append_file</link>)。
|
||
</para>
|
||
</note>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-B</entry>
|
||
<entry>--process-begin</entry>
|
||
<entry>
|
||
<para>
|
||
处理 stdin 之前需要执行的 PHP 代码。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-R</entry>
|
||
<entry>--process-code</entry>
|
||
<entry>
|
||
<para>
|
||
对每个输入行都执行的 PHP 代码。
|
||
</para>
|
||
<para>
|
||
此模式下有两个特殊变量:
|
||
<varname>$argn</varname> 和 <varname>$argi</varname>。
|
||
<varname>$argn</varname> 将包含 PHP 正在处理的行,
|
||
<varname>$argi</varname> 将包含正在处理的行号。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-F</entry>
|
||
<entry>--process-file</entry>
|
||
<entry>
|
||
<para>
|
||
对每个输入行都执行的 PHP 文件。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-E</entry>
|
||
<entry>--process-end</entry>
|
||
<entry>
|
||
<para>
|
||
在处理完输入后执行的 PHP 代码。
|
||
</para>
|
||
<para><example>
|
||
<title>使用 <option>-B</option> 、 <option>-R</option> 、 <option>-E</option>
|
||
选项统计项目总行数。
|
||
</title>
|
||
<screen>
|
||
<![CDATA[
|
||
$ find my_proj | php -B '$l=0;' -R '$l += count(@file($argn));' -E 'echo "Total Lines: $l\n";'
|
||
Total Lines: 37328
|
||
]]>
|
||
</screen>
|
||
</example></para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-S</entry>
|
||
<entry>--server</entry>
|
||
<entry>
|
||
<para>
|
||
启动 <link linkend="features.commandline.webserver">内置 web 服务器</link>.
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-t</entry>
|
||
<entry>--docroot</entry>
|
||
<entry>
|
||
为<link linkend="features.commandline.webserver">内置 web 服务器</link>指定文档根目录。
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-s</entry>
|
||
<entry>--syntax-highlight 和 --syntax-highlighting</entry>
|
||
<entry>
|
||
<para>
|
||
为源代码添加语法高亮显示。
|
||
</para>
|
||
<para>
|
||
此选项将使用内部机制解析文件并将生成的 HTML 高亮版本写入到标准输出。
|
||
注意它所做的只是生成一块 <literal><code> [...] </code></literal>
|
||
HTML 标记,没有 HTML header。
|
||
</para>
|
||
<note>
|
||
<para>
|
||
此选项不能和 <option>-r</option> 一起使用。
|
||
</para>
|
||
</note>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-v</entry>
|
||
<entry>--version</entry>
|
||
<entry>
|
||
<para><example>
|
||
<title>使用 <option>-v</option> 获取 <acronym>SAPI</acronym>
|
||
的名称以及 PHP 和 Zend 的版本号</title>
|
||
<screen>
|
||
<![CDATA[
|
||
$ 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
|
||
]]>
|
||
</screen>
|
||
</example></para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-w</entry>
|
||
<entry>--strip</entry>
|
||
<entry>
|
||
<para>
|
||
显示忽略注释和空格后的源代码。
|
||
</para>
|
||
<note>
|
||
<para>
|
||
此选项不能和 <option>-r</option> 一起使用。
|
||
</para>
|
||
</note>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-z</entry>
|
||
<entry>--zend-extension</entry>
|
||
<entry>
|
||
<para>
|
||
加载 Zend 扩展。如果仅指定了文件名,PHP 将尝试从当前系统默认函数库中尝试加载此扩展
|
||
(例如在 Linux 上通常是 <filename>/etc/ld.so.conf</filename>)。
|
||
传递绝对路径的文件名将不会使用系统库搜索路径。如果用相对路径指定的文件名,则 PHP
|
||
仅试图在当前目录的相对目录加载扩展库。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry></entry>
|
||
<entry>--ini</entry>
|
||
<entry>
|
||
<para>
|
||
展示配置文件名和扫描目录。
|
||
<example>
|
||
<title><literal>--ini</literal> 示例</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ 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)
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>--rf</entry>
|
||
<entry>--rfunction</entry>
|
||
<entry>
|
||
<para>
|
||
展示指定函数或者类方法的有关信息(例如参数名称和数量)。
|
||
</para>
|
||
<para>
|
||
如果 PHP 在编译时启用 <link linkend="book.reflection">Reflection</link>
|
||
支持,该选项才可以使用。
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>基础 <literal>--rf</literal> 用法</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ php --rf var_dump
|
||
Function [ <internal> public function var_dump ] {
|
||
|
||
- Parameters [2] {
|
||
Parameter #0 [ <required> $var ]
|
||
Parameter #1 [ <optional> $... ]
|
||
}
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>--rc</entry>
|
||
<entry>--rclass</entry>
|
||
<entry>
|
||
<para>
|
||
展示指定类的有关信息(常量、属性和方法的列表)。
|
||
</para>
|
||
<para>
|
||
如果 PHP 在编译时启用 <link linkend="book.reflection">Reflection</link>
|
||
支持,该选项才可以使用。
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title><literal>--rc</literal> 示例</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ 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 ] {
|
||
}
|
||
}
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>--re</entry>
|
||
<entry>--rextension</entry>
|
||
<entry>
|
||
<para>
|
||
展示指定扩展的有关信息(&php.ini; 选项、定义函数、常量和类的列表)。
|
||
</para>
|
||
<para>
|
||
如果 PHP 在编译时启用 <link linkend="book.reflection">Reflection</link>
|
||
支持,该选项才可以使用。
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title><literal>--re</literal> 示例</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ php --re json
|
||
Extension [ <persistent> extension #19 json version 1.2.1 ] {
|
||
|
||
- Functions {
|
||
Function [ <internal> function json_encode ] {
|
||
}
|
||
Function [ <internal> function json_decode ] {
|
||
}
|
||
}
|
||
}
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>--rz</entry>
|
||
<entry>--rzendextension</entry>
|
||
<entry>
|
||
<para>
|
||
展示指定 Zend 扩展的配置信息(也可以通过 <function>phpinfo</function> 返回相同信息)。
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>--ri</entry>
|
||
<entry>--rextinfo</entry>
|
||
<entry>
|
||
<para>
|
||
展示指定扩展的配置信息(也可以通过 <function>phpinfo</function> 返回相同信息)。
|
||
使用 “main” 作为扩展名可以获取到核心配置信息。
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title><literal>--ri</literal> 示例</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ 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
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
选项 <literal>-rBRFEH</literal>、 <literal>--ini</literal> 、
|
||
<literal>--r[fcezi]</literal> 仅可以在 &cli; 中使用。
|
||
</para>
|
||
</note>
|
||
</section>
|
||
<!--}}}-->
|
||
|
||
<!--Usage: {{{-->
|
||
<section xml:id="features.commandline.usage">
|
||
<title>执行 PHP 文件</title>
|
||
<titleabbrev>用法</titleabbrev>
|
||
|
||
<para>
|
||
&cli.sapi; 有三种不同的方法执行 PHP 代码:
|
||
<orderedlist>
|
||
<listitem>
|
||
<para>
|
||
让 PHP 运行指定文件。
|
||
</para>
|
||
<informalexample>
|
||
<screen>
|
||
<![CDATA[
|
||
$ php my_script.php
|
||
|
||
$ php -f my_script.php
|
||
]]>
|
||
</screen>
|
||
</informalexample>
|
||
<para>
|
||
以上两种方法(使用或不使用 <option>-f</option> 参数)都能够运行给定的
|
||
<filename>my_script.php</filename> 文件。注意,没有限制可以执行哪种文件,
|
||
特别是文件名也不必用 <literal>.php</literal> 作为扩展名。
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
在命令行中直接传递 PHP 代码执行。
|
||
</para>
|
||
<informalexample>
|
||
<screen>
|
||
<![CDATA[
|
||
$ php -r 'print_r(get_defined_constants());'
|
||
]]>
|
||
</screen>
|
||
</informalexample>
|
||
<para>
|
||
必须特别注意 shell 变量的替代及引号的使用。
|
||
</para>
|
||
<note>
|
||
<para>
|
||
请仔细阅读以上范例,它们没有开始和结束标识符!加上
|
||
<option>-r</option> 参数后不需要这些标记符,并且加上它们还会导致语法错误。
|
||
</para>
|
||
</note>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
通过标准输入(<literal>stdin</literal>)提供需要运行的 PHP 代码。
|
||
</para>
|
||
<para>
|
||
这为动态创建 PHP 代码并通过二进制文件执行提供了强大的能力,就像下面(虚构的)例子展示的一样:
|
||
</para>
|
||
<informalexample>
|
||
<screen>
|
||
<![CDATA[
|
||
$ some_application | some_filter | php | sort -u > final_output.txt
|
||
]]>
|
||
</screen>
|
||
</informalexample>
|
||
</listitem>
|
||
</orderedlist>
|
||
以上三种运行代码的方法不能混合使用。
|
||
</para>
|
||
|
||
<para>
|
||
和所有的 shell 应用程序一样,PHP 的二进制文件及其 PHP 脚本能够接受一系列的参数。PHP
|
||
没有限制传送给脚本的参数的个数( shell 对传递的字符数有限制,但通常都不会超过该限制)。传递给脚本的参数可在全局数组
|
||
<varname>$argv</varname> 中获取。第一个索引(零)始终包含从命令行中调用的脚本名称。注意在命令行内使用 <option>-r</option>
|
||
执行 PHP 代码时, <varname>$argv[0]</varname> 的值将是 <literal>"Standard input code"</literal>;
|
||
在 PHP 7.2.0 之前是破折号(<literal>-</literal>)。如果代码是通过来自 <constant>STDIN</constant> 的管道执行的,同样如此。
|
||
</para>
|
||
|
||
<para>
|
||
另外,第二个全局变量 <varname>$argc</varname> 包含 <varname>$argv</varname>
|
||
数组中元素的个数(而<emphasis role="strong">不是</emphasis>传递给脚本的参数个数)。
|
||
</para>
|
||
|
||
<para>
|
||
只要传送给脚本的参数不是以 <literal>-</literal>
|
||
字符开头,就无需过多的注意什么。向脚本传递以
|
||
<literal>-</literal> 开头的参数会导致错误,因为 PHP
|
||
会认为在执行脚本之前应该由它自身来处理这些参数。为防止发生这种情况,可以用列表分隔符
|
||
<literal>--</literal> 参数来解决。在 PHP 解析此分隔符之后,
|
||
该符号后的所有参数将会被原样传递给脚本程序。
|
||
</para>
|
||
|
||
<informalexample>
|
||
<screen>
|
||
<![CDATA[
|
||
# 以下命令将不会运行 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"
|
||
}
|
||
]]>
|
||
</screen>
|
||
</informalexample>
|
||
|
||
<para>
|
||
然而,在 Unix 系统中还有一个将 PHP 用于 shell 脚本的方法:写个脚本,第一行以 <literal>#!/usr/bin/php</literal> 为开头
|
||
(如果 PHP &cli; 二进制文件路径不一样,则可以指定为任意实际的路径)。文件的剩余部分应该包含通用的 PHP 开始标签、正常的
|
||
PHP 代码、PHP 结束标签。一旦设置正确的文件执行属性(例如 <command>chmod +x test</command>),脚本就像其他
|
||
shell/perl 脚本一样可以执行。
|
||
</para>
|
||
|
||
<example>
|
||
<title>PHP 脚本作为 shell 脚本执行</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
#!/usr/bin/php
|
||
<?php
|
||
var_dump($argv);
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
<para>
|
||
假设在当前目录下,该文件名为 <filename>test</filename>,可以做如下操作:
|
||
</para>
|
||
<screen>
|
||
<![CDATA[
|
||
$ chmod +x test
|
||
$ ./test -h -- foo
|
||
array(4) {
|
||
[0]=>
|
||
string(6) "./test"
|
||
[1]=>
|
||
string(2) "-h"
|
||
[2]=>
|
||
string(2) "--"
|
||
[3]=>
|
||
string(3) "foo"
|
||
}
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<para>
|
||
正如看到的,在向该脚本传递以 <literal>-</literal> 开头的参数时,无需关心这种情况。
|
||
</para>
|
||
|
||
<para>
|
||
PHP 可执行文件可用于运行完全独立于 web 服务器的 PHP 脚本。在 Unix 系统上,需要在 PHP 脚本的第一行指定
|
||
<literal>#!</literal>(或者说 “shebang”)以便系统可以自动判断用哪个程序运行脚本。
|
||
在 Windows 平台上可以使用双击扩展名是<literal>.php</literal>的文件与 <filename>php.exe</filename>
|
||
相关联,也可以编写一个批处理文件使用 PHP 运行脚本。为 Unix 系统增加的指定 shebang 的第一行代码不会影响 Windows (它也是 PHP
|
||
注释的格式),因此也可以用该方法编写跨平台的程序。以下是编写的一个简单
|
||
PHP 命令行程序的示例。
|
||
</para>
|
||
|
||
<para>
|
||
<example>
|
||
<title>试图以命令行方式运行的 PHP 脚本(script.php)</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
#!/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];
|
||
}
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<para>
|
||
在以上脚本中,用包含 Unix shebang 的第一行代码来指明该文件应该由 PHP
|
||
来执行。这里使用 &cli; 版本运行,因此不会输出 <acronym>HTTP</acronym> 头。
|
||
</para>
|
||
|
||
<para>
|
||
程序首先检查是否有需要的参数(除了脚本名,因为它也会被计算进来)。如果没有参数或者参数是 <option>--help</option>、
|
||
<option>-help</option>、 <option>-h</option>、 <option>-?</option>,将会打印出帮助消息,
|
||
在命令行上使用 <varname>$argv[0]</varname> 动态输出脚本名称。否则参数将按照接收的方式进行准确回显。
|
||
</para>
|
||
|
||
<para>
|
||
如果在 Unix 下运行以上脚本,它必须有可执行权限,并简单的以 <command>script.php echothis</command> 或者
|
||
<command>script.php -h</command> 方式调用。在 Windows 下,可以为此类任务编写与以下内容类似的批处理文件:
|
||
</para>
|
||
|
||
<para>
|
||
<example>
|
||
<title>运行 PHP 命令行脚本的批处理文件(script.bat)</title>
|
||
<programlisting role="winbat">
|
||
<![CDATA[
|
||
@echo OFF
|
||
"C:\php\php.exe" script.php %*
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
</para>
|
||
|
||
<para>
|
||
假设将上述程序名为 <filename>script.php</filename>,且
|
||
&cli; 版的 <filename>php.exe</filename> 位于 <filename>C:\php\php.exe</filename>,
|
||
该批处理文件将会运行并传递所有追加选项:
|
||
<command>script.bat echothis</command> 或者 <command>script.bat -h</command>。
|
||
</para>
|
||
|
||
<para>
|
||
参阅 <link linkend="ref.readline">Readline</link> 扩展文档获取更多函数,以用于 PHP
|
||
中增强命令行应用程序。
|
||
</para>
|
||
|
||
<para>
|
||
在 Windows 上, PHP 可以配置为无需提供 <filename>C:\php\php.exe</filename> 或者
|
||
扩展名为 <literal>.php</literal> 的文件运行,如
|
||
<link linkend="install.windows.commandline">PHP 在 Microsoft Windows 下的命令行方式</link>中所述。
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
在 Windows 上,推荐在真实用户账户下运行 PHP。在网络服务下运行某些操作时将会失败,
|
||
因为“帐户名与安全标识间无任何映射完成”。
|
||
</para>
|
||
</note>
|
||
</section>
|
||
<!--}}}-->
|
||
|
||
|
||
<!--I/O Streams: {{{-->
|
||
<section xml:id="features.commandline.io-streams">
|
||
<title>输入输出流</title>
|
||
<titleabbrev>I/O 流</titleabbrev>
|
||
|
||
<para>
|
||
&cli.sapi; 为 I/O 流定义了一些常量,以使命令行变量编程更容易一些。
|
||
</para>
|
||
|
||
<para>
|
||
<table>
|
||
<title>CLI 特定常量</title>
|
||
<tgroup cols="2">
|
||
<thead>
|
||
<row>
|
||
<entry>常量</entry>
|
||
<entry>描述</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry><constant>STDIN</constant></entry>
|
||
<entry>
|
||
<para>已经打开的 <literal>stdin</literal> 流。使得无需再用以下方式打开:
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
$stdin = fopen('php://stdin', 'r');
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
如果想从 <literal>stdin</literal> 中读取一行内容,可以使用如下方式:
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
$line = trim(fgets(STDIN)); // 从 STDIN 读取一行
|
||
fscanf(STDIN, "%d\n", $number); // 从 STDIN 读取数字
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</para></entry>
|
||
</row>
|
||
<row>
|
||
<entry><constant>STDOUT</constant></entry>
|
||
<entry><para>
|
||
已经打开的 <literal>stdout</literal> 流。使得无需再用以下方式打开:
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
$stdout = fopen('php://stdout', 'w');
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</para></entry>
|
||
</row>
|
||
<row>
|
||
<entry><constant>STDERR</constant></entry>
|
||
<entry>
|
||
<para>
|
||
已经打开的 <literal>stderr</literal> 流。使得无需再用以下方式打开:
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
$stderr = fopen('php://stderr', 'w');
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</para>
|
||
</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
|
||
<para>
|
||
综上所述,则无需打开 <literal>stderr</literal> 流,只需使用常量代替流资源:
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
php -r 'fwrite(STDERR, "stderr\n");'
|
||
]]>
|
||
</programlisting>
|
||
无须显式关闭这些流,因为它们会在脚本结束时由 PHP 自动关闭。
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
如果从 <literal>stdin</literal> 中读取 PHP 脚本,则这些常量不可用。
|
||
</para>
|
||
</note>
|
||
</section>
|
||
<!--}}}-->
|
||
|
||
<!--Interactive shell: {{{-->
|
||
<section xml:id="features.commandline.interactive">
|
||
<title>交互式 shell</title>
|
||
|
||
<para>
|
||
如果 PHP 使用 <option role="configure">--with-readline</option> 选项编译,则 &cli.sapi; 使用 <option>-a</option>
|
||
选项时会提供交互式 shell。自 PHP 7.1.0 起,如果启用了 <link linkend="book.readline">readline 扩展</link>
|
||
,交互式 shell 也可以在 Windows 上使用。
|
||
</para>
|
||
|
||
<para>
|
||
使用交互式 shell,你可以输入 PHP 代码并直接执行。
|
||
</para>
|
||
|
||
<example>
|
||
<title>使用交互式 shell 执行代码</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ php -a
|
||
Interactive shell
|
||
|
||
php > echo 5+8;
|
||
13
|
||
php > function addTwo($n)
|
||
php > {
|
||
php { return $n + 2;
|
||
php { }
|
||
php > var_dump(addtwo(2));
|
||
int(4)
|
||
php >
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
交互式 shell 还有对函数、常量、类名、变量、静态方法调用和类常量的 Tab 键补全功能。
|
||
</para>
|
||
|
||
<example>
|
||
<title>Tab 键补全</title>
|
||
<simpara>
|
||
当可能有多个补全时,按两次 Tab 键将会得到补全列表:
|
||
</simpara>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
php > strp[TAB][TAB]
|
||
strpbrk strpos strptime
|
||
php > strp
|
||
]]>
|
||
</programlisting>
|
||
<simpara>
|
||
当仅可能有一个补全,按一次 Tab 键即可在同一行中补全剩余:
|
||
</simpara>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
php > strpt[TAB]ime(
|
||
]]>
|
||
</programlisting>
|
||
<simpara>
|
||
补全也适用于当前交互式 shell 会话期间定义的名称:
|
||
</simpara>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
php > $fooThisIsAReallyLongVariableName = 42;
|
||
php > $foo[TAB]ThisIsAReallyLongVariableName
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<simpara>
|
||
交互式 shell 会存储的操作历史记录,可以通过上下键访问。历史记录存储于 <filename>~/.php_history</filename>
|
||
文件。自 PHP 8.4.0 起,history 文件的路径可以使用 <envar>PHP_HISTFILE</envar> 环境变量设置。
|
||
</simpara>
|
||
|
||
<para>
|
||
&cli.sapi; 提供了 <parameter>cli.pager</parameter> 和
|
||
<parameter>cli.prompt</parameter> 两个 &php.ini; 配置。<parameter>cli.pager</parameter>
|
||
配置允许外部程序(例如 <filename>less</filename>)充当分页器输出而不是直接在屏幕上显示。
|
||
<parameter>cli.prompt</parameter> 配置可以更改 <literal>php ></literal> 提示符。
|
||
</para>
|
||
|
||
<para>
|
||
在交互式 shell 中还可以使用缩写符号设置 &php.ini; 配置。
|
||
</para>
|
||
|
||
<example>
|
||
<title>在交互式 shell 中设置 &php.ini; 配置</title>
|
||
<simpara>
|
||
<parameter>cli.prompt</parameter> 配置:
|
||
</simpara>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
php > #cli.prompt=hello world :>
|
||
hello world :>
|
||
]]>
|
||
</programlisting>
|
||
<simpara>
|
||
使用反引号可以在提示中执行 PHP 代码:
|
||
</simpara>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
php > #cli.prompt=`echo date('H:i:s');` php >
|
||
15:49:35 php > echo 'hi';
|
||
hi
|
||
15:49:43 php > sleep(2);
|
||
15:49:45 php >
|
||
]]>
|
||
</programlisting>
|
||
<simpara>
|
||
设置分页器为 <filename>less</filename>:
|
||
</simpara>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
php > #cli.pager=less
|
||
php > phpinfo();
|
||
(output displayed in less)
|
||
php >
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
<parameter>cli.prompt</parameter> 配置支持一些转义字符:
|
||
<table>
|
||
<title><parameter>cli.prompt</parameter> 转义字符</title>
|
||
<tgroup cols="2">
|
||
<thead>
|
||
<row>
|
||
<entry>字符</entry>
|
||
<entry>描述</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>\e</literal></entry>
|
||
<entry>
|
||
用于添加提示符颜色。一个例子是 <literal>\e[032m\v \e[031m\b \e[34m\> \e[0m</literal>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\v</literal></entry>
|
||
<entry>PHP 版本。</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\b</literal></entry>
|
||
<entry>
|
||
指明 PHP 所在的块。例如 <literal>/*</literal> 表示在多行注释中。外部作用域用 <literal>php</literal> 来表示。
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\></literal></entry>
|
||
<entry>
|
||
指明提示字符。默认是 <literal>></literal>,但当 shell 位于未结束的块或者字符串时会发生变化。可能的字符有
|
||
<literal>' " { ( ></literal>
|
||
</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
在该模式下,通过 <link linkend="ini.auto-prepend-file">auto_prepend_file</link> 和 <link
|
||
linkend="ini.auto-append-file">auto_append_file</link> 解析加载的文件会有一些限制 —— 例如函数必须在调用前定义。
|
||
</para>
|
||
</note>
|
||
|
||
<section xml:id="features.commandline.interactive.mode">
|
||
<title>交互模式</title>
|
||
<para>
|
||
如果 readline 扩展不可用,在 PHP 8.1.0 之前,使用 <option>-a</option> 选项调用 &cli.sapi; 会提供交互模式。
|
||
在此模式中,一个完整的 PHP 脚本应该通过 STDIN 给出,并用 <keycombo action='simul'>
|
||
<keycap>CTRL</keycap>
|
||
<keycap>D</keycap>
|
||
</keycombo>(POSIX)或者 <keycombo action='simul'>
|
||
<keycap>CTRL</keycap>
|
||
<keycap>Z</keycap>
|
||
</keycombo>
|
||
终止然后 <keycap>ENTER</keycap>(Windows),脚本执行。这与不加 <option>-a</option> 选项调用 &cli.sapi; 基本相同。
|
||
</para>
|
||
<para>
|
||
自 PHP 8.1.0 起,如果 readline 扩展不可用,使用 <option>-a</option> 调用 &cli.sapi; 会失败。
|
||
</para>
|
||
</section>
|
||
</section>
|
||
<!--}}}-->
|
||
|
||
<!--Built-in CLI Web Server: {{{-->
|
||
<section xml:id="features.commandline.webserver">
|
||
<title>内置 Web Server</title>
|
||
|
||
<warning>
|
||
<para>
|
||
该 Web 服务器目的是帮助应用程序开发。还可用于测试目的或在受控环境中运行的应用程序演示。但并不是一个功能齐全的 Web 服务器。不应该在公共网络上使用。
|
||
</para>
|
||
</warning>
|
||
|
||
<para>
|
||
&cli.sapi; 提供了内置的 Web 服务器。
|
||
</para>
|
||
|
||
<para>
|
||
Web 服务器仅运行一个单线程进程,因此如果堵塞了请求,PHP 应用程序将停止运行。
|
||
</para>
|
||
|
||
<para>
|
||
URI 请求将从启动 PHP 的当前工作目录提供服务,除非使用 -t 选项指定文档根目录。如果 URI 请求未指定文件,则返回指定目录中的 index.php 或
|
||
index.html。如果两个文件都不存在,则将在父目录中继续查找 index.php 和 index.html,依此类推,直到找到一个文件或到达文档根目录。如果找到
|
||
index.php 或 index.html,则将其返回,并将 $_SERVER['PATH_INFO'] 设置为 URI 的尾部部分。否则将返回 404 响应代码。
|
||
</para>
|
||
|
||
<para>
|
||
如果在命令行上启动 Web 服务器时指定了 PHP 文件,则会将其视为“router”脚本。该脚本在每个 HTTP 请求开始时运行。如果此脚本返回
|
||
&false;,则按原样返回所请求的资源。否则脚本的输出将返回到浏览器。
|
||
</para>
|
||
|
||
<para>
|
||
对于有扩展名的文件,将返回标准的 MIME 类型:
|
||
<simplelist type="inline">
|
||
<member><literal>.3gp</literal></member>
|
||
<member><literal>.apk</literal></member>
|
||
<member><literal>.avi</literal></member>
|
||
<member><literal>.bmp</literal></member>
|
||
<member><literal>.css</literal></member>
|
||
<member><literal>.csv</literal></member>
|
||
<member><literal>.doc</literal></member>
|
||
<member><literal>.docx</literal></member>
|
||
<member><literal>.flac</literal></member>
|
||
<member><literal>.gif</literal></member>
|
||
<member><literal>.gz</literal></member>
|
||
<member><literal>.gzip</literal></member>
|
||
<member><literal>.htm</literal></member>
|
||
<member><literal>.html</literal></member>
|
||
<member><literal>.ics</literal></member>
|
||
<member><literal>.jpe</literal></member>
|
||
<member><literal>.jpeg</literal></member>
|
||
<member><literal>.jpg</literal></member>
|
||
<member><literal>.js</literal></member>
|
||
<member><literal>.kml</literal></member>
|
||
<member><literal>.kmz</literal></member>
|
||
<member><literal>.m4a</literal></member>
|
||
<member><literal>.mov</literal></member>
|
||
<member><literal>.mp3</literal></member>
|
||
<member><literal>.mp4</literal></member>
|
||
<member><literal>.mpeg</literal></member>
|
||
<member><literal>.mpg</literal></member>
|
||
<member><literal>.odp</literal></member>
|
||
<member><literal>.ods</literal></member>
|
||
<member><literal>.odt</literal></member>
|
||
<member><literal>.oga</literal></member>
|
||
<member><literal>.ogg</literal></member>
|
||
<member><literal>.ogv</literal></member>
|
||
<member><literal>.pdf</literal></member>
|
||
<member><literal>.png</literal></member>
|
||
<member><literal>.pps</literal></member>
|
||
<member><literal>.pptx</literal></member>
|
||
<member><literal>.qt</literal></member>
|
||
<member><literal>.svg</literal></member>
|
||
<member><literal>.swf</literal></member>
|
||
<member><literal>.tar</literal></member>
|
||
<member><literal>.text</literal></member>
|
||
<member><literal>.tif</literal></member>
|
||
<member><literal>.txt</literal></member>
|
||
<member><literal>.wav</literal></member>
|
||
<member><literal>.webm</literal></member>
|
||
<member><literal>.wmv</literal></member>
|
||
<member><literal>.xls</literal></member>
|
||
<member><literal>.xlsx</literal></member>
|
||
<member><literal>.xml</literal></member>
|
||
<member><literal>.xsl</literal></member>
|
||
<member><literal>.xsd</literal></member>
|
||
<member><literal>.zip</literal></member>
|
||
</simplelist>
|
||
。
|
||
</para>
|
||
|
||
<simpara>
|
||
从 PHP 7.4.0 开始,内置 Web 服务器可以配置为派生多个工作线程,以便测试需要向内置 Web 服务器发出多个并发请求的代码。在启动服务器之前,将
|
||
<envar>PHP_CLI_SERVER_WORKERS</envar> 环境变量设置为所需的 worker 数量。
|
||
</simpara>
|
||
<note>
|
||
<simpara>此功能不支持 Windows。</simpara>
|
||
</note>
|
||
<warning>
|
||
<para>
|
||
此<emphasis>实验</emphasis>功能<emphasis>不</emphasis>适用于生产用途。通常,内置 Web 服务器<emphasis>不</emphasis>适合生产用途。
|
||
</para>
|
||
</warning>
|
||
|
||
<example>
|
||
<title>启动 Web 服务器</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ cd ~/public_html
|
||
$ php -S localhost:8000
|
||
]]>
|
||
</programlisting>
|
||
<para>
|
||
终端将显示:
|
||
</para>
|
||
<screen>
|
||
<![CDATA[
|
||
PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011
|
||
Listening on localhost:8000
|
||
Document root is /home/me/public_html
|
||
Press Ctrl-C to quit
|
||
]]>
|
||
</screen>
|
||
<para>
|
||
在 URI 请求 http://localhost:8000/ 和 http://localhost:8000/myscript.html 之后,终端会显示类似以下的内容:
|
||
</para>
|
||
<screen>
|
||
<![CDATA[
|
||
PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011
|
||
Listening on localhost:8000
|
||
Document root is /home/me/public_html
|
||
Press Ctrl-C to quit.
|
||
[Thu Jul 21 10:48:48 2011] ::1:39144 GET /favicon.ico - Request read
|
||
[Thu Jul 21 10:48:50 2011] ::1:39146 GET / - Request read
|
||
[Thu Jul 21 10:48:50 2011] ::1:39147 GET /favicon.ico - Request read
|
||
[Thu Jul 21 10:48:52 2011] ::1:39148 GET /myscript.html - Request read
|
||
[Thu Jul 21 10:48:52 2011] ::1:39149 GET /favicon.ico - Request read
|
||
]]>
|
||
</screen>
|
||
<para>
|
||
请注意,在 PHP 7.4.0 之前,在 Windows 上无法访问符号链接的静态资源,除非 router 脚本可以处理这些资源。
|
||
</para>
|
||
</example>
|
||
|
||
<example>
|
||
<title>启动时指定文档根目录</title>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ cd ~/public_html
|
||
$ php -S localhost:8000 -t foo/
|
||
]]>
|
||
</programlisting>
|
||
<para>
|
||
终端将显示:
|
||
</para>
|
||
<screen>
|
||
<![CDATA[
|
||
PHP 5.4.0 Development Server started at Thu Jul 21 10:50:26 2011
|
||
Listening on localhost:8000
|
||
Document root is /home/me/public_html/foo
|
||
Press Ctrl-C to quit
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<example>
|
||
<title>使用 router 脚本</title>
|
||
<para>
|
||
在此示例中,请求图像将显示图片,但对 HTML 文件的请求将显示“Welcome to PHP”:
|
||
</para>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
// router.php
|
||
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
|
||
return false; // 原样提供所请求的资源
|
||
} else {
|
||
echo "<p>Welcome to PHP</p>";
|
||
}
|
||
?>]]>
|
||
</programlisting>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ php -S localhost:8000 router.php
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>检查 CLI Web 服务器的使用</title>
|
||
<para>
|
||
要在使用 CLI Web 服务器开发期间以及稍后使用生产 Web 服务器重复使用的框架 router 脚本:
|
||
</para>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
// router.php
|
||
if (php_sapi_name() == 'cli-server') {
|
||
/* 发送静态资源并返回 false */
|
||
}
|
||
/* 继续正常的 index.php 操作 */
|
||
?>]]>
|
||
</programlisting>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ php -S localhost:8000 router.php
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>处理不支持的文件类型</title>
|
||
<para>
|
||
如果需要提供不由 CLI Web 服务器处理的静态资源的 MIME 类型,请使用:
|
||
</para>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
// router.php
|
||
$path = pathinfo($_SERVER["SCRIPT_FILENAME"]);
|
||
if ($path["extension"] == "el") {
|
||
header("Content-Type: text/x-script.elisp");
|
||
readfile($_SERVER["SCRIPT_FILENAME"]);
|
||
}
|
||
else {
|
||
return FALSE;
|
||
}
|
||
?>]]>
|
||
</programlisting>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ php -S localhost:8000 router.php
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>从远程计算机访问 CLI Web 服务器</title>
|
||
<para>
|
||
可以通过以下方式使 Web 服务器可通过端口 8000 接受任何链接:
|
||
</para>
|
||
<programlisting role="shell">
|
||
<![CDATA[
|
||
$ php -S 0.0.0.0:8000
|
||
]]>
|
||
</programlisting>
|
||
<warning>
|
||
<para>
|
||
内置 Web 服务器不应该在公共网络上使用。
|
||
</para>
|
||
</warning>
|
||
</example>
|
||
|
||
</section>
|
||
<!--}}}-->
|
||
|
||
<section xml:id="features.commandline.ini">
|
||
<title>INI 配置</title>
|
||
<para>
|
||
<table>
|
||
<title>CLI SAPI 配置选项</title>
|
||
<tgroup cols="4">
|
||
<thead>
|
||
<row>
|
||
<entry>&Name;</entry>
|
||
<entry>&Default;</entry>
|
||
<entry>&Changeable;</entry>
|
||
<entry>&Changelog;</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody xml:id="features.commandline.ini.list">
|
||
<row>
|
||
<entry><link linkend="ini.cli-server.color">cli_server.color</link></entry>
|
||
<entry>"0"</entry>
|
||
<entry><constant>INI_ALL</constant></entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
|
||
&ini.descriptions.title;
|
||
|
||
<para>
|
||
<variablelist>
|
||
<varlistentry xml:id="ini.cli-server.color">
|
||
<term>
|
||
<parameter>cli_server.color</parameter>
|
||
<type>boolean</type>
|
||
</term>
|
||
<listitem>
|
||
<para>
|
||
控制内置Web Server的终端输出有无颜色。
|
||
</para>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</para>
|
||
</section>
|
||
|
||
</chapter>
|
||
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|