Broker-Tests

MQTT-Broker-Logs lesen und Clients debuggen

Mosquitto- und EMQX-Logs richtig lesen: passende Log-Level setzen, Connect- und Disconnect-Zeilen deuten, einen einzelnen Client tracen und zur Lösung kommen.

Aktualisiert · 9 Min. Lesezeit

MQTT-Broker-Logs lesen und Clients debuggen

Wenn ein Client connection lost meldet, weiß er meist nicht, warum. Der Broker weiß es. Jeder abgelehnte Login, jeder Keep-Alive-Timeout, jede doppelte Client ID und jeder verweigerte Publish hinterlässt eine Zeile im Broker-Log — sofern das Logging so konfiguriert ist, dass es sie behält. Diese Zeilen zu lesen ist oft der schnellste Weg, einen Client zu debuggen, an den du keinen Debugger hängen kannst.

Diese Anleitung zeigt, wo die Logs liegen, welche Log-Level du einschaltest, wie du Mosquittos Connect- und Disconnect-Zeilen liest, wie du in EMQX einen einzelnen Client tracest und wie aus einer Log-Zeile eine Lösung wird.

Wo die Logs liegen

SetupWo du suchst
Mosquitto aus einem Linux-Paket/var/log/mosquitto/mosquitto.log oder journalctl -u mosquitto -f
Mosquitto in Dockerdocker logs -f mosquitto (mit log_dest stdout)
EMQXKonsolenausgabe in Docker (docker logs -f emqx); Dateien im Verzeichnis log/ der Installation
HiveMQlog/hivemq.log, dazu log/event.log für Connect- und Disconnect-Ereignisse der Clients
Managed BrokerMeist keine rohen Broker-Logs — verlass dich auf Reason Codes und Monitoring (siehe unten)

Bleibt die Mosquitto-Logdatei leer, such in der Startausgabe nach Error: Unable to open log file /var/log/mosquitto/mosquitto.log for writing. — der Broker-Benutzer darf nicht in das Verzeichnis schreiben. Das Logging-Setup im Detail beschreibt Mosquitto-Logging.

Das richtige Log-Level einschalten

Mosquittos Standard-Logging verbirgt das meiste, was du zum Client-Debugging brauchst. Eine sinnvolle Konfiguration während der Untersuchung:

mosquitto.conf — Logging beim Debuggen
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
# Jedes ein- und ausgehende Paket — sehr gesprächig, nur beim Debuggen aktivieren
log_type debug

connection_messages true
log_timestamp true
log_timestamp_format %Y-%m-%dT%H:%M:%S

Starte den Broker nach Änderungen an den Logging-Optionen neu. connection_messages true erzeugt die Connect- und Disconnect-Zeilen, auf denen fast diese ganze Anleitung aufbaut, und ein lesbares Zeitstempelformat erspart dir das Umrechnen von Unix-Sekunden. Eine vollständige Konfiguration erzeugst du mit dem mosquitto.conf-Generator.

Bei EMQX 5 erhöhst du das Konsolen-Level eines Containers mit der Umgebungsvariable EMQX_LOG__CONSOLE__LEVEL=debug oder änderst es zur Laufzeit:

EMQX: Log-Level zur Laufzeit ändern
emqx ctl log set-level debug
# ...Problem reproduzieren...
emqx ctl log set-level warning

Mosquittos Connect-Zeilen lesen

Eine erfolgreiche Verbindung erzeugt zwei Zeilen:

Erfolgreiche Verbindung
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').

Die Klammer am Ende beschreibt das CONNECT-Paket:

FeldBedeutung
p2Protokoll: p2 = MQTT 3.1.1, p5 = MQTT 5 (p1 wäre das alte 3.1)
c1Clean Session / Clean Start: c1 = neue Session, c0 = persistente Session fortsetzen
k60Keep-Alive-Intervall in Sekunden
u'alice'Vom Client gesendeter Benutzername (fehlt, wenn keiner gesendet wurde)

Diese vier Felder beantworten mehrere Fragen auf einmal: Nutzt der Client wirklich die Protokollversion, die du annimmst? Fordert er eine persistente Session an? Welches Keep-Alive hat er tatsächlich gesetzt?

Disconnect-Zeilen und ihre Bedeutung

Die Zeile, die Mosquitto beim Abgang eines Clients schreibt, ist die nützlichste im ganzen Log:

Log-ZeileUrsacheLösung
Client sensor-01 disconnected.Sauberes DISCONNECT vom ClientNichts — gewollt
Client sensor-01 closed its connection.TCP ohne DISCONNECT geschlossenClient abgestürzt, beendet oder ohne Strom
Client sensor-01 has exceeded timeout, disconnecting.Kein Paket für 1,5 × Keep-AliveClient-Schleife, Schlaflogik oder NAT-Timeout korrigieren — siehe Keep-Alive-Timeout
Client sensor-01 already connected, closing old connection.Ein zweiter Client nutzt dieselbe Client IDEindeutige IDs pro Gerät — siehe doppelte Client ID
Client sensor-01 disconnected, not authorised.Falsche Zugangsdaten oder keine Berechtigung zum VerbindenBenutzername, Passwort und Auth-Plugin prüfen
Client sensor-01 disconnected due to protocol error.Fehlerhaftes oder unerwartetes PaketBibliotheksfehler, falsche Protokollversion oder reines MQTT auf einem WebSocket-Listener
Socket error on client sensor-01, disconnecting.Verbindung auf Netzwerkebene abgerissenNetzausfall, TLS-Fehler oder RST einer Middlebox
Outgoing messages are being dropped for client sensor-01.Die Queue des Clients ist vollLangsamer Consumer — Limits erhöhen oder schneller konsumieren

Wechseln sich alle paar Sekunden zwei Zeilen mit already connected, closing old connection ab, streiten zwei Geräte um eine Client ID und verbinden sich in einer Schleife neu. Eindeutige IDs erzeugst du mit dem Client-ID-Generator.

Eine Session auf Debug-Level verfolgen

Mit log_type debug protokolliert Mosquitto jedes Paket. Ein Subscriber und ein Publisher auf einem Test-Topic sehen ungefähr so aus (Mosquitto 2.x, gekürzt):

Debug-Log eines Publish
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)

Die Klammer bei PUBLISH-Zeilen liest sich so: d = DUP-Flag, q = QoS, r = Retain, m = Message ID, danach Topic und Payload-Größe. Siehst du Received PUBLISH, aber kein Sending PUBLISH, hat der Broker die Nachricht angenommen, aber keine passende Subscription gefunden — prüfe den Topic-Filter mit dem Topic-Matcher. Eine Denied PUBLISH-Zeile bedeutet, dass eine ACL blockiert hat; diesen Fall behandelt ACL verweigert stillschweigend.

Um einen Fall schnell nachzustellen, lass das Log in einem Terminal offen und erzeuge in einem zweiten Traffic:

Debugging mit zwei Terminals
# Terminal 1 — die Broker-Seite
docker logs -f mosquitto 2>&1 | grep --line-buffered -E 'sub-01|pub-01'

# Terminal 2 — die Client-Seite, mit Debug-Ausgabe der 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 lässt die Clients ihr eigenes Paket-Log ausgeben (Client sub-01 sending CONNECT, received CONNACK (0)), sodass du beide Sichten Zeile für Zeile vergleichen kannst.

Einen Client in EMQX tracen

Auf einem ausgelasteten EMQX-Broker ist globales Debug-Logging zu laut. Trace stattdessen einen einzelnen Client:

EMQX: eine Client ID tracen
emqx ctl trace start client sensor-01 /tmp/sensor-01.log
# ...Client verbinden, publizieren und scheitern lassen...
emqx ctl trace stop client sensor-01

Die Trace-Datei enthält die Connect-, Authentifizierungs-, Subscribe-, Publish- und Disconnect-Ereignisse dieses Clients, inklusive des Grundes, wenn der Broker die Verbindung schließt. Das Dashboard hat eine Log-Trace-Seite, die dasselbe tut und den Download des Ergebnisses erlaubt. Weißt du nicht, welche Client ID sich danebenbenimmt, kannst du auch nach Topic oder Client-IP tracen.

Ein paar Befehle decken die meisten Log-Suchen ab:

Nützliche Log-Suchen
# Alles zu einem Client in der letzten Stunde
journalctl -u mosquitto --since "1 hour ago" | grep -F 'sensor-01'

# Welche Clients laufen am häufigsten in Timeouts?
grep -o 'Client [^ ]* has exceeded timeout' /var/log/mosquitto/mosquitto.log | sort | uniq -c | sort -rn

# Unix-Zeitstempel aus einer Standard-Mosquitto-Logzeile umrechnen
date -d @1792228321        # GNU date; unter macOS: date -r 1792228321

Korreliere die Broker-Zeit mit den Logs des Clients. Weichen die Uhren ab, richte beide an einem Ereignis aus, das beide Seiten sehen, etwa dem CONNACK.

Wenn es kein Broker-Log gibt

Ohne Zugriff auf die Broker-Logs baust du dasselbe Bild von der Client-Seite aus auf:

  • Protokolliere jeden Reason Code, den deine Bibliothek meldet, und schlag ihn in MQTT-Reason-Codes erklärt oder im Reason-Code-Tool nach.
  • Abonniere die $SYS-Topics des Brokers, sofern verfügbar — Zähler für verbundene Clients und verworfene Nachrichten zeigen oft denselben Trend wie das Log. Siehe Monitoring mit $SYS-Topics.
  • Stell das Problem mit dem Online-MQTT-Client gegen denselben Broker nach. Funktioniert es dort, liegt die Ursache im Code oder Netzwerk des Geräts, nicht beim Broker.

Die Lösung im Log bestätigen

Eine Log-Zeile ist auch dein Abnahmetest. Stell nach einer Änderung das ursprüngliche Szenario nach und beobachte das Log: Die Zeile has exceeded timeout oder already connected sollte nicht mehr erscheinen, und die Zeile New client connected sollte die Parameter zeigen, die du beabsichtigt hast (Protokoll, Clean-Flag, Keep-Alive). Schalte danach das Debug-Logging wieder ab.

Der Broker sieht die Fehler aller Clients, schreibt sie aber nur auf, wenn du ihn darum bittest. Konfiguriere Connection Messages und einen lesbaren Zeitstempel, erhöhe das Level nur während der Untersuchung und lerne die Handvoll Disconnect-Zeilen — sie entsprechen fast eins zu eins der Lösung.

Häufig gestellte Fragen

Wie aktiviere ich Debug-Logging in Mosquitto?

Füge log_type debug (oder log_type all) zusammen mit einem log_dest wie stdout oder file in mosquitto.conf ein und starte den Broker neu. Debug-Logging gibt jedes Paket aus, das der Broker empfängt und sendet — schalte es wieder ab, sobald du das Problem gefunden hast.

Was bedeutet 'has exceeded timeout, disconnecting' in Mosquitto?

Der Broker hat 1,5 Keep-Alive-Intervalle lang nichts vom Client empfangen und die Verbindung geschlossen. Die Netzwerkschleife des Clients stand still, das Gerät schlief oder ein NAT-Gateway hat die Verbindung verworfen. Prüfe den Keep-Alive-Wert in der Zeile 'New client connected' (k60 heißt 60 Sekunden).

Wie sehe ich in EMQX die Logs eines einzelnen Clients?

Nutze einen Log-Trace: emqx ctl trace start client <clientid> <datei> schreibt alles zu dieser Client ID in eine Datei, und das EMQX-Dashboard bietet dasselbe auf seiner Log-Trace-Seite. Beende ihn mit emqx ctl trace stop client <clientid>.