PHP默认可能通过disable_functions禁用exec,需检查php.ini中disable_functions值是否含exec,删掉后重启PHP进程(如php-fpm restart)才生效;safe_mode在PHP 5.4+已移除,旧环境需确认并关闭;CLI与Web SAPI配置文件常不同,须分别验证。

php.ini 里 disable_functions 是否禁用了 exec
这是最常见、也最容易被忽略的卡点。PHP 默认可能已通过 disable_functions 禁用 exec,哪怕你代码写得完全正确,函数调用也会静默失败(不报错、不输出、返回空数组)。
检查方式很简单:
– 找到你实际生效的 php.ini 文件(用 php --ini 或 phpinfo() 确认路径);
– 搜索 disable_functions 这一行;
– 看值里是否包含 exec,比如:disable_functions = exec,system,passthru,shell_exec。
如果存在,删掉 exec(注意保留逗号分隔),保存后必须重启 PHP 进程(如 php-fpm restart 或 service apache2 restart),仅 reload 不生效。
safe_mode 是否还开着(尤其旧环境)
safe_mode 在 PHP 5.4+ 已被彻底移除,但如果你维护的是老旧服务器(如 CentOS 6 + PHP 5.3),它仍可能启用并直接屏蔽 exec 的全部行为。
检查方法:
– 在 php.ini 中搜索 safe_mode;
– 如果值为 On 或 1,改为 Off;
– 同样需要重启 PHP 进程。
注意:修改后建议用 var_dump(ini_get('safe_mode')); 验证是否真正关闭——有些面板或容器会覆盖配置,ini_get 返回 false 才算生效。
立即学习“PHP免费学习笔记(深入)”;
为什么改了 php.ini 还没用?确认加载的是哪个配置
开发机、Docker、宝塔、cPanel 各自可能加载不同 php.ini,尤其当 CLI 和 Web SAPI(如 fpm)共存时,两者的配置文件常不一致。
务必分场景验证:
– Web 页面中跑 <?php phpinfo(); ?>,看 “Loaded Configuration File” 路径;
– 命令行执行 php -i | grep "Loaded Configuration File",对比是否相同;
– 如果不同,两个地方的 disable_functions 都得检查、都得改。
一个典型陷阱:你在宝塔面板里改了网站的 PHP 配置,但 CLI 下的 php -v 仍走系统默认 ini,导致命令行测试始终失败。
exec 调用无报错但没输出?先确认它真被调用了
exec 默认不返回命令输出,只返回最后一行,且不捕获 stderr。容易误判为“没反应”。
快速验证是否真的执行了:
– 用带输出捕获的方式:exec('whoami 2>&1', $output, $return_code); var_dump($output, $return_code);;
– 加个副作用明显的命令:exec('touch /tmp/exec_test_'.time());,然后 ls -l /tmp/exec_test_* 看文件有没有生成;
– 检查 $return_code:0 表示成功,非 0 说明命令崩溃或被拦截(比如权限/SELinux 拒绝)。
真正难缠的不是“执行不了”,而是“执行了但被系统策略无声丢弃”——这时候 $return_code 是唯一可靠线索。



















