node.js execute system command synchronously

JavascriptCommandnode.jsExecSync

Javascript Problem Overview


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

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

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'));

Solution 3 - Javascript

Use ShellJS module.

exec function without providing callback.

Example:

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

Solution 4 - Javascript

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...');
});

Solution 5 - Javascript

Native Node.js solution is:

const {execSync} = require('child_process');

const result = execSync('node -v'); // 👈 this do the trick 

Just be aware that some commands returns Buffer instead of string. And if you need string just add encoding to execSync options:

const result = execSync('git rev-parse HEAD', {encoding: 'utf8'});

... and it is also good to have timeout on sync exec:

const result = execSync('git rev-parse HEAD', {encoding: 'utf8', timeout: 10000});

Solution 6 - Javascript

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.

Solution 7 - Javascript

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);

Solution 8 - Javascript

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

Solution 9 - Javascript

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');

Solution 10 - Javascript

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);
        }
    });
};

Solution 11 - Javascript

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.

Solution 12 - Javascript

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

Solution 13 - Javascript

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/

Solution 14 - Javascript

my way since 5 years is to have 2 lines ;

const { execSync } = require('child_process');
const shell = (cmd) => execSync(cmd, {encoding: 'utf8'});

Then enjoy: shell('git remote -v') or out = shell('ls -l') .. so on

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondisfatedView Question on Stackoverflow
Solution 1 - JavascriptBenjamin GruenbaumView Answer on Stackoverflow
Solution 2 - JavascriptmgutzView Answer on Stackoverflow
Solution 3 - JavascriptfalkoView Answer on Stackoverflow
Solution 4 - JavascriptnabView Answer on Stackoverflow
Solution 5 - JavascriptogramView Answer on Stackoverflow
Solution 6 - JavascriptIvo WetzelView Answer on Stackoverflow
Solution 7 - Javascriptdgo.aView Answer on Stackoverflow
Solution 8 - JavascriptkvzView Answer on Stackoverflow
Solution 9 - JavascriptOlegView Answer on Stackoverflow
Solution 10 - JavascriptscherkaView Answer on Stackoverflow
Solution 11 - JavascriptLoganView Answer on Stackoverflow
Solution 12 - JavascriptMarcus PopeView Answer on Stackoverflow
Solution 13 - JavascriptJason LivesayView Answer on Stackoverflow
Solution 14 - JavascriptAbdennour TOUMIView Answer on Stackoverflow