By disfated


2010-12-14 19:59:43 8 Comments

I need in node.js function

result = execSync('node -v');

that will synchronously execute the given command line and return all stdout'ed by that command text.

ps. Sync is wrong. I know. Just for personal use.

UPDATE

Now we have mgutz's solution which gives us exit code, but not stdout! Still waiting for a more precise answer.

UPDATE

mgutz updated his answer and the solution is here :)
Also, as dgo.a mentioned, there is stand-alone module exec-sync

UPDATE 2014-07-30

ShellJS lib arrived. Consider this is the best choice for now.


UPDATE 2015-02-10

AT LAST! NodeJS 0.12 supports execSync natively.
See official docs

12 comments

@Benjamin Gruenbaum 2015-02-08 14:13:34

Node.js (since version 0.12 - so for a while) supports execSync:

child_process.execSync(command[, options])

You can now directly do this:

const execSync = require('child_process').execSync;
code = execSync('node -v');

and it'll do what you expect. (Defaults to pipe the i/o results to the parent process). Note that you can also spawnSync now.

@Tom Dev 2017-12-19 15:42:56

after 10 hours of despair. THANKS DUDE

@JulianSoto 2018-09-26 04:09:27

How can I disconnect from this subprocess?

@falko 2014-07-29 12:58:04

Use ShellJS module.

exec function without providing callback.

Example:

var version = exec('node -v').output;

@Aram Kocharyan 2014-09-01 02:25:19

Note that at the time of writing, the docs mention that the synchronous exec() is CPU intensive for long processes.

@Nick 2015-05-13 15:41:03

options, {silent:true} is key

@user2503764 2017-04-27 18:06:05

This do something (other than provide shorter syntax) this doesn't? const execSync = require('child_process').execSync; code = execSync('node -v');

@kvz 2014-05-12 18:21:12

Just to add that even though there are few usecases where you should use them, spawnSync / execFileSync / execSync were added to node.js in these commits: https://github.com/joyent/node/compare/d58c206862dc...e8df2676748e

@disfated 2014-05-14 03:58:16

Does this mean we going to have it in v0.12 out of the box?

@balupton 2014-05-18 04:51:52

@Jason Livesay 2013-05-20 21:04:31

I actually had a situation where I needed to run multiple commands one after another from a package.json preinstall script in a way that would work on both Windows and Linux/OSX, so I couldn't rely on a non-core module.

So this is what I came up with:

#cmds.coffee
childproc = require 'child_process'

exports.exec = (cmds) ->
  next = ->
    if cmds.length > 0
      cmd = cmds.shift()
      console.log "Running command: #{cmd}"
      childproc.exec cmd, (err, stdout, stderr) ->
        if err? then console.log err
        if stdout? then console.log stdout
        if stderr? then console.log stderr
        next()
    else
      console.log "Done executing commands."

  console.log "Running the follows commands:"
  console.log cmds
  next()

You can use it like this:

require('./cmds').exec ['grunt coffee', 'nodeunit test/tls-config.js']

EDIT: as pointed out, this doesn't actually return the output or allow you to use the result of the commands in a Node program. One other idea for that is to use LiveScript backcalls. http://livescript.net/

@disfated 2013-05-21 02:32:21

Thanks, but this is not an answer since your code runs commands in series asynchronously

@Jason Livesay 2013-05-21 03:03:46

If you need to execute a series of commands synchronously as per my example it will work. I think I misunderstood your question though, sorry. I added another idea to the answer.

@Logan 2013-02-28 07:25:31

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!

EDIT: However it doesn't return the stdout yet... Just outputs them in real-time. It does now. Well, I just released it today. Maybe we can build on it.

Anyway, I thought it was worth to mention it.

@thealfreds 2013-04-16 22:20:34

This is exactly what I have been looking for. Thank you for putting in the time to make this.

@Logan 2013-11-03 04:09:59

The only thing I haven't figured out and implemented is the build configuration for different nodejs versions. I guess I wrote it on node 0.8 (travis-ci.org/aponxi/npm-execxi/builds/5248535) so as long as npm install succeeds (in other words as plugin compiles), then it is good to go for production. Besides targeting different nodejs versions, I'd say it's patched up for production, or that it's pretty stable. If there are any bugs you can send in a pull request or post an issue at github :)

@dgo.a 2012-09-15 05:49:00

This is the easiest way I found:

exec-Sync: https://github.com/jeremyfa/node-exec-sync
(Not to be confused with execSync.)
Execute shell command synchronously. Use this for migration scripts, cli programs, but not for regular server code.

Example:

var execSync = require('exec-sync');   
var user = execSync('echo $USER');
console.log(user);

@mgutz 2011-06-09 05:23:02

See execSync library.

It's fairly easy to do with node-ffi. I wouldn't recommend for server processes, but for general development utilities it gets things done. Install the library.

npm install node-ffi

Example script:

var FFI = require("node-ffi");
var libc = new FFI.Library(null, {
  "system": ["int32", ["string"]]
});

var run = libc.system;
run("echo $USER");

[EDIT Jun 2012: How to get STDOUT]

var lib = ffi.Library(null, {
    // FILE* popen(char* cmd, char* mode);
    popen: ['pointer', ['string', 'string']],

    // void pclose(FILE* fp);
    pclose: ['void', [ 'pointer']],

    // char* fgets(char* buff, int buff, in)
    fgets: ['string', ['string', 'int','pointer']]
});

function execSync(cmd) {
  var
    buffer = new Buffer(1024),
    result = "",
    fp = lib.popen(cmd, 'r');

  if (!fp) throw new Error('execSync error: '+cmd);

  while(lib.fgets(buffer, 1024, fp)) {
    result += buffer.readCString();
  };
  lib.pclose(fp);

  return result;
}

console.log(execSync('echo $HOME'));

@Mark Kahn 2011-08-24 22:55:33

How would you go about actually getting anything sent to stdout from this? All I can get is the process exit code

@pvorb 2011-12-28 14:45:48

@cwolves: I think async would be better this. (Ivo's answer)

@Mark Kahn 2011-12-28 16:05:52

@pvorb -- yeah, except when you can't use async :)

@Marcus Pope 2012-01-29 07:58:18

@cwolves - see my answer below for getting the stdout results in a synchronous manner, you don't need node-ffi, but you can use the "pipe stdout and stderr to a file path" mechanism with node-ffi and readfilesync the results. My solution however does not return the exit code, not sure if that's possible with command line options or what not, but I bet there's a shell utility that would report the exit code of a sub process to stdout if you needed that and don't want to use node-ffi.

@mgutz 2012-06-09 20:57:14

There are valid reasons for not using the async hammer for every nail. For example, template engines are async in Express 3 and helper functions (locals) need to be synchronous. What if those helper functions need to compile Less files asynchronously on the fly?

@mgutz 2012-06-09 21:09:37

To complete my thought, I use the execSync trick while in DEVELOPMENT mode to precompile cache-busting assets with MD5 sums.

@Michael Härtl 2012-09-05 10:23:05

I wonder why this simple execSync is not part of child_process. I think, it should be.

@Oleg 2012-04-07 19:35:46

You can achieve this using fibers. For example, using my Common Node library, the code would look like this:

result = require('subprocess').command('node -v');

@nab 2012-02-27 13:15:35

There's an excellent module for flow control in node.js called asyncblock. If wrapping the code in a function is OK for your case, the following sample may be considered:

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

asyncblock(function (flow) {
    exec('node -v', flow.add());
    result = flow.wait();
    console.log(result);    // There'll be trailing \n in the output

    // Some other jobs
    console.log('More results like if it were sync...');
});

@Alexey Petrushin 2013-10-19 17:50:02

He asked explicitly about sync version, not control flow libraries.

@nab 2013-10-20 10:57:47

@AlexeyPetrushin Every question here is about a goal, not about particular way to achieve it. Thanks for downvoting though.

@Mendhak 2014-01-02 12:56:41

Also, this is a very useful answer for Windows users; installing exec-sync or ffi on Windows has a huge overhead (VC++, SDKs, Python, etc), but this is lighter.

@Marcus Pope 2012-01-29 07:45:30

you can do synchronous shell operations in nodejs like so:

var execSync = function(cmd) {

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

    //for linux use ; instead of &&
    //execute your command followed by a simple echo 
    //to file to indicate process is finished
    exec(cmd + " > c:\\stdout.txt && echo done > c:\\sync.txt");

    while (true) {
        //consider a timeout option to prevent infinite loop
        //NOTE: this will max out your cpu too!
        try {
            var status = fs.readFileSync('c:\\sync.txt', 'utf8');

            if (status.trim() == "done") {
                var res = fs.readFileSync("c:\\stdout.txt", 'utf8');
                fs.unlinkSync("c:\\stdout.txt"); //cleanup temp files
                fs.unlinkSync("c:\\sync.txt");
                return res;
            }
        } catch(e) { } //readFileSync will fail until file exists
    }

};

//won't return anything, but will take 10 seconds to run
console.log(execSync("sleep 10")); 

//assuming there are a lot of files and subdirectories, 
//this too may take a while, use your own applicable file path
console.log(execSync("dir /s c:\\usr\\docs\\"));

EDIT - this example is meant for windows environments, adjust for your own linux needs if necessary

@Marcus Pope 2012-02-01 22:06:54

Yes, and as fast as your CPU can possibly summon... But hey when you "need" to do something evil, Satan's your man right?

@Robert Gould 2012-03-27 10:35:12

ok, this is pure evil, but awesome. I needed this to handle a filesystem event browserify.on('register'), that did not have a callback. Saved my day!

@badunk 2013-02-20 20:03:08

can you explain why this works on javascript engines? shouldn't the while loop be executed infinitely on the same tick while exec executes on the next one?

@Louis 2013-10-31 12:27:53

Maxing out the CPU by busy waiting is bad design.

@Marcus Pope 2013-10-31 20:33:43

@Louis-DominiqueDubeau Sure, but there isn't really any alternative that doesn't depend on some third party source that may or may not be cross platform compatible. It's also not a true maxing out of the CPU because the OS won't give full priority to the nodejs process. I think sync implementations of shell ops are on the horizon or perhaps here already.

@Marcus Pope 2013-10-31 20:35:35

@badunk - IIRC, exec spawns the process immediately, and the while loop would run in the next tick until the OS created the temp file. Haven't had to use this logic since so I'm not sure if internals have changed :/

@scherka 2011-12-24 15:21:55

I get used to implement "synchronous" stuff at the end of the callback function. Not very nice, but it works. If you need to implement a sequence of command line executions you need to wrap exec into some named function and recursively call it. This pattern seem to be usable for me:

SeqOfExec(someParam);

function SeqOfExec(somepParam) {
    // some stuff
    // .....
    // .....

    var execStr = "yourExecString";
    child_proc.exec(execStr, function (error, stdout, stderr) {
        if (error != null) {
            if (stdout) {
                throw Error("Smth goes wrong" + error);
            } else {
                // consider that empty stdout causes
                // creation of error object
            }
        }
        // some stuff
        // .....
        // .....

        // you also need some flag which will signal that you 
        // need to end loop
        if (someFlag ) {
            // your synch stuff after all execs
            // here
            // .....
        } else {
            SeqOfExec(someAnotherParam);
        }
    });
};

@Ivo Wetzel 2010-12-14 20:10:47

This is not possible in Node.js, both child_process.spawn and child_process.exec were built from the ground up to be async.

For details see: https://github.com/ry/node/blob/master/lib/child_process.js

If you really want to have this blocking, then put everything that needs to happen afterwards in a callback, or build your own queue to handle this in a blocking fashion, I suppose you could use Async.js for this task.

Or, in case you have way too much time to spend, hack around in Node.js it self.

@Alfred 2010-12-14 23:45:01

strange because the file system module has synchronous calls. Why not also execute?

@Ivo Wetzel 2010-12-15 06:46:53

@Alfred The sync FS calls are mainly in there for loading of configs at program start.

@Marcus Pope 2012-01-29 07:49:30

@IvoWetzel - tisk tisk... haven't we learned to never say something is impossible? ;) see my solution below.

@flow 2013-11-16 16:31:51

@IvoWetzel "The sync FS calls..."—right, and sometimes you want to, say, issue a command to compile something at program start and continue on completion.—given that there are sync FS calls, not having a sync exec does look like an oversight. i'm all for asynchronous, but synchronous does have its pros and use cases. gotta use it in a judicious way, of course.

@Lloyd Sargent 2014-01-08 01:05:40

Async is fine, but if WidgetB depends on the final results of WidgetA, all the async in the world won't get the job done. Sometimes processes have to be synchronous. Try cooking asynchronously. ;)

Related Questions

Sponsored Content

63 Answered Questions

[SOLVED] Calling an external command from Python

16 Answered Questions

[SOLVED] Writing files in Node.js

18 Answered Questions

[SOLVED] How to exit in Node.js

  • 2011-03-10 21:30:05
  • Bryan Field
  • 848005 View
  • 1776 Score
  • 18 Answer
  • Tags:   node.js

36 Answered Questions

[SOLVED] How do I debug Node.js applications?

14 Answered Questions

[SOLVED] Check synchronously if file/directory exists in Node.js

  • 2010-12-19 11:19:43
  • Ragnis
  • 713204 View
  • 1117 Score
  • 14 Answer
  • Tags:   node.js

6 Answered Questions

[SOLVED] Read environment variables in Node.js

31 Answered Questions

3 Answered Questions

[SOLVED] How do I get started with Node.js

  • 2010-03-01 04:09:28
  • Joneph O.
  • 1230707 View
  • 1264 Score
  • 3 Answer
  • Tags:   javascript node.js

12 Answered Questions

[SOLVED] What is the purpose of Node.js module.exports and how do you use it?

  • 2011-03-15 11:56:10
  • mrwooster
  • 469153 View
  • 1402 Score
  • 12 Answer
  • Tags:   javascript node.js

17 Answered Questions

[SOLVED] How to decide when to use Node.js?

Sponsored Content