code-8
code-8

Reputation: 58790

How can I run a NodeJS Application as cronjob in Linux Ubuntu?

I have a node application that contain cron in it. Right now, it run perfectly on Ubuntu server.

enter image description here

index.js

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const router = express.Router();
const cron = require('node-cron');

const nodemailer = require('nodemailer');

const request = require('request');
const cheerio = require('cheerio');
const FCM = require('fcm-node');


app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

var admin = require('firebase-admin');
var serviceAccount = require('./serviceAccountKey.json');
var fcm = new FCM(serviceAccount);
var firebase = admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: 'https://ios-base-88.firebaseio.com'
});

const FETCH_DOMAIN = 'https://finance.yahoo.com/lookup/all?s=';

router.get('/', (req, res) => {
    res.json({
        msg: 'Something happening'
    })
});

const checkPrice = () => {
    var db = admin.database();
    var ref = db.ref('alerts');
    ref.on('value', (snapshot) => {
        console.log(snapshot.val());
        if (snapshot.val()) {
            snapshot.forEach((child) => {
                trackPrice(child);
            })
        }
    }, (error) => {
        console.log('The read failed: ' + error.code);
    })
}

const sendEmailNotification = async (email, text, snapshot) => {
    let transporter = nodemailer.createTransport({
        service: 'gmail',
        auth: {
            user: '[email protected]',
            pass: '***'
        }
    });

    let mailOptions = {
        from: '[email protected]',
        to: email,
        subject: text,
        html: text
    };

    let info = await transporter.sendMail(mailOptions);
    // update notify params 
    var db = admin.database();
    var ref = db.ref('alert').child(snapshot.key);
    const company = snapshot.val();
    ref.update({
        companyName: company.companyName,
        price:  company.price,
        ticker: company.ticker,
        notified: true
    })
    console.log('Message sent: %s', info.messageId);
    console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
}

const trackPrice = (child) => {
    var snapshot = child.val();
    const company = snapshot.companyName;
    const price = snapshot.price;
    const url = `${FETCH_DOMAIN}${snapshot.ticker}`;
    request(url, (error, response, html) => {
        if (!error && response.statusCode === 200) {
            var $ = cheerio.load(html);
            var stock_price = null;
            $('table').find('tbody').find('tr').each(function(i, e) {
                var column = $(this).prev();
                if (column.children('td.data-col1').text() === snapshot.companyName) {
                    stock_price = column.children('td.data-col2').text();
                }
            });
            stock_price = parseFloat(stock_price.replace(/,/g, ''));
            if (stock_price && snapshot.price == Math.floor(stock_price)) {
                // send email notification
                admin.auth().listUsers()
                    .then((list) => {
                        list.users.forEach((user) => {
                            var customer = user.toJSON();
                            sendEmailNotification(customer.email, `The company ${snapshot.companyName}' stock price is reached to ${snapshot.price}`, child);
                        });
                    }).catch((error) => {
                        console.log('Error listing users:', error);
                    })
                
                // Send push notification
                var ref = firebase.database().ref('users');
                ref.once('value')
                    .then(function(snapshot) {
                        var data = snapshot.val();


                        var fcmToken = '***';
                            var message = {
                                to: fcmToken,
                                data: {},
                                notification: {
                                    title: 'Stock Price',
                                    body: `The company ${company}' stock price is reached to ${price}`,
                                    tag: collapseKey,
                                    icon: 'ic_notification',
                                    color: '#18d821',
                                    sound: 'default'
                                }
                            };
                            fcm.send(message, function(err, response) {
                                if (err) {
                                    console.log(err);
                                } else {
                                    console.log("Successfully sent with response: ", JSON.stringify(response));
                                }
                            })

                            
                        
                    })
            }
        }
    })
}

const run_job = () => {
    cron.schedule('0 * * * * *', () => {
        checkPrice();
    });
}

//run_job();
checkPrice();
app.use('/api', router);

app.listen(3000, () => {
    console.log('\x1b[33m%s\x1b[0m', '** Express Development is listening on localhost:3000, open your browser on http://localhost:3000 **');
})

I want to make sure it run as cron the background.

I know that I can't do this

* * * * * node /home/forge/bheng/public/ios-base-api/index.js >> /tmp/tmpfile.log 2>&1 &

Because I already cron server in my node already.

How would one go about and debug this further?

Upvotes: 1

Views: 661

Answers (1)

hjbello
hjbello

Reputation: 651

I have faced the same problem and I resolved it using pm2.

install pm2 globally:

npm install -g pm2

if you run your script using npm start run this in your project folder

pm2 start index.js

pm2 will turn your script in to a daemon that will run in the background and it will restart the script if it fails. To check the logs run

pm2 monit

If you want to run your script when the system starts run

pm2 startup

and follow the instructions.

Upvotes: 1

Related Questions