Quand un client annonce connection lost, il ne sait généralement pas pourquoi. Le broker, lui, le sait. Chaque connexion refusée, timeout de keep-alive, client ID en double et publication refusée laisse une ligne dans le log du broker — à condition que la journalisation soit configurée pour la conserver. Lire ces lignes est souvent le moyen le plus rapide de déboguer un client auquel vous ne pouvez pas attacher de débogueur.
Ce guide montre où trouver les logs, quels niveaux activer, comment lire les lignes de connexion et de déconnexion de Mosquitto, comment tracer un client dans EMQX et comment transformer une ligne de log en correction.
Où se trouvent les logs
| Installation | Où regarder |
|---|---|
| Mosquitto installé par paquet Linux | /var/log/mosquitto/mosquitto.log ou journalctl -u mosquitto -f |
| Mosquitto dans Docker | docker logs -f mosquitto (avec log_dest stdout) |
| EMQX | Sortie console dans Docker (docker logs -f emqx) ; fichiers dans le répertoire log/ de l'installation |
| HiveMQ | log/hivemq.log, plus log/event.log pour les connexions et déconnexions de clients |
| Broker managé | Généralement pas de logs bruts — appuyez-vous sur les reason codes et la supervision (voir plus bas) |
Si le fichier de log de Mosquitto reste vide, cherchez dans la sortie de démarrage Error: Unable to open log file /var/log/mosquitto/mosquitto.log for writing. : l'utilisateur du broker ne peut pas écrire dans le répertoire. La configuration de la journalisation est détaillée dans journalisation de Mosquitto.
Activer le bon niveau de log
La journalisation par défaut de Mosquitto masque l'essentiel de ce dont vous avez besoin pour déboguer un client. Une configuration utile pendant l'enquête :
log_dest stdout
log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information
log_type subscribe
log_type unsubscribe
# Chaque paquet entrant et sortant — très verbeux, à n'activer que pour déboguer
log_type debug
connection_messages true
log_timestamp true
log_timestamp_format %Y-%m-%dT%H:%M:%SRedémarrez le broker après avoir modifié les options de journalisation. connection_messages true produit les lignes de connexion et de déconnexion sur lesquelles repose presque tout ce guide, et un format d'horodatage lisible vous évite de convertir des secondes Unix à la main. Vous pouvez générer une configuration complète avec le générateur de mosquitto.conf.
Pour EMQX 5, augmentez le niveau de la console d'un conteneur avec la variable d'environnement EMQX_LOG__CONSOLE__LEVEL=debug, ou changez-le à chaud :
emqx ctl log set-level debug
# ...reproduire le problème...
emqx ctl log set-level warningLire les lignes de connexion de Mosquitto
Une connexion réussie produit deux lignes :
2026-10-17T09:12:01: New connection from 192.168.1.20:52144 on port 1883.
2026-10-17T09:12:01: New client connected from 192.168.1.20:52144 as sensor-01 (p2, c1, k60, u'alice').La parenthèse finale décrit le paquet CONNECT :
| Champ | Signification |
|---|---|
p2 | Protocole : p2 = MQTT 3.1.1, p5 = MQTT 5 (p1 serait l'ancien 3.1) |
c1 | Clean session / clean start : c1 = nouvelle session, c0 = reprise d'une session persistante |
k60 | Intervalle de keep-alive en secondes |
u'alice' | Nom d'utilisateur envoyé par le client (absent s'il n'y en a pas) |
Ces quatre champs répondent à plusieurs questions d'un coup : le client utilise-t-il vraiment la version de protocole que vous pensez ? Demande-t-il une session persistante ? Quel keep-alive a-t-il réellement défini ?
Lignes de déconnexion et leur signification
La ligne écrite par Mosquitto quand un client part est la plus utile de tout le log :
| Ligne de log | Cause | Correction |
|---|---|---|
Client sensor-01 disconnected. | DISCONNECT propre du client | Rien — c'est voulu |
Client sensor-01 closed its connection. | TCP fermé sans DISCONNECT | Le client a planté, a été tué ou a perdu son alimentation |
Client sensor-01 has exceeded timeout, disconnecting. | Aucun paquet pendant 1,5 × keep-alive | Corrigez la boucle du client, la logique de veille ou le timeout NAT — voir timeout de keep-alive |
Client sensor-01 already connected, closing old connection. | Un second client a utilisé le même client ID | Des IDs uniques par appareil — voir client ID en double |
Client sensor-01 disconnected, not authorised. | Identifiants erronés ou pas le droit de se connecter | Vérifiez utilisateur, mot de passe et plugin d'authentification |
Client sensor-01 disconnected due to protocol error. | Paquet malformé ou inattendu | Bug de bibliothèque, mauvaise version de protocole ou MQTT brut sur un listener WebSocket |
Socket error on client sensor-01, disconnecting. | Connexion rompue au niveau réseau | Coupure réseau, erreur TLS ou RST d'un équipement intermédiaire |
Outgoing messages are being dropped for client sensor-01. | La file du client est pleine | Consommateur lent — augmentez les limites ou consommez plus vite |
Quand deux lignes already connected, closing old connection alternent toutes les quelques secondes, deux appareils se disputent un client ID et se reconnectent en boucle. Générez des IDs uniques avec le générateur de client ID.
Suivre une session au niveau debug
Avec log_type debug, Mosquitto journalise chaque paquet. Un subscriber et un publisher sur un topic de test ressemblent à peu près à ceci (Mosquitto 2.x, abrégé) :
Received SUBSCRIBE from sub-01
testmqtt/logs/# (QoS 1)
sub-01 1 testmqtt/logs/#
Sending SUBACK to sub-01
Received PUBLISH from pub-01 (d0, q1, r0, m1, 'testmqtt/logs/a', ... (5 bytes))
Sending PUBACK to pub-01 (m1, rc0)
Sending PUBLISH to sub-01 (d0, q1, r0, m1, 'testmqtt/logs/a', ... (5 bytes))
Received PUBACK from sub-01 (Mid: 1, RC:0)La parenthèse des lignes PUBLISH se lit ainsi : d = flag DUP, q = QoS, r = retain, m = message ID, puis le topic et la taille du payload. Si vous voyez Received PUBLISH sans Sending PUBLISH, le broker a accepté le message mais aucun abonnement ne correspondait — vérifiez le topic filter avec le topic matcher. Une ligne Denied PUBLISH signifie qu'une ACL l'a bloqué ; c'est le cas traité dans ACL refusée silencieusement.
Pour reproduire un cas rapidement, gardez le log ouvert dans un terminal et générez du trafic depuis un autre :
# Terminal 1 — côté broker
docker logs -f mosquitto 2>&1 | grep --line-buffered -E 'sub-01|pub-01'
# Terminal 2 — côté client, avec la sortie de débogage des clients
mosquitto_sub -d -h localhost -i sub-01 -t 'testmqtt/logs/#' -q 1 &
mosquitto_pub -d -h localhost -i pub-01 -t 'testmqtt/logs/a' -q 1 -m 'hello'-d fait afficher aux clients leur propre journal de paquets (Client sub-01 sending CONNECT, received CONNACK (0)), ce qui permet de comparer les deux points de vue ligne par ligne.
Tracer un client dans EMQX
Sur un broker EMQX chargé, la journalisation debug globale est trop bruyante. Tracez plutôt un seul client :
emqx ctl trace start client sensor-01 /tmp/sensor-01.log
# ...laissez le client se connecter, publier et échouer...
emqx ctl trace stop client sensor-01Le fichier de trace contient les événements de connexion, d'authentification, d'abonnement, de publication et de déconnexion de ce client, y compris la raison lorsque le broker ferme la connexion. Le dashboard dispose d'une page de log trace qui fait la même chose et permet de télécharger le résultat. Vous pouvez aussi tracer par topic ou par IP client quand vous ne savez pas quel client ID pose problème.
Rechercher et corréler
Quelques commandes couvrent la plupart des recherches dans les logs :
# Tout ce qui concerne un client depuis une heure
journalctl -u mosquitto --since "1 hour ago" | grep -F 'sensor-01'
# Quels clients tombent le plus souvent en timeout ?
grep -o 'Client [^ ]* has exceeded timeout' /var/log/mosquitto/mosquitto.log | sort | uniq -c | sort -rn
# Convertir un horodatage Unix d'une ligne de log Mosquitto par défaut
date -d @1792228321 # GNU date ; sur macOS : date -r 1792228321Corrélez l'heure du broker avec les logs du client. Si les horloges diffèrent, alignez-les sur un événement visible des deux côtés, comme le CONNACK.
Quand il n'y a pas de log broker
Sans accès aux logs du broker, reconstituez la même image côté client :
- Journalisez chaque reason code renvoyé par votre bibliothèque et consultez-le dans les reason codes MQTT expliqués ou avec l'outil des reason codes.
- Abonnez-vous aux topics
$SYSdu broker s'ils sont exposés : les compteurs de clients connectés et de messages abandonnés montrent souvent la même tendance que le log. Voir supervision avec les topics $SYS. - Reproduisez le problème avec le client MQTT en ligne sur le même broker. Si cela fonctionne là, la cause est dans le code ou le réseau de l'appareil, pas dans le broker.
Confirmer la correction dans le log
Une ligne de log est aussi votre test d'acceptation. Après un changement, reproduisez le scénario initial et surveillez le log : la ligne has exceeded timeout ou already connected ne doit plus apparaître, et la ligne New client connected doit afficher les paramètres voulus (protocole, flag clean, keep-alive). Désactivez ensuite à nouveau le niveau debug.
Le broker voit les erreurs de tous les clients, mais ne les note que si vous le lui demandez. Configurez les messages de connexion et un horodatage lisible, n'augmentez le niveau que pendant l'enquête et apprenez la poignée de lignes de déconnexion : elles correspondent presque une à une à la correction.
Questions fréquentes
Comment activer les logs de débogage dans Mosquitto ?
Ajoutez log_type debug (ou log_type all) dans mosquitto.conf avec un log_dest comme stdout ou file, puis redémarrez le broker. Le niveau debug affiche chaque paquet reçu et envoyé par le broker : désactivez-le dès que vous avez trouvé le problème.
Que signifie 'has exceeded timeout, disconnecting' dans Mosquitto ?
Le broker n'a rien reçu du client pendant 1,5 fois son intervalle de keep-alive et a fermé la connexion. La boucle réseau du client s'est arrêtée, l'appareil s'est endormi ou une passerelle NAT a abandonné la connexion. Vérifiez le keep-alive dans la ligne 'New client connected' (k60 signifie 60 secondes).
Comment voir les logs d'un seul client dans EMQX ?
Utilisez une trace de logs : emqx ctl trace start client <clientid> <fichier> enregistre tout ce qui concerne ce client ID dans un fichier, et le dashboard EMQX propose la même chose sur sa page de log trace. Arrêtez-la avec emqx ctl trace stop client <clientid>.
