Skip to content

Instantly share code, notes, and snippets.

@millermedeiros
Last active September 10, 2022 03:06
Show Gist options
  • Save millermedeiros/4724047 to your computer and use it in GitHub Desktop.
Save millermedeiros/4724047 to your computer and use it in GitHub Desktop.
execute multiple shell commands in series on node.js
// USAGE ------
// ============
var shell = require('./shellHelper');
// execute a single shell command
shell.exec('npm test --coverage', function(err){
console.log('executed test');
}});
// execute multiple commands in series
shell.series([
'node build release'
'git add -A',
'git commit --verbose'
], function(err){
console.log('executed many commands in a row');
});
// spawn a child process and execute shell command
// borrowed from https://github.com/mout/mout/ build script
// author Miller Medeiros
// released under MIT License
// version: 0.1.0 (2013/02/01)
// execute a single shell command where "cmd" is a string
exports.exec = function(cmd, cb){
// this would be way easier on a shell/bash script :P
var child_process = require('child_process');
var parts = cmd.split(/\s+/g);
var p = child_process.spawn(parts[0], parts.slice(1), {stdio: 'inherit'});
p.on('exit', function(code){
var err = null;
if (code) {
err = new Error('command "'+ cmd +'" exited with wrong status code "'+ code +'"');
err.code = code;
err.cmd = cmd;
}
if (cb) cb(err);
});
};
// execute multiple commands in series
// this could be replaced by any flow control lib
exports.series = function(cmds, cb){
var execNext = function(){
exports.exec(cmds.shift(), function(err){
if (err) {
cb(err);
} else {
if (cmds.length) execNext();
else cb(null);
}
});
};
execNext();
};
@rafaelrinaldi
Copy link

Loved this idea, going to implement something like thins on my default build system.
Found a good library to deal with shell commands, don't know if you already use it: shelljs

@shurane
Copy link

shurane commented Nov 15, 2014

There's always async for control flow, too.

@bitsofinfo
Copy link

Cool lib, if you want to exec all the commands over the same shell instance you could try this too: https://github.com/bitsofinfo/stateful-process-command-proxy

@cagataycali
Copy link

maybe you can use g3l.
https://www.npmjs.com/package/g3l

@gsundin
Copy link

gsundin commented Apr 10, 2017

Is there a way to log the terminal output from running commands with this?

@cagcak
Copy link

cagcak commented Apr 22, 2017

the shell.series results that no way to pass a shell command containing whitespaces inside a string

@jay16
Copy link

jay16 commented Nov 16, 2018

thanks!

var chalk = require('chalk')
const { exec } = require('child_process');

var version = require('../version')
var type = process.argv[2],
    moduler = process.argv[3],
    message = process.argv.slice(4, process.argv.length).join(' '),
    commands = [
      "git add .",
      "git commit -m \"" + type + "@" + version.pro_version + "(" + moduler + "): " + message + "\"",
      "git push origin $(git symbolic-ref --short -q HEAD)"
    ]

var exec_commands = (commands) => {
  var command = commands.shift()
  exec(command, (error, stdout, stderr) => {
    console.log(chalk.gray("$ ") + chalk.yellow(command))
    console.log("")
    if (error) {
      console.error(chalk.red(error));
      process.exit(1)
      return;
    }
    if(stdout) console.log(chalk.gray(stdout));
    if(stderr) console.log(chalk.gray(stderr));

    if(commands.length) exec_commands(commands)
  });
}
exec_commands(commands)

@ParadeTo
Copy link

ParadeTo commented Sep 3, 2019

It cannot support this situation: cd to somewhere and then execute the command under that path

@daslicht
Copy link

It cannot support this situation: cd to somewhere and then execute the command under that path

you found a solution for this ?

@swick7
Copy link

swick7 commented Jun 24, 2020

I would also like to see a solution that allows me to pipe the output from one command to the next, like any unix shell allows. For example: find . -name "*.js" | sort | uniq | wc -l

@definoob
Copy link

can we pass env variables here like below?

cycle=312 node index.js

@rajiff
Copy link

rajiff commented Mar 9, 2021

I would also like to see a solution that allows me to pipe the output from one command to the next, like any unix shell allows. For example: find . -name "*.js" | sort | uniq | wc -l

you can use async.workflow (https://caolan.github.io/async/v3/), that does exactly what you are hoping for

if that's not enough, please take a look at https://caolan.github.io/highland/ it does in style of streams

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment