I am new to node.js and following some tutorials. In one of them, I execute the following code and expect to shutdown the terminal gracefully which is not the case
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(chunk) {
process.stdout.write('Data! -> ' + chunk);
});
process.stdin.on('end', function() {
process.stderr.write('End!\n');
});
process.on('SIGTERM', function() {
process.stderr.write("Why are you trying to terminate me?!? :-)");
});
console.log("Node is running as process #" + process.pid);
It works fine, but when I issue, from another terminal the following
taskkill /PID 29884 /F
I don't get the function
process.on('SIGTERM', function()....
get executed.
I came across a thread here at
What is the Windows equivalent of process.on('SIGINT') in node.js?
I get the same behavior, killing the process just goes back to the command line
Then I tried to update the code I got from the thread with some code in order to reprint the Data I enter on the console, it is not getting there (I added rl.on("data", function(chunk))
(process.platform === "win32") {
var rl = require("readline").createInterface({
input: process.stdin,
output: process.stdout
});
rl.output.setEncoding('utf8');
console.log("Node is running as process #" + process.pid);
rl.on("data", function(chunk) {
this.output.write('Data! -> ' + chunk);
});
rl.on("SIGINT", function() {
process.emit("SIGINT");
});
};
process.on("SIGINT", function() {
//graceful shutdown
process.exit();
});
The
rl.on("data", function(chunk) {
this.output.write('Data! -> ' + chunk);
});
just sends back 'Data! -> ' string without the text I enter in the console as the case with the 1st code from the tutorial. What is missing?
Of course, In both cases
process.stderr.write("Why are you trying to terminate me?!? :-)");
is not getting executed
Thanks
Related
I'm looking to build a project based on node that will have a few different websocket connections, I'm fine with the code itself for what I want to do but can't seem to get my head around how to start the websocket modules (code already written and moved to a file named ws.js) to run from the main server.js file.
I have tried spawning as a child process but just get
Error: spawn ws.js ENOENT
I have removed all other code from each file to prevent hidden errors, content of the files are below.
Server.js
var child = require('child_process').spawn('node', ['ws.js']);
child.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
child.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
setTimeout(function() {
child.stdin.write('echo %PATH%');
}, 2000);
ws.js
const Gdax = require('gdax');
const publicClient = new Gdax.PublicClient();
const websocket = new Gdax.WebsocketClient(['BTC-USD', 'ETH-USD']);
websocket.on('message', data => {
/* work with data */
console.log("data received");
});
websocket.on('error', err => {
/* handle error */
});
websocket.on('close', () => {
/* ... */
});
EDIT --------------------------
Thanks for the response below from Elliot server.js now runs without error however the ws.js child never writes to the console so is either not running or failing silently. Any help is appreciated on getting this working.
Cheers
For the console logs, you have to keep in mind that a child process is a new process and does not share a console. You can make it work with spawn(), however, since you are using a child process to execute a nodeJs file, I recommend using child_process.fork() instead of spawn. It is similar to spawn but is specifically used for other nodeJs processes. The benefit is that it makes it much easier for the two processes to communicate.
With that in mind, you can make the following updates:
Server.js:
var child = require('child_process').fork('./ws.js');
child.on('message', function (data) {
console.log('stdout: ' + data);
});
child.on('error', function (data) {
console.log('stderr: ' + data);
});
child.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
ws.js
const Gdax = require('gdax');
const publicClient = new Gdax.PublicClient();
const websocket = new Gdax.WebsocketClient(['BTC-USD', 'ETH-USD']);
websocket.on('message', data => {
/* work with data */
process.send("data received");
});
websocket.on('error', err => {
/* handle error */
});
websocket.on('close', () => {
/* ... */
});
process.send() sends data to its parent process, where a listener (i.e.
child.on('message', callback)) is waiting to receive it.
I am trying to render a webpage and convert it to an image with Phantomjs.
When I run the phantomjs code directly through terminal it works. When I run the code through a node.js child_process request I keep getting errors such as 'select: invalid argument' - this error loops infinitely, so I have to restart the server to end the process.
Example of my phantomDriver.js:
var page = require('webpage').create(),
system = require('system');
page.viewportSize = {
width: 1920,
height: 1080
};
/**
* Check for required parameters
*/
if (system.args.length < 2) {
console.log('Usage: report.js <some URL>');
phantom.exit();
}
page.open('https://github.com/', function(status) {
console.log('Page Loaded');
page.render('github.png');
phantom.exit();
});
My Meteor request for phantomDriver.js:
var phantomjs = Npm.require('phantomjs');
var spawn = Npm.require('child_process').spawn;
Meteor.methods({
runPhantom: function(options){
command = spawn(phantomjs.path, ['assets/app/phantomDriver.js', '']);
command.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
command.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
command.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
}
});
If I replace 'https://github.com/' with '' in the page.Open() method I get:
child process exited with code 0. It seems that phantomjs is working but something is not quite right with it opening/loading a webpage?
*** Added comment:
It seems then when I run page.open(url, function(status){}) any code inside the page.open function callback never gets executed, something happens prior to that that just loops infinitely <- not 100% sure but what it looks like.
Thank you
below is the code with is working fine with node test.js command. but whenever i am trying to run test.js with forever utility it wont work.
var terminal = require('child_process').spawn('bash');
terminal.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
terminal.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
setTimeout(function() {
console.log('Sending stdin to terminal');
terminal.stdin.write("whomi\n");
terminal.stdin.write("sudo ssh instance-solr-1.us-central1-b.versatile-nomad-126504 \"sudo su | . /root/file
.sh >>/dev/null 2>/dev/null\" &\n");
console.log('Ending terminal session');
terminal.stdin.end();
}, 1000);
I am working in node, as it happens via a visual studio code extension. I successfully create child processes and can terminate them on command. I am looking to run code when the process unexpectedly exits, this appears to be what the "exit" event is intended for, but I'm unclear on how to call it, this is the code I am working with, the process runs, but does not detect/log on exit, note that output.append is visual studio code specific version of console.log():
child = exec('mycommand', {cwd: path},
function (error, stdout, stderr) {
output.append('stdout: ' + stdout);
output.append('stderr: ' + stderr);
if (error !== null) {
output.append('exec error: ' + error);
}
});
child.stdout.on('data', function(data) {
output.append(data.toString());
});
Here's four things I have tried that do not work in logging on exit:
child.process.on('exit', function(code) {
output.append("Detected Crash");
});
child.on('exit', function(code) {
output.append("Detected Crash");
});
child.stdout.on('exit', function () {
output.append("Detected Crash");
});
child.stderr.on('exit', function () {
output.append("Detected Crash");
});
Looking at the node.js source code for the child process module, the .exec() method does this itself:
child.addListener('close', exithandler);
child.addListener('error', errorhandler);
And, I think .on() is a shortcut for .addListener(), so you could also do:
child.on('close', exithandler);
child.on('error', errorhandler);
I built a simple TCP server and a simple TCP client in Node.js
Now, when the client sends "exit" to the server, the connection is successfully closed. The server deletes the socket from its sockets list and sends "Bye bye!" to the client.
The connection on the client is closed as well but the app is still waiting for other inputs, so it doesn't die and I'm forced to type CTRL+C.
I tried adding process.exit() after connection closes but it doesn't work:
CLIENT CODE:
var net = require('net'),
config = require(__dirname + '/config.json'),
connection = net.createConnection(config.port, config.host);
connection.setEncoding('utf8');
connection.on('connect', function () {
console.log('Connected');
});
connection.on('error', function (err) {
console.error(err);
});
connection.on('data', function (data) {
console.log('ยป ' + data);
});
connection.on('close', function() {
console.log('Connection closed');
});
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.end();
process.exit();
}
else {
connection.write(data);
}
});
process.stdin.resume();
SERVER CODE:
var server = require('net').createServer(),
config = require(__dirname + '/config.json'),
sockets = [];
server.on('connection', function (socket) {
socket.setEncoding('UTF-8');
socket.on('data', function (data) {
console.log('Received data: ' + data);
if (data.trim().toLowerCase() === 'exit') {
socket.write("Bye bye!\n");
socket.end();
}
else {
sockets.forEach(function (client) {
if (client && client != socket) {
client.write(data);
}
});
}
});
socket.on('close', function () {
console.log('Connection closed');
sockets.splice(sockets.indexOf(socket), 1);
console.info('Sockets connected: ' + sockets.length);
});
sockets.push(socket);
});
server.on('listening', function () {
console.log('Server listening');
});
server.on('close', function () {
console.log('Server is now closed');
});
server.on('error', function (err) {
console.log('error:', err);
});
server.listen(config.port);
EDIT:
I added a client connection "on close" event handler. So, the string "Connection closed" is now printed by the server and by the client too.
I think you're looking for this: socket.unref().
From Node.js documentation (https://nodejs.org/api/net.html#net_socket_unref):
socket.unref()#
Calling unref on a socket will allow the program to exit if this is the only active socket in the event system. If the socket is already unrefd calling unref again will have no effect.
Some time ago when improving the tests suite for node-cubrid module, I had encountered the same problem. After all tests have passed, nodeunit process didn't quit because node-cubrid was using connection.end() to close the client socket when timeout occurs, just like you did.
Then I replaced connection.end() with connection.destroy(), a cleaner way to ensure the socket is really closed without actually terminating the running process, which, I think, is a better solution than the above suggested process.exit(). So, in your client code context, I would do:
process.stdin.on('data', function (data) {
if ((new String(data)).toLowerCase() === 'exit') {
connection.destroy();
}
else {
connection.write(data);
}
});
According to Node.js documentation:
socket.destroy()
Ensures that no more I/O activity happens on this socket. Only necessary in case of errors (parse error or so).
I doubt that if ((new String(data)).toLowerCase() === 'exit') is succeeding because data most likely has a trailing newline (in your server, you trim() before doing the comparison, but not in the client).
If that's fixed, you've got a logic problem: when getting "exit" you close the connection without sending "exit" to the server, so the server code that looks for "exit" will never execute.
You have to put the process.exit() instruction only on the last event handler. So, in this case you have to put it inside the client connection "on close" event handler:
CLIENT:
connection.on('close', function() {
console.log('Connection closed');
process.exit();
});
Try with Event: 'close' in the server:
http://nodejs.org/api/net.html#net_event_close