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}`);
});
Related
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
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();
I have running a daemon server to post the social network feeds on scheduled time.
Currently, I have issue while running daemon server which is written in node.js and express framework backed with mongodb.
Please see the following error which I got from heroku logs command.
←[36m2014-11-05T12:07:26.934753+00:00 app[web.1]:←[0m Daemon worker process is online.
←[36m2014-11-05T12:07:28.147952+00:00 app[web.1]:←[0m Starting daemon server
←[36m2014-11-05T12:07:28.230621+00:00 app[web.1]:←[0m APN agent connected.
←[36m2014-11-05T12:07:27.730718+00:00 app[web.1]:←[0m Successfully connected to MongoDB
←[36m2014-11-05T12:08:27.375215+00:00 heroku[web.1]:←[0m State changed from starting to crashed
←[36m2014-11-05T12:07:23.455341+00:00 heroku[web.1]:←[0m State changed from crashed to starting
←[36m2014-11-05T12:08:26.523383+00:00 heroku[web.1]:←[0m Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
←[36m2014-11-05T12:08:26.523870+00:00 heroku[web.1]:←[0m Stopping process with SIGKILL
←[36m2014-11-05T12:08:27.369727+00:00 heroku[web.1]:←[0m Process exited with status 137
As you can see that daemon server script run successfully but after that Heroku log showing me the boot timeout error.
var cluster = require('cluster')
if(cluster.isMaster){
cluster.fork()
cluster.on('online', function(worker){
console.log('Daemon worker process is online.')
})
cluster.on('exit', function(worker){
console.log('Daemon worker process has died. Booting another.')
cluster.fork()
})
} else {
var mongoose = require('mongoose')
var mongoDbURI
if(process.argv.indexOf('localdb') != -1){
mongoDbURI = 'mongodb://[IP]/[appname]'
} else {
//mongoDbURI = 'mongodb://[db url]'
mongoDbURI = '[db url]'
}
var mongoDbOptions = {}
if(process.env.MONGODB_URI)
mongoDbURI = process.env.MONGODB_URI
if(process.env.MONGODB_OPTIONS)
mongoDbOptions = JSON.stringify(process.env.MONGODB_OPTIONS)
var Agenda = require('agenda')
var agenda = new Agenda()
.database(mongoDbURI, 'daemonTasks')
.processEvery('1 minute')
//On termination of daemon, gracefully shut down jobs
function gracefulShutdown() {
agenda.stop(function() {
console.log("Shutting down daemon server")
process.exit(0)
})
}
process.on('SIGTERM', gracefulShutdown)
process.on('SIGINT' , gracefulShutdown)
var fs = require('fs-extra')
mongoose.connect(mongoDbURI, mongoDbOptions)
var db = mongoose.connection
db.on('error', function(err){
//If the database can not be connected to, die
console.error("Error connecting to MongoDB\r\n", err)
process.exit()
})
db.once('open', function(){
//Connection successful
console.log("Successfully connected to MongoDB")
//Begin loading our schema
require('./Models/models')(mongoose, function(err, models){
//Set up the agenda piece
var Agenda = require('agenda')
models.Agenda = new Agenda()
.database(mongoDbURI, 'daemonTasks')
// Connect to the Apple Push Notification Service
models.APNAgent = require('./Modules/apnAgent')(models)
if(err){
console.log("Error loading models\r\n", err)
process.exit()
}
var async = require('async')
fs.readdir('./Daemons/', function(err, files){
if(err){
console.log(err)
cb(err)
} else {
async.each(files, function(file, cb){
fs.lstat('./Daemons/' + file, function(err, stat){
if(err){
cb(err)
} else {
if(stat.isFile()){
var daemon = require('./Daemons/' + file)(models)
agenda.define(daemon.name, daemon.options, daemon.job)
cb(null)
} else {
cb(err)
}
}
})
}, function(err){
if(err){
console.log("Error starting daemon server: ", err)
return
}
console.log("Starting daemon server")
agenda.start()
})
}
})
})
})
}
I have researched on web and found some solutions which suggest for this problem is to increase the web process time but did not find the place on Heroku where I can set this value.
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() {});
});
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);