traitement automatique d'un fichier

De Linux France
Aller à : navigation, rechercher

Introduction

Le script de shell proposé, destiné à Linux et utilisable en tant que spouleur, surveille un répertoire donné (de spool). Lorsqu'il y détecte création d'un fichier il lance automagiquement un traitement.

Il emploie le service « inotify » donc ne polle pas.

Installation

Installer les utilitaires « inotifywait » (sous Debian: paquetage « inotify-tools » ) et « logger » (Debian: « bsdutils »).

Éditer le script:

  • la variable « SPOOLDIR » doit contenir le nom d'un répertoire, existant et vide, où tout fichier à traiter sera déposé
  • la variable ARCHIVEDIR doit contenir le nom d'un répertoire existant où le script déplacera tout fichier traité
  • la section « traitement » doit effectuer les traitements (la variable TMPFILNAM contient le nom du fichier à traiter). Dans le script proposé le traitement consiste à révéler à bogofilter et à SpamAssassin qu'un fichier recelant un courriel est du ham. Note: idéalement les logiciels impliqués communiquent eux aussi via syslog

Invoquer le script via la ligne de commande, en avant-plan, puis le tester et mettre au point en plaçant (créant, copiant ou déplaçant) un fichier dans le répertoire SPOOLDIR. Le script confie ses messages à syslog, donc surveiller les logs.

Lorsque tout fonctionne, paramétrer de sorte qu'il soit automatiquement invoqué sous le compte utilisateur adéquat, par exemple en éditant /etc/rc.local afin qu'il contienne:

su - nat -c ~nat/outils/ham &

remplacer 'nat' par le nom de connexion associé au compte, et '~nat/outils/ham' par le chemin complet du fichier script. On peut préférer le faire via init ou bien cron (/etc/crontab , date spéciale "@reboot", voir « man 5 crontab »).

Utilisation

Placer tout fichier à traiter dans le répertoire SPOOLDIR. Son nom importe peu.

Pour faciliter cela on peut établir un lien symbolique, par exemple ainsi:

cd # retour au répertoire HOME
mkdir -p tmp/ham_spool # création du SPOOLDIR
ln -s tmp/ham_spool .ham # création d'un lien

Il suffira ensuite, pour requérir traitement d'un fichier, de le copier par exemple dans « ~/.ham/m », ce qui est moins long à saisir que « ~/tmp/ham_spool/l ».

Limitations

Aucun verrouillage, donc plusieurs instances (sens 2) de ce script peuvent simultanément fonctionner. Si c'est inadéquat il sera facile d'y remédier.

Les fichiers présents dans le SPOOLDIR lors du démarrage du script ne sont pas traités. C'est délibéré. Pour déclencher leur traitement, lancer le script puis les toucher.

Chaque fichier est individuellement pris en charge, il n'est pas possible de traiter plusieurs fichiers à la fois.

Aucun filtrage ou sélection n'est assuré, qui offrirait par exemple moyen de lancer un traitement dépendant du nom du fichier ou de son heure de création.

Script

#!/bin/bash
#set -o errexit
 
# Nom de ce script, tel qu'il apparaîtra dans les logs
MYNAME=ham
 
# Nom du répertoire où ce script trouvera les fichiers à traiter
SPOOLDIR=~/tmp/ham_spool
 
# Nom du répertoire où ce script déplacera les fichiers après traitement
ARCHIVEDIR=~/tmp/ham
 
# syslog facility
SYSLOGFAC=daemon
 
## No configuration after this line
 
MYVERSION=0.12
 
MYLOGNAME="$MYNAME"_"$MYVERSION"
 
logger -i -p "$SYSLOGFAC".info -t "$MYLOGNAME" -- Starting
 
[ ! -d "$ARCHIVEDIR" ] && { logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- No ARCHIVEDIR directory found, please create it; exit 4; }
[ ! -d "$SPOOLDIR" ] && { logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- No SPOOLDIR directory found, please create it; exit 5; }
 
cd "$SPOOLDIR" || { logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- "Cannot reach SPOOLDIR"; exit 6; }
 
while TMPPREFILNAM="$SPOOLDIR"/$(inotifywait -e close_write --format="%f" -q ./) ; do
 
    logger -i -p "$SYSLOGFAC".info -t "$MYLOGNAME" -- Despooling "$TMPPREFILNAM"
 
    TMPFILNAM=`mktemp --tmpdir="$SPOOLDIR" ham_tmpXXXXXX`
    if [ ! -f "$TMPFILNAM" ] ; then
        logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- Cannot create tmp file "$TMPFILNAM"
        exit 7
    fi
 
    mv "$TMPPREFILNAM" "$TMPFILNAM" || { logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- mv failed "$TMPFILNAM"; exit 8; }
 
    [ ! -s "$TMPFILNAM" ] && logger -i -p "$SYSLOGFAC".notice -t "$MYLOGNAME" -- Warning: "$TMPFILNAM" file is empty
#    [ ! -f "$TMPFILNAM" ] && logger -i -p "$SYSLOGFAC".notice -t "$MYLOGNAME" -- Warning: "$TMPFILNAM" is not a regular file
    [ ! -r "$TMPFILNAM" ] && logger -i -p "$SYSLOGFAC".notice -t "$MYLOGNAME" -- Warning: "$TMPFILNAM" file cannot be read
 
# traitement
    bogofilter -S -I "$TMPFILNAM"
    [ "$?" -ne 0 ] && logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- Warning: bogo1 failed
    sa-learn --forget "$TMPFILNAM"
    [ "$?" -ne 0 ] && logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- Warning: sa-learn1 failed
 
    bogofilter -n -I "$TMPFILNAM"
    [ "$?" -ne 0 ] && logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- Warning: bogo2 failed
    sa-learn --ham "$TMPFILNAM"
    [ "$?" -ne 0 ] && logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- Warning: sa-learn2 failed
 
# déplacement (archivage)
    mv --backup=numbered "$TMPFILNAM" "$ARCHIVEDIR" || logger -i -p "$SYSLOGFAC".err -t "$MYLOGNAME" -- Cannot mv "$TMPFILNAM"
 
done