You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP执行tar恢复备份时报Cannot unlink: Read-only file system错误如何解决

问题排查与解决思路

1. 优先排查PHP运行环境的systemd沙箱限制

Arch Linux默认给php-fpm、httpd服务配置了systemd安全沙箱规则,会主动将系统目录设为只读,哪怕进程有sudo权限也无法写入:

  • 查看php-fpm服务的配置文件:/usr/lib/systemd/system/php-fpm.service 或 /etc/systemd/system/php-fpm.service.d/ 目录下的自定义配置
  • 检查是否存在如下参数:
    • ProtectSystem=strict/ProtectSystem=true:会将/usr、/etc等系统目录挂载为只读
    • ReadOnlyPaths=/etc:显式设置/etc目录只读
  • 修复方案:
    在php-fpm的自定义配置中添加允许读写的目录规则,示例:
    [Service]
    ReadWritePaths=/etc
    
    执行systemctl daemon-reload && systemctl restart php-fpm生效。

2. 验证sudoers配置的合法性

  • 确认sudoers中给http用户的授权没有参数限制,推荐配置格式:
    http ALL=(ALL) NOPASSWD: /usr/bin/tar
    
    避免限制参数后,实际执行的tar参数与授权规则不匹配导致权限失效。
  • 排查sudo的secure_path配置,确保tar命令的路径在secure_path的允许范围内,或者直接在命令中写tar的绝对路径/usr/bin/tar,避免环境变量差异导致命令调用异常。

3. 排查PHP执行命令的环境差异

shell_exec的调用环境和交互式shell存在差异,可在PHP中执行如下命令打印运行时信息排查问题:

// 将输出写入日志确认运行状态
file_put_contents('/tmp/debug.log', shell_exec('whoami && pwd && mount | grep /etc && sudo -n true 2>&1'));

重点确认:

  • 执行用户确实为http
  • /etc目录挂载状态为rw(可写)
  • sudo调用无密码验证错误

4. Laravel命令调用优化

不要直接用字符串拼接的方式调用shell_exec,容易出现特殊字符解析错误,推荐使用Laravel自带的Symfony Process组件传参数数组执行:

use Symfony\Component\Process\Process;

$process = new Process(['sudo', '/usr/bin/tar', '-xf', $backupPath . $dirName, '--recursive-unlink', '--unlink-first'], '/');
$process->run();

5. Docker环境特殊排查

如果在Docker容器中运行:

  • 确认容器启动时没有将/etc目录设为只读卷
  • 可临时加--privileged参数启动容器验证是否为安全限制导致,验证通过后调整security-opt、cap-add参数授予对应写入权限即可,无需长期开启特权模式。

内容的提问来源于stack exchange,提问作者Maksat Baigazy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 11:45:04