前言
从一个命令开始我们今天的话题: vue create
通过vue create
创建项目,并使用淘宝源来安装,我们会输入如下的命令:
vue create vue-test-app -r https://registry.npm.taobao.org
首先来拆解一下这个命令
上面这个命令有4个部分组成:
- 主命令:vue
- command: create
- command 的 param: vue-test-app
- command 的 option,用来辅助命令确认在特定场景下用户的选择(可以理解为配置)
这里的 -r
是 option, -r
其实是简写,等同于 --registry
进入正题:输入这个命令后,究竟发生了什么事情?
which vue
/usr/local/bin/vue
cd /usr/local/bin/vue
ls -ll
lrwxr-xr-x 1 root wheel 39 1 5 11:08 vue -> ../lib/node_modules/@vue/cli/bin/vue.js
我们首先在查找vue
命令的位置,发现在 /usr/local/bin/vue
这个目录
进入这个目录之后,输出所有文件信息
得到了他是链接文件,链接到实际的的文件是 ../lib/node_modules/@vue/cli/bin/vue.js
链接文件,这是什么?
软链接与硬链接
注:本章内容节选自详解 Linux 中的硬链接与软链接
在开始介绍软链接和硬链接之前,我们首先介绍一下文件系统
在 Linux 文件系统中,一个文件被分成两个部分:元数据(metadata)与用户数据(user data)。
元数据为文件的附加属性,如索引节点(Inode)、文件大小、文件创建时间、文件所有者等。
「元数据中并不包含文件名,文件名仅仅是为了方便用户使用。Linux 文件系统为每一个保存在磁盘分区中的文件(无论什么类型)都分配一个索引节点号(Inode Number),索引节点号是文件在一个文件系统中的唯一标识,不同文件所对应的索引节点号是不相同的;」
用户数据,即文件数据块(data block),文件数据块中以二进制的形式记录着文件的真实内容。
软链接 ---- ln -s 源文件 链接文件
软链接(也称符号链接)可以看成是一个普通的文件, 「只不过这个文件中的数据块存放的是源文件的索引节点号。」 可以通过为ln
指令添加-s
(s: soft 的意思)选项创建软链接:
ln -s 源文件 链接文件
为 hello.txt 文件创建一个软链接:
chenkc:~$ ln -s hello.txt softlink_hello.txt
chenkc:~$ ls -il
total 675236
1837900 -rw-r--r-- 1 chenkc chenkc 36 8-р с 25 18:55 hello.txt
6705 lrwxrwxrwx 1 chenkc chenkc 9 8-р с 25 18:57 softlink_hello.txt -> hello.txt
...
源文件的索引节点号为 1837900,而软链接文件的索引节点号为 6705,显然源文件和软链接文件并不是同一个文件,其实从两个文件的大小也可以看出来,其中源文件大小为 36 个字节,而软链接文件大小仅仅为 9 个字节。
硬链接 ---- ln 源文件 链接文件
在 Linux 中允许多个文件名指向同一个索引节点号,而硬链接(hard link, 也称链接)指的是通过索引节点号进行的链接。可以通过ln
指令为文件创建硬链接:
ln 源文件 链接文件
为 hello.txt 文件创建两个硬链接:
chenkc:~$ ln hello.txt hardlink_hello.txt
chenkc:~$ ln hello.txt hardlink_hello2.txt
chenkc:~$ ls -il
total 675432
1837900 -rw-r--r-- 3 chenkc chenkc 56 8-р с 24 21:34 hello.txt
1837900 -rw-r--r-- 3 chenkc chenkc 56 8-р с 24 21:34 hardlink_hello.txt
1837900 -rw-r--r-- 3 chenkc chenkc 56 8-р с 24 21:34 hardlink_hello2.txt
...
源文件和两个硬链接文件的索引节点号都为 1837900,而索引节点号为文件的唯一标识,「因此源文件和硬链接文件是仅文件名不同的相同文件,创建文件的硬链接相当于为文件又起了一个新的文件名。」
此时的 hello.txt、hardlink_hello.txt 以及 hardlink_hello2.txt 拥有相同的索引节点号,查看文件内容也会发现为同一个文件
软链接的应用
运用软链接的知识,我们回到最初的话题,当我们输入 vue create vue-test-app
命令的时候,终端究竟在做什么
下图是我们软链的链接过程
- 终端在全局环境变量中找到
vue
命令which vue
- 终端根据
vue
命令链接到实际的文件lib/node_modules/@vue/cli
中的bin/vue.js
- 终端利用node执行
vue.js
vue.js
解析command optionsvue.js
执行command- 执行完毕,退出
总结一下:vue脚手架命令的全过程,如下图
我们接下来对这个问题进行一点深入:
1、问:为什么全局安装 @vue/cli
后,就会添加命令为 vue
?
npm install -g @vue/cli
可以查看 node_modules/@vue/cli
中的 package.json
"bin": {
"vue": "bin/vue.js"
},
在项目中安装 @vue/cli
的时候,由于 bin
的配置,会在环境变量(全局或者局部)中按照 bin
的配置生成一个软链接,例如:
/user/local/bin/vue ---> lib/node_modules/@vue/cli/bin/vue.js
2、问:为什么 vue
指向一个 js
文件,我们可以直接通过 vue
命令直接执行它?
#!/usr/bin/env node
.... // 代码块
因为文件添加了这句话告诉了系统在我们的环境变量中找到 node
命令 解析
/usr/bin/env
命令可以找到所有的命令,其中包含 node
命令
/usr/bin/env node test.js
等价于
node test.js
等价于
#!/usr/bin/env node
...
3、问:怎么实现,添加一个全局命令"test",当在终端输入"test",执行hello.js的内容
// hello.js
#!/usr/bin/env node
console.log('已经执行了hello.js')
在 /usr/local/bin
下配置,/XXX/hello.js
是这个文件的路径
ln -s /XXX/hello.js test
/usr/local/bin ls -il
total 0
6760614 lrwxr-xr-x 1 root wheel 29 1 12 19:51 test -> XXX/hello.js
然后在其他任何目录下 执行 test
就会执行 hello.js
文件
~ test
已经执行了hello.js
npm link
npm link
其实与软链接也有很大的关系,我们接下来了解一下这个命令
npm link是一种把包链接到包文件夹的方式,即:可以在不发布npm模块的情况下,调试该模块,并且修改模块后会实时生效,不需要通过npm install进行安装
从上面的vue
命令的学习中,很容易就能知道
而当我们在 npm install -g
的时候,其实是将相关文件安装在 /usr/local/lib/node_modules
目录下,同时在全局命令 /usr/local/bin
目录下会有一个映射脚本,将其指向 /usr/local/lib
下的真实文件。
同样的,npm link
做的事情也是一样,唯一的区别是,它在 /usr/local/lib
下的 node_modules
里不是存的真实的文件,而是存了一个软链接,指向你当前执行 npm link
的目录。如果开发的的是node包,则执行的命令名和真实执行的文件入口,会根据项目的 package.json
里 bin
的配置来获取。
如何使用
cd ~/projects/node-redis # go into the package directory
# 全局链接,根据node-redis目录下package.json中的bin的配置
#生成一个软链接,指向~/projects/node-redis目录
#然后全局都可以使用命令redis
npm link
# 进入另一个目录,这个目录依赖安装包 node-redis
cd ~/projects/node-bloggy
# 会在当前目录的node_modules下生成一个软链接,指向redis,redis也是一个软链接,指向~/projects/node-redis
npm link redis # link-install the package
这样就能实现当修改node-redis
包,不需要重新安装,依赖这个包的 node-bloggy
也能实时生效了
取消链接
cd ~/projects/node-bloggy
npm unlink redis
cd ~/projects/node-redis
npm unlink
lerna link
// lerna link 源码
function createSymlink(src, dest, type) {
log.silly("createSymlink", [src, dest, type]);
if (process.platform === "win32") {
return createWindowsSymlink(src, dest, type);
}
return createPosixSymlink(src, dest, type);
}
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));
}
简单看一下源码:
使用 fs.symlink
创建软链接,& chmod等等
内部其实还是这一套 npm link
fs.symink
在 node 中,我们可以使用方法 fs.symink(target, path)
建立软链接(符号链接),没有直接的方法建立硬链接(就算通过子进程的方式直接指向 shell 命令也不能跨平台)
总结
软链硬链在很多地方都有应用,例如:软链接应用之快捷方式,硬链接应用之文件多人共享等等,大家可以多多挖掘。