在非登录shell中执行shebang的bash脚本的正确语法是什么?

3

背景:我正在尝试通过脚本顶部的shebang,在非登录shell中使nvm正确设置node

登录shell中,node脚本的shebang为:

#!/usr/bin/env node   

这种方法对于非登录shell无效,因此我想要做相当于以下操作的事情:

#!/usr/bin/env [[ -s $HOME/.nvm/nvm.sh ]] && source "$HOME/.nvm/nvm.sh" && node

但是我无法正确地写出语法(查看下面的错误)。我已经尝试了几种方式,包括对脚本进行引号处理或尝试运行 bash -c。但每次都会遇到解析错误。

完整脚本如下:

#!/usr/bin/env node

const semver = require('semver');
console.log("Hello World! You're using " + process.version)

错误:

在登录 shell 中出现(我不需要它的地方)

❯ bin/nodesample.js
env: [[: No such file or directory

在非登录Shell中,我想找到一个解决方案。

env: [[: No such file or directory

如果我尝试运行#!/usr/bin/env "[[ -s $HOME/.nvm/nvm.sh ]] && source "$HOME/.nvm/nvm.sh" && node"
env: "[[: No such file or directory

Shebang 告诉操作系统哪个二进制文件可以运行你的脚本。因此,使用 #!/whatever/node 的 shebang 就是告诉操作系统使用 node 二进制文件来运行脚本。我认为这不是你想要的。你可能仍然希望你的脚本运行 bash 命令并从 bash 运行 nvm。 - Julien B.
@JulienB 谢谢你。然而,如果你看一下这个脚本的 shebang,它运行二进制文件 /usr/bin/env ,然后再运行 node。它不像你的例子那样直接运行 node。你能给我一个从 bash 脚本本身运行内联 node 代码的例子吗?我已经加入了我正在运行的完整脚本。作为参考,在不运行 nvm 脚本的情况下,node 路径是无法确定的。 - Preet Sangha
@JulienB。请参考https://dev59.com/g2kv5IYBdhLWcg3wwTZm了解我所说的内容。 - Preet Sangha
1
@JamesRisner - 我已经添加了错误信息 - 抱歉之前遗漏了它们。 - Preet Sangha
1
既不是shebang,也不是'env'的第一个参数是任意的shell命令:它是一个可执行文件的名称。 - chepner
1
没有跨平台的保证,你可以在 shebang 上提供一个以上的参数(不包括解释器本身的名称,在执行的文件名被附加之前),因此除了必须是可执行文件(而不是 shell 命令)的限制外,还有一个空间限制的限制,不能做太复杂的事情。 - Charles Duffy
2个回答

4

shebang并不适合运行复杂的命令,它的作用只是告诉内核你想用哪个解释器来运行脚本。它不在你的shell中执行,因此像[[&&甚至$parameter这样的概念都不存在。在错误消息中,env告诉您它想要一个可以在路径上找到的命令,而[[是bash关键字,所以不起作用。

如果您需要在运行命令之前进行一些设置,则标准解决方案是使用包装脚本,就像Julien建议的那样。

#!/usr/bin/env bash
[[ -s $HOME/.nvm/nvm.sh ]] && source "$HOME/.nvm/nvm.sh" && node bin/nodesample.js

你甚至可以进一步安装一个包装脚本,然后将其用在其他Node脚本的shebang行上。

#!/usr/bin/env bash
# nodewrapper script - place in e.g. /bin
[[ -s $HOME/.nvm/nvm.sh ]] && source "$HOME/.nvm/nvm.sh" && exec node "${@}"

#!/bin/nodewrapper
const semver = require('semver');
console.log("Hello World! You're using " + process.version)

请注意,在shebang中使用脚本是不可移植的,例如在BSD系统(如MacOS)上是被禁止的。 - Charles Duffy

2

[[: 没有这个文件或目录

双左括号是bash和zsh中内置的测试。

通常,测试是/bin/[。但[[没有相关的二进制文件。

这个错误报告说它无法在您的路径中找到[[

#!/usr/bin/env [[ -s $HOME/.nvm/nvm.sh ]] && source "$HOME/.nvm/nvm.sh" && node

那是行不通的。你应该重新格式化它:

#!/usr/bin/env bash

[[ -s $HOME/.nvm/nvm.sh ]] && source "$HOME/.nvm/nvm.sh" && node << EOF
const semver = require('semver');
console.log("Hello World! You're using " + process.version)
EOF

测试工作是否正常:

$ ./left
Hello World! You're using v18.9.0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接