Drahcir
Drahcir

Reputation: 11972

Execute cygwin command from NodeJS

Using Node's child_process module, I'd like to execute commands via the cygwin shell. This is what I'm trying:

var exec = require('child_process').execSync;
exec('mkdir -p a/b/c', {shell : 'c:/cygwin64/bin/bash.exe -c'});
TypeError: invalid data
    at WriteStream.Socket.write (net.js:641:11)
    at execSync (child_process.js:503:20)
    at repl:1:1
    at REPLServer.defaultEval (repl.js:262:27)
    at bound (domain.js:287:14)
    at REPLServer.runBound [as eval] (domain.js:300:12)
    at REPLServer. (repl.js:431:12)
    at emitOne (events.js:82:20)
    at REPLServer.emit (events.js:169:7)
    at REPLServer.Interface._onLine (readline.js:212:10)

I can see Node's child_process.js will add the /s and /c switches, regardless of the shell option being set, bash.exe doesn't know what to do with these arguments.

I found a work around for this problem but it's really not ideal:

exec('c:/cygwin64/bin/bash.exe -c "mkdir -p a/b/c"');

Doing the above would obviously only work on Windows not unix systems.

How can I execute commands in the cygwin shell from NodeJS?

Upvotes: 13

Views: 1201

Answers (1)

Jean Vincent
Jean Vincent

Reputation: 12435

This is not a complete generic solution, because more would need to be done with some of the options of exec(), but this should allow you to write code that will work on unixes, Windows and cygwin, differentiating between the later two.

This solution assumes that Cygwin is installed in a directory which name includes the string cygwin.

var child_process = require( 'child_process' )
  , home = process.env.HOME
;

function exec( command, options, next ) {
  if( /cygwin/.test( home ) ) {
    command = home.replace( /(cygwin[0-9]*).*/, "$1" ) + "\\bin\\bash.exe -c '" + command.replace( /\\/g, '/' ).replace( /'/g, "\'" ) + "'";
  }

  child_process.exec( command, options, next );
}

You could alternatively hijack child_process.exec conditionally when running under Cygwin:

var child_process = require( 'child_process' )
  , home = process.env.HOME
;

if( /cygwin/.test( home ) ) {
  var child_process_exec = child_process.exec
    , bash = home.replace( /(cygwin[0-9]*).*/, "$1" ) + "\\bin\\bash.exe"
  ;

  child_process.exec = function( command, options, next ) {
    command = bash + " -c '" + command.replace( /\\/g, '/' ).replace( /'/g, "\'" ) + "'";

    child_process_exec( command, options, next )
  }
}

Upvotes: 4

Related Questions