Node child process spawn stdout returning as null
Asked Answered
S

3

19

I'm writing a Yeoman generator and using child_process.spawn() (via yeoman's spawnCommand() - see https://github.com/yeoman/generator/blob/master/lib/actions/spawn_command.js)

My code looks like this:

var list = this.spawnCommand('npm', ['list', 'sails'], {stdio: 'pipe'});
list.stdout.on('data', /* callback here that wants to consume the command's output */);

I can see that list.stdio exists, and that it has [0,1,2] as keys. Each of them is null (or undefined). That is, logging _.keys(list).join() outputs ,,. list.stdout.on() gives me an exception stating that stdout is null.

What I need to accomplish is to check whether a particular packages is installed and see what the version number is. But I also later need to do other things where I parse the output of CLI commands (for example, git log output), so I need a general solution. .spawn() seems like what I want, but examples I've seen seem to indicate that stdout should be something that has an .on() method. For example, the one given here: http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options where it shows running ls -lh /usr.

Am I missing something simple? I'm wondering if the command I run returns no output at all if that means stdout will be null. If that's the case, then I'll just need to identify commands that may have no output and simply check to make sure stdout isn't null before trying to use it.

edit actually, the npm list command's output is showing up on the command line, but after the log statements I was using to diagnose the issue (which I'd put after the .spawnCommand() call and before the .on() call. But I need access to it in my code - having it show up on the command line is beside the point (other than it lets me know the process ran the CLI command successfully).

Sidman answered 5/1, 2015 at 19:12 Comment(2)
Ever find out what the cause was? I am looking for an answer now, too.Avian
Not so far :( sorrySidman
C
16

If the child was spawned with stdio set to anything other than 'pipe', then subprocess.stdout will be null.

See

Contaminate answered 3/9, 2017 at 13:41 Comment(1)
yup.. i changed stdio option to "pipe" and it works smoothly.. tyCultigen
L
15

I just ran into this – haven't looked too deep into the details, but I can tell you that setting {stdio: 'whatever'} in the spawn's option prevents the spawn from returning an object with stdout and stderr streams - both will be null.

If you remove that option, they'll be fully-fledged streams again (and accessible via .on().

From the docs you linked to, it looks like you can set the stdio to an existing stream - maybe that's the flexibility you're looking for?

Lelialelith answered 13/3, 2015 at 3:24 Comment(3)
Is there a way to set { stdio: 'inherit or whatever' } and have access to the child's stdout/stderr streams?Sardine
@KennethWorden Based on my understanding of the docs, pipe is that option, but the OP's question indicates that isn't working. Not sure why.Chian
@KennyWorden Maybe it's late now but if you do this {stdio: [process.stdin, 'pipe', process.stderr]} you can access stdin and stderr normally with spawn.stdin.on\spawn.stderr.on but to get the stdout you need to go with spawn.stdio[1].on. I'm guessing that if you use {stdio: 'pipe'} you have to access all streams from spawn.stdio array.Ingleside
L
0

The data given on('data', ...) listener is null when you already listened to on('readable', ...), I would have been happy to be aware of that so I am sharing it here 😉.

Lysimachus answered 19/6, 2020 at 7:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.