Why is my Node child process that I created via spawn() hanging? - node.js

I am using spawn() to make a git call. Sometimes it works fine but others it appears to be hanging. I see no events firing (error, exit, close) yet I see evidence that the process did in fact complete successfully.
var spawn = require('child_process').spawn;
spawn('git', ['push', 'origin', 'master'])
.on('error', function(error) {
console.log("ERROR: DETAILS: " + error);
})
.on('close', function(code) {
console.log("SUCCESS: CODE: " + code);
})
.on('exit', function(code) {
console.log("EXIT: CODE: " + code);
})

As it turns out once the stderr buffer exceeds 24kb you must be reading from it or you not see any events for completion. Possible workarounds:
Set the stdio option on the spawn call.
spawn('git', ['push', 'origin', 'master'], {stdio: 'ignore'});
See Node ChildProcess doc for all of the possibilities - there are lots.
Add an on(data) handler.
var git = spawn('git', ['push', 'origin', 'master']);
...
git.stderr.on('data', function(data) {
// do something with it
});
Pipe it to stdout / stderr. This may be too verbose for your application but including it for completeness.
var git = spawn('git', ['push', 'origin', 'master']);
...
git.stderr.pipe(process.stderr);
git.stdout.pipe(process.stdout);

Related

How to get the output from a Mac OS executable file in node js?

I have an executable file that outputs every few seconds of data once i run it via the Terminal on Mac OS.
How can i get the data using node js?
Thank you.
You can run the command, which you run in the terminal, as a Node.js child process using spawn or exec.
Example:
const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
ls.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
The more information you can find here

nodejs: do not wait spawned process

I am using child_process.spawn for running some app and I want to execute some actions after this app was started. But spawn blocks main process
const spawnAsync = Promise.promisify(require('child_process').spawn);
console.log('BEFORE');
await spawnAsync('../node_modules/.bin/some-app', ['-p', '3333'], {
detached: true
});
console.log('AFTER');
In my console, I see BEFORE and AFTER would be logged only after killing process on 3333 port. I don't want to wait spawned process, I want to do some actions after spawnSync calling.
Looking at spawn documentation you should use it that way
const childProcess = require('child_process');
const newProcessDescriptor = childProcess.spawn(
'../node_modules/.bin/some-app',
['-p', '3333'],
{ detached: true }
);
newProcessDescriptor.on('error', (error) => {
console.log(`child process creating error with error ${error}`);
});
newProcessDescriptor.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});

How to run a windows batch file with node js

What I have tried: Using Node JS Child Process API to spawn the bat file in my projectfolder. But I couldnt get it running.
projectfolder/
├──src/
| ├──app
| ├──home
| ├──home.component.ts
|── my.bat (File Type: Bat shortcut)
home.component.ts
let spawn = require('child_process').spawn,
ls = spawn('cmd.exe', ['/c', 'my.bat']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
ls.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
Error
stderr: 'my.bat' is not recognized as an internal or external command,
operable program or batch file.
home.component.ts?71c4:159 child process exited with code 1
I have also tried
const exec = require('child_process').execFile;
exec('my.bat', function (err, data) {
console.log(err);
console.log(data);
});
with error
Error: spawn my.bat ENOENT
at exports._errnoException (util.js:1050)
at Process.ChildProcess._handle.onexit (internal/child_process.js:193)
at onErrorNT (internal/child_process.js:367)
at _combinedTickCallback (internal/process/next_tick.js:80)
at process._tickCallback (internal/process/next_tick.js:104)
Update: I found the issue.
My File Type is a Bat shortcut
The above code only works for Windows Batch File, but not a shortcut

node.js: How to spawn detached child in foreground and exit

According to the docs for child_process.spawn I would expect to be able to run a child process in the foreground and allow the node process itself to exit like so:
handoff-exec.js:
'use strict';
var spawn = require('child_process').spawn;
// this console.log before the spawn seems to cause
// the child to exit immediately, but putting it
// afterwards seems to not affect it.
//console.log('hello');
var child = spawn(
'ping'
, [ '-c', '3', 'google.com' ]
, { detached: true, stdio: 'inherit' }
);
child.unref();
Instead of seeing the output of the ping command, it simply exits without any message or error.
node handoff-exec.js
hello
echo $?
0
So... is it possible in node.js (or at all) to run a child in the foreground as the parent exits?
Buggy Node Versions
I found that removing console.log('hello'); allows the child to run, however, it still doesn't pass foreground stdin control to the child. That's obviously not intended, therefore something must be buggy in the version of node I was using at the time...
https://github.com/nodejs/node/issues/5549
Solution
The code in the question was actually correct. There was a legitimate bug in node at the time.
'use strict';
var spawn = require('child_process').spawn;
console.log("Node says hello. Let's see what ping has to say...");
var child = spawn(
'ping'
, [ '-c', '3', 'google.com' ]
, { detached: true, stdio: 'inherit' }
);
child.unref();
The snippet above will run effectively the same as if it had been backgrounded by the shell:
ping -c 3 google.com &
You are missing
// Listen for any response:
child.stdout.on('data', function (data) {
console.log(data.toString());
});
// Listen for any errors:
child.stderr.on('data', function (data) {
console.log(data.toString());
});
and you don't need the child.unref();

Launching Two Node Child Processes From Single Gulp File Results In Error: listen EADDRINUSE

I'd like to manage two apps with one gulpfile. I can launch them both with the following code. However, when I modify one of the files, and gulp.watch restarts the server, I get Error: listen EADDRINUSE. Something must be wrong in my gulp server task, but what is it?
// Dependencies
var gulp = require('gulp'),
spawn = require('child_process').spawn,
node;
// Server Task
gulp.task('server', function() {
if (api) node.kill();
if (dashboard) node.kill();
var api = spawn('node', ['./api/server.js'], {
stdio: 'inherit'
});
var dashboard = spawn('node', ['./dashboard/server.js'], {
stdio: 'inherit'
});
api.on('close', function(code) {
if (code === 8) console.log('API – Error detected, waiting for changes...');
});
dashboard.on('close', function(code) {
if (code === 8) console.log('Dashboard – Error detected, waiting for changes...');
});
});
// Watch Statement
gulp.task('default', ['server'], function() {
// Watch files for changes
gulp.watch(alljsLocations, ['server'], function() {});
});

Resources