php 增量备份需同时校验源目标文件的 mtime 和 size:目标不存在则直接复制;存在时须满足源 mtime > 目标 mtime 且源 size ≠ 目标 size 才更新,并用 recursiveiteratoriterator 遍历、路径过滤、copy+touch 组合保留时间戳。

如何用 PHP 判断文件是否需要备份(mtime + size)
只比对 mtime 不够可靠:NFS 挂载、某些容器环境或时钟不同步会导致时间漂移;只比对 size 更危险,相同大小但内容不同的文件会被跳过。必须两者同时满足「源文件 mtime > 目标文件 mtime」且「源文件 size ≠ 目标文件 size」才视为变更——但注意:如果目标文件不存在,就该直接复制。
实操建议:
- 用
filemtime()获取时间戳,失败时返回false,需显式检查(比如目标文件被 chmod 为只读但存在,filemtime()可能失败) - 用
filesize()前先用is_file()确认是普通文件,避免目录或符号链接触发警告 - 时间比较前统一转为整数(
(int)filemtime($path)),避免浮点精度或时区隐式转换干扰 - 目标路径可能尚未创建父目录,需在复制前调用
mkdir($dest_dir, 0755, true)
递归遍历源目录并生成相对路径映射
增量备份的核心是保持目录结构一致,不能只靠 scandir() 一层层硬写循环——容易漏掉深层嵌套,也难做路径拼接。推荐用 RecursiveIteratorIterator + RecursiveDirectoryIterator,它天然跳过 . 和 ..,且能通过 getSubPathname() 直接拿到相对于根的路径。
示例关键逻辑:
$iter = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($src, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iter as $file) {
if (!$file->isFile()) continue;
$rel_path = $iter->getSubPathname(); // 如 "logs/app.log"
$src_full = $file->getPathname();
$dst_full = $dst . '/' . $rel_path;
}
注意:getSubPathname() 在 Windows 下返回反斜杠,建议统一用 str_replace('\', '/', ...) 或直接用 dirname()/basename() 拆解再拼接,避免路径分隔符问题。
跳过不需要备份的文件(.git、临时文件等)
不加过滤会导致备份大量无意义文件,拖慢速度甚至撑爆空间。PHP 层面过滤比 shell 层更可控,尤其在 Windows 或权限受限主机上。
常见过滤策略:
- 用
pathinfo($rel_path, PATHINFO_EXTENSION)检查扩展名,如log、tmp、swp - 用
str_starts_with($rel_path, '.')排除隐藏文件和目录(如.git/、.DS_Store) - 对整个路径做白名单匹配,例如
in_array($rel_path, ['composer.lock', 'config.php'], true) - 避免用
preg_match对每个文件执行正则——简单字符串判断更快,除非真有复杂模式需求
复制文件时保留 mtime 并处理失败场景
copy() 只复制内容,不保留修改时间;而增量逻辑依赖 mtime 判断后续变更,所以必须用 touch($dst_full, filemtime($src_full)) 补上。但顺序很重要:先 copy() 成功,再 touch(),否则可能留下时间戳错乱的空文件。
必须处理的失败情况:
-
copy()返回false:可能是磁盘满、权限不足或源文件被占用,应记录$src_full . ': copy failed'到日志,而非静默跳过 -
touch()失败:目标文件已存在但只读,或所在目录不可写,此时应尝试chmod($dst_full, 0644)后重试一次 - 不要用
@copy()抑制警告——错误信息对排障至关重要
最后提醒:mtime 在 FAT32 或某些网络文件系统上只有 2 秒精度,若业务对秒级变更敏感,得额外加 checksum(如 md5_file())校验,但会显著降低性能。多数场景下 mtime+size 已足够,别一上来就加哈希。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











