linux - #!/usr/bin/env

本文深入探讨了Linux脚本中使用#!/usr/bin/env与直接指定解释器路径的优劣,解析了env如何提高脚本的灵活性和兼容性,尤其是在多版本解释器共存的情况下的优势。

Description

在linux的一些脚本,需在开头一行指定脚本的解释程序

#!/usr/bin/env bash           #lends you some flexibility on different systems

#!/usr/bin/bash               #gives you explicit control on a given system of what executable is called
#!/usr/bin/env python         #这种用法是为了防止操作系统用户没有将python装在默认的/usr/bin路径里。
                              #当系统看到这一行的时候,首先会到env设置里查找python的安装路径,再调用对应路径下的解释器程序完成操作。

#!/usr/bin/python            #告诉操作系统执行这个脚本的时候,调用/usr/bin下的python解释器;
#!/usr/bin/env -S -P /usr/local/bin:/usr/bin:${PATH} perl  
                               #加上-P参数来指定一些目录去寻找perl这个程序, 
                               #在/usr/local/bin和/usr/bin和PATH变量中定义的目录下寻找perl。 

手册的定义

env - run a program in a modified environment

 

Distinguish

脚本用env启动的原因,是脚本解释程序在linux中可能被安装于不同的目录,env可以在系统的PATH目录中查找。同时,env还规定一些系统环境量。 而如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题。

 

Advantage & Disadvantage

  • 在某些情况下,第一个可能是首选(如运行python脚本与多个版本的python,而不必重做可执行);但是在以安全性为重点的情况下,后者将是首选,因为它限制了代码注入的可能性。
  • 这跟linux系统里安装python的目录有关。#!/usr/bin/python相当于写死了python路径;#!/usr/bin/env python会去环境设置寻找python目录,推荐这种写法。
  • “ #!/usr/bin/env bash”  的好处是可以查找当前环境中程序的默认版本。这样,您不必在系统上的特定位置查找它,因为这些路径可能位于不同系统上的不同位置,只要它在你的路径上,你就会找到它。
  • 一个缺点是如果你想支持Linux,你将无法传递多个参数(例如你将无法编写/usr/bin/env awk -f),如POSIX is vague关于如何解释这一行,并且Linux在第一个空格之后解释所有内容以表示单个参数。您可以在某些版本的env上使用/usr/bin/env -S来解决这个问题,但随后脚本将变得更不便携,并且在相当近期的系统上中断(例如,如果不是更晚的话,甚至是Ubuntu 16.04)。
  • 另一个缺点是,由于您没有调用显式可执行文件,因此可能存在错误,并且存在多用户系统安全问题(例如,如果有人设法在您的路径中获取名为bash的可执行文件)。
  • “ #!/usr/bin/env bash” is definitely better because it finds the bash executable path from your system environment variable.
  • ” #!/usr/bin/bash”  searches PATH for bash, and bash is not always in /bin, particularly on non-Linux systems. For example, on my OpenBSD system, it's in /usr/local/bin, since it was installed as an optional package.
  • If you are absolutely sure bash is in /bin and will always be, there's no harm in putting it directly in your shebang—but I'd recommend against it because scripts and programs all have lives beyond what we initially believe they will have.

 

Operation

env -- It will print all your environment variables.

env python -- 发现可以进到python的shell里面。因此,脚本语言的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它。

​​env bash / echo $BASH -- It will print your bash path (according to the environment variable list) that you should use to build your correct shebang path in your script.

 

Reference

Why is #!/usr/bin/env bash superior to #!/bin/bash?

 

<think>我们正在处理一个关于在npm脚本中传递多个参数的问题,用户的问题是关于在package.json的scripts中如何传递多个参数。 之前的回答已经详细介绍了如何使用`--`分隔符传递位置参数、键值对参数、处理复杂参数以及跨平台注意事项等。 现在用户的新输入是:`#! /usr/bin/env node`,这看起来像是一个shebang行,通常用于指定脚本的解释器。 但是,结合上下文,用户可能是在问如何在一个Node.js命令行工具(使用shebang指定用node执行)中处理多个参数。 因此,我们需要解释如何在Node.js脚本中解析传递的多个参数,特别是当这个脚本被npm run调用时。 注意:用户的问题可能是在问,当在package.json的scripts中配置了一个使用shebang的Node.js脚本时,如何传递多个参数。 例如,假设package.json中有: "scripts": { "myscript": "./myscript.js" } 而myscript.js的开头有:`#! /usr/bin/env node` 那么,当运行`npm run myscript -- arg1 arg2`时,在myscript.js中如何获取这些参数? 所以,回答应该包括: 1. 在Node.js脚本中,通过`process.argv`数组获取参数。 2. 注意`process.argv`的前两个元素是node的路径和脚本的路径,所以实际参数从第三个元素开始(即索引2)。 3. 如果使用npm run并传递参数,需要加上`--`,这样npm才会把后面的参数传递给脚本。 另外,也可以提到使用参数解析库如minimist、yargs等。 最后,按照要求,在回答后提出3-5个相关问题。 注意:用户的问题只有一行`#! /usr/bin/env node`,可能是在问关于这个shebang行与参数传递的关系,或者如何在这种脚本中接收参数。 因此,我们这样回答:</think>### Node.js Shebang (`#! /usr/bin/env node`) 解析与使用指南 #### 核心作用 `#! /usr/bin/env node` 是 Unix/Linux 系统的 **shebang 指令**,用于: 1. **指定脚本解释器**:告知系统使用 Node.js 执行该脚本 2. **跨平台兼容**:通过 `env` 在系统 PATH 中动态查找 `node` 可执行文件 3. **直接执行权限**:配合 `chmod +x` 可直接运行脚本(无需显式调用 `node`) #### 典型使用场景 ```javascript // 示例:cli-tool.js #!/usr/bin/env node console.log("参数列表:", process.argv.slice(2)); ``` #### 配置步骤 1. **创建可执行文件** ```bash touch my-cli && chmod +x my-cli ``` 2. **配置 package.json** ```json { "name": "my-cli", "bin": { "mycmd": "./my-cli" // 关键配置 } } ``` 3. **全局安装使用** ```bash npm install -g . # 本地安装测试 mycmd arg1 --flag=value ``` #### 参数处理技巧 - **获取参数**:`process.argv` 数组(索引0: node路径, 索引1: 脚本路径, 索引2+:用户参数) - **高级解析**: ```javascript const args = require(&#39;minimist&#39;)(process.argv.slice(2)); console.log(args._); // 位置参数 console.log(args.flag); // 命名参数 ``` #### 常见问题解决 1. **权限错误** (EACCES) ```bash sudo chmod 755 /usr/local/bin/mycmd # 修复权限 ``` 2. **Windows 兼容问题** - 需通过 `npm i -g` 安装,不要直接复制文件 - 使用 [win-node-env](https://www.npmjs.com/package/win-node-env) 兼容包 3. **ENOENT 错误** ```bash # 确保文件首行无空格或BOM sed -i &#39;1s/^\xEF\xBB\xBF//&#39; my-cli # 移除UTF-8 BOM ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vanci587

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值