I'm starting to tinker with node.js server, I created a node application which keeps a database in sync, the function of this app/script is to run an async function in 5 minutes intervals, for this I'm using node-cron, so far I got it to work after I visit my express route / .
Issue is I don't want to have to visit a route to start/stop/whatever the cron job, I have read about pm2 and would like to be able to execute my application as background with it.
Ideally I'd start and stop the cron job from the command line, where can I find a tutorial on how to do this in an ubuntu server?
My app.js file looks like this:
var express = require('express');
var app = express();
//process.env.DB_HOST
app.get('/', async (req, res) =>
{
const job = new CronJob('0 */5 * * * *', function()
{
try
{
const databaseService = new DatabaseService();
databaseService.syncDB();
}
catch(err)
{
console.error(err);
}
});
job.start();
res.send('Hello world');
});
app.listen(3000, function()
{
console.log('Example app listening on port 3000!');
});
How to handle cron job without visiting route/script running from console in the background
If you want node to manage just the cronjob, remove express
const job = new CronJob('0 */5 * * * *', function(){
try
{
const databaseService = new DatabaseService();
databaseService.syncDB();
}
catch(err)
{
console.error(err);
}
});
job.start();
As #Randy Casburn mentioned, you can just run the database sync function in node and have the cron daemon schedule that for you instead of using pm2 to manage a long running node process.
Related
Learning node from past week and got some hold on node and express. But now I am facing a problem. I am trying to run multiple express servers on different port and want them to return response after 10 seconds. After running the program, servers are starting fine but when I hit http://localhost:3000 or any of the server's url, observing following:
- on client side I am getting proper response from all servers after 10 secs
- server is getting into infinite loop and continuously printing "returning data..." after the delay of 10 secs
I tried using a function, using a js file to export the server and another class importing it and calling inside for loop. But sever is constantly printing "returning data..." after the delay of 10 secs. Below is my code:
var express = require('express');
const data = '{"key":"value"}';
const server = function (port) {
let app = express();
app.get('/', (req, res) => {
setInterval(function () {
console.log('returning data...')
res.end(data);
}, 10000); //want a delay of 10 secs before server sends a response
})
app.listen(port, () => console.log("Server listening at http://%s:%s",
"localhost", port))
}
console.log('\nStarting servers.......')
for (var i = 0; i < 5; i++) {
server(3000 + i)
}
You need to create multiple app instances from express. Below is the code snippet to start multiple server on different ports from same file.
var express = require('express');
let app1 = express();
let app2 = express();
app1.listen(3000, () => {
console.log("Started server on 3000");
});
app2.listen(3002, () => {
console.log("Started server on 3002");
});
You are using window.setInterval instead of window.setTimeout, that's why is running multiple times.
already answered: https://stackoverflow.com/a/71831233/17576982
(3 ways to start multiple servers on one run in nodejs)
So I'm trying to build a Discord bot. These types of threads tend to get downvoted a lot on stackoverflow, so I'm hoping this doesn't happen to me.
This particular feature is acting as a temporary solution to my dashboard problem. Due to the nature of glitch.com's hosting, it's supposed to fall asleep after 5 minutes of http inactivity. I solved that already by adding a script that pings the URL every 4 minutes, but that caused another issue. I think what's happening is that because that script and the bot script are constantly running, and never technically 'finish', it never lets any incoming connection actually load the webpage. So my solution to that problem was to create another glitch project that would act as the dashboard website, and transfer information from the bot project. Of course then I'd need to create more scripts that communicate with each other via some internet protocol. The info recorded by the bot is all recorded in a private JSON database using the node-json-db npm library.
My problem is: I don't know what protocol would be best for this kind of thing. Even if I did know, then I'd have to go digging through the docs for the info I'm looking for.
My question is: What protocol should I use, and what docs do I need to read for this?
I've included some snippets of the code here:
The bot's server code (where I would add the script for communicating with the dashboard):
// server.js
// where your node app starts
// init project
const express = require('express');
const app = express();
const JsonDB = require('node-json-db');
const db = new JsonDB("myDataBase", true, true);
// we've started you off with Express,
// but feel free to use whatever libs or frameworks you'd like through `package.json`.
// http://expressjs.com/en/starter/static-files.html
app.use(express.static('public'));
// http://expressjs.com/en/starter/basic-routing.html
app.get('/', function(request, response) {
response.sendFile(__dirname + '/views/index.html');
});
app.post('/login/c3RvcCBoYWNrZXIh', function(request, response) {
var servername = request.param('servername');
var password = request.param('password');
if (db.getData("/" + servername + "/password") === password) {
response.json(db.getData("/" + servername));
} else {
response.json(null);
}
});
// listen for requests :)
const listener = app.listen(process.env.PORT, function() {
console.log('Your app is listening on port ' + listener.address().port);
});
// to keep the bot alive, since glitch puts projects to sleep after 5 mins of inactivity.
const http = require('http');
setInterval(() => {
http.get(`http://${process.env.PROJECT_DOMAIN}.glitch.me/`);
}, 270000);
The server.js on the dashboard website:
// server.js
// where your node app starts
// init project
const express = require('express');
const app = express();
const request = require('request');
// we've started you off with Express,
// but feel free to use whatever libs or frameworks you'd like through `package.json`.
// http://expressjs.com/en/starter/static-files.html
app.use(express.static('public'));
// http://expressjs.com/en/starter/basic-routing.html
app.get('/', function(request, response) {
response.sendFile(__dirname + '/views/index.html');
});
app.post('/login', function(request, response) {
var servername = request.param('servername');
var password = request.param('password');
if ("thereisnopassword" === password) {
response.sendFile(__dirname + '/dashboard/index.html');
} else {
response.sendFile(__dirname + '/views/wronginfo.html');
}
});
// listen for requests :)
const listener = app.listen(process.env.PORT, function() {
console.log('Your app is listening on port ' + listener.address().port);
});
I had this too, but solved it by simply putting the code to start the express server before the http loop.
// Require packages
const http = require('http');
const express = require('express');
const app = express();
// Express
app.get("/", (request, response) => {
response.sendStatus(200);
});
app.listen(process.env.PORT);
// Interval
setInterval(() => {
http.get(`http://${process.env.PROJECT_DOMAIN}.glitch.me/`);
}, 240000);
// Bot code
const Discord = require('discord.js');
const client = new Discord.Client();
I've set up a node server on a raspberry pi to display a sequence of colors on an Adafruit Dotstar light strip. The functionality works as follows: I make an HTTP request to localhost:8000/fade, and the server responds by running the fade.js file, which is an infinite loop that fades through different colors on the light strip. Unfortunately, I'd like to be able to exit this command and shut off the light strip with another request to localhost:8000/off.
I've experimented with the child_process package in order to run the "fade" code, while also listening to new requests. However, I'm unable to kill the "fade" process.
Posted below is my app.js code. Any suggestions on how to kill the child_process, or perhaps restructure the code in some other way to accomplish the same goal? I really just need to be able to run the "fade" code continuously, while also responding to new requests.
p.s. This is my first JS project so go easy! Any help is appreciated.
app.js:
var express = require('express'),
app = express();
app.get('/', function (req, res) {
res.send('App is responding to requests');
});
app.get('/fade', function (req, res) {
var fork = require('child_process').fork;
child = fork('./sequences/fade.js');
});
app.get('/off', function (req, res) {
var fork = require('child_process').fork;
child = fork('./sequences/off.js');
});
app.listen(8000, function () {
console.log('Example app listening on port 8000!')
})
fade.js:
console.log("running fade.js");
var dotstar = require('dotstar'),
SPI = require('pi-spi'),
sleep = require('sleep');
spi = SPI.initialize('/dev/spidev0.0');
const ledStripLength = 30;
const ledStrip = new dotstar.Dotstar(spi, {
length: ledStripLength
});
while(1) {
fade(); //where fade is a long sequence of colors
};
var child; // Outer scope, available in both functions.
app.get('/fade', function (req, res) {
var fork = require('child_process').fork;
child = fork('./sequences/fade.js');
});
app.get('/off', function (req, res) {
// (might be a good idea to check if child exists and is running first...)
child.kill('SIGHUP');
});
Also http://programmergamer.blogspot.com/2013/05/clarification-on-sigint-sigterm-sigkill.html
SIGHUP: ... A process has to explicitly handle this signal for it to work. ...
So SIGINT if you want to close without handling it on the fork side, or SIGKILL to just kill that mofo.
I am new to nodeJS...and programming. But I have tried to get this bit of code to work and I cannot understand why it does not seem to work. Whats worse is I do not know how to troubleshoot it either. If I use console.log statements, I can see that once I launch the webpage, it DOES connect, but the webpage never gets a message from the nodeJS server and the server never gets a message from the webpage. I am using Chrome browser.
server.js:
var express = require('express'),
app = express(),
server = require('http').createServer(app),
io = require('socket.io').listen(server);
server.listen(80);
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
var SerialPort = require('serialport');
var portName = process.argv[2];
var sp = new SerialPort(portName, {
baudRate: 9600,
dataBits: 8,
parity: 'none',
stopBits: 1,
flowControl: false
});
io.sockets.on('connected', function (socket) {
socket.emit('connected', {
data: 'connected'
});
socket.on('connected', function (data) {
console.log(data);
//Code
console.log('Sending Packet. Contents:');
sp.write(packet);
console.log(packet);
console.log('Packet Sent');
});
});
I launch it from command prompt on raspbery pi zero w:
sudo node server.js /dev/ttyACM0
The index.html references the interface.js. The top part of interface.js:
$(document).ready(function() {
// Connect to the node.js server. Gets server's local ip.
// Using this method robot can only be connected to on
// local network.
var ip = location.host;
var socket = io.connect(ip); // Connects to server
// Upon establishing a connection to the socket.io server...
socket.on('connected', function (data) {
console.log(data);
// Send out a message to the server
socket.emit('connected', { command: 'nothing' });
});
When I have console.log statements in the interface.js I get them until the socket.on statement.
node -v
v6.4.0
npm -v
5.3.0
npm list socket.io
socket.io#2.0.3
uname -m
armv6l
Edit: Updated messaging commands. Same issue. Also
Well, turns out I have the wrong version of socket.io.js. So. That was a week of learning. Thanks for the help.
I'd like to start my node js application on boot. Therefore I start a service from Systemd:
[Unit]
Description=Node.js server
After=network.target
[Service]
ExecStart=/usr/bin/node /var/www/Raspberry-Pi-Status/js/server.js
Restart = always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=nodejs-server
Environment=NODE_ENV=production PORT=8000
Environment=PYTHONPATH=/usr/bin/python
[INSTALL]
WantedBy=multi-user.target
The server.js looks like this:
var util = require('util'),
spawn = require('child_process').spawn,
py = spawn('python',['temperature.py'],{detached: true});
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'monitor',
password : 'password',
database : 'temps'});
var app = require('http').createServer(handler),
io = require('socket.io').listen(app),
fs = require('fs'),
sys = require('util'),
exec = require('child_process').exec,
child;
// Listen on port 8000
app.listen(8000);
// If all goes well when you open the browser, load the index.html file
function handler(req, res) {
fs.readFile(__dirname+'/../index.html', function(err, data) {
if (err) {
// If no error, send an error message 500
console.log(err);
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
py.stdout.on('data', function(data){
console.log('testing');
date = new Date().getTime();
temp = parseFloat(data);
io.sockets.emit('temperatureUpdate',date,temp);
});
// When we open the browser establish a connection to socket.io.
// Every 5 seconds to send the graph a new value.
io.sockets.on('connection', function(socket) {
console.log('user connected');
});
The node.js application should start a python script which reads out a temperature sensor. When I start node.js via the console everything works fine. However, when I start from Systemd, the python script is not spawned.
What's the problem there? Am I missing something?
Thanks in advance
Alexander
An issue could be the difference in the current working directory when run manually vs systemd. The spawn call used is documented has a default to inherit the current working directory.
When run via the shell, that would be whatever directory you are currently in. In man systemd.exec, you find the "WorkingDirectory=` directive, which documents systemd's default current working directory: "defaults to the root directory when systemd is running as a system instance".
So if your temperature.py is located in /var/www/Raspberry-Pi-Status, then set:
workingDirectory=/var/www/Raspberry-Pi-Status in your `[Service]` section.