linkinfo 函数有什么用?PHP 判断硬链接数量与 stat 用法对比
linkinfo() 是 PHP 文件系统函数里存在感很低的一个,但在“判断一个路径是不是硬链接文件”这件事上,它比 is_file() + filetype() 更直接。本文说清它的返回值、与 stat/inode 的关系,以及实际能用来干什么。

一、函数定义与返回值
官方手册页 https://www.php.net/manual/zh/function.linkinfo.php 给出的签名:
linkinfo(string $filename): int
作用:返回指定文件的硬链接数量(inode 的 link count)。三种结果:
- 返回大于 0 的整数:文件存在,数值就是硬链接个数;普通新建文件通常是
1;被ln old new硬链接过一次则为2。 - 返回
-1:文件不存在,或路径指向的是目录(linkinfo 不用于目录)。 - 返回
0:极少数平台或权限不足时的失败值。判断失败建议写$n = linkinfo($f); if ($n < 1) { ... }。
注意它是 Unix 语义的函数。在 Windows 上普通文件恒返回 1,与是否创建过硬链接关系不强,跨平台代码不要依赖它做判断。
二、和 is_file / filetype / stat 的区别
PHP 里判断路径类型的函数很多,容易混:
file_exists($p):文件或目录存在都为 true。is_file($p):仅“是普通文件”为 true;is_link($p)只对符号链接为 true。filetype($p):返回 file/dir/link/block 等字符串。stat($p):返回数组,第 4 项(索引 3)就是硬链接数,等价于 linkinfo:stat($p)['nlink']。linkinfo($p):只要硬链接数,不给你其它信息,性能与可读性都更聚焦。
$f = '/data/www/index.php'; $n = linkinfo($f); echo $n > 1 ? "存在硬链接引用,谨慎删除" : "独占文件"; // 等价写法 $info = stat($f); echo $info['nlink'];
关键区分:硬链接(link() 创建)共享同一 inode,nlink>1;软/符号链接(symlink() 创建)是独立文件、nlink=1,用 is_link() 或 readlink() 判断。linkinfo 对符号链接本身返回 1,它不会跟踪目标。
三、实际用途
1. 安全删除前的检查。备份脚本删原文件前,先确认是否有其它硬链接指向同一 inode,避免误以为“删了就腾出空间”:
if (linkinfo($file) > 1) {
unlink($file); // 只减引用,不释放磁盘
fwrite($log, "$file unlinked, still referenced\n");
} else {
unlink($file); // 真正释放空间
}
2. 排查“删了文件磁盘没变化”的经典故障:日志被进程持有或存在硬链接时,rm 后 df 不见空间回升。用 linkinfo 或 stat -c '%h %n' 就能确认。
3. 校验增量备份结构。rsync 的 --link-dest 会把未变化文件做成硬链接,遍历一遍统计 nlink>1 的文件占比,可以粗估备份节省的空间:
$iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/backup/latest'));
$same = $total = 0;
foreach ($iter as $f) {
if (!$f->isFile()) continue;
$total++;
if (linkinfo($f->getPathname()) > 1) $same++;
}
printf("硬链接复用率 %.1f%%\n", $total ? $same / $total * 100 : 0);
4. 简易完整性检查:某些 CMS 的缓存目录被人为建了额外硬链接会引发权限混乱,安装检查里加一条 linkinfo 判断能提前发现问题。
四、注意事项与常见错误
- 不能用它判目录。目录要取子项数用
scandir();判类型用is_dir()。对目录 linkinfo 返回 -1。 - 受 open_basedir 限制:跨出白名单会报 warning 并返回 -1,用
@linkinfo()抑制或用is_readable()提前判断。 - 权限不足时返回 -1,不是 0,写代码时不要把两种失败混为一谈。
- 结果可能被 stat 缓存影响:PHP 会缓存文件状态,同一请求内刚创建硬链接后再查,需先
clearstatcache(true, $file)。 - 与之配套的函数:
link($target, $link)创建硬链接、symlink()创建软链接、readlink()读软链接目标、realpath()解析真实路径。
五、常见问题 FAQ
问:linkinfo 能替代 file_exists 吗?
答:不建议。linkinfo() 对目录也返回 -1,和“不存在”无法区分,必须搭配 is_file() 使用。
问:为什么我的普通文件返回 2?
答:说明该 inode 还有一个目录项指向它(别人 ln 过、或文件系统快照/去重机制造成)。可以用 find / -samefile 路径 找出所有硬链接。
问:NFS/SMB 挂载目录下准确吗?
答:依赖远程文件系统实现,某些挂载会统一返回 1。跨网络存储别用它做删除决策。
一句话:linkinfo 是“看 inode 被引用了几次”的窗口,日常判类型仍用 is_file/is_link,只有在硬链接、备份、磁盘释放这类场景里它才不可替代。
生产内容,同时打通搜索引擎(SEO)与AI搜索引擎(GEO)流量入口的软件! 点击进入365建站器 »
