我想使用coffee
可执行程序运行命令行脚本,但我想通过npx
调用该可执行程序。
像#!/usr/bin/env npx coffee
这样的东西不起作用,因为env
只支持一个参数。
那么,有没有办法通过env
运行一个npx
可执行程序呢?
我想使用coffee
可执行程序运行命令行脚本,但我想通过npx
调用该可执行程序。
像#!/usr/bin/env npx coffee
这样的东西不起作用,因为env
只支持一个参数。
那么,有没有办法通过env
运行一个npx
可执行程序呢?
这里有一个使用ts-node
的解决方案。
ts-node
#!/usr/bin/env ts-node
// TypeScript code
您可能还需要全局安装 @swc/core
和 @swc/cli
,除非您进行了进一步的配置或调整(请参见末尾的注释)。如果您遇到任何与它们有关的问题,请确保安装最新版本。
ts-node
未全局安装#!/usr/bin/env npx ts-node
// TypeScript code
在 macOS 上是否总是有效尚不清楚。可能会有一些魔法与节点 安装 shell 命令 shim 有关(感谢 @DaMaxContext 的评论)。
这在 Linux 中不起作用,因为 Linux 发行版将 env
后的所有字符都视为命令,而不是将空格视为分隔不同参数。或者如果节点命令 shim 不存在,则在 Linux 中不起作用(尚未确认它的工作方式,但在我的测试中,它在 Linux Docker 容器中不起作用)。
这意味着 npx ts-node
将被视为一个具有空格的单个可执行文件名称,这显然不起作用,因为那不是一个可执行文件。
有关 npx
缓慢性的注释,请参见底部说明。
ts-node
在 macOS 上未全局安装,并在 Linux 中进行一些设置创建一个 shebang,可以在 macOS 和 Linux(或在运行 Linux 映像的 Docker 中使用 macOS)中工作,而无需在 macOS 中全局安装 ts-node
和其他依赖项,如果愿意在 Linux/Docker 方面进行一些设置,则可以实现。显然,Linux 必须安装 node
。
#!/usr/bin/env npx ts-node
shebang。我们只需要欺骗Linux以为带有空格的npx ts-node
实际上是一个有效的可执行文件名。npx ts-node
解析为ts-node
。.ts
脚本chmod +x script.ts
都可以通过从命令行运行它们来执行,例如./test-script.ts
。您还可以将上面的sh
替换为脚本的名称(但一定要在前面加上./
,以便Docker知道将其作为可执行文件运行而不是将其传递为node
的参数)。
有其他方法可以实现所需的功能。
docker run
命令可以将文件挂载到镜像中,包括在各个目录中挂载可执行文件。巧妙地使用此功能可以避免需要先安装任何内容或构建 Docker 镜像。docker run
的一部分而不是预先构建镜像,但这样会在每次执行时执行,时间会更长。docker build
中修改 PATH
,以添加包含 ts-node 的 bin.js
的文件夹,该文件夹来自于任何 ts-node 的 dist
目录,然后使用 #!/usr/bin/env bin.js
的 shebang 理论上应该可以工作(也可以尝试使用 bin-esm.js
来避免需要 SWC,虽然这会进入实验性的 Node 领域,可能不适合生产脚本)。这在 macOS 中、在不属于 npm 项目的 Docker 中以及在配置为使用 TS 和 swc 的 npm 项目内的 Docker 中均可工作,通过向 ts-node 传递 --skipProject
标志或设置环境变量 TS_NODE_SKIP_PROJECT=true
来实现。一个可行的测试命令行示例:docker run -it --rm -v "$(pwd):/app" -e TS_NODE_SKIP_PROJECT=true -w /app --entrypoint sh node:16-alpine -c 'PATH="$PATH:/app/node_modules/ts-node/dist" ./test.ts'
。#!/usr/bin/env executable
)。它可以是 shell 脚本、二进制文件或任何其他类型的文件。可以将 shell 脚本轻松放置在已知位置,添加到 PATH 中,然后调用您喜欢的任何内容。它可以是多语句的,将文件编译为 .js
,然后运行该文件。无论您的需求是什么。node
作为 shebang 可执行文件,并通过环境变量设置 node 选项来强制使用 ts-node 作为加载器。有关更多信息,请参见 ts-node Recipes:Other。注释:
SWC_BINARY_PATH
环境变量 确保 ts-node 能够找到特定架构的 swc
编译器(避免错误“Bindings not found”)。如果您只在一个架构上运行,那么您就不需要它。或者,如果您挂载了已经安装了这些 @swc 包(是正确架构)的 node_modules
,那么您不需要它。.yarnrc.yml
中一次性定义要安装的二进制文件。使用环境变量,npm 和可能的 yarn 1(和 2?)也有其他选项。ts-node
提供了无需 swc 运行的选项(虽然速度较慢)。您可以尝试使用带有 ts-node-esm
的 shebangs 代替 ts-node
。查看 /usr/local/bin
文件夹中的所有符号链接或参考 ts-node 文档以获取更多信息。node --loader=ts-node
在最近版本(16+?)中可以使用。实验模式警告可以被抑制。sh
shebang,但 clever shell 语句将执行转移到基本上被 JavaScript 忽略的 node 上。这并不好,因为它需要额外的把戏行,但可能会帮助一些人。页面上的其他答案也很有教育意义,值得审查以获取完整的图片。.ts
文件,则此处的某些复杂性可能会消失。在我自己的 Docker 测试中,上下文始终在具有自己的 tsconfig.json
和已安装的 swc
的项目中,因此您可能会获得不同的结果。很难让 ts-node
忽略执行的 .ts
文件找到的 npm 项目上下文。executable [options] [file]
的形式从命令行运行脚本,那么您应该能够通过混合和匹配这里介绍的所有思路来弄清如何使用适当的 shebang 运行 ./[file]
。您不必使用 ts-node。您可以直接使用 node
、swc
、tsc
本身(首先编译,然后在找到的上下文中运行任何 .js 文件或一组 .js 文件),或任何能够编译或运行 TypeScript 的实用程序或工具。npx
比直接运行 ts-node
要慢得多,因为每次运行时它可能需要下载 ts-node
包和依赖项。
`#!/usr/bin/env -S npx ts-node --compiler-options {"module":"commonjs"}`
不幸的是,在Debian Buster上还不能使用。 - Scott Willeke