Parse maillog

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Domaine Extraction d'adresses mail depuis des fichiers de log
Outils grep, cut, sed
Voir aussi Grep · Sed · Bash

Script qui extrait toutes les adresses mail présentes dans un jeu de fichiers de log (typiquement des logs de MTA au format <adresse@domaine>), les dédoublonne, puis les insère dans une base MySQL — utile par exemple pour constituer une liste d'adresses observées à partir de journaux de courrier.

Script

#!/bin/bash

HOST_SQL=localhost
USER_SQL=collecte_mail
PASSWORD_SQL=
DATABASE_SQL=mail

# emplacement des fichiers source
DIR_FILE=/root/mail*
LISTE_MAIL=liste_mail.txt

TMP_MAIL=$(mktemp)
for file in ${DIR_FILE}; do
    grep '@' "$file" | cut -d'<' -f2- | cut -d'>' -f1 >> "$TMP_MAIL"
    grep '@' "$file" | cut -d'<' -f3- | cut -d'>' -f1 >> "$TMP_MAIL"
done

sort -u "$TMP_MAIL" > "$LISTE_MAIL"
rm -f "$TMP_MAIL"

# insertion en base, une ligne à la fois (lent sur un gros volume)
while IFS= read -r mail; do
    mysql -h "$HOST_SQL" -u "$USER_SQL" -p"$PASSWORD_SQL" "$DATABASE_SQL" \
        -e "INSERT INTO mail (adresse) VALUES ('${mail//\'/}')"
done < "$LISTE_MAIL"

Corrections apportées par rapport au script d'origine :

  • les liens wiki [[grep]] insérés directement dans les commandes (probablement collés depuis une page listant les commandes) rendaient le script invalide tel quel une fois copié-collé — remplacés par les commandes réelles.
  • boucle for i in $(cat fichier) remplacée par while read (plus sûre sur des lignes contenant des espaces, bien que peu probable ici pour des adresses mail).
  • utilisation d'un fichier temporaire (mktemp) au lieu d'un nom de fichier fixe (file_mail.tmp) qui pouvait entrer en collision entre deux exécutions concurrentes.

Points de vigilance

  • Injection SQL : la valeur insérée n'est pas échappée pour MySQL, seule l'apostrophe est retirée (${mail//\'/}) plutôt qu'échappée — une adresse contenant un autre caractère spécial SQL resterait un risque. Pour un usage au-delà d'un script ponctuel sur des données de confiance, préférer un import via LOAD DATA INFILE ou un vrai échappement (mysql --execute ne fait pas d'échappement automatique des valeurs interpolées côté shell).
  • Compte MySQL dédié : utiliser un compte applicatif avec les seuls droits nécessaires (INSERT sur la table visée), pas un compte administrateur.
  • Performance : une requête INSERT par ligne est très lent sur un gros volume — un LOAD DATA INFILE ou un INSERT multi-lignes est nettement plus rapide.

Voir aussi

  • Grep / Sed — extraction et transformation de texte en ligne de commande
  • Bash — boucles, substitution de paramètres