写点什么

五分钟了解 Node.js Shebang

  • 2020-09-11
  • 本文字数:2018 字

    阅读完需:约 7 分钟

五分钟了解 Node.js Shebang

本文最初发布于 Medium 网站,经原作者授权由 InfoQ 中文站翻译并分享。



JavaScript是一种解释性语言,需要将其源代码提供给某些解释器才能运行。如果要使用Node.js运行 JavaScript 文件,通常会运行以下命令:


$ node yourfile.js
复制代码


输入解释器(node)的名称后,你就明确告诉了外壳如何运行脚本。


但是这些知识可以放在脚本本身中,这样就可以像运行二进制文件一样直接运行它:


$ ./yourfile.js
复制代码


仅当你对该文件有执行权限(例如,可以使用 chmod u+x yourfile.js 设置)并设置了正确的“Shebang”时,此方法才有效。

Shebang

Shebang 或 hashbang(#!代码的英文发音)是文件的第一行,它告诉 OS 使用哪个解释器。它通常看起来像这样:


#!/absolute/path/to/the/interpreter [optional params]
复制代码


Shebang 是一项操作系统特性,可用于运行任何解释语言:Python、Perl 等。对于 Node.js,它可以(但通常不会)看起来像这样:


#!/usr/bin/node
复制代码


只有 Shebang 在文件的第一行时,Node.js 才会高兴地将其忽略为注释(即使它前面有空行或//comment 行也不会起作用)。浏览器也会将其忽略(Chrome74+,FF67+)。


多数人在/usr/bin/node 上都有一个 Node.js 二进制文件或符号链接。如果 Node.js 不在/usr/bin/node 上,操作系统就会抱怨了。例如 bash 会说 bad interpreter: No such file or directory script won’t execute。但有没有办法告诉操作系统使用 Node.js 运行脚本,而不用在乎它安装在哪里呢?


#!node是没用的,因为 Shebang 需要绝对路径。

认识一下 env 吧

env 主要用于在修改后的环境中运行命令。这里的重点是“命令”,因为 env 几乎总是位于/usr/bin/env,而“命令”可以是 PATH 上的任何内容。


如果我们不是写/usr/bin/node 而是写/usr/bin/env node,我们就会告诉 OS 运行 env,而 env 将运行 node,最后 node 将依次执行脚本。

简单来说

这是 Node 脚本最常见的 Shebang:


#!/usr/bin/env node
复制代码


但是,env 还可以使用其他一些技巧。

将参数传递给 Node.js

将-S 选项传递给 env 会使它解析之后发生的一切,从而打开一扇新的大门:将参数传递给命令。


例如,假设我们要运行带有特殊标志的 node,以在运行当前文件时启用 ESM 模块。我们可以使用这个 Shebang:


#!/usr/bin/env -S node --experimental-module
复制代码


再举一个例子:如果我们想在运行当前脚本之前运行另一个脚本,可以使用 Node 的-r 选项:


#!/usr/bin/env -S node -r ./my/other/file.js
复制代码


或打开检查口:


#!/usr/bin/env -S node --inspect
复制代码


请注意,如果你运行诸如 nodeyourfile.js 之类的脚本,Node.js 将不会尝试解析 Shebang 中的参数,而只会忽略它。内核在运行文件之前使用 Shebang 来确定如何运行它。

设置环境变量

还记得我们说过 env 可以在修改后的环境中运行命令吗?实际上这就是它名称的来源,而且它的功能非常强大。假设我们希望脚本以生产模式运行,我们可以设置 NODE_ENV 环境变量:


#!/usr/bin/env -S NODE_ENV=production node
复制代码


否则,运行脚本时 NODE_ENV 将为 undefined 或使用用户终端的设置。


Node.js支持许多环境变量。例如,我们可以使用 NODE_OPTIONS 传递下列 CLI 标志:


#!/usr/bin/env -S NODE_OPTIONS=--experimental-modules node
复制代码

从一个空环境开始

如果我们希望脚本在运行时不访问用户终端上的任何环境变量,则可以使用-i 标志来运行它,该标志代表“忽略环境”:


#!/usr/bin/env -S -i node
复制代码


符号-相当于-i,所以我们也可以这样写:


#!/usr/bin/env -S - node
复制代码

强制禁用 DEBUG

也许我们不想清除所有环境变量,但要屏蔽其中一些。例如 DEBUG(如果你使用的是流行的 debug 包)。也许我们不希望脚本用户将 DEBUG 作为脚本运行时设置标志。那么我们使用-u 标志代表未设置的环境变量。


#!/usr/bin/env -S -u=DEBUG - node
复制代码


如果用户以DEBUG=* ./yourfile.js运行脚本,他们将看不到任何调试信息,但你还是可以用DEBUG=* node ./yourfile.js运行脚本,从而看到 DEBUG 输出。

锁定 Node.js 运行时版本

有时你想锁定用于运行脚本的 node 版本。在 NPM@3 之前,我们可以使用 engineStrict,但是该功能已移除,现在我们只能在package.json中设置engines,它可能位于脚本旁边也可能不在,取决于 engine-strictconfig 配置标志的设置。


但是有一种更简单的方法。由于 node 也是 NPM 包,并且 npx 允许运行任何 NPM 包,因此你可以编写:


#!/usr/bin/env -S npx node@6
复制代码


这可能会在运行脚本后尝试下载请求的 Node 版本(因此,如果 NPX 缓存中不存在所请求版本的 Node,则无法在没有互联网连接的情况下运行)。


提示:你可以使用 process.version 检查节点版本

使用 TypeScript 运行它

没有规则说我们必须运行 node。假设TypeScript和 TS Node 全局可用(npm -i g typescript ts-node),我们可以指定 ts-node 作为解释器:


#!/usr/bin/env ts-node
复制代码


并让它作为 TypeScript 程序运行文件。


在这些示例中,文件都可以使用.js 扩展名或你喜欢的其他任何文件类型,甚至可以没有扩展!


原文链接:《Node Shebang》


2020-09-11 09:575307

评论

发布
暂无评论
发现更多内容

Vue3 Composition API如何替换Vue Mixins

源字节1号

前端开发 小程序开发

比Postman更适合国人的接口调试工具

伤心的辣条

程序员 自动化测试 接口测试 Python自动化 程序员程序人生

Android ShapeableImageView使用详解,告别shape、三方库

yechaoa

android 6月月更 material design ShapeableImageView

【Java Web系列】Cookie的原理分析和使用细节

倔强的牛角

Java javaWeb Cookie 6月月更

Archiva 运行时提示 JAXBException 错误

HoneyMoose

G1收集器概述

Nick

Java GC G1垃圾回收器 6月月更 Garbage-First Collector

Python代码自动提取Win10内置的锁屏壁纸

宇宙之一粟

Python 6月月更

浅谈隐私计算与数据安全

I

学习笔记 数据安全 隐私计算 可信安全计算

【愚公系列】2022年06月 通用职责分配原则(一)-信息专家原则

愚公搬代码

6月月更

leetcode 310. Minimum Height Trees 最小高度树(中等)

okokabcd

LeetCode 搜索 数据结构与算法

攻防演练中六条安全体系建议

穿过生命散发芬芳

6月月更 攻防演练

改造微服务的三个时机

阿泽🧸

微服务 6月月更

架构实战营模块 8 作业

热猫

线程的创建方法

卢卡多多

线程池 线程安全 6月月更

读书笔记之:认知觉醒

甜甜的白桃

读书 书单 阅读 6月月更

MobX 获取网络数据来渲染酷炫的曲线

岛上码农

flutter ios 前端 安卓 6月月更

模块四(千万级学生管理系统的考试试卷存储方案)

Geek_701557

flutter系列之:flutter中常用的ListView layout详解

程序那些事

flutter 程序那些事 6月月更

人人都在搞数据治理

奔向架构师

数据治理 数据管理 6月月更

【最佳实践】修改Anaconda中的Jupyter Notebook默认工作路径

迷彩

Python Anaconda Jupyter Notebook 6月月更

推荐的十个Flutter插件

坚果

6月月更

黄硕:百度飞桨文心大模型在语音文本审核中的应用

声网

RTC Dev Meetup 生态专栏 语音处理

前端uni框架学习day_2

恒山其若陋兮

前端 6月月更

spring4.1.8扩展实战之三:广播与监听

程序员欣宸

Java spring Spring Framework 6月月更

Camtasia2022全新版功能详情讲解

茶色酒

Camtasia Studio2022

NodeJS 5分钟 连接MySQL 增删改查 🥇

德育处主任

node.js MySQL 6月月更

【sql语句基础】——查(select)(合并查询+连接查询)

写代码两年半

sql 查询 MySQL 数据库 数据库· 6月月更

物联网低代码平台如何查询授权信息?

AIRIOT

物联网 低代码开发

【涨姿势】你没用过的BadgeDrawable

yechaoa

android 6月月更 material design BadgeDrawable

Docker常用命令总结

乌龟哥哥

6月月更

数组(二)

Jason199

数组 js 数组操作 6月月更

五分钟了解 Node.js Shebang_语言 & 开发_Alex Ewerlöf_InfoQ精选文章