Dans ce guide, nous allons voir comment loguer les commandes shell sur un serveur Linux basé sur Debian ainsi que comment les envoyer à un serveur syslog. Cela peut être intéressant à mettre en place sur des infrastructures avec des serveurs Linux critiques où il est nécessaire d’avoir un visuel de ce qui est fait sur le serveur. Il est aussi possible de mettre en place des méchanismes de détection d’activité suspecte, cependant, nous ne le couvrirons pas dans ce guide. Nous verrons comment configurer le logging sur bash et zsh

Installation de rsyslog

Pour ce guide, nous aurons besoin du paquet rsyslog. Il est déjà présent sur la plupart des distributions Linux. Sur les distributions basées sur Debian, il peut être installé avec cette commande.

apt install rsyslog

Configuration du shell

Pour loguer notre commande, nous devrons l’intercepter avant son exécution et la loguer.

Sur ZSH

preexec() est une fonction spéciale de ZSH qui s’exécutte automatiquement juste avant chaque commande lancée dans le terminal. Dans notre cas, elle nous servira à intercepter la commande tapée et de la loguer. Il suffit juste d’ajouter ce bloc de code à la fin du fichier ~/.zshrc :

preexec() {
    # Eviter de logger le logger lui-même pour ne pas boucler
    [[ "$1" == logger* ]] && return

    # Envoyer la commande au syslog
    logger -p local0.notice -t zsh "$USER@$(hostname): $1"
}

Sur Bash

Bash ne fournit pas de fonction preexec(), nous devrons donc la contourner. Il est possible de créer un hook qui s’éxécuttera avant chaque commande et remplacera preexec(). Le code se présente ainsi et peut être ajouté au fichier ~/.bashrc

__bash_preexec() {
    # Commande sur le point d'être exécutée
    local cmd="$BASH_COMMAND"

    # Éviter de logger le logger lui-même
    [[ "$cmd" == logger* ]] && return

    # Envoyer la commande au syslog
    logger -p local0.notice -t bash "$USER@$(hostname): $cmd"
}

# Hook avant chaque commande
trap '__bash_preexec' DEBUG

Configuration de rsyslog

Les commandes loguées par logger sont envoyées directement à syslog et sont catégorisés dans la facility local0. Les facilities sont utilisés par syslog pour catégoriser les logs et pouvoir les traiter. Comme facilities, on retrouve notamment :

  • auth pour l’authentification
  • cron pour les tâches planifiées (cronjobs)
  • daemon pour les services système
  • etc… Les facilities local sont des catégories libres et peuvent être utilisés pour divers usages. Pour récupérer les logs par rsyslog et les transmettre à notre serveur de logs, nous pouvons créer une configuration dans /etc/rsyslog.d/. /etc/rsyslog.d/30-shell-logs.conf
template(name="syslog-shell" type="string" string="<%PRI%>%TIMESTAMP% %HOSTNAME%-shell %syslogtag% %msg%\n")

if $programname == 'zsh' then {
    action(
        type="omfwd"
        target="<SERVEUR SYSLOG>"
        port="514"
        protocol="udp"
        template="syslog-shell"
    )
    stop
}

Dans notre config, nous commencons d’abord par créer une template de log dans lequel nous définissons le format de notre log. Il est tout à fait possible de modifier ce template en fonction de vos besoins. Pour facilement distinguer les logs shell d’autres potentiels logs, le champ hostname contient la chaine -shell à la fin. Il ne faudra pas oublier de remplacer <SERVEUR SYSLOG> par l’IP de votre serveur syslog et vérifier le port syslog.

Une fois la configuration modifiée, nous pouvons relancer le service rsyslog avec la commande

systemctl restart rsyslog

Nous pouvons maintenant fermer la session sur le serveur et nous reconnecter pour relancer un nouveau shell.
En parallèle, nous pouvons lancer un tcpdump avec la commande tcpdump port 514 sur notre serveur syslog et entrer une commande sur l’autre serveur pour vérifier qu’il envoie bien les logs au serveur syslog.

root@loki ~                                                                                    [21:52:50]
> # tcpdump port 514                                                                                     
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
21:56:37.407625 IP ubuntu-lab.nbl.sh.58841 > loki.nbl.sh.syslog: SYSLOG local0.notice, length: 79
21:56:37.407625 IP ubuntu-lab.nbl.sh.58841 > loki.nbl.sh.syslog: SYSLOG local0.notice, length: 49
21:56:38.524490 IP ubuntu-lab.nbl.sh.58841 > loki.nbl.sh.syslog: SYSLOG local0.notice, length: 49
3 packets captured
3 packets received by filter
0 packets dropped by kernel

Si tout est bon, vous devriez voir une sortie similaire avec des paquets syslog interceptés par le serveur syslog. Vous pouvez maintenant réutiliser ces logs dans votre dashboard de monitoring. Voici un exemple de sortie que j’ai sur mon dashboard Grafana.

2026-02-06 22:52:55.476 INFO  root@ubuntu-lab: ls
2026-02-06 22:45:57.825 INFO  root@ubuntu-lab: cat /etc/passwd
2026-02-06 22:28:19.471 INFO  root@ubuntu-lab: echo "Hello World !"

J’espère que ce guide vous aura été utile, si besoin n’hésitez pas à me contacter sur Matrix -> @jan:matrix.nobell.fr.