Skip to content

Weird behaviour when spawning bash scripts #29831

Closed
@Choppel

Description

@Choppel

There seem to be multiple issues when spawning bash scripts. Regular binaries (e.g. php, docker) seem to work fine at this point. I am running nodejs v10.16.3 on ubuntu.

Summary

When spawning a bash script with nodejs with stdin set to inherit, the output of the read command inside the bash script is not printed to stdout. It is printed to stderr although I think it doesn't belong there.
When setting stdin to pipe and piping process.stdin to this pipe, the output of the read command is not available anymore on stderr. Also, the app can only be exited by hitting enter after the child process exited.

Test cases

Consider the following bash script to be spawned via nodejs

#!/bin/sh

echo "Greeting"
read -r -p "Input: " varA

echo "Output ${varA}"

Case 1.) nodejs file spawning the bash script with stdin set to inherit

'use strict';

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

const child = spawn(path.join(__dirname, 'index.sh'), null, {
  'stdio': ['inherit']
});

child.stdout.on('data', (data) => {
  console.log('stdout: ' + data);
});

child.stderr.on('data', (data) => {
  console.log('stderr: ' + data);
});

child.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

Calling the script above in a terminal ("node index.js"), the output is the following

stdout: Greeting

stderr: Input: 
a
stdout: Output a

child process exited with code 0

The weird part here is that the "read -p" text "Input: " is written to stderr. Is that a bug with bash or its "read" command? Or is nodejs doing something wrong. Everything else seems to work right at this point.

Case 2.) nodejs file spawning the bash script with stdin set to pipe

'use strict';

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

const child = spawn(path.join(__dirname, 'index.sh'), null, {
  'stdio': ['pipe']
});

process.stdin.pipe(child.stdin);

child.stdout.on('data', (data) => {
  console.log('stdout: ' + data);
});

child.stderr.on('data', (data) => {
  console.log('stderr: ' + data);
});

child.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

Calling the script above in a terminal ("node index.js"), the output is the following

stdout: Greeting

a
stdout: Output a

child process exited with code 0

You can see the first echo ("Greeting") of the bash script and it is written to stdout. The text of the "read" command ("Input: ") is not visible anymore. The rest of the script is running as expected except that after the child process exits I have to hit enter a second time to exit the whole application.

Case 3.) nodejs file spawning the bash script with stdout, stderr and stdin set to pipe

'use strict';

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

const child = spawn(path.join(__dirname, 'index.sh'), null, {
  'stdio': 'pipe'
});

process.stdin.pipe(child.stdin);
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);

child.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

The output and behaviour is basically the same as in case 2.

Greeting
d
Output d
child process exited with code 0

The "Input: " line is not visible and I have to hit enter after "child process exited..." to exit the application.

Addendum

For one of our products I need to automate different external applications (e.g. php scripts, docker commands, bash scripts). I want to pipe stdin, stderr and stdout so that I can read from stdout and write to stdin. If a specific line is written to stdout (e.g. "Do you really want to start the process now?") I 'answer' by writing "y\n" to stdin and the external process continues.
Because of the problems described above I am not able to do this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions