![通用 Node.js shebang?](https://linux22.com/image/29059/%E9%80%9A%E7%94%A8%20Node.js%20shebang%EF%BC%9F.png)
Node.js这些天很受欢迎,我一直在用它写一些脚本。不幸的是,兼容性是一个问题。正式地,Node.js 解释器应该被称为node
,但 Debian 和 Ubuntu 提供了一个名为 的可执行文件nodejs
。
我想要 Node.js 可以在尽可能多的情况下使用的可移植脚本。假设文件名是foo.js
,我真的希望脚本以两种方式运行:
./foo.js
node
如果或nodejs
位于 中,则运行脚本$PATH
。node foo.js
还运行脚本(假设解释器被调用node
)
笔记:xavierm02 和我自己的答案是多语言脚本的两种变体。我仍然对纯粹的 shebang 解决方案感兴趣(如果存在的话)。
答案1
我想出的最好的办法是这个“两行 shebang”,它实际上是一个多语言(Bourne shell / Node.js)脚本:
#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"
console.log('Hello world!');
显然,第一行是 Bourne shell shebang。 Node.js 会绕过它找到的任何 shebang,因此就 Node.js 而言,这是一个有效的 javascript 文件。
:
第二行使用参数调用 shell no-op //
,然后使用该文件的名称作为参数执行nodejs
or 。用来代替便携性。命令替换语法并不严格是 Bourne,因此如果您在 20 世纪 80 年代运行此命令,请选择反引号。node
command -v
which
$(...)
Node.js 只是评估 string ':'
,这就像一个无操作,并且该行的其余部分被解析为注释。
文件的其余部分只是普通的旧 JavaScript。子 shell 在exec
第二行完成后退出,因此 shell 永远不会读取文件的其余部分。
感谢 xavierm02 的灵感以及所有评论者提供的更多信息!
答案2
这只是基于 Debian 的系统上的一个问题,在该系统上策略克服了意义。
我不知道Fedora什么时候提供了一个名为nodejs的二进制文件,但我从未见过它。该软件包称为nodejs,它安装一个名为node.js 的二进制文件。
只需使用符号链接将常识应用到基于 Debian 的系统,然后您就可以使用理智的 shebang。无论如何,其他人都会使用 sane shebangs,所以你将需要该符号链接。
#!/usr/bin/env node
console.log("Spread the love.");
答案3
#!/bin/sh
//bin/false || `which node || which nodejs` << `tail -n +2 $0`
console.log('ok');
//bin/false
与 是相同的,/bin/false
只是第二个斜杠将其转换为节点的注释,这就是它在这里的原因。然后,对第一个的右侧||
进行评估。'which node || which nodejs'
使用反引号而不是引号启动节点并为其<<
提供右侧的任何内容。我可以使用//
像 dancek 那样以开头的分隔符,它会起作用,但我发现开头只有两行会更干净,所以我过去常常tail -n +2 $0
让文件自行读取,除了前两行。
如果您在节点中运行它,第一行将被识别为 shebang 并被忽略,第二行是单行注释。
(显然,sed可以用来代替tail打印文件内容,不包含第一行和最后一行)
编辑前回答:
#!/bin/sh
`which node || which nodejs` <<__HERE__
console.log('ok');
__HERE__
你不能做你想做的事,所以你要做的就是运行一个 shell 脚本,因此#!/bin/sh
.该 shell 脚本将获取执行节点所需的文件的路径,即which node || which nodejs
.反引号在这里以便它被执行,因此'which node || which nodejs'
(使用反引号而不是引号)只需调用 node.然后,您只需使用<<
.它们__HERE__
是您脚本的分隔符。这console.log('ok');
是一个脚本示例,您应该将其替换为您的脚本。
答案4
为了完整起见,这里有一些执行第二行的其他方法:
// 2>/dev/null || echo yes
false //|| echo yes
但两者都比所选答案没有任何优势:
':' //; || echo yes
另外,如果您知道会找到其中一个node
或nodejs
(但不是两者),则可以执行以下操作:
exec `command -v node nodejs` "$0" "$@"
但这是一个很大的“如果”,所以我认为所选的答案仍然是最好的答案。