shell_exec被禁用时需检查并修改disable_functions配置,确认PHP环境是否禁用该函数,同时解决权限、PATH、容器缺失命令及stderr捕获等问题。

shell_exec 被禁用时直接报错
Webman 启动或运行中调用 shell_exec 报 “Function disabled” 是最常见现象,不是代码写错了,而是 PHP 环境主动拦住了。宝塔、Docker 镜像、甚至某些云主机默认就把 shell_exec、exec、proc_open 加进 disable_functions 了。
先确认是否真被禁:执行 php -i | grep disable_functions,如果输出里含 shell_exec,就得改配置。别只改 php.ini 里那一行——要找到“Loaded Configuration File”路径(用 php --ini 查),编辑那个文件,删掉 shell_exec(以及可能连带的 exec、passthru)。
- 改完必须重启 CLI 环境(关掉终端重开,或
source ~/.bashrc) - 容器内修改后要重建镜像或 exec 进去验证,单纯 reload 无效
- 宝塔用户注意:PHP 设置页里的“禁用函数”是独立配置项,和 php.ini 不同步,得在面板里清空再保存
权限与路径问题比语法更常导致失败
shell_exec('which wkhtmltopdf') 返回空,并不等于命令不存在,很可能是当前 Webman 工作进程用户(如 www-data 或 nginx)没权限执行它,或者 PATH 环境变量不包含该命令所在目录。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
- 用绝对路径调用二进制:比如
/usr/local/bin/wkhtmltopdf而不是wkhtmltopdf - 检查命令所有者和权限:
ls -l /usr/local/bin/wkhtmltopdf,确保执行用户有 x 权限 - 必要时在命令前加
sudo -u www-data(仅限调试,生产环境慎用) - 若命令依赖网络(如 curl 请求外链生成 PDF),确认该用户能访问外网(
su -c 'curl -I https://httpbin.org' www-data测试)
捕获错误输出比忽略更关键
直接 shell_exec($cmd) 只拿到 stdout,stderr 被丢弃。很多失败根本看不到报错信息,比如 wkhtmltopdf 缺字体、PDF 页面加载超时、权限拒绝等。
换成更可控的方式:
$cmd = '/usr/local/bin/wkhtmltopdf --quiet input.html output.pdf 2>&1';
$output = shell_exec($cmd);
if (false === $output || trim($output)) {
\Log::error('wkhtmltopdf failed: ' . $output);
}
-
2>&1把 stderr 合并到 stdout,才能捕获完整错误 - 用
exec()替代shell_exec()可以同时拿到 exit code:exec($cmd, $outputLines, $returnCode) - 避免在高并发场景下无限制调用外部命令,建议加锁或走队列(如 Webman 的
workerman/crontab或 Redis Queue)
容器环境里命令根本不在镜像里
Docker 部署 Webman 时,基础镜像(如 php:8.2-cli)默认不含 wkhtmltopdf、ffmpeg 等工具。你不能指望 apt install 在运行时生效——容器启动后文件系统是只读的(除非挂载 tmpfs)。
- 必须在 Dockerfile 中显式安装:
RUN apt-get update && apt-get install -y wkhtmltopdf - Alpine 镜像要用
apk add wkhtmltopdf,注意 Alpine 版本兼容性(有些插件不支持 musl) - 安装后验证:
docker run --rm your-webman-image which wkhtmltopdf - 别把命令装在 host 上指望容器能访问——容器是隔离的,除非用
host网络模式并挂载 bin 目录(不推荐)

















