从命令行(Node JS)运行脚本中的函数

352

我正在使用Node编写一个Web应用程序。如果我有一个JS文件db.js,其中包含一个名为init的函数,我该如何从命令行调用该函数?


使用npm run-func https://dev59.com/yF0a5IYBdhLWcg3wCE3P#43598047 - Pawel
5
我更喜欢被接受的答案,因为它不需要安装第三方依赖项,这可能会失去支持或包含漏洞。这是您在使用任何依赖项时都需要考虑的风险,因此将依赖项限制为经过充分审查和维护的依赖项始终是一个好主意。 - winhowes
你也可以使用 https://www.npmjs.com/package/invoke-script 包。 - Stefan van de Vooren
16个回答

535

不对你想要做这件事情的原因发表评论,也不谈什么是更加标准的做法:以下是你问题的解决方案...请记住,所需引号类型可能会因命令行而异。

db.js文件中,导出init函数。有很多方法,但以下是一个例子:

    module.exports.init = function () {
      console.log('hi');
    };

假设你的 db.js 文件与命令提示符处于同一目录下,则可以按以下方式调用:

node -e 'require("./db").init()'

如果你的db.js是一个模块db.mjs,使用动态导入来加载该模块:

node -e 'import("./db.mjs").then( loadedModule => loadedModule.init() )'

对于其他读者而言,原帖中的 init 函数可以被称为任何名称,它并不重要,只是问题中使用的特定名称。


124
这是一个有用的提示,用于测试从AWS Lambda运行的某些JavaScript代码 - 谢谢。 - Alex Hinton
19
如果函数是异步的,会发生什么? - Augustin Riedinger
34
如果有其他人想在他们的 package.json 文件中作为 npm 脚本尝试此操作,我已经尝试过用单引号和双引号嵌套,但是直到我将它们进行了切换才成功: "start": "node -e "require('./server')()""。 - Sako73
2
感谢@winhowes回复,我刚刚使用了您的示例 module.exports.init = function () { console.log('hi'); }; 但是 node -e 'require("./db").init()' 对我不起作用。 我不确定我做错了什么,但是遵循您的思路,我使用了 module.exports = myFunction, ,然后 node -e 'require("./myFunction")()' 对我有效。 - C.Lee
3
作为对 @AlexHinton 评论的补充,我现在使用以下内容来模拟事件和回调:node -e 'require("./index").handler(require("./fixtures/sample_event_01.json"), {}, console.log)'。中间的 {} 是上下文,可以自由调整。另外 console.log 有点原始但是一个不错的开端。当然,您也可以编写一个专用的 CLI.js,该文件会依次使用 index.js/handler,就像其他评论所述。 - Adrian Föder
显示剩余15条评论

86

2020年更新 - 命令行界面(CLI)

如@mix3d所指出,你可以运行一个命令,其中file.js代表你的文件,someFunction是你的函数名称,可选择跟随参数以空格分隔。

npx run-func file.js someFunction "just some parameter"

就是这样。

file.js 在上面的示例中被调用。

const someFunction = (param) => console.log('Welcome, your param is', param)

// exporting is crucial
module.exports = { someFunction }

更加详细的描述

直接从命令行界面运行(全局)

安装

npm i -g run-func

使用方法,即运行函数“init”,必须进行导出,参见底部

run-func db.js init

或者

从 package.json 脚本(本地)运行

安装

npm i -S run-func

设置

"scripts": {
   "init": "run-func db.js init"
}

使用方法

npm run init

参数

任何接下来的参数都将作为函数参数传递 init(param1, param2)

run-func db.js init param1 param2

重要提示

在包含该函数的文件中,必须导出该函数(例如,在本示例中为init函数)。

module.exports = { init };

或者 ES6 导出

export { init };

1
我本来想使用 eye_mew 的建议来使用 make-runnable,但是这个方法比那个好多了,我认为。谢谢。 - luis.espinal
1
这对我不起作用;$ run-func db.js init bash:run-func:找不到命令 - Patlatus
4
多亏了 npx,我们可以使用 npx run-func file.js functionName 来运行函数,而无需全局安装 run-func。 #胜利! - mix3d
4
你应该提到,你是 run-func 软件包的贡献者之一... - A_blop
1
这个命令对我有用。谢谢。 npx run-func /path/to/folder/file.js myfunction - Jay Teli
显示剩余13条评论

78

按照其他答案的建议,在someFile.js中添加以下内容。

module.exports.someFunction = function () {
  console.log('hi');
};

接着可以将以下内容添加到package.json文件中:

"scripts": {
   "myScript": "node -e 'require(\"./someFile\").someFunction()'"
}

从终端,您可以调用以下命令

npm run myScript

我发现这是记住命令并使用它们的更简单方法。


1
在我的Win10机器上,这个语法只是在PowerShell或命令提示符终端中回显脚本。直接运行它而不是通过“npm run”运行会抛出“意外的标记”,指向require参数的开头。我还没有想出如何使它工作。 - CalvinDale
@CalvinDale 我也是一样,除了我可以在 PowerShell 中正常运行脚本本身。 - ferr
13
在我的电脑上(Windows 10),我不得不切换双引号和单引号,像这样:"myScript": "node -e "require('./someFile').someFunction()"" 否则,Node 只会打印出单引号中的命令,而不会对其进行评估。也许这可以解决 @CalvinDale 和 ferr 的问题。 - Christoph
7
如果我们想要向函数调用中添加参数,该怎么办? - Miguel Stevens

38

试试make-runnable

在db.js中,将require('make-runnable')添加到末尾。

现在你可以这样做:

node db.js init

任何进一步的参数都将以列表或键值对的形式传递给init方法。


27

有时候你想通过CLI运行一个函数,有时候你想从另一个模块中require它。以下是如何做到两者兼顾。

// file to run
const runMe = () => {}
if (require.main === module) {
  runMe()
} 
module.exports = runMe

19

这个有点脏但是能用 :)

我将从我的脚本中调用main()函数。 以前我只在脚本的末尾放置了对main的调用。不过,现在我添加了一些其他函数并从脚本中导出它们(以便在代码的其他部分中使用函数)-但是我不想每次在其他脚本中导入函数时都执行main()函数。

所以我这样做了,在我的脚本中删除了对main()的调用,而是在脚本的末尾放置了这个检查:

if (process.argv.includes('main')) {
   main();
}

因此,当我想在CLI中调用该函数时:node src/myScript.js main


1
对我来说足够了,在 package.json 脚本中不需要强制使用双引号转义。 - Marecky
2
我认为这一点都不糟糕。它简单明了,而且它能够正常工作。 :-) - Holf
1
你不知道你给我这个想法带来了多大的帮助!非常感谢!! - m4design
这是我个人认为最实际的答案。 - undefined

11

简单的方法:

假设您在项目结构中的helpers目录中有一个名为db.js的文件。

现在进入helpers目录并进入node控制台。

 helpers $ node

2) 要求引入 db.js 文件

> var db = require("./db")

3) 调用你的函数(在你的情况下是init())

> db.init()

希望这可以帮到您


10
如果将 db.js 转换为模块,您可以从 db_init.js 中 require 它,然后只需运行 node db_init.js 即可。 db.js
module.exports = {
  method1: function () { ... },
  method2: function () { ... }
}

db_init.js:

var db = require('./db');

db.method1();
db.method2();

10

更新至2022年 - 如果您已切换到ES模块,您不能使用require技巧,您需要使用动态导入:

node -e 'import("./db.js").then(dbMod => dbMod.init());'

或者使用 --experimental-specifier-resolution=node 标记:

node --experimental-specifier-resolution=node -e 'import("./db").then(dbMod => dbMod.init());'

7

你还可以使用ts-node来运行TypeScript,类似于@LeeGoddard的answer
在我的情况下,我希望分别使用appinit进行测试。

// app.ts

export const app = express();

export async function init(): Promise<void> {
   // app init logic...
}

// commonjs
npx ts-node -e 'require("./src/app").init();'
// esmodule
npx ts-node -e 'import("./src/app").then(a => a.init());'

不必使用 npx,只需执行 ts-node -e 'require("./index.ts").run();' 即可。 - Dave
除非全局安装了 ts-node 的二进制文件,否则 npx 将为 ts-node 提供一致的可重现性。 - Filip Seman

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