PHP CLI 运行脚本有三种方式:①php script.php(需注意路径);②php -r "code"(适合单行调试);③php -f file.php(显式指定文件)。环境差异常导致Web能运行而CLI报错。

PHP CLI 模式下直接运行脚本,不需要 web 服务器,但必须注意 php 命令的调用方式和环境差异——很多“脚本在浏览器能跑,CLI 报错”的问题,根源都在这里。
php 命令执行脚本的三种基本写法
CLI 下运行 PHP 脚本不是只有 php script.php 这一种方式,不同写法适用不同场景:
-
php script.php:最常用,适合带参数、需明确入口文件的脚本;注意当前路径要对,否则报File not found -
php -r "echo 'hello';":适合单行调试或简单逻辑,-r后面不加<?php标签,也不需要文件 -
php -f script.php:和第一种效果一样,但显式声明“强制解析为文件”,某些旧版 PHP 或容器环境里更稳妥
CLI 和 Web 环境的 php.ini 差异导致行为不一致
CLI 默认加载的是独立的 php.ini(通常是 /etc/php/*/cli/php.ini),和 Apache/FPM 的配置完全隔离。常见踩坑点:
- 扩展没启用:比如脚本用了
pdo_mysql,但 CLI 的php.ini里没开,运行就报Class 'PDO' not found - 时区未设置:
date()在 CLI 下可能返回Warning: date(): It is not safe to rely on the system's timezone settings,因为 CLI ini 里常缺date.timezone - 内存限制太小:CLI 默认
memory_limit可能是 128M,而 Web 是 512M,大数据处理时容易Fatal error: Allowed memory size exhausted
查当前 CLI 加载的配置:运行 php --ini;看具体 ini 内容:运行 php -i | grep "Loaded Configuration File"
立即学习“PHP免费学习笔记(深入)”;
脚本里判断是否在 CLI 模式运行
别靠 $_SERVER['HTTP_HOST'] 或其他 Web 特有变量来判断——CLI 下它们根本不存在,会触发 Notice。正确方式是:
- 用
php_sapi_name() === 'cli':最可靠,返回字符串,兼容所有 PHP 版本 - 用
PHP_SAPI === 'cli':效果一样,但PHP_SAPI是常量,更轻量 - 避免用
!isset($_SERVER['REMOTE_ADDR']):Web CLI 都可能为空(比如 FPM + nginx 配置异常时),误判率高
示例:
if (PHP_SAPI !== 'cli') {
die('This script can only run in CLI mode.');
}
argv 和 getopt 处理命令行参数的取舍
PHP CLI 脚本传参,$argv 简单直接,getopt() 更规范,但两者混用会出问题:
-
$argv是原始数组,$argv[0]是脚本名,$argv[1]开始才是参数;适合快速脚本,但不支持长选项(如--verbose) -
getopt('hf:', ['help', 'file:'])支持短选项(-f file.txt)和长选项(--file=file.txt),冒号表示该选项必带值;但注意:它会修改$argv,后续再读$argv可能为空或错位 - 如果脚本既要兼容简单调用(
php script.php input.txt),又要支持选项(php script.php -v --output=out.json),建议统一用getopt(),别混搭
常见错误:写了 getopt('v') 却传 -v=true,实际应传 -v(布尔开关不用等号);传 --verbose=true 则需写成 getopt('', ['verbose::'])(双冒号表示可选值)
CLI 模式下最易被忽略的,其实是 exit 状态码和输出缓冲——脚本失败时没设 exit(1),上游 shell 脚本就无法判断成败;开了 ob_start() 却忘了 ob_end_flush(),日志看起来像卡住了一样。



















