最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Capturing child_process spawnSync or execSync stdout - Stack Overflow

programmeradmin3浏览0评论

Is there an easy way of capturing child_process spawnSync or execSync stdout/stderr? I have seen other posts say a few years ago that it wasn't possible at the time since it was synchronous.

I have a problem where I need to capture another threads output so I can parse what is sent to stdout. The problem is, I haven't found anything past just using spawn and use the stdout.on events.

This causes issues since my program isn't meant to be asynchronous.

Edit:

The tool I have is called eslint-watch. It adds functionality to eslint like file watching and specifies a default directory. The problem is in this discussion we came to the conclusion that I needed to execute eslint as a binary and grab the help options from it.

After eslint returns its help options I parse them and funnel them into opinionator. So my wrapper has the same help context menu as eslint but also has my mands in there. Problem is grabbing the help is one of the first things I do so I can parse the mands from the terminal.

Is there an easy way of capturing child_process spawnSync or execSync stdout/stderr? I have seen other posts say a few years ago that it wasn't possible at the time since it was synchronous.

I have a problem where I need to capture another threads output so I can parse what is sent to stdout. The problem is, I haven't found anything past just using spawn and use the stdout.on events.

This causes issues since my program isn't meant to be asynchronous.

Edit:

The tool I have is called eslint-watch. It adds functionality to eslint like file watching and specifies a default directory. The problem is in this discussion https://github./eslint/eslint/issues/2831 we came to the conclusion that I needed to execute eslint as a binary and grab the help options from it.

After eslint returns its help options I parse them and funnel them into opinionator. So my wrapper has the same help context menu as eslint but also has my mands in there. Problem is grabbing the help is one of the first things I do so I can parse the mands from the terminal.

Share Improve this question edited Aug 12, 2015 at 16:39 Rizowski asked Aug 11, 2015 at 15:31 RizowskiRizowski 3,5985 gold badges24 silver badges31 bronze badges 1
  • Note for people like me who just want to do a simple stdout capture: as of Node v4.3, you can use capturedOutput = child_process.execSync("your_subprocess") More details in the doc of the current Node version: nodejs/api/… – TanguyP Commented Mar 23, 2016 at 11:11
Add a ment  | 

3 Answers 3

Reset to default 6

Things have changed since your edit.

execSync now returns stdout on pletion.

//will return date() on *nix systems;
console.log(require("child_process").execSync(`date`).toString());

>>> Fri Jul 10 14:19:41 UTC 2020

Referring to require('child_process').spawnSync() or .exexSync(), the Node API docs state pretty clearly that:

These methods are synchronous, meaning they WILL block the event loop, pausing execution of your code until the spawned process exits.

Blocking calls like these are mostly useful for simplifying general purpose scripting tasks and for simplifying the loading/processing of application configuration at startup.

So, you're correct. It is not possible to process stdio events while running an external process synchronously because the Node event loop is halted until the external process pletes.

You might consider capturing the processes stdout and/or stderr to one or more files using shell output redirection (i.e. using bash: COMMAND 1>stdout.txt 2>stderr.log) which you would do by running your mand in the bash shell.

The simplest way to do this from Node would be to:

file:runner.sh

#/bin/sh
PATH_TO_YOUR_COMMAND_HERE 1>mand_stdout.txt 2>mand_stderr.txt

file:nodeprocess.js

var fs = require('fs'),
    spawnSync = require('child_process').spawnSync,
    args = ['/bin/sh', 'runner.sh'];

spawnSync(args); // Event Loop will wait here.

if(fs.existsSync('./mand_stdout.txt')){
  // process standard output from your mand here
}
if(fs.existsSync('./mand_stderr.txt')){
  // process error output from your mand here
}

Of course, you should do all the proper file system hygiene things, like writing your output files into /tmp and removing them after you're done with them, but I leave those things to your imagination.

I'm curious why you cannot use .spawn() or .fork() since, if a mand can be run from the mand line, there should be no reason it cannot be run asychronously from Node.

I'm not sure if I understand correctly and would guess an anwser is of no interrest to poster anymore. However since I struggled with something similar here some example:

var karma = spawnSync("node",
    ["node_modules/karma/bin/karma", "start", "karma.conf.js", "--single-run"],
    {
        stdio: [null, process.stdout, process.stderr]
    }
);
if (karma.status != 0) {
    console.log(`Karma reported error(s) (${karma.status}). Build aborted\n`.red);
    process.exit(1);
} else {
    console.log(`Karma success\n`.green);
}

The above example starts Karma and performs the tests specified in the config file. What I want with this is to force perform a test when webpack is set to do a release build. The idea is that the build server cannot perform a release without testing first, even if the build is missconfigured.

This ment introducing the above block into the webpack.conf.js and blocking the executing thread until karma is done, meanwhile piping karmas stdout/err onto the console. Using spawnSync instead of spawn is only neccessary since once the thread returns from the webpack.conf.json Webpack immediately starts and potentially build the project with failing tests.

What is described in the original question sound like an asynchronous thing to me. Call the process and once stdout arrives add your additional output in an event handler. If you still wan't to do it synchronously, the stdio array just takes streams. This means you could create a wrapper stream for stdout and tell the child-process to use that.

发布评论

评论列表(0)

  1. 暂无评论