Skip to content

2020

Advanced Cron

Per gestire l'emergenza Covid-19 è necessario elaborare e trasmettere diversi flussi informativi a diverse piattaforme (piattaforme aziendali, bucket regionali, in formato csv o excel, applicativi di gestione casi, dashboard di aggregazione o analisi dei dati, etc.).

Ho quindi predisposto diversi task che: - richiamano dei piccoli applicativi Perl per estrarre via SQL le informazioni necessarie, le trasformano, e le salvano in file in formato CSV - comprimono i dati, eventualmente con password complesse - trasmettono i dati verso bucket aws, su altri server Qlik o Pentaho - generano mail puntuali o di riepilogo

Il testo che segue non è un "manuale" su come fare le cose, ma un elenco di appunti che mi aiutano a ricordare quali operazioni ho fatto e qual è la logica sottostante.

La schedulazione avviene con il servizio crond. Tuttavia nel corso del tempo il numero di task è diventato numeroso, la configurazione della crontab è diventa complessa, e modificare o monitorare il corretto funzionamento dei task è diventato poco agevole.

Ho quindi voluto riorganizzare il servizio con il seguente sistema. La tabella con i task è minimale, questo un task che necessita di essere eseguito ogni ora:

0  *  *  *  * /home/fede/scripts/hourly_tasks.sh

Questo task a sua volta si occupa di lanciare tutti gli script che devono essere eseguiti ogni ora, gestendone correttamente l'output stdout e stderr nei file di log opportuni:

#!/bin/bash

LOG_FILE=/var/log/covid_out.log
LOG_ERROR=/var/log/covid_err.log

exec 1>>"$LOG_FILE" 2>>"$LOG_ERROR"

./task01.sh &
./task02.sh &
./task03.sh &
...

In questo caso i vari task vengono eseguiti in parallelo, ed ereditano gli output verso i file di log.

Tuttavia per ogni task voglio fare in modo che il log contenga la data e l'ora, ed il nome del task eseguito:

#!/bin/bash
PROGNAME=$(basename $0)

exec  > >(sed --unbuffered "s/^/$(date +'%Y-%m-%d %H:%M:%S'),$PROGNAME: /")
exec 2> >(sed --unbuffered "s/^/$(date +'%Y-%m-%d %H:%M:%S'),$PROGNAME: /" >&2)

...

Il parametro --unbuffered assicura che la singola riga viene processata immediatamente, senza utilizzare un buffer, in modo che data e l'ora presentate nel file di output siano quelle effettive di quando l'output è stato realizzato e che i vari output siano sequenziali.

Inoltre per gestire correttamente eventuali errori, ho predisposto una funzione come segue:

error_exit()
{
        echo "${1:-"Unknown Error"}" 1>&2
        exit 1
}

La struttura completa del task risulta essere questa:

#!/bin/bash
PROGNAME=$(basename $0)

error_exit()
{
        echo "${1:-"Unknown Error"}" 1>&2
        exit 1
}

exec  > >(sed --unbuffered "s/^/$(date +'%Y-%m-%d %H:%M:%S'),$PROGNAME: /")
exec 2> >(sed --unbuffered "s/^/$(date +'%Y-%m-%d %H:%M:%S'),$PROGNAME: /" >&2)

echo "Inizio elaborazione"

perl "extract.pl" -prepare || error_exit "$LINENO: Errore preparazione dati."
perl "extract.pl" -extract > $output || error_exit "$LINENO: Errore estrazione dati."

...

Come scaricare un file più recente da aws via cli:

latest=`$AWS s3 ls s3://bucket/path/documento | sort | tail -1 | awk '{ print $4 }'`                   
$AWS s3 cp --no-progress s3://bucket/path/$latest /home/fede/csv/documento.csv

Per scaricare il file più recente da un altro unix, in questo caso utilizzando sshpass (da valutare ovviamente se è la soluzione opportuna):

latest=$(sshpass -p $pass ssh fede@server 'ls -t /var/export/documento* | head -1')
sshpass -p $pass scp fede@server:/$latest $output_dir/$output_file

Millennium Bug? Quale Millennium Bug?

Commento del 17 gennaio 2020 su un blog, in risposta a una discussione sul Millennium Bug e sugli scenari apocalittici del 1999.

Io c'ero, e sono convinto che gli scenari apocalittici che si sarebbero dovuti verificare esattamente allo scoccare della mezzanotte fossero in gran parte superstizione.

Poi è assolutamente vero che migliaia di programmi (gestionali, contabilità, etc.) calcolavano le date con 2 cifre invece di 4 e che quindi dovevano essere corretti. All'epoca abbiamo lavorato mesi su questo fronte. Alcuni programmi però avrebbero dato risultati errati già mesi prima della fatidica presunta fine del mondo, altri avrebbero dato risultati errati mesi dopo. Soprattutto, non era necessario aspettare la mezzanotte per saperlo, si poteva testare tutto agevolmente in anticipo.

(a dire la verità ci sono programmi che ancora oggi fanno confusione ogni volta che cambia l'anno, e per capire come mai basta guardare gli snippet di codice che girano per il web e che i programmatori inesperti copiano ed incollano sui loro progetti: la maggior parte di questi snippet sono buggati! Anche il calcolo degli anni bisestili non è sempre corretto, ed anche il cambio ora legale/ora solare ha spesso effetti deleteri)

Quella notte i colleghi del servizio informativo avevano una reperibilità speciale, con tanto di radio a pile per essere raggiungibili anche in caso di blackout. Ricordo che il pomeriggio di quel fatidico 31 dicembre i colleghi più anziani, che poi sarebbero rimasti reperibili tutta la notte, erano sollevati dal fatto che le notizie provenienti dall'Asia fossero positive: nessun grave problema. Io, che sono malvagio, li ho spaventati facendo notare come tutti i sistemi unix compresi i nostri dovessero avere il clock sincronizzato con UTC, per cui in Asia non avevano ancora raggiunto la "vera" mezzanotte, anzi nella mia malvagità avevo sganciato una bomba, facendo presente che semmai ci fosse stato qualche disastro questo si sarebbe verificato alla mezzanotte UTC in contemporanea su tutti i sistemi del pianeta. Poi sono andato a festeggiare in montagna :)

Precisazione tecnica: i sistemi Unix sincronizzano tipicamente il clock con UTC (Coordinated Universal Time), che per semplicità potremmo considerare equivalente al fuso orario di Greenwich (GMT), anche se dal punto di vista scientifico non è la stessa cosa. Il mio ragionamento scherzoso non era quindi del tutto sballato: il momento critico era lo stesso per tutti i sistemi sincronizzati a UTC, indipendentemente dal fuso locale. Ma nessuno ci aveva pensato.

Per chiarire meglio il mio pensiero, è vero che di programmi buggati ce n'erano parecchi ed è stato un bene averli sistemati. Clock hardware buggati invece ne sono stati trovati? Gli articoli giornalistici dell'epoca erano più dettati dalla superstizione che non dalla reale conoscenza dei sistemi.

Infine, il vero Millennium Bug avverrà nel 2038, alle 03:14:07 UTC del 19 gennaio, e non a mezzanotte come nel 1999. Ed è ancora troppo sottovalutato.