您现在的位置: 365建站网 > 365文章 > linkinfo 函数有什么用?PHP 判断硬链接数量与 stat 用法对比

linkinfo 函数有什么用?PHP 判断硬链接数量与 stat 用法对比

文章来源:365jz.com 点击数:11 更新时间:2024-12-09 11:32

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

PHP linkinfo 函数 判断硬链接

一、函数定义与返回值

官方手册页 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建站器 »