8

I'm trying to execute a child_process synchronously in node.js (Yes, I know this is bad, I have a good reason) and retrieve any output on stdout, but I can't quite figure out how...

I found this SO post: node.js execute system command synchronously that describes how to use a library (node-ffi) to execute the command, and this works great, but the only thing I'm able to get is the process exit code. Any data the command executes is sent directly to stdout -- how do I capture this?

> run('whoami')
username
0

in otherwords, username is echo'd to stdout, the result of run is 0.

I'd much rather figure out how to read stdout

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
  • Try to look [here][1]. It's discussion of the same question. [1]: http://stackoverflow.com/questions/4443597/node-js-execute-system-command-synchronously/8625316#8625316 – scherka Dec 24 '11 at 15:32

5 Answers5

3

So I have a solution working, but don't exactly like it... Just posting here for reference:

I'm using the node-ffi library referenced in the other SO post. I have a function that:

  • takes in a given command
  • appends >> run-sync-output
  • executes it
  • reads run-sync-output synchronously and stores the result
  • deletes this tmp file
  • returns result

There's an obvious issue where if the user doesn't have write access to the current directory, it will fail. Plus, it's just wasted effort. :-/

2

I have built a node.js module that solves this exact problem. Check it out :)

exec-plan

Update

The above module solves your original problem, because it allows for the synchronous chaining of child processes. Each link in the chain gets the stdout from the previous process in the chain.

Ryan
  • 1,557
  • 9
  • 11
  • Which method(s) in this module can be used to get the output of a command? – Anderson Green Oct 20 '12 at 04:52
  • The intention of the module is to set up a chain of commands as a plan, and stdout/err would be made available to the "preLogic" function of the "next" command in the plan. So, for example: if you had execPlan.add('ps -ef'); Then, on your next 'add', you can use a "pre logic" function as the first parameter to use the output of 'ps -ef'. For example: execPlan.add(function (stdout) { // do something with stdout from 'ps -ef' that runs before 'grep ls' }, 'grep ls');. If this comment didn't clarify very well, could you post on the module's github site itself? Also, checkout the README.md :) – Ryan Oct 21 '12 at 03:20
  • Is it possible to return the command-line output as a string using this module (instead of just printing it using console.log?) – Anderson Green Nov 16 '12 at 02:01
  • Also, it would be better if this answer actually explained *how* the module would solve the problem, instead of simply providing a relevant link. – Anderson Green Nov 16 '12 at 02:02
  • 1
    I updated the answer. Thanks for the suggestion on providing better clarifications. – Ryan Nov 16 '12 at 16:34
1

I had a similar problem and I ended up writing a node extension for this. You can check out the git repository. It's open source and free and all that good stuff !

https://github.com/aponxi/npm-execxi

ExecXI is a node extension written in C++ to execute shell commands one by one, outputting the command's output to the console in real-time. Optional chained, and unchained ways are present; meaning that you can choose to stop the script after a command fails (chained), or you can continue as if nothing has happened !

Usage instructions are in the ReadMe file. Feel free to make pull requests or submit issues!

However it doesn't return the stdout yet... Well, I just released it today. Maybe we can build on it.

Anyway, I thought it was worth to mention it. I also posted this to a similar question: node.js execute system command synchronously

Community
  • 1
  • 1
Logan
  • 10,649
  • 13
  • 41
  • 54
0

Since Node version v0.11.12, there is a child_process.execSync function for this.

Thomas
  • 174,939
  • 50
  • 355
  • 478
-1

Other than writing code a little diferent, there's actually no reason to do anything synched.

What don't you like about this? (docs)

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

exec('whoami', function (error, username) {
    console.log('stdout: %s', username);
    continueWithYourCode();
});
dresende
  • 2,211
  • 1
  • 16
  • 25
  • Actually there is in this case. I have a library hooking into `stylus` that compiles CSS sprites from individual images. Since `stylus` is written synchronously, any hook has to be sync as well. I'm not about to re-write the entire parsing engine, and even if I did it likely wouldn't be accepted into the master branch and my external library would only work off of my branch. –  Oct 12 '11 at 23:13
  • 5
    -1 "there's no reason..." and how can you tell? I hate these pointless arguments that can never be proved correct and in fact you are wrong, there are several cases when it's either a must or of help to do things synchronously. – Tower Apr 21 '12 at 17:15
  • @rFactor: there's actually no reason. You can say it's easier for you to right synched code because you're used to it but there's actually no reason. – dresende Apr 24 '12 at 21:03
  • @dresende it has little to do with "easiness". For example, I for one now have an issue with this. I am trying to get Dart frog compiler to work with Node's `require()`. The official and only way to do this is to use `module.require.extensions['.dart'] = ...`. The compilation works, however, `require` is synchronous, so my Dart compiler cannot be async and the compiler is a 3rd party executable so I can just exec it. See? There's no way around this problem except exec'ing synchronously. – Tower Apr 25 '12 at 08:49
  • Try to take the blinds out of your eyes and think about the algorithm before you code. If you can't, there are so many helpers out there like https://github.com/creationix/step and others.. – dresende Jul 23 '12 at 09:28