当前位置: 首页 > 知识库问答 >
问题:

如何将命令行参数传递给从可执行脚本启动的NodeJ

淳于玺
2023-03-14

对于从启动程序脚本运行的NodeJS进程,如何将命令行参数设置为node?(sh/CMD脚本npm放入node_modules/.bin

许多NodeJS库/框架都带有自己的运行脚本,例如通常从npm脚本执行的zeit/micro分子。这是开发中的一个问题,因为在我的例子中,我想做相当于:

node --inspect -r ts-node/register -r dotenv-safe/config src/index.ts

(当然,这没有任何作用,因为index.ts只是输出一些东西让跑步者捡起来。)

是否有一些“干净的”,最好是通用的(也就是说,不是特定于一个给定框架的运行程序公开这些命令行参数)的方式,我没有做到这一点,理想情况下,作为一个npm脚本工作?看起来唯一可行的方法是,例如micro

node-dev -r ts-node/register ./node_modules/micro-dev/bin/micro-dev.js ./src/index.ts

这有点像是冗余部门的冗余部门,似乎可以避免使用那些启动脚本。(如果运行程序生成其他节点进程,它也不会工作,但这不是我实际遇到的问题。)我不想重复启动器脚本已经在做的事情。我也知道npx有--node arg,但npx是另一整罐蠕虫。(在Windows上,运行我已经安装的脚本只需要五秒钟的启动时间和一条虚假的错误消息;如果找不到它的.cmd启动程序脚本,例如在使用Docker运行开发环境时,它也找不到已经安装的包。简而言之,我不想使用npx来实现这一点。)

为了澄清注释中出现的混乱:我想重写影响NodeJS运行时本身执行运行脚本行为的命令行参数,而不是将参数传递给脚本本身或代码。也就是这里列出的选项:https://nodejs.org/api/cli.html

共有3个答案

壤驷凯
2023-03-14

我不清楚您的问题的具体情况,但作为您的问题标题,我们可以使用npm库从nodejs执行any cmd命令,如:

import Promise from 'bluebird'
import cmd from 'node-cmd'

const getAsync = Promise.promisify(cmd.get, { multiArgs: true, context: cmd })

getAsync('node -v').then(data => {
  console.log('cmd data', data)
}).catch(err => {
  console.log('cmd err', err)
})  
向俊贤
2023-03-14

nodejs应用程序被解析为一个名为process的数组之后,在命令行中传递的所有内容。argv。所以

node myapp.js foo bar hello 5000

在你的nodejs代码中。。。

const args = process.argv;
console.log(args[0]);
console.log(args[1]);
console.log(args[2]);
console.log(args[3]);

会让。。。

foo
bar
hello
5000
庾兴发
2023-03-14

一个选项是编写一个小包装器脚本,使用当前进程execPath运行child_进程。执行文件。

所以这里的样本是能够做到

节点-暴露-http 2-零填充缓冲区-r./some-module.js./test.js

但实际上并没有写出来,而是wrap.js注入args:

节点wrap.jstest.js

我在package.json中测试了通过npm运行这个,它工作正常。我测试了它的工作原理是让some-module.js在全局对象上粘贴一个值,然后将其记录在test.js中。

涉及的文件:

wrap。js

const child_process = require('child_process');

const nodeArgs = ['--expose-http2', '--zero-fill-buffers', '-r', './some-module.js'];
const runTarget = process.argv[2];

console.log('going to wrap', runTarget, 'with', nodeArgs);

const finalArgs = nodeArgs.concat(runTarget).concat(process.argv.slice(2));

const child = child_process.execFile(
  process.execPath,
  finalArgs,
  {
    env: process.env,
    cwd: process.cwd(),
    stdio: 'inherit'
  }, (e, stdout, stderr) => {
    console.log('process completed');
    if (e) {
      process.emit('uncaughtException', e);
    }
  });

child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);

一些模块。js

global.testval = 2;

测试。js

console.log('hi guys, did the wrap work?', global.testval)

编辑:所以进一步考虑,这个解决方案实际上只满足于包装最初的跑步者。但大多数工具,比如摩卡咖啡,会重新生成一个子过程,然后失去这种效果。为了真正完成这项工作,您可以代理每个子进程调用,并在一定程度上强制执行对spawn的调用,这些调用还包括您的参数。

我重写了代码来反映这一点。这里有一个新的设置:

软件包。json

{
  "scripts": {
    "test": "node -r ./ensure-wrapped.js node_modules/mocha/$(npm view mocha bin.mocha) ./test.js"
  },
  "dependencies": {
    "mocha": "^5.1.0"
  }
}

ensure-wrapped.js

const child_process = require('child_process');

// up here we can require code or do whatever we want;

global.testvalue = 'hi there'
const customParams = ['--zero-fill-buffers'];

// the code below injects itself into any child process's spawn/fork/exec calls
// so that it propogates

const matchNodeRe = /((:?\s|^|\/)node(:?(:?\.exe)|(:?\.js)|(:?\s+)|$))/;
const ensureWrappedLocation = __filename;

const injectArgsAndAddToParamsIfPathMatchesNode = (cmd, args, params) => {
  params.unshift(...customParams);
  params.unshift(args);
  if (!Array.isArray(args)) { // all child_proc functions do [] optionally, then other params
    args = []
    params.unshift(args);
  }

  if (!matchNodeRe.test(cmd)) {
    return params;
  }

  args.unshift(ensureWrappedLocation);
  args.unshift('-r');

  return params;
}

child_process._exec = child_process.exec;
child_process.exec = (cmd, ...params) => {
  // replace node.js node.exe or /path/to/node to inject -r ensure-wrapped.js ...args..
  // leaves alone exec if it isn't calling node
  cmd = cmd.replace(matchNodeRe, '$1 -r ' + ensureWrappedLocation + ' ');
  return child_process._exec(cmd, ...params)
}
child_process._execFile = child_process.execFile;
child_process.execFile = (path, args, ...params) => {
  params = injectArgsAndAddToParamsIfPathMatchesNode(path, args, params);
  return child_process._execFile(path, ...params)
}
child_process._execFileSync = child_process.execFileSync;
child_process.execFileSync = (path, args, ...params) => {
  params = injectArgsAndAddToParamsIfPathMatchesNode(path, args, params);
  return child_process._execFileSync(path, ...params);
}
child_process._execSync = child_process.execSync;
child_process.execSync = (cmd, ...params) => {
  cmd = cmd.replace(matchNodeRe, '$1 -r ' + ensureWrappedLocation + ' ');
  return child_process._exec(bin, ...args)
}
child_process._fork = child_process.fork;
child_process.fork = (module, args, ...params) => {
  params = injectArgsAndAddToParamsIfPathMatchesNode(process.execPath, args, params);
  return child_process._fork(module, ...params);
}
child_process._spawn = child_process.spawn;
child_process.spawn = (cmd, args, ...params) => {
  params = injectArgsAndAddToParamsIfPathMatchesNode(cmd, args, params);
  return child_process._spawn(cmd, ...params)
}
child_process._spawnSync = child_process.spawnSync;
child_process.spawnSync = (cmd, args, ...params) => {
  params = injectArgsAndAddToParamsIfPathMatchesNode(cmd, args, params);
  return child_process._spawnSync(cmd, ...params);
}

测试。js

describe('test', () => {
  it('should have the global value pulled in by some-module.js', (done) => {
    if (global.testvalue !== 'hi there') {
      done(new Error('test value was not globally set'))
    }
    return done();
  })
})

请永远不要把这样的代码放到已发布的节点模块中。修改全局库函数是非常糟糕的。

 类似资料:
  • 问题内容: 是否可以通过命令行将参数传递给MySQL脚本? 在此示例中,类似于@start_date的内容: 问题答案: 发现在网络上的答案在这里。 基本上,假设我们要运行以下查询: 我们可以这样传递“ start_date”和“ end_date”:

  • 我在Eclipse中工作。 我的Maven程序有一个pom。带有exec插件的xml文件: 我试图传递一个参数,但仍然出现错误: 未知的生命周期阶段“..\src\test\resources\file.txt”。您必须以以下格式指定有效的生命周期阶段或目标:或:[:]。可用的生命周期阶段包括:验证、初始化、生成源、流程源、生成资源、流程资源、编译、流程类、生成测试源、流程测试源、生成测试资源、流

  • 问题内容: 我有一个名为的python文件,该python文件需要两个命令行参数:,Dockerfile如下所示: 如何通过这两个命令行参数,并以?我试过了但是没用。 问题答案: 您不能按预期使用和,因为它们是的选项。 启动一个终端。 将Docker容器作为守护程序启动。 要在Dockerfile中设置环境变量,请使用命令。 请参阅Dockerfile参考。 另一种选择是通过以下方式传递环境变量:

  • 问题内容: 我从Eclipse项目构建了可运行的JAR,该项目处理给定的XML文件并提取纯文本。但是,此版本要求文件在代码中进行硬编码。 有没有办法做这样的事情 并让jar在xml文件上执行? 我已经四处查看,给出的所有示例都与在命令行上编译JAR有关,而没有一个处理传入参数。 问题答案: 为什么不 ? 只需修改您的参数即可接收论据并对其进行操作。 在命令行中指定完整路径。

  • 要启动Java程序,我可以传递如下参数: 在gradle命令行中有哪些好的方法可以做到这一点: 这是正在建造的。格雷德尔:

  • 问题内容: 我有一个PHP文件,需要从命令行运行(通过crontab)。我需要传递给文件,但我不知道如何。我试过了: 但是返回了此错误: 无法打开输入文件:myfile.php?type = daily 我能做什么? 问题答案: 该参数(在结束了阵列)仅适用于网络访问的页面。 您需要像调用它一样,并从数组中检索该参数(为,因为为)。 如果该页面也用作网页,则可以考虑两个选项。使用shell脚本和w