如何使用 nodejs child_process.spawn 捕获 ENOENT?

Posted

技术标签:

【中文标题】如何使用 nodejs child_process.spawn 捕获 ENOENT?【英文标题】:How to catch an ENOENT with nodejs child_process.spawn? 【发布时间】:2016-03-16 11:38:59 【问题描述】:

我正在使用spawn 生成一个长时间运行的进程,该进程会随着时间的推移将输出发送到 stdio,并由我的 nodejs 脚本读取和处理。棘手的部分是我不能保证发送的命令总是有效的。如何在生成时发现错误?最好这不会涉及安装全局异常处理程序,因为我不想处理任何其他异常。 (如果这是唯一的方法,我需要弄清楚生成的进程何时正确启动,然后卸载处理程序,这是我不想陷入的混乱。)

我想运行的代码是这样的:

var spawn = require('child_process').spawn;

try 
    spawn("zargle");
 catch (e) 
    console.error("I'm handling the error!");

但这只是在节点事件循环的某处引发了一个 uncaughtException,可能是因为调用是异步的,甚至没有尝试在我的脚本时间片上启动子进程。

需要捕获的唯一异常是 spawn 根本无法启动进程(例如,名称不正确并抛出 ENOENT)。我(目前)不关心生成的进程可能自行产生的任何问题。


相似但不同:How do I debug "Error: spawn ENOENT" on node.js?

我确切地知道我为什么会得到 ENOENT,并且我知道要改变什么才能不发生错误。我的问题是,如果错误是不可避免的,如何优雅地应对这种情况。

【问题讨论】:

【参考方案1】:

与节点中的许多东西一样,子进程可以发出error event。为此添加一个侦听器,您将能够捕获它(不需要try-catch):

var spawn = require('child_process').spawn;
var child = spawn('foo');
child.on('error', function(err) 
  console.log('Oh noez, teh errurz: ' + err);
);

【讨论】:

所以你是完全正确的。我什至从未尝试过,因为我没有想到 spawn 会根据是否附加了错误处理程序来选择性地抛出异常。 (如果文档能提到这样的事情来帮助我们节点新手,那就太好了。) FWIW error 事件一直是一个特殊的事件,如果没有 error 事件侦听器(并且在 process 上没有 uncaughtException 事件处理程序),当它发出时,错误将被抛出。节点文档中有一个关于错误here 的专门部分。 我刚试过,但没有用。如果 spawn 尝试运行不存在的文件,这是否有效? 如果添加事件处理程序对您不起作用,您应该发布一个新问题。 我刚刚复制了您的控制台消息。我的代码现在可以发货了;)【参考方案2】:

就像 mscdex 说的,你必须附加 'error' 事件,但是,你应该添加 try catch 因为一些错误,比如 EPERM 不会触发错误事件并抛出Error异常。

var spawn = require('child_process').spawn;
try
    var child = spawn('foo');
    child.on('error', function(err) 
      console.log('Oh noez, teh errurz: ' + err);
    );
catch(err)
    console.log("exception: "+err)

【讨论】:

你能举例说明你的意思吗?你的回答似乎模棱两可,我不知道我是否应该进一步调查。 我同意,不清楚,我更新了我的答案,希望它更清楚。【参考方案3】:

您可以尝试使用 process uncaughtException 事件来捕获它。 但我相信剩下的任务并不容易。

process.on('uncaughtException', function (err) 
  console.log(err);
);

【讨论】:

以上是关于如何使用 nodejs child_process.spawn 捕获 ENOENT?的主要内容,如果未能解决你的问题,请参考以下文章

Nodejs如何独立检查PID运行的进程?

nodejs 怎样检测子进程执行完成

nodejs child_process.spawnSync 或 child_process.spawn 包裹在 yieldable 生成器中,它返回输出

Nodejs child_process 模块

如何在nodejs里调用执行系统命令

如何使用 node.js child_process API 运行 jar 文件?