RSYNC depuis AIX vers Linux

Ce billet aurait pu s’intituler “mes aventures dans le monde AIX” ou bien “comment faire du nohup sur AIX” mais se serait être malhonnête car laisserait croire que tous mes problèmes venaient de cet OS propriétaire. Pour être exact le contexte était celui d’un transfert de fichiers depuis une machine AIX 5.3 vers un Linux Cent OS.

Je ne pensais pas que j’allais être confronté à tant de subtilités. Si certaines sont imputables à la limite de mes connaissances en scripting, d’autres ont pour cause les différences entre le monde merveilleux de Linux et celui de AIX.

En premier lieu voici la liste des contraintes imposées par des besoins fonctionnelles, des contraintes de sécurités et des raisons pratiques.

  • c’est AIX qui pilote le transfert: la sécurité impose ce sens de flux
  • les fichiers les plus récents  doivent être copiés en premier: besoin fonctionnel
  • seul les fichiers de moins d’un certain âges seront copiés: contrainte fonctionnelle.
  • la commande de transfert doit être en nohup: raison pratique car le transfert va être long.

Le chemin fut semé d’embûches avant d’arriver à mes fins dont la plupart vient des spécificités du système AIX.

La première difficulté est venue du tri pour obtenir les fichiers les plus récents en premier. Sous Linux on fait un find avec un printf suivi d’un sort

find . -type for -ctime -1460 -printf "T@ %p\n" | sort -r | awk '{print $(NF)}'

pas de printf dans la fin de AIX

la clé NF pour le awk non plus ou conséquence du point precendent

J’avais envie d’utiliser l’option exec du find en lui passant un stat comme ceci

find . -type for -ctime -1460 -exec stat -c '%Y %n' {} \; | sort -r | awk '{print $(2)}'

Pas de stat sous AIX

Malheureusement la commande stat n’existe pas sous AIX et la commande qui s’en rapproche n’a pas la même fonctionnalité. La solution est de passer par une commande perle dans le exec du find

find . -type for -ctime -1460 -exec perl -e '@tmp=stat ($ARGV [0]); print "$tmp [10]\t $ARGV [0]\n";' | sort -r | awk '{print $(2)}'

Mon dieu que c’est compliqué ! Et je n’étais pas au bout de mes peines.

Nohup et pipe

Le lecture ajoutera de lui même un pipe supplémentaire pour faire le rsync. Là n’est pas la question…. quoique on verra plus tard. Il s’agit surtout de mettre toutes ces commandes en nohup. Comme

nohup cmd1 | cmd2

ne porte le nohup que sur cmd1 l’idée est de passer par un seul sous she’ll qui sera vu comme une seule commande.

nohup $SHELL<<EOF &
find . -type for -ctime -1460 -exec perl -e '@tmp=stat ($ARGV [0]); print "$tmp [10]\t $ARGV [0]\n";' | sort -r | awk '{print $(2)}'
EOF

Ceci fonctionne bien sous Linux et il suffit de remplacer les commandes compliquées par un sleep mais sous AIX ?

Pas de sous shell avec le nohup AIX

La documentation IBM AIX disponible sur Internet est formelle. Si le nohup AIX prend en argument une et une seule commande. La seule moyen est de passer un script qui sera vu comme une commande pour le nohup.

nohup sh mon_script.sh

Rsync

Apres les difficultés liées à AIX j’avais également oublié de faire un échange de clé car en nohup on ne pourra pas saisir de mot de passe. Cela n’a rien à voir avec l’AIX, j’étais seulement absorbé sur les spécificités de l’AIX que j’en ai oublié cette subtilité.

Juste pour le plaisir… CC-BY-SA

Ransomware Linux

Il est loin le temps où avoir une machine  sous Linux protégeait des attaques des Virus. Quand j’ai commencé à héberger mon site web, au début des années 2000 j’avais utilisé un serveur Web dédié  (Savant Web serveur) sur Windows et j’avais été très étonné de constater le nombre de tentative  d’accès à des répertoires système de L’OS.  Ces tentatives échouaient car le serveur Web n’était pas IIS….

Depuis j’ai passé toutes mon informatique personnelle en GNU/Linux et je n’ai jamais été confronté à des attaques…. jusqu’à la semaine dernière.

Les pirates ciblent désormais également les machines Linux. Ainsi mes fichiers de disques de VM se sont mis à être renommés avec des suffixes .enc ! Ce que je pensais être un problème d’espace dans ma VM était bel et bien une attaque d’un virus de type ransomware. Tous mes fichiers personnels ainsi que la configurations apache et celle du serveur DNS étaient cryptées.

Heureusement que j’ai des sauvegardes… mais le désagrément causé est certain: rupture de service, éventuelle perte de données (de quand date la dernière sauvegarde?). On ne pense jamais assez aux sauvegardes ! La première chose à faire façe à une infection que l’on ne peut pas éradiquer (manque de littérature et désintérêt des éditeurs) est de limiter la casse. Arrêter le système car le virus à réussi à obtenir les droits root ou du groupe root puisqu’il chiffre des fichiers en écriture à root. Donc arrêter le système puis débrancher le câble d’alimentation ! Ensuite démarrer depuis une clé usb de type live-cd pour récupérer ce qui peut l’être. Enfin réinstaller le système complètement.

Après l’incident il faut également cherchez à s’en prémunir. Comment une telle infection à pu survenir ? Il y a 2 ou 3 semaines mon  serveur n’a pas redémarré sur échec de montage d’un Volume logique. Suite à cet étrange incident je n’avais trouvé comme solution que de démarrer sur un kernel précédent: coïncidence ou la première étape de l’attaque ? M’obliger à utiliser un kernel ancien contenant des failles ?

Ne jamais utiliser de kernel non à jour !

Leçon à retenir: Linux n’est plus sous les radars. Il faut donc s’équiper d’antivirus et d’antispam. Les solutions existent:clamav et spamassasin.

Juste pour le plaisir… CC-BY-SA

Sauvegarde à chaud de VM

Avoir du RAID redondé c’est bien pour éviter la coupure de service en cas de panne matériel mais cela ne protège pas des effacements par erreur. Il faut des sauvegardes.

Comme ce que je recherche c’est de pouvoir revenir à  un l’état de mes données dans le passé, je laissz dz côté la sauvegarde de la définition des VM.

Un script glané sur le site de Debian me sert de base //wiki.debian.org/fr/RsyncSnapshots. Il utilise rsync avec des liaison dur avec la précédente sauvegarde. Un peu inutile quand les VM sont allumée en permanence mais trouve son intérêt quand les fichiers ne changent pas d’une sauvegarde à l’autre.

Voici le script:

#!/bin/sh
##==========================================================================
## Auteur      : Thierry BRESSURE
## Licence     : GNU GPL v3 – //www.gnu.org/licenses/gpl.html
## Description : Script de sauvegarde disques des VM
##============================================================================
## Parametres d’entree : liste des profils a sauvegarder.
## Exemple d’appel     : rsync.sh blog kitejust4fun
## Code de retour      :
##  0 – La sauvegarde des disques s’est correctement terminee.
##============================================================================

ROOT_BACKUP=/media/backup
DEVICE_BACKUP=/dev/sdc1

#####################################
# GESTION DE L’APPEL DE LA COMMANDE #
#####################################

# Recuperation des profils passes en parametre.
if [ $# -ne 0 ]
then
    while [ $# -ne 0 ]
    do
        domains=”$domains $1 ”
        shift
    done
# Aucun domain n’est passe en parametre, on fait donc la sauvegarde pour tout
# le monde.
else
    # lister les vm
    domains=`virsh list | sed 1,2d | awk ‘{print $2}’`   
fi

###################################
# MONTAGE DU DISQUE DE SAUVEGARDE #
###################################

if [ ! -d $ROOT_BACKUP ]
then
   rm -rf $ROOT_BACKUP
   mkdir $ROOT_BACKUP
fi

montage=0

mount | grep “$ROOT_BACKUP” 2>/dev/null
if [ $? -ne 0 ]
then
mount -t ext4 $DEVICE_BACKUP $ROOT_BACKUP && montage=1

fi

####################################
# BOUCLE DE SAUVEGARDE DES PROFILS #
####################################

for un_domain in $domains
do

date_sauvegarde=$(date “+%Y%m%d_%H%M%S”)

echo
echo “${date_sauvegarde} – sauvegarde de la VM ${un_domain}”
        echo “—————————————–”
     

nombre_de_sauvegardes=2
# Creation d’un fichier temporaire pour y ecrire les fichiers et
# repertoires a ne pas sauvegarder (pour ne mettre que le fichier
# temporaire en parametre de la commande rsync)
ce_quil_ne_faut_pas_sauvegarder=$(tempfile)
:>$ce_quil_ne_faut_pas_sauvegarder
# Exclusions generales
echo “*~” >> $ce_quil_ne_faut_pas_sauvegarder

## DECOUVRIR LES DISQUES DE LA VM

        les_disques=`virsh domblklist ${un_domain} –details | sed 1,2d | grep ^file | awk ‘{print $3}’`
        les_images_disques=`virsh domblklist ${un_domain} –details | sed 1,2d | grep ^file | awk ‘{print $4}’`
               
       

## CREER UN SNAPSHOT
    virsh snapshot-create-as –domain ${un_domain} “${date_sauvegarde}” –atomic –disk-only

        ## garder en memoire les disques temporaires de la VM

        les_disques_temp=`virsh domblklist ${un_domain} –details | sed 1,2d | grep ^file | awk ‘{print $3}’`
        les_images_disques_temp=`virsh domblklist ${un_domain} –details | sed 1,2d | grep ^file | awk ‘{print $4}’`

## SAUVEGARDE

  # Si le repertoire de sauvegarde n’existe pas, je le cree.
    if [ ! -d $ROOT_BACKUP/vm_”${un_domain}” ]
    then
        echo “L’emplacement de la sauvegarde n’existait pas.”
        mkdir $ROOT_BACKUP/vm_”${un_domain}”
    fi

    ##############
    # SAUVEGARDE #
    ##############
   
    #il peut avoir plus d’un disque à sauvegarder
    for ce_quil_faut_sauvegarder in ${les_images_disques}
    do
    if [ -L $ROOT_BACKUP/vm_”${un_domain}”/current ] \
        && [ -d $ROOT_BACKUP/vm_”${un_domain}”/current ]
   then
        # Si une precedente sauvegarde existe, on la lie en dur.
        rsync  –delete-excluded –partial \
       –skip-compress=gz/jpg/mp[34]/7z/bz2 –stats -rlpthz \
       –link-dest=$ROOT_BACKUP/vm_”${un_domain}”/current \
–exclude-from “${ce_quil_ne_faut_pas_sauvegarder}” \
“${ce_quil_faut_sauvegarder}” \
      $ROOT_BACKUP/vm_”${un_domain}”/”${date_sauvegarde}”/
else
        # Sinon, on en cree une toute neuve !
      rsync –delete-excluded –partial \
      –skip-compress=gz/jpg/mp[34]/7z/bz2 –stats -rlpthz \
–exclude-from “${ce_quil_ne_faut_pas_sauvegarder}” \
       “${ce_quil_faut_sauvegarder}” \
       $ROOT_BACKUP/vm_”${un_domain}”/”${date_sauvegarde}”/
    fi

    retour_rsync=$?
if [ $retour_rsync -ne 0 ]
then
echo “le disque ${ce_quil_faut_sauvegarder} n’a pas pu etre sauvegarder, on annule le reste”
break
fi      
echo # Pour passer une ligne 🙂

    done

    # Suppression du fichier temporaire qui stocke les repertoires a exclure
    rm $ce_quil_ne_faut_pas_sauvegarder

    #######################
    # GESTION DES ERREURS #
    #######################

    # Pas d’erreur
    if [ $retour_rsync -eq 0 ]
    then
        # La sauvegarde a reussit, on cree un lien “current” pour retenir la
        # derniere.
        rm -f $ROOT_BACKUP/vm_”${un_domain}”/current 2>/dev/null
        ln -s $ROOT_BACKUP/vm_”${un_domain}”/”${date_sauvegarde}”/ \
            $ROOT_BACKUP/vm_”${un_domain}”/current

        # Si le nombre de snapshots depasse nombre_de_sauvegardes, je purge.
        nombre_snapshots=$((`ls $ROOT_BACKUP/vm_”${un_domain}” | wc -l` – 1))
        if [ ${nombre_snapshots} -gt $nombre_de_sauvegardes ]
        then
            # On supprime la plus vieille des sauvegardes
            plus_ancienne=”$(ls $ROOT_BACKUP/vm_”${un_domain}” | head -n 1)”
            rm -rf $ROOT_BACKUP/vm_”${un_domain}”/”${plus_ancienne}”
            echo “Purge de la plus ancienne sauvegarde : ${plus_ancienne}.”
        else
            echo “Aucune sauvegarde anterieure ne doit etre supprimee.”
        fi
    # Probleme lors de la sauvegarde rsync
    else
        # La sauvegarde a echouee, on affiche une erreur et on supprime la
        # tentative.
        echo “La commande rsync a echouee pour l’utilisateur ${un_domain}.”
        echo “Suppression de la sauvegarde en erreur : ${date_sauvegarde}.”
        rm -rf $ROOT_BACKUP/vm_”${un_domain}”/”${date_sauvegarde}”/
    fi
   

## REBASCULER LA VM VERS CHAQUE DISQUE ORIGINAL
    for un_disque in $les_disques
do
    virsh blockcommit ${un_domain} ${un_disque} –active –verbose –pivot
done
   
## SUPPRIMER LE SNAPSHOT DEVENU INUTILE
        virsh snapshot-delete –domain ${un_domain} –metadata ${date_sauvegarde}

## supprimer les disques temporaires qui ne sont hélas pas supprimés par la commande précédente
for image_temp in $les_images_disques_temp
do
echo “suppression du disque temporaire ${image_temp}…”
rm -rf “${image_temp}” && echo “$image_temp supprimé”
done
done

###########################
# démontage si nécessaire #
###########################

if [ $montage -eq 1 ]
then
    umount $ROOT_BACKUP
fi

exit 0

Juste pour le plaisir… CC-BY-SA

Installation Linux par clé USB

La clé USB étant devenue la disquette des temps modernes, il est naturel de s’en servir comme support pour accueillir les ISO des cd/dvd d’installation de Linux. Depuis l’OS propriétaire il existe plusieurs outils pour réaliser cette tâche préliminaire avant de pouvoir booter sur la clé.

Ainsi il y a très longtemps j’avais utilisé  Unetbootin mais ce n’est pas le bon outil si la distribution est un peu personnalisée avec des scripts d’installation spécifiques. Un autre outil USB Universal Installer ne fait pas mieux outrepassant une installation depuis des dépôts spécifiques pour aller chercher les paquets sur internet.

J’ai trouvé le salut avec Rufus qui ne change pas le menu d’installation de l’ISO et conserve bien les scripts d’installation. Un petit écueil que mérite bien un passage de mon poste de travail professionnel sous Linux.

Le libre dans le dessin vectoriel et l’animation

Je n’ai jamais utilisé autre chose que GIMP pour faire des dessins libres. Les fonctions de bases répondaient parfaitement à mes besoins: redimensionner, ajouter du texte etc. Par ailleurs je voyais souvent des gens utiliser des logiciels plus sophistiqués mais privateurs de libertés pour faire du dessin vectoriel ou de l’animation. Ces gens prétendaient que Linux (sic) ne proposait pas une alternative à leur besoin. Comme ces gens étaient ni plus ni moins que des utilisateurs occasionnels de ces  logiciels (i.e. n’utilisant que 10% des fonctions), je mettais en doute leur parole:

“Le libre propose une alternative dans la dessin vectoriel et l’animation”

Comme toujours je fais l’effort d’apprendre à utiliser un logiciel que si c’est nécessaire. Il se trouve que pour les besoins de mon hobby j’avais besoin de faire des schémas, des animations et des vidéos. Voilà une bonne raison de tester les logiciels libres destinés à cet usage.

Inkscape

Le logiciel de dessin vectoriel Inkscape est facile d’accès et permet de dessiner des objets vectoriels que l’on pourra cloner, changer de forme et de tailles perdre en qualité. Ce logiciel est très pratique pour réaliser des schémas ou faire des affiches. Le format de fichier consacré est SVG. Utilisez ce format au lieu des formats propriétaires ! Pour l’export utilisez le format PNG.

360 paire
Exemple de schéma réalisé avec Inkscape

Blender

Le logiciel Blender permet de faire de la modélisation et de l’animation en 3D. Il peut paraître compliqué (et il l’est !) mais pas plus que les solutions propriétaires. De plus sa puissance est stupéfiante:

Cinelerra

Pour le montage vidéo à proprement parler, la solution que je préfère est Cinelerra qui propose une interface similaire à Blender et des fonctions avancées (fusion d’image, nombre de pistes illimités, effet vidéos etc). Cinelerra travaille sans détruire les sources. Il crée un vrai description du montage dont un aperçu du rendu est affiché pendant l’édition. Un mode rendu en tâche de fond existe et permet de réaliser le véritable rendu en tâche de fond afin que l’aperçu soit une version réaliste du rendu final. Exemple de vidéo montée avec Cinelerra:

Les exemples de réalisation n’ont pas vocation à montrer l’état de l’art de ce que l’on peut obtenir avec ces logiciels mais montrent que sans expérience préalable, ni talent artistique particulier on peut réaliser des documents (dessin, animation, vidéos) de qualité acceptable en utilisant uniquement du Logiciel Libre.

Une distribution libre et humanitaire: Emmabuntüs

Dans ma quête de la distribution libre et peu gourmande en ressource, je suis arrivé à la conclusion que Debian/LXDE est pour moi le couple idéal pour faire fonctionner mes machines sans avoir à me soucier de changer de processeur tous les 2 ans ni d’augmenter la quantité de mémoire vive tous les 4 ans. Je trouve en effet que c’est une bêtise de consommer 800Mo de RAM juste pour afficher le bureau… Cette solution est tellement économique en ressource que je peux faire fonctionner un portable de 2008 acheté en occasion et sur lequel j’ai dû malheureusement supprimer le système privateur installé par le reconditonneur.

Le bureau LXDE encore moins gourmand que XFCE s’avère être un choix de premier plan pour toutes les machines d’occassion. L’utilisation de matériel reconditionné n’est pas seulement une contrainte économique mais également un acte écologique et politique. Il ne manquait plus qu’une distribution dans ce sens à l’opposé de la surenchère de puissance que l’on constate dans les magasins en cette période de débauches festives où l’Hommo-economicus perd la raison. Cette distribution s’appelle Emmabuntüs disponible sur sourceforge

Ubuntu a-t-il mal vieilli ?

Je conseillais jusque là Ubuntu comme distribution linux pour débutant à cause de sa simplicité d’utilisation mais j’avais arrêté de mettre à jour mon système restant sur une LTS il y a 2 ou 3 ans. En effet l’interface Unity, de plus en plus gourmande ne m’intéressait plus. Finalement j’ai migré vers Debian il y a quelque mois. A vrai dire le couple Debian/LXDE me donne entièrement satisfaction !

On m’a demandé récemment quelle distribution pour un windosien ? J’ai répondu Ubuntu car c’est celle qui m’avait permis d’introduire Linux à la maison en 2006. Mais Ubuntu a mal vieilli. Le windosien est revenu vers moi, complètement perdu pas l’interface Unity, dérouté pas les explications et conseil du magazine Ubuntu dans lequel il avait eu des CD d’installation de la toute derniére version 14.10.

Si certains défauts sont classiques, comme celui de la dalle LCD de résolution non standard que l’installeur ne pourra configurer tout seul, d’autres posent problême lors du passage de windows à ubuntu. Celui qui est habitué à de vieux windows (Menu démarrer, Mes Programmes etc) risque d’être perdu par Unity. La présence d’une icône Amazon chantre du commerce electronique et producteur de la liseuse qui efface vos livres peut dérouter celui à qui on vanté les vertues du libre et de sa gratuité de fait. Le gestionnaire d’application d’ubuntu sélectionne également certaines applications pour effectuer des tâches données: quid de la liberté de l’utilisateur ?

Est-ce pour autant des défauts ? Ubuntu permet de choisir un bureau différent tel que LXDE pour celui qui comme moi préfère une interface vieillote. Le choix de Canonical de mettre en avant certains logiciels peut être mis sur le compte de la cohérence d’ensemble. Cela est le rôle du fournisseur de la distribution. Pour autant le gestionnaire de paquet synaptic permettra d’installer tous les paquets issus de Debian.

Heureusement dans le monde du libre, le choix n’est pas un vain mot. On pourra se retourner vers une distribution plus soucieuse de l’éthique telle que Debian ou pour les puristes gNewSense ou Trisquel adoubées par la FSF.

Du bonne usage de la commande LS

Sous Linux, le ls est sans doute une des commandes les plus utilisées. En effet une fois arrivé dans un répertoire, qui ne lance pas un ls pour visualiser son contenu ? Cette commande est un peu le coup d’oeil qu’on lance autour pour juger son environnement.

Usage du ls

La pluspart du temps l’utilisateur fait

ls

ou alors pour avoir plus d’information sur les fichiers

ls -l

Cela correspond à un usage normal de la commande ls qui est d’obtenir la liste du contenu d’un répertoire.

Détournement du ls

Malheureusement cela se gâte quand on est dans un répertoire avec de très nombreux fichiers et que l’on veut juste des information sur certains d’entre eux. On utilise alors un motif de complétion en * pour effectuer ce genre de commande:

ls -l toto*

On obtient ainsi la liste des fichiers (i.e.les informations sur) commençant par toto. L’utilisateur a alors l’impression que ls fait une recherche des fichiers commençant par toto. C’est faux. Pour s’en convaincre il suffit d’activer le débug du shell par

set -x

Cela permet de voir ce que le shell exécute, puis lancez la commande:

ls *

On constate que l’expansion de shell remplace l’étoile par tous les fichiers présents dans le répertoire avant d’evaluer la commande ls suivie des paramètres ainsi constitués. Donc a en fait lancé la commande :

ls fichier1 fichier2 fichier3

C’est l’expansion de shell qui fait la soit disant recherche et ls ne fait que donner des informations sur les fichiers trouvés. Comme on ne passe pas de commutateur tel que -l, on n’obtient ni plus ni mpoins confirmation que les fichiers existent bien (travail effectué par l’expansion de shell).

Mauvais usage du ls

De la se servir de ls pour tester l’existense de fichier, il n’y a qu’un pas qu’il ne faut pas franchir. En effet on vu que c’est l’expansion de shell qui fait le boulot. Cela conduit à un effet désagréable quand l’expansion de shell ramène beaucoup trop de fichiers si bien que le shell ne peut exécuter la commande ls avec tant d’argument. Sur un linux récent faire n ls * dans un répertoire avec 100000 fichiers dont le nom fait 20 caractères chacun, conduit à:

ls *
bash: /bin/ls: Liste d'arguments trop longue

Laissons à ls ce qui appartient à ls: donner des informations sur des fichiers (taille, droits etc.). Pour la recherche de fichier il y a find

find -name "toto*"

En mettant entre guillemet le motif du nom de fichier, on empêche l’expansion de shell. On garde une ligne de commande courte. find interprête le meta-caractère étoile pour faire la recherche.

Existence de fichier selon un motif

Si on veut juste vérifier l’existence de fichier ayant un certain motif, on peut faire sur un Linux récent:

find -name "toto*" -print -quit | wc -l

Cela permet de chercher en s’arrêtant sur le premier trouvé puis de compter le nombre de fichier trouvé: soit 0 soit 1.

Si findutils n’est pas au moins en version 4.2.3 sur votre système alors l’option -quit n’est pas disponible. Son absence aura pour effet de vous priver d’un arrêt de la commande au premier fichier trouvé…. et donc obligera de faire une recherche complète.

Si l’on veut récupérer l’information d’existence où non de fichier via un code retour, on pourra avantageusement utiliser grep combiné à un ls comme ceci

if (ls | grep "2014*" 1>/dev/null 2>&1) then echo "trouve"; else echo "pas trouvé"; fi

Compression de log Tomcat 6 avec log4j 1.2

Le sujet est largement débattu mais il n’est pas trivial de trouver la solution de bout en bout. Diversité des cas, obsolescence de Tomcat 6 ou de log4j 1.2 ? En tout cas voici comment on peut mettre en place la compression de log de Tomcat 6 à l’aide de log4j 1.2.15 !

D’abord pourquoi mettre en place de la compression de log ? La log de Tomcat (ex catalina.out) ne devrait contenir que peu de messages et seulement de rare erreurs, non ? La diversité des programmeurs peut amener ces log à grossir et les framework qui génèrent des URL mal formées existent (caractère illégal). La rotation des fichiers de log si elle limite la taille ne permet pas de garder un historique c’est pourquoi je lui préfère la compression.

La documentation de Tomcat 6 permet de mettre en place rapidement log4j 1.2.17 et de disposer de la log de  Tomcat configurée par un fichier log4j.properties. L’activation de la compression des log se fait par l’utilisation de l’appender RollingFileAppender mais il ne s’agit pas de celui du paquet log4j mais plutôt du sous-paquet rolling (en gras dans l’exemple suivant). Ensuite il faut choisir la politique de rotation basée sur le temp TimeBasedRollingPolicy et enfin en spécifiant un motif de nom de fichier avec extension gz ou zip, le fichier sera compressé. Pour tester immédiatement la compression des log catalina.out, vous pouvez utiliser le fichier de configuration suivant où le niveau de log est passé à DEBUG et génère un fichier compressé par seconde.

log4j.rootLogger=DEBUG, CATALINA

# Define all the appenders
log4j.appender.CATALINA=org.apache.log4j.rolling.RollingFileAppender
log4j.appender.CATALINA.File=${catalina.base}/logs/catalina.
log4j.appender.CATALINA.RollingPolicy=org.apache.log4j.rolling.TimeBasedRollingPolicy
log4j.appender.CATALINA.RollingPolicy.ActiveFileName =${catalina.base}/logs/catalina.log
log4j.appender.CATALINA.RollingPolicy.FileNamePattern=${catalina.base}/logs/catalina.%d{yyyyMMdd.HHmmss}.gz
log4j.appender.CATALINA.Append=true
log4j.appender.CATALINA.Encoding=UTF-8
log4j.appender.CATALINA.layout = org.apache.log4j.PatternLayout
log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.LOCALHOST=org.apache.log4j.DailyRollingFileAppender
log4j.appender.LOCALHOST.File=${catalina.base}/logs/localhost.
log4j.appender.LOCALHOST.Append=true
log4j.appender.LOCALHOST.Encoding=UTF-8
log4j.appender.LOCALHOST.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.LOCALHOST.layout = org.apache.log4j.PatternLayout
log4j.appender.LOCALHOST.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.MANAGER=org.apache.log4j.DailyRollingFileAppender
log4j.appender.MANAGER.File=${catalina.base}/logs/manager.
log4j.appender.MANAGER.Append=true
log4j.appender.MANAGER.Encoding=UTF-8
log4j.appender.MANAGER.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.HOST-MANAGER=org.apache.log4j.DailyRollingFileAppender
log4j.appender.HOST-MANAGER.File=${catalina.base}/logs/host-manager.
log4j.appender.HOST-MANAGER.Append=true
log4j.appender.HOST-MANAGER.Encoding=UTF-8
log4j.appender.HOST-MANAGER.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.HOST-MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.HOST-MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

# Configure which loggers log to which appenders
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=INFO, LOCALHOST
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager]=\
  INFO, MANAGER
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager]=\
  INFO, HOST-MANAGER

Cette configuration fonctionne avec log4j 1.2.17 mais pas seulement. En remplaçant le jar log4j.jar par celui de la version 1.2.16, cela fonctionne aussi. En rétrogradant en version 1.2.15 il faudra utiliser un fichier de configuration au format XML (car le support du fichier dde conf en propriété a été introduit dans la version suivante 1.2.16). Voici un exemple de fifichier de configuration au format XML:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="//jakarta.apache.org/log4j/">
  <appender name="console"> 
      <param name="file" value="${catalina.base}/logs/catalina."/>        
       <rollingPolicy>
      <param name="FileNamePattern" value="${catalina.base}/logs/catalina.%d{yyyyMMdd.HHmmss}.gz"/>
      <param name="ActiveFileName" value="${catalina.base}/logs/catalina.log" />
    </rollingPolicy>
    <layout> 
      <param name="ConversionPattern" value="%-5p %c{1} - %m%n"/> 
    </layout> 
  </appender> 

  <root> 
    <priority value ="debug" /> 
    <appender-ref ref="console" /> 
  </root>
  
</log4j:configuration>