如何从 node.js 应用程序运行命令行工具

Posted

技术标签:

【中文标题】如何从 node.js 应用程序运行命令行工具【英文标题】:How to run a command line tool from node.js application 【发布时间】:2018-02-03 23:02:36 【问题描述】:

我的问题的标题是,因为我认为这里的答案将适用于可从 npm 安装的所有命令行实用程序。我已经看到与从 node.js 运行命令行相关的问题,但它们似乎不适用于我的情况。具体来说,我正在尝试运行一个类似于 npm 的节点命令行实用程序(在它的使用方式上,但不是它的功能),称为 tilemantle。

tilemantle 的 documentation 显示全局安装 tilemantle 并从命令行运行程序。

我想做的是使用 npm install tilemantle --save 在本地安装 tilemantle 作为 npm 项目的一部分,然后从我的项目内部运行 tilemantle。

我尝试了`tilemantle = require('tilemantle'),但是tilemantle项目中的index.js文件是空的,所以我认为这没有任何帮助。

我尝试了node-cmd的项目

const cmd = require('node-cmd');
cmd.run('./node_modules/tilemantle/bin/tilemantle', 'http://localhost:5000/layer/z/x/y/tile.png', '-z 0-11', '--delay=100ms', '--point=37.819895,-122.478674', '--buffer=100mi'

这不会引发任何错误,但它也不起作用。

我也尝试过子进程

const child_process = require('child_process');
child_process.exec('./node_modules/tilemantle/bin/tilemantle', 'http://localhost:5000/layer/z/x/y/tile.png, -z 0-11 --delay=100ms --point=37.819895,-122.478674 --buffer=100mi'

这也不会引发任何错误,但它也不起作用。

有没有办法让它工作,这样我就可以从我的程序内部运行 tilemantle 而无需全局安装它?

更新

我可以使用 tilemantle 从我的终端运行

node './node_modules/tilemantle/bin/tilemantle', 'http://localhost:5000/layer/z/x/y/tile.png', '--delay=100ms', '--point=37.819895,-122.478674', '--buffer=100mi', '-z 0-11'

如果我按照jkwok 的建议运行以下命令

child_process.spawn('tilemantle', ['http://myhost.com/z/x/y.png',
  '--point=44.523333,-109.057222', '--buffer=12mi', '-z', '10-14'],
   stdio: 'inherit' );

我得到spawn tilemantle ENOENT,如果我用./node_modules/tilemantle/bin/tilemantle.js 替换tilemantle,我得到spawn UNKNOWN

基于jfriend00's answer,听起来我实际上需要生成节点,所以我尝试了以下方法

child_process.spawn('node', ['./node_modules/tilemantle/bin/tilemantle.js', 'http://myhost.com/z/x/y.png', '--point=44.523333,-109.057222', '--buffer=12mi', '-z', '10-14'],  stdio: 'inherit' );

这给了我错误spawn node ENOENT 这似乎很奇怪,因为我可以从我的终端运行它,我检查了我的路径变量并且C:\Program Files\nodejs 在我的路径上。

只是为了检查我尝试使用节点的完整路径运行以下命令。

child_process.spawn('c:/program files/nodejs/node.exe', ['./node_modules/tilemantle/bin/tilemantle.js', 'http://myhost.com/z/x/y.png', '--point=44.523333,-109.057222', '--buffer=12mi', '-z', '10-14'],  stdio: 'inherit' );

它在没有 ENOENT 错误的情况下运行,但它再次静默失败,只是没有预热我的磁贴服务器。

我正在使用 Node 6.11.0 运行 Windows 10 x64

【问题讨论】:

我链接的帖子有一条关于在 Windows 上运行的评论here 【参考方案1】:

您似乎正试图通过运行文件而不是从命令行捕获tilemantle 的输出。如果是这样,我做了以下操作并让它工作。

像你一样在本地安装 tilemantlechild_process 到一个新的 npm 项目中,并将以下内容添加到该项目的文件中。

//  test.js file
var spawn = require('child_process').spawn;

spawn('tilemantle', ['http://myhost.com/z/x/y.png', '--
  point=44.523333,-109.057222', '--buffer=12mi', '-z', '10-14'],  stdio: 'inherit' );

在项目中使用node test.js 运行它。

我尝试了this post 中的许多其他选项,但只能让上述选项与其他输出一起打印进度。希望这会有所帮助!

【讨论】:

【参考方案2】:

您可以在本地安装任何可执行文件,然后使用 child_process 运行它。为此,您只需弄清楚可执行文件的确切路径,并将该路径传递给child_process.exec()child_process.spawn() 调用。

看起来你最终想要运行的是一个命令行:

node <somepath>/tilemantle.js

当您在 Windows 上安装时,如果您运行,它将为您完成大部分工作:

node_modules\.bin\tilemantle.cmd

如果你想直接运行js文件(例如在其他平台上),那么你需要运行:

node node_modules/tilemantle/bin/tilemantle.js

注意,使用 child_process,您必须指定实际的可执行文件,在这种情况下是“节点”本身,然后是您希望运行的 js 文件的路径。

当然,这一切都假定节点在您的路径中,以便系统可以找到它。如果它不在您的路径中,那么您还必须使用节点可执行文件的完整路径。

【讨论】:

【参考方案3】:

许多命令行实用程序都带有“程序化”API。不幸的是,tilemantle 没有,这就是为什么您无法在代码中require 该模块。

但是,您可以从 npm 脚本轻松访问本地安装的 CLI 版本。我对 tilemantle 一无所知,所以我将提供一个使用tldr 命令行工具的示例。在你的 package.json 中:


  "name": "my-lib",
  "version": "1.0.0",
  "scripts": 
    "test": "tldr curl"
  ,
  "dependencies": 
    "tldr": "^2.0.1"
  

您现在可以从项目中的终端运行npm test 作为tldr curl 的别名。

根据this post,您可以使用 global-npm 包从您的代码中运行 npm 脚本:

const npm = require('global-npm')

npm.load(, (err) => 
  if (err) throw err

  npm.commands.run(['test'])
)

瞧,您现在可以以编程方式(ish)运行本地安装的 CLI,即使它没有为此提供 API。

【讨论】:

以上是关于如何从 node.js 应用程序运行命令行工具的主要内容,如果未能解决你的问题,请参考以下文章

使用Node.js构建命令行工具

如何将命令行参数传递给 Node.js 程序?

如何将命令行参数传递给 Node.js 程序?

如何将命令行参数传递给 Node.js 程序?

如何将命令行参数传递给 Node.js 程序?

如何将命令行参数传递给 Node.js 程序?