Using stdin with a daemon process? - javascript

I have a script that needs to be running 24/7, so I have been running it using pm2. However, I also would like to be able to occasionally check on the script. Before running it as a daemon I set it to read the stdin, but for daemons this does not work. Is there a simple way to do this and run a daemon process?
I understand that this is pretty contradictory to the nature of daemons, but I need the script to run continuously and have limited user input.

It can be done by using process.spawn, the following example is taken from the book: Professional Node.js
Create a file named plus_one.js:
// unpause the stdin stream
process.stdin.resume();
process.stdin.on('data', function(data) {
var number;
try {
// parse the input data into a number
number = parseInt(data.toString(), 10);
// increment by one
number += 1;
// output the number
process.stdout.write(number + "\n");
} catch(err) {
process.stderr.write(err.message + "\n");
}
});
You can run this simple program by calling:
$ node plus_one.js
create a file named plus_one_test.js:
var spawn = require('child_process').spawn;
// Spawn the child with a node process executing the plus_one app var
child = spawn('node', ['plus_one.js']);
// Call this function every 1 second (1000 milliseconds):
setInterval(function() {
// Create a random number smaller than 10.000
var number = Math.floor(Math.random() * 10000);
// Send that number to the child process:
child.stdin.write(number + "\n");
// Get the response from the child process and print it:
child.stdout.once('data', function(data) {
console.log('child replied to ' + number + ' with: ' + data);
});
}, 1000);
child.stderr.on('data', function(data) {
process.stdout.write(data);
});
Here you launch the +1 app as a child process on lines 1 to 4.
Then you use the setInterval function to do the following every second:
Create a random natural number smaller than 10,000. Send that number as a string to the child process. Wait for the child process to reply with a string.

Related

Arduino Uno and Johnny-Five stops after few seconds

I am using Arduino Uno, Node.js and Johnny-Five for one of my projects. When I try to run the code below everything works just fine, I get the feedback from the sensor. After few seconds the Node.js just stops not giving me any reason. I tested the code on Ubuntu and Node runs infinitely but not on Windows 7. Do you know any troubleshooting technique that will help me identify why Node.js stops? Many thanks.
var five = require("johnny-five");
var board = new five.Board();
board.on("ready", function() {
// Create a new `ping` hardware instance.
var ping = new five.Ping(7);
// ping.in
//
// Calculated distance to obstruction in inches
//
// ping.cm
//
// Calculated distance to obstruction in centimeters
//
ping.on("change", function(err, value) {
console.log("Object is " + this.in + "inches away");
});
});

How to run interactive shell command inside node.js?

I have to run some interactive shell command inside node.js. Lets our interactive shell be $ python:
var cp = require('child_process');
var pythonChildProcess = cp.spawn('python');
pythonChildProcess.stdout.on("data", function(data) {
console.log('data successfully written!', data); // never outputs anything
});
pythonChildProcess.stdin.write('1 + 1');
pythonChildProcess.stdin.end();
This code does not output anything (but stdout should be 2).
But if it would, there will be another problem: how to make it interactive? The process ends when I call pythonChildProcess.stdin.end();! But I just wanted to end stdin and write next stdin!
UPD:
If I could emulate pressing of enter button - I would be able to interactively write to the process. But adding \n to the end of the input string does not help.
This works great for me:
const { spawn } = require('child_process')
const shell = spawn('sh',[], { stdio: 'inherit' })
shell.on('close',(code)=>{console.log('[shell] terminated :',code)})
First and foremost, one of the things preventing node from interfacing with other interactive shells is that the child application must keep its "interactive" behavior, even when stdin doesn't look like a terminal. python here knew that its stdin wasn't a terminal, so it refused to work. This can be overridden by adding the -i flag to the python command.
Second, as you well mentioned in the update, you forgot to write a new line character to the stream, so the program behaved as if the user didn't press Enter.
Yes, this is the right way to go, but the lack of an interactive mode prevented you from retrieving any results.
Here's something you can do to send multiple inputs to the interactive shell, while still being able to retrieve each result one by one. This code will be resistant to lengthy outputs, accumulating them until a full line is received before performing another instruction. Multiple instructions can be performed at a time as well, which may be preferable if they don't depend on the parent process' state. Feel free to experiment with other asynchronous structures to fulfil your goal.
var cp = require('child_process');
var childProcess = cp.spawn('python', ['-i']);
childProcess.stdout.setEncoding('utf8')
var k = 0;
var data_line = '';
childProcess.stdout.on("data", function(data) {
data_line += data;
if (data_line[data_line.length-1] == '\n') {
// we've got new data (assuming each individual output ends with '\n')
var res = parseFloat(data_line);
data_line = ''; // reset the line of data
console.log('Result #', k, ': ', res);
k++;
// do something else now
if (k < 5) {
// double the previous result
childProcess.stdin.write('2 * + ' + res + '\n');
} else {
// that's enough
childProcess.stdin.end();
}
}
});
childProcess.stdin.write('1 + 0\n');
A tl;dr version of #E_net4's answer, for those who understand just by reading the code. For a detailed explanation, please do read his answer. He has described it well.
var spawn = require('child_process').spawn
var p = spawn('node',['-i']);
p.stdout.on('data',function (data) {
console.log(data.toString())
});
p.stdin.write('1 + 0\n');
Output:
>
1

How does concurrency work in Node.js + Express application?

(Solution found)
I would like to start my question with code example:
var express = require('express');
var customModule = require('./custom-module');
var app = express();
// Page A
app.get('/a', function(req, res) {
res.type('text/plain');
customModule.doHeavyOperation(25, function(result) {
res.send('Page A, number = ' + result);
});
});
// Page B
app.get('/b', function(req, res) {
res.type('text/plain');
res.send('Page B');
});
app.listen(8082);
For Page A call doHeavyOperation() which performs some actions and when they are done, it runs my callback which sends some information to user.
cutsom-module.js:
exports.doHeavyOperation = function(number, callback) {
for (var i=0; i<2000000000; i++) {
number++;
}
callback(number);
};
For doHeavyOperation() it takes ~5 seconds to perform it's logic and to call my callback. When I open in my browser two pages: localhost:8082/a and localhost:8082/b, the second page needs to wait until the first one will load. That means that requests are handled not concurrently.
Instead of doHeavyOperation there can be any other function which will freeze my clients while they try to use my web application. For example, I may want to process some big images that my user upload, to apply some filters on them, etc. It can take 1-3 seconds. So if there will be 100 people using my website at the same time, it will cause big problems.
For example, Apache + PHP deals with this situation pretty good. While script a.php performs some actions, script b.php can be loaded without problems.
How to achieve this behaviour in Node.js + Express?
================================================================================
Accodring to the kamituel's comment, my decidion was to spawn new process for performing "Heavy" calculations and return the result to the parent process. Now application works as I wanted.
I modified my code:
var express = require('express');
var app = express();
// Page A
app.get('/a', function(req, res) {
// Creating child process
var child = require('child_process').fork('custom-module.js');
// Sending value
child.send(25);
// Receiving result
child.on('message', function(result) {
res.type('text/plain');
res.send('Page A, number = ' + result);
});
});
// Page B
app.get('/b', function(req, res) {
res.type('text/plain');
res.send('Page B');
});
app.listen(8082);
custom-module.js:
function doHeavyOperation(number, callback) {
for (var i=0; i<2000000000; i++) {
number++;
}
callback(number);
};
process.on('message', function(number) {
doHeavyOperation(number, function(result) {
process.send(result);
});
});
More info about child_process here.
Javascript (so Node.js as well) uses one main thread for (almost) all of the JS code you write. This means that if you have some long running task (like a huge loop as in your example), this task will block execution of other code (i.e. callbacks).
What can you do about that?
Break the loop into smaller pieces, and yield the control occasionally (i.e. using setTimeout/nextTick or similar). I.e. you can iterate from 0 to 1000, then do the next 1000 of the loop iterations on the next tick and so on.
spawn a new process and handle the heavy task there. Since new process will be outside of Node.js itself, it will not block it.

child process in node is not getting the correct PID id

while i trying to spawn a batch file am not getting the correct PID of that child process.
when i tried to kill the PID of the child process ,the running process is not stoping and it stops another cmd
i dont know how it is happening.
in my batch file am doing to open another cmd and change the directry to C:\AppiumForWindows-1.0.0\Appium\node_modules\appium\bin and run a node process node appium
.i want to execute that node process in seperate cmd (While spawning that batch file it will execute with the same script .i don't need that.)that's what i use separate cmd.
Am confusing due this reason am not getting the correct PID of that process?i don't know...
var startappium = function (dev, callback) {
var ports = {};
var execCmd = __dirname+"//Start.bat";
var args = ['1000'];
var start = spawn(execCmd, args);
console.log("pid id----------------------",start.pid)
var pid =start.pid
start.stdout.on('data', function (d) {
setTimeout(function() {
start .kill() // it does not kill the process
},5000);
console.log(d.toString())
return callback(null, ports);
});
start.stderr.on('data', function (ta) {
return callback(null, ta);
});
start.on('close', function (code) {
console.log("close: ",code)
});
}
startappium()
Start.bat file
#echo off
start cmd /k " call "C:\Program Files\nodejs\nodevars.bat" & pushd C:\AppiumForWindows-1.0.0\Appium\node_modules\appium\bin && node appium -p %1 --chromedriver-port %2"
pause
while running tasklist it shows cms with several PID's and i tried to kill one by one and killed that running batch file process in one PID .
PID getting from the child process id not killing the batch process running.
Please suggest a solution for this.
You can't kill a pid as it's an integer. You want to kill the spawned process:
start.kill();

<video>.currentTIme doesn't want to be set

I'm trying to write a piece of Javascript that switches between two videos at timed intervals (don't ask). To make matters worse, each video has to start at specific place (about ten seconds, and again, don't ask.)
I got the basics working by just using the YUI Async library to fire to switch the videos at intervals:
YUI().use('async-queue', function (Y) {
// AsyncQueue is available and ready for use.
var cumulativeTime = 0;
var q = new Y.AsyncQueue()
for (var x = 0; x < settings.length; x++) {
cumulativeTime = cumulativeTime + (settings[x].step * 1000)
q.add( {
fn: runVideo,
args: settings[x].mainWindow,
timeout: cumulativeTime
})
}
q.run()
});
So far, so good. The problem is that I can't seem to get the video to start at ten seconds in.
I'm using this code to do it:
function runVideo(videoToPlay) {
console.log('We are going to play -> ' + videoToPlay)
var video = document.getElementById('mainWindow')
video.src = '/video?id=' + videoToPlay
video.addEventListener('loadedmetadata', function() {
this.currentTime = 10 // <-- Offending line!
this.play();
})
}
The problem is that this.currentTime refuses to hold any value I set it to. I'm running it through Chrome (the file is served from Google Storage behind a Google App Engine Instance) and when the debugger goes past the line, the value is always zero.
Is there some trick I'm missing in order to set this value?
Thanks in advance.
Try use Apache server.
setCurrentTime not working with some simple server.
ex) python built in server, php built in server
HTTP server should be Support partial content response. (HTTP Status 206)

Categories