Wednesday, February 12, 2014

Node.js spawn command line in Linux

This is just a wrapper of the Node.js spawn in Linux containing Bash. A trick is to use /bin/bash for the child process and just pipe the command there.
run = (cmd, arg1, arg2) ->
  throw new Error 'The last argument needs to be a fn.' \
      if arg2? and typeof arg2 isnt 'function' or \
      !arg2? and typeof arg1 isnt 'function'

  options =
    'quiet': false

  if typeof arg1 is 'object'
    options[k] = v for k, v of arg1

  terminal = require('child_process').spawn('bash');

  stdout = ''
  terminal.stdout.on 'data', (data) ->
    stdout += data.toString()
    process.stdout.write data.toString() unless options['quiet']

  stderr = ''
  terminal.stderr.on 'data', (data) ->
    stderr += data.toString()
    process.stderr.write data.toString() unless options['quiet']

  terminal.on 'close', (code) ->
    stdout = stdout.replace(/^\s+|\s+$/g, '')
    stdout = if stdout.length > 0 then stdout.split '\n' else []
    stderr = stderr.replace(/^\s+|\s+$/g, '')
    stderr = if stderr.length > 0 then stderr.split '\n' else []

    callback = if typeof arg1 is 'function' then arg1 else arg2
    if code == 0
      callback null, stdout, stderr
    else
      callback new Error("#{cmd} exited with code #{code}."), stdout, stderr

  console.log "+ #{cmd} (#{new Date()})" unless options['quiet']
  terminal.stdin.write cmd
  terminal.stdin.end()

run 'ls -al *.coffee', (err, stdout, stderr) ->
  console.log err
  console.log stdout
  console.log stderr