Capturing Terminal Output With Node.js
January 20, 2018
In this post I’ll demonstrate how to capture and act upon output a Node.js program.
The code that does the capturing:
// capture-internal-process.js
//
// ======================================
// Capture and Trigger Function on Output
// stdout produced internally
//
// We accept:
// success_condition
// - check this on output
//
// success_fn
// - invoked when success_condition is true
function capture(success_condition, success_fn) {
const real_stdout = process.stdout.write
process.stdout.write = process_output
function process_output(output) {
real_stdout.apply(process.stdout, [output])
if (success_condition(output)) {
// Restore stdout
process.stdout.write = real_stdout
success_fn()
}
}
}
Test case:
In this test case, we’ll re-enact a scene from 2001: A Space Odyssey. Here astronaut Dave is trying to persuade Hal to open the pod bay doors.
I’ve altered the scene so that if Hal says the word “mission”, the pod bay doors will open and the program will stop.
If we don’t successfully capture the word “mission”, Dave is doomed to perish in outer space.
// capture-internal-process.js (continued)
//
// =========
// Test case
function test_case() {
const lines = [
"DAVE: Open the pod bay doors, Hal.",
"HAL: I’m sorry, Dave. I’m afraid I can’t do that.",
"DAVE: What’s the problem?",
"HAL: I think you know what the problem is just as well as I do.",
"DAVE: What are you talking about, Hal?",
"HAL: This mission is too important ...",
"HAL: ... for me to allow you to jeopardize it.",
"DAVE: I don’t know what you're talking about, Hal.",
"HAL: I know that you and Frank were planning to disconnect me,",
"HAL: ... and I’m afraid that's something I can’t allow to happen.",
"DAVE: Where the hell did you get that idea, Hal?",
"HAL: Although you took very thorough precautions in the pod",
"HAL: ... against my hearing you, I could see your lips move.",
"DAVE: All right, Hal. I’ll go in through the emergency air lock.",
"HAL: Without your space helmet, Dave, ...",
"HAL: ... you’re going to find that rather difficult.",
"DAVE: Hal, I won’t argue with you anymore. Open the doors!",
"HAL: Dave...This conversation can serve no purpose anymore.",
"HAL: Goodbye."
]
// Display the next line in `lines` and
// remove it from the array
function display_line() {
console.log(lines.shift())
// If we're properly capturing output, the program
// will end before this if statement is true
if (lines.length == 0)
dave_never_gets_back_in()
}
// This function should execute when Hal says 'mission'
function dave_gets_back_in() {
console.log(`
Hal says 'mission' and the pod bay doors open!
Dave climbs back into the spacecraft and disables Hal.
`)
process.exit()
}
// This function should never execute
function dave_never_gets_back_in() {
console.log(`
This line should never be reached.
Dave is trapped out in space forever!
`)
process.exit()
}
// Check to see if the output contains the word 'mission'
const hal_says_mission = output => output.includes('mission')
// Capture and check all output
capture(hal_says_mission, dave_gets_back_in)
// Output each line each line, one a second
setInterval(display_line, 1000)
}
test_case()
In an upcoming post I’ll demonstrate capturing output from an external program spawned by Node (update: that post is now up).
Enjoy!