chmod 对 ZIP 包内文件无效,因其权限存储在 ZIP 元数据中且 PHP ZipArchive 不读写 Unix 扩展字段;仅能通过系统 zip -X 命令打包并配合 unzip -X 解压来有限支持。
PHP 修改文件权限(chmod)对 ZIP 压缩包本身有效,但对 ZIP 包内部的文件无效——ZIP 文件内的文件权限是存储在压缩包元数据中的,不是操作系统层面的属性,chmod 完全无法触达。
chmod 对 ZIP 包内文件没用ZIP 格式确实支持存储 Unix 权限(通过 extra field 中的 Unix extension),但 PHP 的原生 ZipArchive 类在添加/提取文件时默认不读写该字段,也不提供直接设置内部文件权限的 API。调用 chmod($zipFilePath, 0644) 只会改 ZIP 文件自身的权限,和里面的内容无关。
unzip -X 才尝试恢复)ZipArchive::addFile() 和 ZipArchive::addFromString() 均无参数控制内部权限zip -Z store -X 命令打包并带上权限,PHP 的 ZipArchive 读取时也忽略这些字段真正可控的只有两件事:打包时尽量写入权限信息(有限支持),以及提醒使用者用兼容方式解压。PHP 本身做不到“在 ZIP 中强制设定某文件为 0755”。
exec('zip -r -X archive.zip dir/') 调用系统 zip 命令,-X 会尝试保存 Unix 权限(需目标文件系统支持且 zip 版本 ≥ 3.0)chmod 0755 script.php),系统 zip 才可能记录它unzip -X archive.zip && chmod +x bin/start.sh
试图用 PHP 给 ZIP 内文件“设权限”,往往表现为静默失败或奇怪行为:
$zip->addFile('/path/to/exec.sh'); chmod('/path/to/exec.sh', 0755); —— 这只改了源文件权限,不影响 ZIP 内副本unzip -l -v archive.zip 发现 External Attributes 列显示 00000000(即权限未保存)ZipArchive::setArchiveComment() 或 setCommentName() 试图“注入权限” —— 完全无效,那是注释字段
真正在 ZIP 层面稳定控制权限,目前没有纯 PHP 方案;最靠谱的是用系统 zip 命令 + 明确的解压文档,或者换用 phar(支持 Phar::setSignatureAlgorithm() 和权限位写入,但仅限 PHP 运行环境)。