通常需要由解释器执行的脚本在顶部都会有shebang line,以告诉操作系统如何执行它们。
如果你有一个名为foo
的脚本,其第一行为#!/bin/sh
,系统将读取该行并执行相当于/bin/sh foo
的命令。因此,大多数解释器被设置为接受脚本文件名作为命令行参数。
#!
后面的解释器名称必须是完整路径;操作系统不会搜索$PATH
来查找解释器。
如果你有一个要由node
执行的脚本,显然编写第一行的方法是:
#!/usr/bin/node
但是如果在/usr/bin中未安装node命令,则无法正常工作。
一个常见的解决方法是使用env命令(这并不是真正的目的):
#!/usr/bin/env node
如果您的脚本名为
foo
,操作系统将执行等效于以下内容的操作:
/usr/bin/env node foo
“env”命令执行其命令行上给定的另一个命令,并将任何后续参数传递给该命令。这里使用“env”的原因是,“env”将在“$PATH”中搜索命令。因此,如果“node”安装在“/usr/local/bin/node”中,并且您的“$PATH”中有“/usr/local/bin”,则“env”命令将调用“/usr/local/bin/node foo”。
“env”命令的主要目的是使用修改后的环境(添加或删除指定的环境变量)执行另一个命令。但是,如果没有其他参数,它只会使用未更改的环境执行该命令,在这种情况下,这就是您所需要的。
这种方法存在一些缺点。大多数现代类Unix系统都有
/usr/bin/env
,但我曾经在旧的系统上工作过,在那里
env
命令安装在不同的目录中。使用此方法可能存在对传递的附加参数的限制。如果用户
没有包含
$PATH
中的
node
命令所在的目录,或者有一些名为
node
的不同命令,则可能会调用错误的命令或根本无法工作。
其他方法包括:
- 使用一个
#!
行,指定node
命令本身的完整路径,并根据需要更新脚本以适应不同的系统;或者
- 将你的脚本作为参数调用
node
命令。
另请参见
这个问题(以及
我的答案), 以了解更多关于
#!/usr/bin/env
的讨论。
顺便提一下,在我的系统上(Linux Mint 17.2),它被安装在
/usr/bin/nodejs
。根据我的笔记,在Ubuntu 12.04和12.10之间,它从
/usr/bin/node
更改为
/usr/bin/nodejs
。除非您设置符号链接或类似的东西,否则
#!/usr/bin/env
技巧无法解决这个问题。更新:mtraceur的评论说(重新格式化):
A workaround for the nodejs vs node problem is to start the file with
the following six lines:
#!/bin/sh -
':' /*-
test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
test2=$(node --version 2>&1) && exec node "$0" "$@"
exec printf '%s\n' "$test1" "$test2" 1>&2
*/
This will first try nodejs
and then try node
, and only
print the error messages if both of them are not found. An explanation
is out of scope of these comments, I'm just leaving it here in case it
helps anyone deal with the problem since this answer brought the
problem up.
我最近没有使用NodeJS。希望自我发布此回答以来,nodejs
与node
的问题已得到解决。在Ubuntu 18.04上,nodejs
软件包将/usr/bin/nodejs
安装为指向/usr/bin/node
的符号链接。在早期的某些操作系统(Ubuntu或Linux Mint,我不确定),有一个名为nodejs-legacy
的软件包,它提供了将node
作为指向nodejs
的符号链接。不能保证我对所有细节都正确。
node
。 - Marc Bnpm
将Node.js源脚本安装为(可能是全局可用的)_CLI_,你必须使用shebang行 -npm
甚至会在Windows上使其工作;请参见我再次更新的答案。 - mklement0