4 settembre 2015

Cron: quando l'automazione incontra "Linux"



Oggi parliamo di... Cron, l'utile e spesso indispensabile servizio di scheduling dei sistemi Unix e Unix-like.



Cos'è Cron?

Immaginate di dover eseguire a determinati orari, giorni, mesi o per un determinato numero di volte, uno o più processi (processi di backup da lanciare ogni notte, processi di log che devono "aggiornarsi" ogni minuto, etc.), e supponiamo di voler "automatizzare" il processo; come fare? Ecco a voi, Cron, il demone pianificatore. Cron vi permette di programmare l'esecuzione di un lavoro ("job" o "cronjob") in qualsiasi momento desideriate, specificando i minuti, le ore, i giorni o i mesi... fantastico, vero?


... ma prima un po' di teoria

Cron, installato di default su quasi tutte le distro, viene lanciato in background all'avvio del sistema e non richiede, quindi, avvio manuale. Il demone, che "opera" tramite il comando crontab, legge, ad ogni avvio, il file /etc/crontab per i "jobs" di sistema, i file contenuti nella directory /etc/cron.d/ e i file in /var/spool/cron/crontabs per tutti i "jobs" relativi agli utenti presenti sulla distro. Com'è facile intuire, quindi, ogni utente, root compreso, ha il proprio crontab che può contenere uno o più "jobs".


Utilizzo:

Come già detto, per interagire con il demone Cron, si utilizza il crontab e la sua sintassi è abbastanza semplice:
crontab [-u user] [options]
-u : questa opzione comunica al sistema il nome dell'utente che "possiede" il file. Se l'opzione -u è omessa, il sistema deduce per default che si sta operando sul crontab dell'utente che lancia il comando. 
-l : questa opzione dice a crontab di elencare i file nello standard output, cioè di visualizzare il file.
-e : questa opzione dice a crontab di editare il file. Cron usa l'editor definito dalle variabili EDITOR o VISUAL. Se nessuna di queste due variabili è definita, parte in automatico l'editor di default. L'editor salva il file in /tmp; quando si esce dall'editor, il file è immediatamente salvato in /var/spool/cron/crontabs e viene aggiornato il campo data/ora. Questo è il comando principale da utilizzare se si vuole modificare il proprio file crontab per cancellare o inserirvi i lavori da assegnare a Cron.
-r : questa opzione rimuove il file crontab. Se nessun utente viene specificato attraverso l'opzione '-u', rimuove il file crontab dell'utente che lancia il comando.

nota: per editare crontab dell'utente root, basta dare il comando con i permessi di root (sudo crontab -e)



Avviando l'editor  con crontab -e (supponiamo per semplicità di voler editare/impostare un "cronjob" per l'utente attualmente in uso) vi troverete di fronte alla schermata qui sopra e quello che a noi interessa è la parte finale, quella vuota per intenderci, dove andremo ad impostare i nostri "jobs".


Come si impostano i "jobs"? 

La sintassi è semplice:

      .---------------- [m]inute: minuto (0 - 59)
      |   .------------- [h]our: ora (0 - 23)
      |   |  .---------- [d]ay [o]f [m]onth: giorno del mese (1 - 31)
      |   |  |  .------- [mon]th: mese (1 - 12) OPPURE jan, feb, mar, apr...
      |   |  |   |  .---- [d]ay [o]f [w]eek: giorno della settimana (0 - 6) (domenica=0 or 7)  OPPURE sun, mon, tue, wed, thu, fri, sat 
      |   |  |   |  |
      *  *  *  *  *  comando da eseguire


Gli asterischi indicano che il valore è lasciato libero; in altre parole, un asterisco in corrispondenza delle ore, indica che il comando verrà eseguito "a tutte le ore". Non ci resta che salvare e attendere che il "job" venga eseguito (ndr. non c'è bisogno di riavviare per rendere effettive le modifiche).

Ricapitolando:
a) crontab -e
b) imposto il "job"
c) salvo ed esco
d) fine!!! 


Esempi:

1) supponiamo di voler eseguire alle 15:30 del 3 febbraio, indipendentemente da quale giorno sia, il comando "ping -c 3 www.google.com"; la sintassi sarà:
30   15   3   2    *     ping -c 3 www.google.com
2) supponiamo di voler eseguire il comando "sudo pacman -Syu" per l'aggiornamento di archlinux ogni lunedì del mese (mon = 1), all'accensione/login del computer/utente; la sintassi sarà:
*     *     *    *     1    sudo pacman -Syu
3) supponiamo di voler eseguire uno script.sh presente nella nostra home, alle 14:00 e alle 19:00 dei primi quindici giorni di ogni mese e anche ogni venerdì (giorno 5):
00     14,19    1-15     *       5       sh /home/utente/script.sh

ATTENZIONE!!!
Poiché i giorni possono essere specificati sia nel terzo che nel quinto campo, nel caso in cui questi due campi abbiano entrambi un valore diverso dall'asterisco, il demone Cron lancia il comando quando i campi corrispondono alla data corrente e in maniera indipendente l'uno dall'altro. Nell'esempio #3, dunque, verrà eseguito il comando sia negli specificati giorni del mese sia nei giorni specificati della settimana. Se si vuole ottenere il risultato di lanciare un comando in un particolare giorno della settimana solo se questo coincide con un giorno del mese o se appartiene a un intervallo di giorni del mese, bisogna eseguire un test separato sulla data. Il test può essere fatto sia all'interno di crontab, sia all'interno di uno script lanciato da crontab.

si riportano a titolo informativo, due esempi estratti dal wiki di Debian, che meglio chiariscono questo particolare aspetto:

4) questo è un esempio che mostra come eseguire un comando solo alla mezzanotte della prima domenica di ogni mese:
00 00 1-7 * * [ $(/bin/date '+\%u') -eq 7 ] && /comando/da/eseguire
5) quest'altro esempio mostra come eseguire un comando alle 20,00 nei giorni che vanno dal 5 al 10 di ogni mese e solo se questi giorni corrispondono a martedì o venerdì:
00 20 5-10 * * [ $(/bin/date '+\%u') -eq 2 -o $(/bin/date '+\%u') -eq 5 ] && /comando/da/eseguire



Esistono, poi, delle stringhe speciali che semplificano e condensano alcune configurazioni dei campi ora/data  

   @reboot          Lancia il comando all'avvio del sistema
   @yearly           Lancia il comando una volta all'anno. Uguale a "0 0 1 1 *"
   @annually       (come @yearly)
   @monthly        Lancia il comando una volta al mese. Uguale a "0 0 1 * *"
   @weekly          Lancia il comando una volta alla settimana. Uguale a "0 0 * * 0"
   @daily              Lancia il comando una volta al giorno. Uguale a "0 0 * * *"
   @midnight       (come @daily)
   @hourly           Lancia il comando una volta all'ora. Uguale a "0 * * * *"

Per esempio, supponiamo di voler lanciare un comando, tutti i giorni del mese, a qualsiasi ora; la sintassi sarà:
@reboot /comando/da/eseguire
oppure, "alla vecchia maniera":
*   *   *   *   *    /comando/da/eseguire
Dato che "tutti i giorni del mese, a qualsiasi ora" equivale a dire "all'avvio del sistema".


Conclusioni:

Come vedete, semplicità d'uso, versatilità ed estrema potenza, fanno di cron uno strumento indispensabile. 

aaah, un ultimo esempio... quello personale che ha ispirato la stesura di questo articolo.
Possiedo una download station+server samba+media center realizzato con un Odroid C1 + Ubuntu 14.04LTS senza DE, gestita completamente da ssh/terminale. Per effettuare i miei downloads, utilizzo il clien pyLoad, downloader manager scritto in python, leggero ma estremamene potente. pyLoad, a differenza del più blasonato jDownloader (scritto in java), viene eseguito come demone (gira, quindi, in background) e si controlla completamente da interfaccia web. Usandolo molto spesso, avevo la necessità di avviare il demone ad ogni avvio del sistema e quindi ho cercato il corrispettivo servizio in modo da attivarlo in avvio. Sia su archlinux, sia su ubuntu (x86 e arm), il servizio c'è ma non legge la configurazione presente nella home e nemmeno modificando lo script e/o seguendo le guide reperite in rete, sono riuscito ad avviare pyLoad all'avvio.
Per qualche mese, ad ogni accensione del server, ero costretto ad un login via ssh e all'avvio manuale del demone; poi si è accesa una lampadina e... crontab!!!!
@reboot    pyLoadCore --daemon --no-remote
e voilà! quando l'automazione incontra "linux".



bcclsn

Nessun commento:

Posta un commento

Licenza
Licenza Creative Commons

Quest' opera è distribuita con licenza Creative Commons Attribuzione - Non commerciale - Non opere derivate 3.0 Unported. Questo blog non rappresenta una testata giornalistica, in quanto viene aggiornato senza alcuna periodicità. Non può, pertanto, considerarsi un prodotto editoriale, ai sensi della legge n. 62 del 7/03/2001

Disclaimer immagini

Le immagini utilizzate in questo blog appartengono ai loro rispettivi autori e sono utilizzati per scopi educativi, personali e senza scopo di lucro. Ogni eventuale violazione del copyright non è intenzionale, ma se si riconosce un'immagine protetta da copyright, fatemelo sapere qui, e sarò lieto di aggiungere i credits o modificarla o rimuoverla.

Disclaimer images

Images used on this blog belong to their respective authors and are used for educational, personal and no profit purposes. Any eventual copyright infringement is not intentional, but if you recognize a copyrighted image, please let me know here, and I'll happily provide to add the right credits or modify or remove it.