Quando um cliente diz connection lost, normalmente ele não faz ideia do motivo. O broker sabe. Cada login recusado, timeout de keep-alive, client ID duplicado e publicação negada deixa uma linha no log do broker — desde que o logging esteja configurado para guardá-la. Ler essas linhas costuma ser a forma mais rápida de depurar um cliente ao qual você não consegue acoplar um debugger.
Este guia mostra onde encontrar os logs, quais níveis de log ativar, como ler as linhas de conexão e desconexão do Mosquitto, como rastrear um cliente no EMQX e como transformar uma linha de log em uma correção.
Onde ficam os logs
| Instalação | Onde procurar |
|---|---|
| Mosquitto via pacote Linux | /var/log/mosquitto/mosquitto.log ou journalctl -u mosquitto -f |
| Mosquitto no Docker | docker logs -f mosquitto (com log_dest stdout) |
| EMQX | Saída do console no Docker (docker logs -f emqx); arquivos no diretório log/ da instalação |
| HiveMQ | log/hivemq.log, mais log/event.log para eventos de conexão e desconexão de clientes |
| Broker gerenciado | Geralmente sem logs brutos do broker — use reason codes e monitoramento (veja abaixo) |
Se o arquivo de log do Mosquitto continua vazio, procure na saída de inicialização por Error: Unable to open log file /var/log/mosquitto/mosquitto.log for writing. — o usuário do broker não consegue escrever no diretório. A configuração de logging em detalhes está em logging do Mosquitto.
Ative o nível de log certo
O logging padrão do Mosquitto esconde quase tudo de que você precisa para depurar clientes. Uma configuração útil durante a investigação:
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
# Cada pacote de entrada e saída — muito verboso, ative só durante o debug
log_type debug
connection_messages true
log_timestamp true
log_timestamp_format %Y-%m-%dT%H:%M:%SReinicie o broker depois de mudar as opções de logging. connection_messages true gera as linhas de conexão e desconexão em que quase todo este guia se baseia, e um formato de timestamp legível poupa a conversão manual de segundos Unix. Você pode gerar uma configuração completa com o gerador de mosquitto.conf.
No EMQX 5, aumente o nível do console de um container com a variável de ambiente EMQX_LOG__CONSOLE__LEVEL=debug, ou mude em tempo de execução:
emqx ctl log set-level debug
# ...reproduza o problema...
emqx ctl log set-level warningLendo as linhas de conexão do Mosquitto
Uma conexão bem-sucedida gera duas linhas:
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').O parêntese no final descreve o pacote CONNECT:
| Campo | Significado |
|---|---|
p2 | Protocolo: p2 = MQTT 3.1.1, p5 = MQTT 5 (p1 seria o antigo 3.1) |
c1 | Clean session / clean start: c1 = sessão nova, c0 = retomar sessão persistente |
k60 | Intervalo de keep-alive em segundos |
u'alice' | Username enviado pelo cliente (ausente se não houver) |
Esses quatro campos respondem várias perguntas de uma vez: o cliente usa mesmo a versão de protocolo que você imagina? Ele pede uma sessão persistente? Qual keep-alive ele realmente definiu?
Linhas de desconexão e o que significam
A linha que o Mosquitto imprime quando um cliente sai é a mais útil de todo o log:
| Linha de log | Causa | Correção |
|---|---|---|
Client sensor-01 disconnected. | DISCONNECT limpo do cliente | Nada — é o esperado |
Client sensor-01 closed its connection. | TCP fechado sem DISCONNECT | O cliente travou, foi encerrado ou perdeu energia |
Client sensor-01 has exceeded timeout, disconnecting. | Nenhum pacote por 1,5 × keep-alive | Corrija o loop do cliente, a lógica de sleep ou o timeout de NAT — veja timeout de keep-alive |
Client sensor-01 already connected, closing old connection. | Um segundo cliente usou o mesmo client ID | IDs únicos por dispositivo — veja client ID duplicado |
Client sensor-01 disconnected, not authorised. | Credenciais erradas ou sem permissão para conectar | Verifique username, password e plugin de autenticação |
Client sensor-01 disconnected due to protocol error. | Pacote malformado ou inesperado | Bug da biblioteca, versão de protocolo errada ou MQTT puro em um listener WebSocket |
Socket error on client sensor-01, disconnecting. | A conexão quebrou no nível de rede | Queda de rede, erro de TLS ou RST de um equipamento intermediário |
Outgoing messages are being dropped for client sensor-01. | A fila do cliente está cheia | Consumidor lento — aumente os limites ou consuma mais rápido |
Quando duas linhas com already connected, closing old connection se alternam a cada poucos segundos, dois dispositivos estão disputando um client ID e reconectando em loop. Gere IDs únicos com o gerador de client ID.
Acompanhando uma sessão em nível debug
Com log_type debug, o Mosquitto registra cada pacote. Um subscriber e um publisher em um topic de teste ficam mais ou menos assim (Mosquitto 2.x, resumido):
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)O parêntese das linhas PUBLISH se lê assim: d = flag DUP, q = QoS, r = retain, m = message ID, depois o topic e o tamanho do payload. Se você vê Received PUBLISH mas nenhum Sending PUBLISH, o broker aceitou a mensagem, mas não havia assinatura correspondente — confira o topic filter no topic matcher. Uma linha Denied PUBLISH significa que uma ACL bloqueou a mensagem; esse caso é tratado em ACL negada em silêncio.
Para reproduzir um caso rapidamente, deixe o log aberto em um terminal e gere tráfego em outro:
# Terminal 1 — o lado do broker
docker logs -f mosquitto 2>&1 | grep --line-buffered -E 'sub-01|pub-01'
# Terminal 2 — o lado do cliente, com saída de debug do cliente
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'O -d faz os clientes imprimirem o próprio log de pacotes (Client sub-01 sending CONNECT, received CONNACK (0)), então você compara as duas visões linha a linha.
Rastreando um cliente no EMQX
Em um broker EMQX movimentado, o log de debug global é barulhento demais. Rastreie um único cliente:
emqx ctl trace start client sensor-01 /tmp/sensor-01.log
# ...deixe o cliente conectar, publicar e falhar...
emqx ctl trace stop client sensor-01O arquivo de trace contém os eventos de conexão, autenticação, assinatura, publicação e desconexão daquele cliente, incluindo o motivo quando o broker fecha a conexão. O dashboard tem uma página de log trace que faz o mesmo e permite baixar o resultado. Você também pode rastrear por topic ou pelo IP do cliente quando não sabe qual client ID está se comportando mal.
Buscando e correlacionando
Alguns comandos cobrem a maioria das buscas nos logs:
# Tudo sobre um cliente na última hora
journalctl -u mosquitto --since "1 hour ago" | grep -F 'sensor-01'
# Quais clientes dão timeout com mais frequência?
grep -o 'Client [^ ]* has exceeded timeout' /var/log/mosquitto/mosquitto.log | sort | uniq -c | sort -rn
# Converter um timestamp Unix de uma linha de log padrão do Mosquitto
date -d @1792228321 # GNU date; no macOS: date -r 1792228321Correlacione o horário do broker com os logs do próprio cliente. Se os relógios divergem, alinhe por um evento que os dois lados veem, como o CONNACK.
Quando não há log do broker
Sem acesso aos logs do broker, monte o mesmo quadro a partir do lado do cliente:
- Registre cada reason code que sua biblioteca reportar e consulte em reason codes do MQTT explicados ou na ferramenta de reason codes.
- Assine os topics
$SYSdo broker se estiverem expostos — contadores de clientes conectados e de mensagens descartadas costumam mostrar a mesma tendência do log. Veja monitoramento com topics $SYS. - Reproduza o problema com o cliente MQTT online no mesmo broker. Se lá funciona, a causa está no código ou na rede do dispositivo, não no broker.
Confirme a correção no log
Uma linha de log também é o seu teste de aceitação. Depois de uma mudança, reproduza o cenário original e observe o log: a linha has exceeded timeout ou already connected não deve mais aparecer, e a linha New client connected deve mostrar os parâmetros que você pretendia (protocolo, flag clean, keep-alive). Depois desative o log de debug novamente.
O broker vê os erros de todos os clientes, mas só os anota se você pedir. Configure as mensagens de conexão e um timestamp legível, aumente o nível só durante a investigação e aprenda o punhado de linhas de desconexão — elas correspondem quase uma a uma à correção.
Perguntas frequentes
Como ativar o log de debug no Mosquitto?
Adicione log_type debug (ou log_type all) ao mosquitto.conf junto com um log_dest como stdout ou file e reinicie o broker. O log de debug imprime cada pacote que o broker recebe e envia, então desative-o assim que encontrar o problema.
O que significa 'has exceeded timeout, disconnecting' no Mosquitto?
O broker não recebeu nada do cliente por 1,5 vez o intervalo de keep-alive e fechou a conexão. O loop de rede do cliente parou, o dispositivo dormiu ou um gateway NAT derrubou a conexão. Confira o keep-alive na linha 'New client connected' (k60 significa 60 segundos).
Como ver os logs de um único cliente no EMQX?
Use um log trace: emqx ctl trace start client <clientid> <arquivo> grava tudo daquele client ID em um arquivo, e o dashboard do EMQX oferece o mesmo na página de log trace. Pare com emqx ctl trace stop client <clientid> quando terminar.
