宝塔面板中chown/chmod修改权限失效,是因为“网站文件防篡改”和计划任务(如日志切割、自动备份)会自动重置权限;应关闭防篡改、检查计划任务、按目录精细化设权,并配合nginx配置禁止上传目录执行php。

为什么 chown 和 chmod 直接改权限会失效
宝塔面板里手动用 chown 或 chmod 把网站目录设成只读,过一会儿又变回可写——这不是你操作错了,是宝塔的「文件防篡改」和「计划任务自动修复」在背后起作用。比如开启「网站文件防篡改」后,宝塔会定期检查并重置目录权限;又或者开启了「自动备份」或「日志切割」,这些功能默认需要写入权限,会悄悄把 public_html 或 wwwroot 下的权限拉回来。
实操建议:
- 先去「网站」→「设置」→「配置」页,关闭「网站文件防篡改」(它本质是靠定时脚本 + 权限锁实现的)
- 检查「计划任务」里有没有自定义的权限修复脚本,尤其是名称含
fixperm、chmod或wwwroot的任务 - 确认「日志切割」是否开启:如果开启,它会在每天零点清空
logs/并重置父目录权限,建议关闭或改用只对logs/单独授权
用宝塔原生功能实现「代码只读 + 运行可写」隔离
真正安全的做法不是全站只读,而是分离「代码层」和「运行时层」:PHP 代码文件(.php、.ini)应不可写,而缓存、上传、日志等目录必须可写。宝塔支持按目录单独设权限,比全局 chmod -R 444 更可靠。
实操建议:
- 进入「网站」→「根目录」→ 右键点击你的网站根目录 →「设置权限」
- 勾选「禁止写入」,但注意:这只会对当前目录生效,子目录仍继承原权限
- 接着右键点开
runtime/、uploads/、logs/等需要写的子目录,逐个取消「禁止写入」 - 若用 ThinkPHP、Laravel 等框架,务必确保
storage/或bootstrap/cache/目录处于「可写」状态,否则报错file_put_contents(): failed to open stream: Permission denied
nginx 配置级防护:禁止执行上传目录里的 PHP
光靠文件权限不够。攻击者上传 shell.php 到 uploads/ 后,只要 nginx 允许执行,权限再低也白搭。必须从 Web 服务器层面拦截。
实操建议:
- 进「网站」→「设置」→「配置文件」,在
server块末尾插入:
location ~ ^/uploads/.*\.(php|php5|phtml|jsp|asp|sh)$ {
deny all;
}
- 替换
/uploads/为你实际的上传路径(如/wp-content/uploads/) - 保存后点「重载配置」,不要只点「保存」——没重载等于没改
- 验证方式:上传一个
test.php到该目录,访问时应返回 403,而不是显示 PHP 信息
权限数值别硬记,用宝塔的「数字权限」视图避坑
很多人查教程照搬 chmod 644 或 755,但在宝塔里直接填数字容易出错:比如填了 444,结果整个网站打不开,因为 nginx 用户(通常是 www)连读都做不到。宝塔的图形化权限面板其实更准,它背后映射的是用户组逻辑。
实操建议:
- 在「设置权限」弹窗中,优先用勾选方式而非手动输数字
- 「所有者」对应 FTP 用户(可写),「所属组」对应
www(建议只读),「其它用户」一律不勾「写入」 - 如果非要用命令行,记住两个安全基线:
– 代码文件(.php):chmod 644(所有者可读写,组/其它只读)
– 代码目录:chmod 755(所有者可读写执行,组/其它可读+执行) - 切勿对整个
wwwroot执行chmod -R 444:会导致 PHP 无法读取自身文件,报错failed to open stream: Permission denied in Unknown on line 0
最麻烦的其实是框架自动生成的缓存文件,它们常被写进 vendor/ 或 composer 目录,一旦设成只读,下次更新就失败。这类目录得留白——不是所有“代码”都该只读,得看它是不是运行时产物。










