73

I am trying to spawn an external process phantomjs using node's child_process and then send information to that process after it was initialized, is that possible?

I have the following code:

var spawn = require('child_process').spawn,
    child = spawn('phantomjs');

child.stdin.setEncoding = 'utf-8';
child.stdout.pipe(process.stdout);

child.stdin.write("console.log('Hello from PhantomJS')");

But the only thing I got on the stdout is the initial prompt for phantomjs console.

phantomjs> 

So it seems the child.stdin.write is not making any effect.

I am not sure I can send additional information to phantomjs ater the initial spawn.

starball
  • 20,030
  • 7
  • 43
  • 238
zanona
  • 12,345
  • 25
  • 86
  • 141
  • just in case someone is using IPC and JSON serialization, what I observed is that it sends message from Child-to-Parent but not Parent-to-Child using `send()` function. When I used `fork` instead of `spawn`, it started sending messages in both ways. – Ankur Thakur Apr 27 '23 at 14:07

2 Answers2

132

You need to pass also \n symbol to get your command work:

var spawn = require('child_process').spawn,
    child = spawn('phantomjs');

child.stdin.setEncoding('utf-8');
child.stdout.pipe(process.stdout);

child.stdin.write("console.log('Hello from PhantomJS')\n");

child.stdin.end(); /// this call seems necessary, at least with plain node.js executable
Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
Vadim Baryshev
  • 25,689
  • 4
  • 56
  • 48
  • yes but why? or maybe a semicolon instead of a newline, also? – Alexander Mills Dec 17 '16 at 06:00
  • 1
    I added the child.stdin.end() call – Alexander Mills Dec 17 '16 at 06:18
  • 9
    @AlexanderMills CLRF `\r\n` since it's the line terminator that triggers `write` to pipe a new line. `child.stdout.pipe(process.stdout);` is unnecessary actually. – loretoparisi May 03 '17 at 01:03
  • 8
    The `child.stdin.end()` call is critical. Banged my head for a while until I found this. Thanks @AlexanderMills – karmakaze Jul 26 '18 at 20:46
  • 5
    @AlexanderMills child.stdin.end() isn't critical, In my case i need the process to stay open. And write as i need. to run some tts command (so it will be fast). And it work fine without child.stdin.end() [\r\n is the critical thing, which is well known] [I'm spawning powershell.exe, don't know about phanthomjs]. [How it's different for you ? How it's critical? ty] – Mohamed Allal Apr 29 '19 at 18:50
  • 1
    adding stdin.end creates an infinite loop for me. in my case I want the process to wait for the next user input and stay open. – Alok Rajasukumaran Mar 11 '20 at 06:00
  • without child.stdin.end(); sometimes the child process sis not taking the input even with \r and ]n – Alok Rajasukumaran Mar 15 '20 at 19:20
4

You need to surround your write by cork and uncork, the uncork method flushes all data buffered since cork was called. child.stdin.end() will flush data too, but no more data accepted.

var spawn = require('child_process').spawn,
    child = spawn('phantomjs');

child.stdin.setEncoding('utf-8');
child.stdout.pipe(process.stdout);

child.stdin.cork();
child.stdin.write("console.log('Hello from PhantomJS')\n");
child.stdin.uncork();
Jennal
  • 77
  • 1
  • 2
  • 11