inode
在解说软 / 硬链接之前,先理解一个 linux 零碎中重要的概念 inode。家喻户晓,文件存储在硬盘上,硬盘的最小存储单位叫做 “ 扇区 ”(Sector, 每个扇区存储 512 字节). 操作系统读取硬盘的时候,不会一个个扇区地读取,因为这样效率太低,而是一次性间断读取多个扇区, 这种一次性读取的间断多个扇区就是 ” 块 ”(block)。这种由多个扇区组成的 ” 块 ”,是文件存取的最小单位。” 块 ” 的大小,最常见的是 4KB,即间断八个 sector 组成一个 block。
文件数据都贮存在 “ 块 ” 中,那么很显然,前端培训咱们还必须找到一个中央贮存文件的元信息,比方文件的创建者、文件的创立日期、文件的大小等等。这种贮存文件元信息的区域就叫做 inode,中文译名为 “ 索引节点 ”。
留神:咱们关上一个一个文件时,零碎首先找到文件名对应的 inode 号码,而后通过 inode 号码获取 inode 信息,而后依据 inode 信息中的文件数据所在 block 读出数据。
上述概念的文章内容比拟多,不太容易记忆,看图!
inode 中包含了哪些内容?
inode 蕴含文件的元信息,具体来说有以下内容:
- 文件的字节数
- 文件拥有者的 User ID
- 文件的 Group ID
- 文件的读、写、执行权限
- 文件的工夫戳,共有三个:ctime 指 inode 上一次变动的工夫,mtime 指文件内容上一次变动的工夫,atime 指文件上一次关上的工夫。
- 链接数,即有多少文件名指向这个 inode
- 文件数据 block 的地位
linux 命令如何获取一个文件的 inode 信息
能够间接应用 linux 命令 stat 查看某个文件的 inode 信息
stat example.js
输入信息
koala node % stat example.js
16777223 11904170 -rw-r–r– 1 koala staff 0 0 “Mar 24 13:46:08 2021” “Mar 24 13:46:08 2021” “Mar 24 13:46:26 2021” “Mar 24 13:46:08 2021” 4096 0 0x40 example.js
Node.js 中如何获取一个文件的 inode 信息
在 Node.js 中,fs 提供了 stat 函数查看相干信息
fs.statSync(‘./example.js’);
输入信息
文件信息 Stats {
dev: 16777223,
mode: 33188,
nlink: 1,
uid: 501,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 11904170,
size: 0,
blocks: 0,
atimeMs: 1616564768255.48,
mtimeMs: 1616564768255.48,
ctimeMs: 1616564786778.5532,
birthtimeMs: 1616564768255.48,
atime: 2021-03-24T05:46:08.255Z,
mtime: 2021-03-24T05:46:08.255Z,
ctime: 2021-03-24T05:46:26.779Z,
birthtime: 2021-03-24T05:46:08.255Z
}
每一个 inode 都有一个惟一的标识码,下面的输入信息中 ino 就是 inode 的惟一标识码,在 linux 零碎外部应用 inode 的标识码来辨认文件,并不应用文件名。之前系的
在 linux 零碎中,目录也是一种文件。目录文件蕴含一系列目录项,每一个目录项由两局部组成:所蕴含文件的文件名,以及文件名对应的 inode 标识码。咱们能够应用 ls -i 来列出目录中的文件以及所有的 inde 标识码。这里也能够解释可能小伙伴们感觉说不通的问题,仅批改目录的读权限,并不能实现读取目录下所有文件内容的起因,最初须要通过递归目录下的文件来进行批改。
软链接与硬链接
什么是软链接 (soft link, 也叫符号链接)
软链接相似于 Window 中的“快捷方式”。创立软链接会创立一个新的 inode,比方为文件 a 创立了软链接文件 b,文件 b 外部会指向 a 的 inode。当咱们读取文件 b 的时候,零碎会主动导向文件 a,文件 b 就是文件 a 软连贯(或者叫符号链接)。
• 拜访:创立了软链接后咱们就能够应用不同的文件名拜访雷同的内容,
• 批改:批改文件 a 的内容,文件 b 的内容也会产生扭转,对文件内容的批改向放映到所有文件。
• 删除:当咱们删除源文件 a 时,在拜访软连贯文件 b 是,会报错 “No such file or directory”
能够间接应用 linux 命令 ln -s source target 来创立软链接 (留神:示意 target “ 指向 ” source)
ln -s ./target/a.js b.js
执行 shell 命令后,会呈现 b.js 文件,软链接创立胜利。
Node.js 中创立软链接
根底用法
Node.js 官网文档提供了 symlinkSync 函数创立软链接。
fs.symlinkSync(target,path,type)
target <string> | <Buffer> | <URL> // 指标文件
path <string> | <Buffer> | <URL> // 创立软链对应的地址
type <string>
它会创立名为 path 的链接,该链接指向 target。type 参数仅在 Windows 上可用,在其余平台上则会被疏忽。它能够被设置为 ‘dir’、‘file’ 或 ‘junction’。如果未设置 type 参数,则 Node.js 将会自动检测 target 的类型并应用 ‘file’ 或 ‘dir’。如果 target 不存在,则将会应用 ‘file’。Windows 上的连接点要求指标门路是绝对路径。当应用 ‘junction’ 时,target 参数将会主动地标准化为绝对路径。
• 应用示例
const res = fs.symlinkSync(‘./target/a.js’,’./b.js’);
这段代码的意思是为 创立一个软链接 b.js 指向了文件 ./targert/a.js, 当 a.js 中的内容发生变化时,b.js 文件也会产生雷同的扭转。
⚠️留神:如果对目录创立软链接,办法中第三个参数须要传 ’dir'(尽管第三个参数只在 windows 下失效,这样传递能够确保跨平台不会呈现问题): fs.symlink(target,path,’dir’)
下面解说了 linux 和 Node.js 创立软链接的两种形式,认真看的小伙伴可能发现问题,为什么 Node.js 中 fs.symlink(target,path) 和 shell 命令中的 ln -s source target 两个参数如同是反的呢,是不是会有这样的疑难?
其实如果后面的小例子你都尝试了,会发现前面传递的两个参数程序理论是统一的,都是让前面新建的的 ” 指向 =>” 后面的哦!
什么是硬链接 (hard link)
个别状况,一个文件名 ” 惟一 ” 对应一个 inode。然而 linux 容许多个文件名都指向同一个 inode。示意咱们能够应用不同对文件名拜访同样的内容;对文件内容进行批改将放映到所有文件;删除一个文件不影响另一个文件对拜访。这种机制就被称为 ” 硬链接 ”
硬链接的创立
能够间接应用 linux 命令 ln source target 来创立硬链接(留神:source 已存在的文件,target 是将要建设的链接)
ln ./target/a.js c.js
执行 shell 命令后,会呈现 c.js 文件,硬链接创立胜利。
与软连贯不同,只能给文件建设硬链接,不能给目录建设硬链接。并且 source 文件必须存在,否则创立硬链接时会报错。
删除一个文件不会影响另一个文件的拜访。起因是什么?实际上,文件 inode 中还有一个链接数的信息,每多一个文件指向这个 inode,该数字就会加 1,每少一个文件指向这个 inode,该数字就会减 1,当值减到 0,零碎就主动回收 inode 及其对应的 block 区域。很像是一种援用计数的垃圾回收机制。
当咱们对某个文件建设了硬链接后,对应的 inode 的链接数会是 `2(原文件自身曾经有一个指向),当删除一个文件时,链接数变成 1
,并没达到回收的条件,所以咱们还是能够拜访文件。
软链接与硬链接比照剖析总结
- 应用 ln source target 建设硬链接;应用 ln -s source target 建设软链接
- 硬链接不会创立额定 inode,和源文件共用同一个 inode;软链接会创立额定一个文件(额定 inode),指向源文件的 inode
- 建设硬链接时,source 必须存在且只能是文件;建设软链接时,source 能够不存在而且能够是目录
- 删除源文件不会影响硬链接文件的拜访(因为 inode 还在);删除源文件会影响软链接文件的拜访(因为指向的 inode 曾经不存在了)
- 对于曾经建设的同名链接,不能再次建设,除非删掉或者应用 -f 参数
利用场景
npm link
npm link 的原理也是通过软链来实现的。当咱们想要调试本地开发的 npm 模块包(还没有公布或者批改了一些内容) 时,须要应用 npm link 来进行调试 举个例子:
有两个我的项目 create-mono-repo 和 create-mono-repo-testCli 在 create-mono-repo 我的项目节点下执行 npm link 胜利后 , 在 create-mono-repo-testCli 我的项目目录下执行 npm link create-mono-repo 这样就能够实现调试了
lerna
lerna 创立的我的项目, packages 目录下各模块相互依赖也是基于 fs.symlinkSync 创立软链接实现的。
具体实现代码和地址如下:
function createSymbolicLink(src, dest, type) {
log.silly(“createSymbolicLink”, [src, dest, type]);
return fs
.lstat(dest)
.then(() => fs.unlink(dest))
.catch(() => {/* nothing exists at destination */})
.then(() => fs.symlink(src, dest, type));
}