Skip to content

Instantly share code, notes, and snippets.

@sptramer
Created May 3, 2012 05:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sptramer/2583397 to your computer and use it in GitHub Desktop.
Save sptramer/2583397 to your computer and use it in GitHub Desktop.
CLI ipc support
/*
* Uses child_process (stable: 3)
*/
var child_process = require('child_process');
var console = require('console');
/*
* NOTE: Because node is naturally asynchronous, this is inappropriate.
* We require blocking on execs, which means that we need to use an
* infrastructure which allows blocking...
* BUT these all rely on node-fibers, which, from the git page:
* "Only Linux, SunOS and OS X environments are supported.
Windows support is totally possible, but I'm not going to do it for you."
* https://github.com/laverdet/node-fibers
*
* We require Windows support.
*/
// NOTE: We can, however, always follow a pattern where the callback
// on an invoke then resumes program flow control... but this is
// cumbersome and may often be inappropriate.
//
// Note that we could do a very gross and naieve usleep()
// with this: https://github.com/ErikDubbelboer/node-sleep
// Chances of that code ever failing are pretty much zero,
// unless node changes V8 interface.
child_process.exec("ps aux", function(error, stdout, stderr) {
console.log(stdout);
});
// Always going to be printed before the exec() exit
console.log('Finished!');
// spawn() has similar problems, although the object it returns
// has an 'exit' event, which makes it easier to synchronize.
// Also, for long-running events, synchronous behavior may not
// always be desired (i.e. we want to pump the child process
// stdin/stdout to a specialized log). node is actually good at this.
// Also there is the VERY IMPORTANT consideration from the nodejs docs,
// regarding the stdout "readable stream":
/*
Note that the data will be lost if there is no listener
when a Readable Stream emits a 'data' event.
*/
// This implies that if a process begins before we can
// attach a listener to the stream (node is async) we may lose
// data.
var ps = child_process.spawn("ps", ['aux']);
var grep = child_process.spawn("grep", ['node']);
ps.stdout.on('data', function(data) {
grep.stdin.write(data.toString());
});
ps.stderr.on('data', function(data) {
console.warn('ps stderr: '+data);
});
ps.on('exit', function(code) {
if (code != 0) {
console.error('ps exit code error: '+code);
}
grep.stdin.end();
});
grep.stdout.on('data', function(data) {
console.log(data.toString());
});
grep.stderr.on('data', function(data) {
console.warn('grep stderr: '+data);
});
grep.on('exit', function(code) {
if (code != 0) {
console.error('grep exit code error: '+code);
}
});
#!/usr/bin/env python
import subprocess
import sys
import time
# lowly exec - note that we could hook stdout/stdin to a logger filehandle
result = subprocess.call(["ps", "aux"]);
print "Finished!"
# longer process
ps = subprocess.Popen(["ps", "aux"],
stdin=None,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
grep = subprocess.Popen(["grep", "py"],
stdin=ps.stdout,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
# Note that instead of a poll loop, we could instead
# tie the stdout/stderr of the process to a logger
# handler
while grep.poll() is None:
for line in grep.stderr:
print 'grep stderr: ', line.rstrip()
for line in grep.stdout:
print line.rstrip()
time.sleep(100 / 1e6) #usleep(100)
#!/usr/bin/env ruby
# As with python, ruby can tie file descriptors to logs, and redirect stdin/stdout/stderr
# making this a bit more flexible.
Process.waitpid(spawn("ps", "aux"));
ps = IO.popen(["ps", "aux"])
IO.popen(["grep", "ruby"], mode="r+") do |grep|
ps.each { |line| grep.write(line) }
grep.close_write
puts grep.read
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment