exec第二个参数必须是引用数组,否则$output为空;其元素为每行输出(自动去除\n),重复调用需手动清空数组,二进制数据应避免使用该参数。

exec 第二个参数必须是引用数组,否则拿不到输出
传给 exec 的第二个参数不是普通变量,而是必须用 &$output 这种引用方式声明的数组。如果只写 $output(没加 &),PHP 不会报错,但数组始终为空——因为 exec 内部是往引用地址写内容的,非引用传参等于白传。
常见错误写法:exec('ls', $output); → $output 保持空数组;正确写法:exec('ls', $output);(注意定义时已带 & 或函数调用时显式传引用)。
- PHP 7.2 默认禁用
register_globals,不存在自动变量注入,别指望不传参也能拿到结果 - 数组元素是按行切分的,每行末尾的
\n被自动剥离,所以$output[0]是第一行纯文本,不含换行符 - 如果命令输出含空行,
$output里对应位置是空字符串'',不是null
反复调用 exec 时,$output 数组必须手动清空
因为 exec 是往数组末尾追加(append),不是覆盖写入。连续执行两次不同命令却共用一个 $output 变量,第二次结果会拼在第一次后面,导致数据错乱。
典型场景:循环检查多个服务健康状态,每次调用 exec('curl -s http://x/health', $output),但忘了重置 $output。
- 安全做法:每次调用前加
$output = [];或unset($output); $output = []; - 不能依赖
array_splice($output, 0);,它只清内容不重置数组结构,某些 PHP 版本下仍可能残留键名干扰 - 如果用函数封装调用逻辑,建议把
$output声明为局部变量,避免跨作用域污染
输出内容编码与二进制数据限制
exec 的第二个参数只适合接收文本输出。如果命令返回的是二进制数据(比如 cat image.jpg 或 ffmpeg 截帧输出),$output 数组里的每一项会被当成 UTF-8 字符串处理,遇到 \0 或高位字节可能截断或乱码。
- 需要处理二进制流时,改用
passthru()或shell_exec()+bindec()等组合,不要碰$output数组 - 中文路径或含 UTF-8 输出时,确保 shell 环境 locale 设置一致(如
export LANG=C.UTF-8),否则$output可能出现问号或乱码 - 超长单行输出(如 base64 编码的证书)不会被截断,但整行作为一个数组元素存在,内存占用直线上升
和 shell_exec() 的关键区别:返回值语义完全不同
exec() 的返回值只是最后一行(字符串),而 shell_exec() 返回全部输出合并成一个字符串(含换行符)。很多人误以为 exec($cmd, $out); $result = implode("\n", $out); 和 $result = shell_exec($cmd); 等价——其实不完全对。
-
exec的$output数组中,每行结尾的\n已被移除;shell_exec返回的字符串保留原始换行符(包括\r\n) - 若命令输出以
\r\n结尾(Windows 风格),shell_exec会保留它;exec的$output则完全丢弃所有行尾控制符 - 性能上,
exec+ 数组更省内存(尤其大输出时),shell_exec一次性加载全部内容到字符串,PHP 7.2 下容易触发 memory_limit
$output 总是空或者数据混在一起。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











