Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute cygwin command from NodeJS

Tags:

node.js

cygwin

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?

like image 871
Drahcir Avatar asked Sep 06 '16 13:09

Drahcir


1 Answers

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 )
  }
}
like image 114
Jean Vincent Avatar answered Oct 15 '22 15:10

Jean Vincent