通用 Node.js 服务?

Sta*_*cek 48 scripting compatibility node.js

Node.js现在非常流行,我一直在用它编写一些脚本。不幸的是,兼容性是一个问题。正式地,Node.js 解释器应该被称为node,但 Debian 和 Ubuntu 提供了一个名为的可执行文件nodejs。

我想要 Node.js 可以在尽可能多的情况下使用的可移植脚本。假设文件名是foo.js,我真的希望脚本以两种方式运行:

  1. ./foo.js如果node或nodejs在 中,则运行脚本$PATH。
  2. node foo.js还运行脚本(假设调用了解释器node)

注意: xavierm02 和我自己的答案是多语言脚本的两种变体。如果存在,我仍然对纯粹的shebang解决方案感兴趣。

Sta*_*cek 62

我想出的最好的是这个“两行shebang”,它确实是一个多语言(Bourne shell / Node.js)脚本:

#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"

console.log('Hello world!');
Run Code Online (Sandbox Code Playgroud)

显然,第一行是 Bourne shell shebang。Node.js 会绕过它找到的任何 shebang,因此就 Node.js 而言,这是一个有效的 javascript 文件。

第二行:使用参数调用shell no-op ,//然后执行nodejs或node使用此文件的名称作为参数。command -v用于代替which便携性。命令替换语法$(...)不是严格的 Bourne,因此如果您在 1980 年代运行它,请选择反引号。

Node.js 只是评估 string ':',这就像一个空操作,而该行的其余部分被解析为注释。

文件的其余部分只是普通的旧 javascript。子shellexec在第二行完成后退出,因此shell 永远不会读取文件的其余部分。

感谢 xavierm02 的灵感和所有评论者的更多信息!

  • 我会小心将 `#!/usr/bin/env sh` 宣传为“更便携”。同一篇维基百科文章说“这主要是有效的,因为路径 /usr/bin/env 通常用于 env 实用程序......”这不是一个很好的认可,我猜你会遇到没有`/usr 的系统/bin/env` 比你遇到没有 `/bin/sh` 的系统更频繁,如果频率有任何差异的话。 (3认同)

she*_*onh 14

这只是基于 Debian 的系统上的一个问题,在那里策略克服了意义。

我不知道 Fedora 何时提供了一个名为 nodejs 的二进制文件,但我从未见过它。该包名为 nodejs,它安装了一个名为 node.js 的二进制文件。

只需使用符号链接将常识应用于基于 Debian 的系统,然后您就可以使用理智的shebang。其他人无论如何都会使用理智的shebangs,所以你将需要那个符号链接。

#!/usr/bin/env node

console.log("Spread the love.");
Run Code Online (Sandbox Code Playgroud)

  • 没必要道歉。你说得很对。我的回答没有回答你的问题。它说明了您的问题,表明该问题将范围限制为比可用解决方案更有用的解决方案。我根据历史提供实用的建议。Node 并不是第一个在这里找到自己的解释器。你应该已经看到导致 Larry Wall 宣布 perl shebang 必须是 `#!/usr/bin/perl` 的骚动。也就是说,您没有义务喜欢或应用我的建议。和平。 (10认同)

xav*_*m02 10

#!/bin/sh
//bin/false || `which node || which nodejs` << `tail -n +2 $0`
console.log('ok');
Run Code Online (Sandbox Code Playgroud)

//bin/false/bin/false除了第二个斜杠将它转换为节点的注释之外,它是一样的,这就是它在这里的原因。然后,第一个的右侧||被评估。'which node || which nodejs'使用反引号而不是引号启动节点并将其<<提供给右侧的任何内容。我可以使用//像dancek那样开头的分隔符,它会起作用,但我发现开头只有两行更干净,所以我曾经tail -n +2 $0让文件自己读取,除了前两行。

如果你在 node 中运行它,第一行被识别为 shebang 并被忽略,第二行是单行注释。

(显然, sed 可用于替换没有第一行和最后一行的tail Print 文件内容)


编辑前回答:

#!/bin/sh
`which node || which nodejs` <<__HERE__
console.log('ok');
__HERE__
Run Code Online (Sandbox Code Playgroud)

你不能做你想做的,所以你要做的是运行一个 shell 脚本,因此#!/bin/sh. 该 shell 脚本将获取执行 node 所需文件的路径,即which node || which nodejs. 反引号在这里以便它被执行,因此'which node || which nodejs'(使用反引号而不是引号)只需调用 node.js 即可。然后,您只需使用<<. 该__HERE__是你的脚本的分隔符。这console.log('ok');是您应该用您的脚本替换的脚本示例。

  • `which` 命令也不可移植。 (2认同)