How to prefix every line of the output of a child_process spawn() call with text?
Asked Answered
H

2

5

I execute several processes using spawn() from child_process.

const { spawn } = require('child_process');

spawn("sh", ["script1.sh"], { shell: false, stdio: "inherit"});
spawn("sh", ["script2.sh"], { shell: false, stdio: "inherit"});
spawn("sh", ["script3.sh"], { shell: false, stdio: "inherit"});

Question: How to prefix the output of the scripts with text?

The idea is that I would be able to easily distinguish what each script logs.

I went through the spawn documentation but couldn't find anything that would help achieve this.

Note: I cannot modify the scripts.

Hampden answered 1/12, 2020 at 14:23 Comment(0)
B
8

You have stdio set to "inherit".

If you set this to "pipe", Node.js will give you back readable streams for stderr and stdin, which you can use to add your prefix.

const { spawn } = require('child_process');

const one = spawn("sh", ["script1.sh"], { shell: false, stdio: "pipe"});
let oneStdout = ''
one.stdout.on('data', function (chunk) {
  oneStdout += chunk
  const lines = oneStdout.split('\n')
  while(lines.length > 1) {
    const line = lines.shift()
    console.log('one',line)
  }
  oneStdout = lines.shift()
})
one.stdout.on('end', function () {
  console.log('one', oneStdout)
})

Here is the relevant section in the docs: https://nodejs.org/api/child_process.html#child_process_subprocess_stdio

Potential gotcha:

When "prefixing" you likely want to prefix each new line but not all scripts write to stdout a full line at a time. Play around with a few scripts that use echo -n "foobar" throughout the output to test that you're handling line breaks correctly.

Botulinus answered 3/12, 2020 at 20:51 Comment(0)
M
2

Here is how I run external commands and capture their output, e.g. to prefix each line with a timestamp:

const { spawn } = require("child_process"),
  command = "echo",
  args = ["Studies have shown that people watch TV more than any other appliance."];

const child = spawn(command, args);

child.stdout.on('data', buff => {
  const line = buff.toLocaleString();
  console.info(new Date(), line);
});
child.stderr.on('data', buff => { // also catch any error output
  const line = buff.toLocaleString();
  console.error(new Date(), line);
});
child.on('exit', code => {console.info(`Command exited with code ${code}`)});

Here's what it looks like when you run it:

$ node thatScript.js 
2020-12-10T11:46:51.455Z Studies have shown that people watch TV more than any other appliance.

Command exited with code 0
$ 
Maki answered 10/12, 2020 at 11:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.