Tutorial > Come impostare operazioni pianificate con Node.js e Node Cron

Come impostare operazioni pianificate con Node.js e Node Cron

Pubblicato il: 12 febbraio 2021

Cron Node.js Sviluppo

Introduzione

Il modulo cron, appartenente a node, ti permette di pianificare dei processi e definire quante volte e quando debbano ripetersi all'interno del tuo server Node.js.

Per utilizzare cron, ti basterà utilizzare un modulo chiamato node-cron. Tale modulo userà una particolare sintassi, chiamata crontab, che potresti conoscere già nel caso in cui avessi utilizzato l'applicativo su sistemi Unix.

Negli esempi di questo tutorial, verrà mostrato come eseguire le operazioni pianificate tipiche di un web server, come cancellazione di files di log, backup di un database o invio email programmate.

Per prima cosa dovrai connetterti al tuo server tramite una connessione SSH. Se non l’hai ancora fatto, ti consigliamo di seguire la nostra guida per connetterti in sicurezza con il protocollo SSH. In caso di server locale puoi passare al punto successivo e aprire il terminale del tuo server.

Pre-requisiti

L'unico requisito per poter procedere con questa guida è quello di avere installato e configurato un ambiente di sviluppo Node.js. Se non hai già configurato un ambiente Node.js, puoi seguire la nostra guida su Come installare Node.js su Ubuntu 18.04.

Creare una applicazione Node e installare le dipendenze

Il primo passo è la creazione di una nuova applicazione. Per farlo, inizia creando una nuova cartella di progetto e spostati al suo interno, tramite i comandi:

$ mkdir pianificazioni-cron-node

$ cd pianificazioni-cron-node

N.B. Il nome utilizzato nell'esempio è stato scelto esclusivamente per fini esplicativi, ma puoi nominare la tua directory come preferisci.

Per inizializzare la directory e prepararla al progetto, utilizza un altro comando per creare il file package.json:

$ npm init -y

Prosegui poi installando il framework web denominato express e il modulo node-cron per permettere, rispettivamente, l'accensione del tuo web server e la pianificazione dei tasks.

$ npm install express @numeroversione node-cron @numeroversione

Puoi specificare la versione che preferisci, scrivendo il carattere "@" seguito dal numero della versione.

A questo punto, avrai completato la configurazione iniziale del tuo progetto.

Creare il server back-end e pianificare un Cron Job

Per iniziare a lavorare col tuo web server e pianificare le prime operazioni, comincia creando un file index.js :

$ nano index.js

All'interno del file appena aperto, dovrai inserire alcune istruzioni, per richiedere express e cron:

const cron = require('node-cron');
const express = require('express');

Subito dopo, aggiungi le istruzioni per dichiarare una nuova istanza di Express e aggiungere una piccola funzione di pianificazione.

app = express();

cron.schedule('* * * * *', function() {
  console.log('Processo in esecuzione ogni minuto');
});

app.listen(3000);

Al termine di queste operazioni, dovresti avere un file completato come in figura:

Esempio script Node Cron

Potrai notare la presenza di asterischi nella funzione di pianificazione di cron, denominata cron.schedule.

La funzione prende in input:

  • Una specifica sull'intervallo di tempo considerato, dichiarata tramite gli asterischi;
  • Una function da te definita, che sarà ripetuta con la frequenza specificata nel primo parametro di input (nel nostro caso, la semplice stampa a video di un messaggio).

La notazione ad asterischi fa parte della sintassi di crontab, che rappresenta le unità di tempo nella seguente maniera:

  * * * * * *
  | | | | | |
  | | | | | giorno della settimana
  | | | | mese
  | | | giorno del mese
  | | ora
  | minuto
  secondo ( facoltativo )

Riprendendo l'esempio, nel caso di cinque asterischi, stai indicando a cron di ripetere la funzione (di stampa a video) ogni minuto.

Gli asterischi, però, non sono gli unici valori da poter inserire per le specifiche sulla frequenza della pianificazione. Potrai infatti sostituire quei caratteri con dei valori per creare pianificazioni più complesse.

Uno strumento molto utile per capire come inserire questi valori, in base alle proprie esigenze, è il tool online Crontab.guru.

Ora, puoi provare a verificare se le istruzioni appena specificate restituiscano l'ouput richiesto con la frequenza specificata.

$ node index.js

Se tutto è andato a buon fine, dovresti ricevere sulla console un ouput simile:

Output scritta Node Cron

Con la combinazione CTRL+C, potrai interrompere l'esecuzione del file.

Cancellare regolarmente un file di log

Immagina di voler cancellare un file di log degli errori sul server ogni venticinquesimo giorno del mese. Un simile scenario può essere tranquillamente implementato con le funzionalità di cron.

Come primo passo, crea un file log di esempio che potrai chiamare, per esempio, errors.log:

$ nano errors.log

Nell'editor, inserisci un testo a piacere, come:

Questo testo è un esempio di un file di log da cancellare ogni 25esimo giorno del mese.

Successivamente, vai a modificare il file index.js, come visto prima:

$ nano index.js

Questa volta occorrerà usare fs per scollegare un file. Aggiungilo alle dichiarazioni iniziali:

const cron = require('node-cron');
const express = require('express');
const fs = require('fs');

Successivamente, per non perdere le modifiche fatte prima, Usa i caratteri /* e */ per racchiudere il blocco di istruzioni specificate prima in un commento e non perderle.

/* cron.schedule('* * * * *', function() {
  console.log('Processo in esecuzione ogni minuto');
}); */

Ora che hai disattivato quel pezzo di codice, puoi inserire le nuove istruzioni per cancellare il file di log.

//Cancella il file errors.log il 25esimo giorno del mese
cron.schedule('0 0 25 * *', function() {
  console.log('---------------------');
  console.log('Eseguendo processo Cron');
  fs.unlink('./errori.log', err => {
    if (err) throw err;
    console.log('File errors.log cancellato con successo!');
  });
});

A questo punto, il tuo file index.js dovrebbe apparire così:

Esempio script Node Cron cancellazione errori

All'interno del file, nella funzione che indica la pianificazione (cron.schedule), potrai notare la presenza sia del carattere * che di altri valori.

Analizzando i valori dati in input alla funzione:

La combinazione di questi parametri fa capire a cron che la procedura di cancellazione di errori.log e di stampa di un messaggio di conferma vada eseguita all'inizio del 25esimo giorno del mese.

Per eseguire lo script sul server, basterà invocare nuovamente il comando:

$ node index.js

Per testare che le nuove istruzioni funzionano, potrai semplicemente cambiare i valori del tempo pianificato e verificare che compaia l'output indicato nelle istruzioni e, soprattutto, che il file errori.log scompaia dopo il tempo specificato.

Effettuare regolarmente il backup del tuo database

Tra i tanti usi della pianificazione tramite cron, potresti trovare molto utile l'associazione di questa funzionalità con quella di backup di un possibile database collegato al server.

Immagina, per esempio, di avere un database SQLite collegato al tuo server e di voler effettuare una copia di backup ogni giorno alle 12:32.

N.B. Per semplicità, nell'esempio di seguito viene presentato un database configurato localmente, senza entrare nei dettagli su come crearlo.

Immagina, allora, una possibile istruzione di backup su SQLite:

$ sqlite3 database.sqlite .dump > dump_dati.sql

L'istruzione qui sopra, prenderà il database database.sqlite ed eseguirà il .dump, salvando in output il file di backup dump_dati.sql.

Successivamente, installa il modulo shelljs che ti permetterà di eseguire l'istruzione di backup specificata sopra.

$ npm install shelljs@numeroversione

Il prossimo passaggio è, come prima, andare a modificare il file index.js.

$ nano index.js

Nella parte delle dichiarazioni, aggiungi la stringa:

const shell = require('shell.js');

Nella parte dedicata alle istruzioni da specificare, inserisci invece le seguenti linee di codice:

// Esegui un backup del database alle 12:32.
cron.schedule('32 12 * * *', function() {
  console.log('---------------------');
  console.log('Eseguendo processo Cron');
  if (shell.exec('sqlite3 database.sqlite .dump > data_dump.sql').code !== 0) {
    shell.exit(1);
  }
  else {
    shell.echo('Backup del database completato!');
  }
});

Analizzando i valori dati in input alla funzione di pianificazione:

La restante parte del codice dovrebbe, invece, eseguire il backup o, in caso di errore, restituire un messaggio.

Il risultato finale del file index.js non ti verrà mostrato stavolta poichè hai già potuto capire, negli esempi precedenti, come strutturarlo la prima volta e come modificarlo nel caso in cui tu voglia cambiare la pianificazione e le istruzioni.

Eseguendo, infine, il comando:

$ node index.js

Dovresti notare che, ogni giorno alle 12.32, il server mostrerà un messaggio di avvenuto backup e, all'interno della directory, dovresti poter trovare il file dump_dati.sql.

Pianificare l'invio di email da parte del server

Potrebbe anche capitare che tu abbia bisogno di inviare una email in automatico con una certa frequenza. Il pacchetto node-cron ti permette di pianificare anche questo.

N.B. É importante, nelle fasi di prova della guida e soprattutto sui server in produzione, evitare di usare un account email personale, ma utilizzare invece un account separato per evitare rischi.

Il primo passo è installare un modulo, chiamato nodemailer, per gestire l'invio delle email:

$ npm install nodemailer@numeroversione

Come per i passi precedenti, ora è il momento di modificare il file index.js.

Nella sezione dichiarativa del file, aggiungi la dichiarazione:

const nodemailer = require('nodemailer');

Nella sezione delle istruzioni per definire la procedura, inserisci invece il seguente codice:

// ...

// Crea un traportatore per le emails.
let transporter = nodemailer.createTransport({
  host: 'tua_email_prova_smtp_host.esempio.com',
  port: tua_email_prova_porta,
  secure: true,
  auth: {
    user: '[email protected]',
    pass: 'tua_password_email_prova'<^>
  }
});

Questo blocco di istruzioni ti servirà a specificare alcune caratteristiche di base dell'indirizzo email da cui verranno spedite le mail. Ricorda di utilizzare un protocollo SMTP.

Successivamente, inserisci un altro pacchetto di istruzioni:

// Invia emails ogni mercoledi.
cron.schedule('0 0 * * 3', function() {
  console.log('---------------------');
  console.log('Eseguendo processo Cron');

  let messageOptions = {
    from: '[email protected]',
    to: '[email protected]',
    subject: 'Email programmata',
    text: 'Ciao user! Questa email è stata programmata per l'invio automatico, ogni mercoledì.'
  };

  transporter.sendMail(messageOptions, function(error, info) {
    if (error) {
      throw error;
    } else {
      console.log('Email inviata con successo!');
    }
  });
});

Questo secondo blocco è la vera parte di pianificazione ed esecuzione. Puoi osservare, infatti, la funzione di pianificazione e i suoi valori di input:

Successivamente, trovi le istruzioni che specificano il mittente, il destinatario, l'oggetto e il corpo della email. Tutti i campi sono stati compilati con degli esempi per mostrarti i rispettivi valori da inserire.

Infine, ci sarà la parte di conferma tramite l'output del messaggio riguardante il successo dell'invio.

Ricorda, le istruzioni vanno inserite in questo ordine:

  1. app = express();
  2. istruzioni del caso d'uso
  3. app.listen (3000);

Infine, come per gli esempi precedenti, sarà sufficiente mandare in esecuzione il file index.js:

$ node index.js

In questo modo, ogni mercoledì, dovresti ricevere la conferma di invio della email programmata.

Conclusioni

A questo punto, ti sono stati presentati diversi casi d'uso comuni in cui Cron può risultare di grande d'aiuto nel gestire lo scheduling di alcune operazioni sul tuo web server.

Ricorda che puoi esplorare tanti altri tool disponibili per Node da poter combinare con Cron per automatizzare i tuoi processi mediante Cron Jobs.