rsync比纯php同步更可靠,因其内置处理符号链接、权限、时间戳、增量传输和断点续传;php调用需注意末尾斜杠和--delete参数。

用 rsync 命令比纯 PHP 更可靠
PHP 自身没有内置的「文件夹同步」抽象层,硬写递归对比 + 复制 + 删除逻辑极易出错。生产环境强烈建议调用系统 rsync —— 它已处理好符号链接、权限、时间戳、增量传输、断点续传等边界问题。PHP 只需用 shell_exec() 或 proc_open() 调起即可,例如:
shell_exec('rsync -av --delete /path/src/ /path/dest/');
注意末尾斜杠:/src/ 表示同步内容,/src(无斜杠)会把整个目录复制进去;--delete 是关键,否则目标端残留旧文件。
RecursiveDirectoryIterator 遍历容易漏掉软链接和权限
如果必须用纯 PHP 实现(如共享主机禁用 shell),RecursiveDirectoryIterator 是起点,但它默认跳过符号链接,且不保留文件权限、所有者、修改时间。你需要手动补全:
- 加
FilesystemIterator::SKIP_DOTS和FilesystemIterator::FOLLOW_SYMLINKS才能正确处理软链 - 用
chmod()、touch()分别重置权限和 mtime,但 Windows 下chmod()无效,touch()对 NTFS 时间精度也受限 - 删除目标端多余文件需先完整扫描目标目录,再与源目录 diff —— 内存占用随文件数线性增长,万级文件易 OOM
判断文件是否变更不能只靠 filemtime()
仅比较修改时间(filemtime())在多机场景下不可靠:时钟不同步、NFS 挂载延迟、甚至 FAT32 文件系统只有 2 秒精度。更稳妥的方式是组合判断:
立即学习“PHP免费学习笔记(深入)”;
- 先比大小:
filesize()不同 → 必定不同 - 大小相同再比
md5_file()(小文件)或hash_file('xxh128', $f)(大文件,PHP 8.1+,比 MD5 快且抗碰撞) - 跳过哈希计算的优化:对超大文件(>10MB)可只比前 4KB + 后 4KB 的哈希,覆盖常见追加/截断操作
注意:md5_file() 会读完整文件,IO 开销大,别在循环里无脑调用。
Windows 下 copy() 失败常因路径长度或权限
Windows 默认路径限制 260 字符,PHP 的 copy()、unlink() 在长路径下直接报错 Warning: copy(): Cannot copy...。解决方案有限:
- 启用长路径支持(Windows 10 1607+):修改组策略「计算机配置 → 管理模板 → 系统 → 文件系统 → 启用 Win32 长路径」
- 改用
robocopy命令替代 PHP 文件函数:robocopy C:\src C:\dest /MIR /Z /R:1 - 避免在 PHP 中用
realpath()展开长路径,它可能触发内部缓冲区截断
跨平台脚本里,别假设 dirname(__FILE__) 总是返回正斜杠 —— Windows 返回反斜杠,拼接路径时用 DIRECTORY_SEPARATOR 或 str_replace() 统一。











