Cron

Permet de lancer une tâche à une date précise ou à intervalles réguliers.
Il suffit d'indiquer la tâche et le moment dans un fichier que l'on édite avec vi en lançant la commande : crontab -e.
Il y a une table cron par utilisateur : si je me connecte sous xxx, j'accède à la table cron de xxx.

Syntaxe

mm hh jj MMM JJJ tâche > log

Exemple :

30 08 29 001 001 /user/local/loris/cgi/filip/test_cron.pl > /user/local/loris/cgi/filip/cron_log.lst

Cette entrée lance le script test_cron.pl à 8h30 le lundi 29 janvier. Le résultat est envoyé dans un fichier journal cron_log.lst.

Chacune des 5 indications de temps peut être remplacée par une * qui permet de ne rien indiquer, autrement dit de demander à cron de lancer la tâche chaque minute, chaque heure, chaque jour, chaque mois et/ou chaque jour de la semaine. Par exemple :
30 * * * * tâche : lance la tâche chaque demi-heure.

On peut aussi préciser des périodes, des unités de temps qui se suivent : 1-5 (001-005) dans la zone JJJ signifie : du lundi au vendredi.

On peut aussi donner des suites discontinues : 1,3,5 = lundi, mercredi et vendredi.

On peut aussi préciser une fréquence : */15 dans la zone des minutes signifie : tous les quarts d'heure.

On peut ajouter une ligne de commentaire introduite par #.

Si l'on ne spécifie pas de fichier journal, le résultat de la commande cron est envoyé dans le fichier : /var/spool/mail/loris (faire cd /var/spool/mail/ puis vi loris).

Test

J'ai créé un perl : dispo2en_pret.pl :

#!/opt/perl/bin/perl -w
# Remet en Statut disponible les exemplaires qui ont une date de pret
# Suite à bug de l'import xml

use DBI;
use DBD::Oracle;

my $utilisateur = 'XXX';
my $motdepasse = 'XXX';

my $dbconnect = DBI->connect('DBI:Oracle:',$utilisateur,$motdepasse);
my $sql = $dbconnect->prepare( <<FINSQL );
UPDATE EXEMPLAIRE
SET ETAT = 2
WHERE DATE_PRET IS NOT NULL AND ETAT = 1
FINSQL
$sql->execute();
$sql->finish();
undef $sql;
$dbconnect->disconnect();

J'ai envoyé ce script dans : user/local/loris/cgi/filip/cron/
et je lui ai donné les droits d'exécution.

Puis j'ai fait crontab -e :

50 07 * * 1-5 user/local/loris/cgi/filip/cron/dispo2en_pret.pl

Ça ne marche pas. Parce que, lorsqu'on essaie de se connecter à Oracle à partir d'un cron, les variables d'environnement d'Oracle ne sont pas connues. La connexion échoue donc.
Pour remédier à cela, il faut ajouter au script les variables de connexion :
my $dbconnect = DBI->connect(''dbi:Oracle:host=<hostname>;sid=<oracle_sid>;port=<port>'',$utilisateur,$motdepasse);
Cela donne pour nous :
my $dbconnect = DBI->connect(''dbi:Oracle:host=cacao;sid=V817;port=1522'',$utilisateur,$motdepasse);

Messages

Lorsqu'il y a une erreur, un message est écrit dans le fichier loris dans le répertoire : /var/spool/mail/

Comment enregistrer les messages d'erreur et les recevoir par courriel ?

Il suffit de réorienter STDERR vers un fichier texte, que l'on enverra ensuite.

Pour enregistrer STDERR :
open STDERR, ">$rep/nouveautes.log";

Ensuite on peut imprimer dans STDERR comme dans dans tout autre fichier :
print STDERR $madate."\n";

À la fin on ferme STDERR :
close STDERR;

Puis on envoie :

open (my $LOG, "<$fichier_log");
while (<$LOG>)
        {
        $chaine_log .= $_;
        }
close $LOG;

open (my $MAIL, "| /usr/sbin/sendmail -t -i  -FPhilippe Combot") or die "Impossible d'ouvrir sendmail $!";
print {$MAIL} "To: combot\@univ-tln.fr\n";
print {$MAIL} "Reply-To: combot\@univ-tln.fr\n";
print {$MAIL} "Subject: Rapport Script Nouveautes\n\n";
print {$MAIL} $chaine_log;
close $MAIL or die "Erreur en fermant sendmail : $!";

Passage par un fichier .sh

Si on veut lancer plusieurs scripts les uns à la suite des autres, il est plus simple de faire un fichier .sh qui sera lancé par cron.
Exemple de fichier : nouveautes.sh

ORACLE_SID=V817;export ORACLE_SID
LD_LIBRARY_PATH=/user/local/oraclev8/app/oracle/product/8.1.7/lib; export LD_LIBRARY_PATH
ORACLE_HOME=/user/local/oraclev8/app/oracle/product/8.1.7;export ORACLE_HOME
NOUVEAUTES=/user/local/loris/filip/nouveautes_v2;export NOUVEAUTES
NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1;export NLS_LANG

$NOUVEAUTES/nouveautes.pl
$NOUVEAUTES/fabrique_tournant.pl

Ici NOUVEAUTES est une variable, que l'on peut récupérer dans le script perl comme ceci :
my $rep = $ENV{"NOUVEAUTES"};

Ce passage par un fichier .sh permet aussi de lancer plus facilement des commandes dans le répertoire bin de Loris (dt_index...), plutôt que d'utiliser system($commande) de perl.