ARM64服务器AppArmor阻止Chromium转HTML为PDF及PHP执行故障解决
问题排查与修复方案
1. 先修正最直观的问题:路径拼写错误
你PHP代码里的命令存在两处明显的路径拼写错误:
- 生成PDF的路径写为
/home/joedoe/...,但命令行实际使用的是/home/johndoe/... - 移动文件时又误写为
/home/joendoe/...,和前后路径都不匹配
因为命令用&&串联,前面的步骤失败会直接终止整个流程,这是PHP执行失败的直接原因之一。
2. PHP运行用户的权限差异问题
命令行使用的是johndoe用户,但PHP默认以www-data用户运行,两者权限范围完全不同:
/home/johndoe目录默认仅对johndoe用户开放读写权限,www-data无法在此创建PDF文件- 即便PDF生成成功,
mv到/var/www/files.domain.com/docs/时,www-data也需要该目录的写入权限
修复方式:
- 放弃使用用户主目录作为临时路径,改用系统临时目录
/tmp(所有用户均有读写权限),或专门创建一个给www-data使用的临时目录:sudo mkdir /var/www/chromium-tmp sudo chown www-data:www-data /var/www/chromium-tmp sudo chmod 755 /var/www/chromium-tmp - 确保目标目录对
www-data开放写入权限:sudo chown -R www-data:www-data /var/www/files.domain.com/docs/
3. Snap版Chromium的AppArmor沙箱限制
你当前使用的是Snap安装的Chromium,它的AppArmor沙箱机制会严格限制进程的系统资源访问权限。命令行中johndoe用户能生成PDF,是因为Snap默认允许访问用户主目录,但www-data不在授权范围内,导致PHP执行时Chromium被直接拦截。
修复方式:
- 卸载Snap版Chromium,改用系统官方仓库的版本,彻底避开Snap的沙箱限制:
之后可直接使用sudo snap remove chromium sudo apt update && sudo apt install chromium-browserchromium-browser命令,或创建软链接简化调用:sudo ln -s /usr/bin/chromium-browser /usr/bin/chromium - 若必须使用Snap版,需修改AppArmor策略,但操作复杂且存在安全风险,不推荐。
4. PHP exec的环境变量缺失问题
PHP的exec运行时的PATH环境变量与命令行用户的环境变量不一致,可能导致无法找到chromium命令。解决办法是直接使用Chromium的绝对路径:
- Snap版路径:
/snap/bin/chromium - 仓库版路径:
/usr/bin/chromium-browser
修正后的PHP代码示例
<?php // 使用系统临时目录存放生成的PDF,避免权限问题 $tmpPdfPath = '/tmp/407163caf78c6deedcb8bf732e7e1326-fr.pdf'; $targetPdfPath = '/var/www/files.domain.com/docs/407163caf78c6deedcb8bf732e7e1326-fr.pdf'; $htmlUrl = 'https://files.domain.com/docs/407163caf78c6deedcb8bf732e7e1326.html'; // 使用仓库版Chromium的绝对路径,避免环境变量找不到命令 $command = "/usr/bin/chromium-browser --headless --disable-gpu --no-sandbox --no-pdf-header-footer --print-to-pdf='$tmpPdfPath' '$htmlUrl' && mv '$tmpPdfPath' '$targetPdfPath' && echo 'files.domain.com/docs/407163caf78c6deedcb8bf732e7e1326-fr.pdf'"; $output = []; $returnStatus = 0; exec($command . ' 2>&1', $output, $returnStatus); echo "Return Status: $returnStatus\n"; echo "Output:\n" . implode("\n", $output); if ($returnStatus !== 0) { echo "Command failed.\n"; } else { echo "Command succeeded.\n"; } ?>
内容的提问来源于stack exchange,提问作者Richardson Oge
相关产品推荐
相关产品推荐

