符号链接(Symbolic)、package.json的bin属性与Shebang

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:以全局方式安装的npm包,如在解释这些问题前,先了解下linux上文件执行相关内容,会更容易理解些最开始接触shell时,一般会提及shell脚本文件的不同执行方式。先创建有一条简单命令的shell脚本文件

以全局方式安装的npm包,如 gulpwebpack 等为什么可以像 mkdircopy 这样的 shell 命令(或程序)一样,在任何文件夹都可以通过命令行调用?跟环境变量又有什么关系?什么是符号链接?

在解释这些问题前,先了解下 linux 上文件执行相关内容,会更容易理解些

◎ Linux文件执行的方式

最开始接触shell时,一般会提及shell脚本文件的不同执行方式。先创建有一条简单命令的shell脚本文件 hello.sh

echo "hello world"
复制代码
  • 一种方式是,直接运行shell解释器,把脚本名作为解释器命令的参数
/bin/sh hello.sh 
# or /bin/zsh hello.sh or zsh hello.sh
hello world
复制代码

其中 /bin/sh/bin/zsh 为系统支持的不shell类型,直接使用zsh、sh也是等效的,因为shell会根据环境变量($PATH)路径找到相应的 /bin/sh/bin/zsh

  • 另一种方式,现在hello.sh做一点小改变
#! /bin/zsh
echo "hello world"
复制代码

改好之后,需要先让hello.sh文件具有执行权限,因为会直接使用hello.sh执行,否则会报 permission denied 的错误(即没有执行权限)。拥有执行权限后,就可以这样执行了

>> ./hello.sh   # ro /path/to/hello.sh
hello world
复制代码

实际上,现在依然可以使用 /bin/sh hello.sh 的形式来执行。问题是,为什么加了 #! /bin/zsh 后可以 ./hello.sh 这样执行呢?

#! /bin/zsh 这行有个术语,叫 Shebang (or Hashbang),是shell脚本的标准起始行, #! 后面是指定解释器的绝对路径。它由shell程序解析,作用是告诉shell程序使用 #! 后面路径指定的解释器来执行本文件,并把当前文件作为解释器的参数。所以 ./hello.sh 作用与 /bin/zsh hellow.sh (或 /bin/zsh $PWD/hello.sh )等效。

◎ 执行js文件

执行shell脚本的方式,同样适用js文件和其他文件的执行,只要指定相应的解释程序(即程序命令)。如一个简单的node文件, hello.js

console.log('hello world!')
复制代码

可以这样执行(已经安装了node)

>> node hello.js
hello world! 
# or 
>> /usr/local/bin/node hello.js 
# 根据不同系统,可能node命令的路径不一样,这里使用的是Mac 
hello world!
复制代码

也可以使用使用Shebang的方式, hello.js 增加一行,告诉shell程序,用node解释器执行该文档,并给文件增加执行权限

#! /usr/local/bin/node
console.log('hello world!')

// 第一行也可以这样
// #! /usr/bin/env node 
// 跟上面的区别是,会使用最先出现在环境变量的node解释器
复制代码

就可以这样执行

>> ./hello.js # or $PWD/hello.js
hello world!
复制代码

既然可以使用 ./hello.sh(./hello.js) 直接执行文件,那是否可以使用 hello.sh(hello.js) 来直接执行呢?当然是可以的。

一个方式就是把当前目录下的hello.js 移动到当前环境变量的任一目录下(使用echo $PATH 查看当前配置的环境变量)或者把当前目录添加进环境变量,这样就可以直接test.js来执行了,因为shell可以通过环境变量目录检索到test.js这个文件,不仅可以在当前目录直接使用,也可以在其他任何目录使用,跟其他命令一样。 当然这并不是推荐的做法,而且确实不好。

更好的方式是使用 符号链接 (Symbolic link)

◎ 符号链接与package.json的bin字段

符号链接 (Symbolic link)或软链接,是一种特殊的文件,包含一条以绝对路径或相对路径形式指向其他文件或目录的引用,跟快捷方式的功能类似。继续以hello.js作为示例

上面谈到,为了能直接使用文件名hello.js的方式执行,一种方式是让文件处于shell程序通过环境变量可检索到的目录内;另一种即是通过对文件建立符号链接的方式,使用ln命令

  • 创建符号链接
# 创建symbolic命令语法,-s为创建symbolic链接
# ln -s /path/to/file /path/to/symbolic 
ln -s $PWD/hello.js /usr/local/bin/hello.js
复制代码

这里把符号链接文件放入环境变量路径下面,这样在当前用户任意目录下面,都可以通过hello.js命令执行,当然,如果符号链接不在环境变量下,则执行方式还是一样的./hello.js。 符号链接的名字是可以随意的,只要不与现有符号链接重名就好

# 创建全局的符号链接后
>> hello.js
hello world!
# 改为其他名字 
>> ln -s $PWD/hello.js /usr/local/bin/hello
>> hello
hello world!
复制代码
  • 删除符号链接 删除符号链接的方式与删除文件一样,只是删除符号文件,对原文件没有影响
rm /usr/local/bin/hello
复制代码
  • packge.json的bin字段

    有了以上关于符号链接、文件执行、环境变量相关的概念。则npm包命令的执行就很好理解了。以全局方式安装的npm包,npm会在安装的时候在 /usr/local/bin/ 目录(一般会在环境变量里面)下面创建bin字段所指定的symbolic,如package.json的bin配置为

{ "bin" : { "myapp" : "./cli.js" } }
复制代码

则会创建 /usr/local/bin/myapp 符号链接指向可执行的cli.js。如果是以本地方式安装,则会在项目下的 node_modules/.bin/myapp 下面创建符号链接(这个只能再 node_modules/.bin 目录下通过 ./myapp 方式执行)。myapp命令执行的其实是cli.js,且官方也要求需要写 Shebang#! /use/bin/env node ,指定解释器为node

参考:


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ant Colony Optimization

Ant Colony Optimization

Marco Dorigo、Thomas Stützle / A Bradford Book / 2004-6-4 / USD 45.00

The complex social behaviors of ants have been much studied by science, and computer scientists are now finding that these behavior patterns can provide models for solving difficult combinatorial opti......一起来看看 《Ant Colony Optimization》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具