Os logs de erro do IBM MQ são um dos primeiros lugares que um administrador olha quando um Queue Manager, canal, regra de segurança ou conexão aplicacional se comporta inesperadamente. A forma tradicional de ler os logs exige acesso ao sistema de arquivos do host do Queue Manager.
O IBM MQ 9.4.5 introduziu o comando PCF MQCMD_INQUIRE_ERROR_LOG. Um cliente MQ autorizado pode agora solicitar um log de erro do Queue Manager diretamente ao próprio MQ. Isso é importante para monitorização centralizada porque não é necessário iniciar uma sessão de shell com o sistema remoto ou usar um sistema de arquivos compartilhado ou ter conhecimento da estrutura de armazenamento do Queue Manager.
Este artigo explica o modelo de solicitação e resposta PCF e depois constrói um laboratório com:
- Um Queue Manager IBM MQ 10.0
- Um container separado para o cliente Java
- Uma ligação remota do cliente usando um canal MQI
- Obtenção do conteúdo completo ou incremental do
AMQERR01.LOG
Considerações: a configuração usa a imagem IBM MQ Advanced for Developers e um canal de desenvolvimento protegido por senha intencionalmente simples. Esta configuração é adequada para um laboratório em ambiente de desenvolvimento ou testes, e não para produção. Implementações em produção precisam de mecanismos mais fortes de segurança.
1. O que mudou no IBM MQ 9.4.5
Surge o novo comando PCF:
MQCMD_INQUIRE_ERROR_LOGEle está disponível no IBM MQ for Multiplatforms a partir da versão 9.4.5 e também está presente no IBM MQ 10.0. O comando obtém o conteúdo dos logs de erro do Queue Manager.
Quando usado sem parâmetros, o MQ retorna o log ativo (AMQERR01.LOG). Existem dois parâmetros opcionais que permitem ajustar a solicitação:
| Parâmetro PCF | Finalidade |
|---|---|
MQCACF_ERROR_LOG_NAME | Selecionar AMQERR01, AMQERR02 ou AMQERR03, com ou sem o sufixo .LOG |
MQCACF_ERROR_LOG_AFTER_ISOTIME | Retornar entradas cujo timestamp seja mais recente ou igual ao horário UTC fornecido |
O formato do timestamp deve ser ISO 8601 UTC terminando em Z. O IBM MQ aceita segundos, milissegundos ou microssegundos, por exemplo:
2026-07-22T10:15:00Z
2026-07-22T10:15:00.123Z
2026-07-22T10:15:00.123456ZO MQ responde com uma ou mais mensagens PCF:
| Parâmetro de resposta | Significado |
|---|---|
MQCACF_ERROR_LOG_RECORD | Texto do log de erro solicitado |
MQCACF_ERROR_LOG_ISOTIME | Timestamp do último registro de erro no log |
O texto do log retornado é sub-dividido em mensagens de resposta de até 1 MB e portanto, um coletor deve processar cada resposta e não apenas a primeira. O timestamp final é um cursor que pode ser armazenado e fornecido na próxima solicitação.
2. Como funciona a administração PCF
O PCF é o protocolo administrativo do IBM MQ que funciona através de mensagens com representação estruturada de comandos. Um aplicativo cliente cria uma mensagem de comando, adiciona parâmetros e envia-a ao servidor de comandos do Queue Manager. O servidor de comandos executa a operação e retorna mensagens de resposta estruturadas.
O fluxo de comando e resposta é:

A classe Java PCFMessageAgent lida com acesso à fila de comandos, filas de resposta, correlação, codificação PCF e coleta de respostas. O aplicativo ainda precisa:
- Estabelecer uma conexão cliente MQ autenticada
- Construir o comando correto e os parâmetros
- Processar cada mensagem de resposta
- Verificar os códigos de retorno (completion e reason)
- Guardar o timestamp final para poder ser utilizado em recolhas incrementais
3. Modelo de autorização
A documentação do IBM descreve a autorização +ctrl no objeto Queue Manager como a autoridade específica necessária para obter o conteúdo dos logs de erro. Também é necessário ter as permissões normais necessárias para estabelecer a ligação e efetuar as comunicações.
Um authorization record com as autorizações necessárias pode ser estabelecido como mostrado abaixo:
setmqaut -m LOGQM -t qmgr -p pcfreader +connect +inq +ctrlNão conceda a um identificador de monitoramento a pertença ao grupo mqm apenas para fazer o comando funcionar. Em produção, crie uma identidade dedicada, conceda apenas as autoridades que ela precisa e restrinja o canal do cliente com TLS e regras CHLAUTH.
Este laboratório usa o usuário administrativo da imagem de desenvolvimento MQ para que o exercício permaneça focado no novo comando PCF.
4. Requisitos do laboratório
Use uma máquina de desenvolvimento com:
- Docker Engine ou Docker Desktop
- Docker Compose v2
- Pelo menos 4 GB de memória livre
- Acesso através da internet a
icr.io - Um host AMD64 Linux, ou Docker Desktop em Apple silicon com emulação AMD64 habilitada
O laboratório fixa a imagem de desenvolvimento do IBM MQ 10.0:
icr.io/ibm-messaging/mq:10.0.0.0-r2Fixar a imagem mantém o exercício repetível. MQCMD_INQUIRE_ERROR_LOG está disponível porque o Queue Manager é mais recente que o nível mínimo 9.4.5.
5. Criar o diretório do laboratório
Crie um projeto vazio:
mkdir -p "$HOME/mq-pcf-error-log-lab/config" \
"$HOME/mq-pcf-error-log-lab/client"
cd "$HOME/mq-pcf-error-log-lab"Registre a imagem no arquivo .env:
cat > .env <<'EOF'
MQ_IMAGE=icr.io/ibm-messaging/mq:10.0.0.0-r2
EOFOntenha-a explicitamente:
set -a
. ./.env
set +a
docker pull --platform linux/amd64 "$MQ_IMAGE"
docker run --rm --platform linux/amd64 \
--entrypoint dspmqver "$MQ_IMAGE"Confirme que o resultado indica o IBM MQ 10.0.0.0.
6. Configurar o Queue Manager
A imagem de desenvolvimento MQ pode aplicar as instruções MQSC durante a criação do Queue Manager. Defina uma fila de teste e use o canal administrativo pré-configurado da imagem.
Crie config/20-config.mqsc:
cat > config/20-config.mqsc <<'MQSC'
DEFINE QLOCAL(LAB.EVENTS) DESCR('Queue used by the PCF error-log lab')
MQSCO canal DEV.ADMIN.SVRCONN e a identidade admin são criados pela imagem de desenvolvimento quando MQ_ADMIN_PASSWORD é fornecido.
A imagem do servidor MQ contém uma JVM, mas não contém javac. Compile o cliente com uma imagem JDK e obtenha o JAR all-client do IBM e suas dependências transitivas da runtime do Maven Central.
Crie o ficheiro client/pom.xml:
cat > client/pom.xml <<'XML'
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>mq-pcf-error-log-client</artifactId>
<version>1.0.0</version>
<properties>
<mq.client.version>10.0.0.0</mq.client.version>
</properties>
<dependencies>
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>${mq.client.version}</version>
</dependency>
</dependencies>
</project>
XMLCrie o ficheiro client/Dockerfile:
cat > client/Dockerfile <<'DOCKERFILE'
FROM maven:3.9.11-eclipse-temurin-21
ARG MQ_CLIENT_VERSION=10.0.0.0
COPY pom.xml /tmp/mq-client/pom.xml
RUN mvn -q -f /tmp/mq-client/pom.xml dependency:copy-dependencies \
-Dmq.client.version=${MQ_CLIENT_VERSION} \
-DincludeScope=runtime \
-DoutputDirectory=/opt/mq
WORKDIR /work
ENTRYPOINT ["/bin/bash", "-lc"]
CMD ["sleep infinity"]
DOCKERFILECrie o ficheiro compose.yaml:
cat > compose.yaml <<'YAML'
services:
mq:
image: ${MQ_IMAGE:-icr.io/ibm-messaging/mq:10.0.0.0-r2}
platform: linux/amd64
hostname: mq
environment:
LICENSE: "accept"
MQ_QMGR_NAME: "LOGQM"
MQ_ADMIN_PASSWORD: "passw0rd"
MQ_APP_PASSWORD: "passw0rd"
ports:
- "1414:1414"
- "9443:9443"
volumes:
- qmdata:/mnt/mqm
- ./config/20-config.mqsc:/etc/mqm/20-config.mqsc:ro
healthcheck:
test: ["CMD-SHELL", "dspmq -m LOGQM | grep -q 'STATUS(Running)'"]
interval: 5s
timeout: 5s
retries: 40
pcf-client:
build:
context: ./client
args:
MQ_CLIENT_VERSION: "10.0.0.0"
profiles: ["tools"]
entrypoint: ["/bin/bash", "-lc"]
command: ["sleep infinity"]
volumes:
- ./client:/work
working_dir: /work
depends_on:
mq:
condition: service_healthy
volumes:
qmdata:
YAMLInicie o Queue Manager:
docker compose up -d mq
docker compose ps
docker compose logs --tail 40 mqConfirme a versão do MQ do container em execução:
docker compose exec mq dspmqver7. Criar o cliente Java PCF
O programa suporta três argumentos:
ErrorLogReader [log-name] [after-isotime] [cursor-file]- Sem argumentos, ele obtém todo o
AMQERR01.LOG log-namepermite selecionarAMQERR01,AMQERR02ouAMQERR03after-isotimehabilita a recuperação incrementalcursor-filearmazena o último timestamp retornado pelo MQ
Crie o ficheiro client/ErrorLogReader.java:
cat > client/ErrorLogReader.java <<'JAVA'
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Hashtable;
import com.ibm.mq.MQException;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.CMQCFC;
import com.ibm.mq.headers.pcf.PCFMessage;
import com.ibm.mq.headers.pcf.PCFMessageAgent;
public final class ErrorLogReader {
private static final String HOST = env("MQ_HOST", "mq");
private static final int PORT = Integer.parseInt(env("MQ_PORT", "1414"));
private static final String CHANNEL = env("MQ_CHANNEL", "DEV.ADMIN.SVRCONN");
private static final String QMANAGER = env("MQ_QMGR", "LOGQM");
private static final String USER = env("MQ_USER", "admin");
private static final String PASSWORD = env("MQ_PASSWORD", "passw0rd");
private static String env(String name, String fallback) {
String value = System.getenv(name);
return value == null || value.isBlank() ? fallback : value;
}
public static void main(String[] args) throws Exception {
String logName = args.length > 0 ? args[0] : "AMQERR01.LOG";
String afterIsoTime = args.length > 1 ? args[1] : null;
Path cursorFile = args.length > 2 ? Path.of(args[2]) : null;
Hashtable<String, Object> properties = new Hashtable<>();
properties.put(CMQC.HOST_NAME_PROPERTY, HOST);
properties.put(CMQC.PORT_PROPERTY, PORT);
properties.put(CMQC.CHANNEL_PROPERTY, CHANNEL);
properties.put(CMQC.USER_ID_PROPERTY, USER);
properties.put(CMQC.PASSWORD_PROPERTY, PASSWORD);
properties.put(CMQC.TRANSPORT_PROPERTY, CMQC.TRANSPORT_MQSERIES_CLIENT);
MQQueueManager queueManager = null;
PCFMessageAgent agent = null;
try {
queueManager = new MQQueueManager(QMANAGER, properties);
agent = new PCFMessageAgent(queueManager);
PCFMessage request = new PCFMessage(CMQCFC.MQCMD_INQUIRE_ERROR_LOG);
request.addParameter(CMQCFC.MQCACF_ERROR_LOG_NAME, logName);
if (afterIsoTime != null && !afterIsoTime.isBlank()) {
request.addParameter(
CMQCFC.MQCACF_ERROR_LOG_AFTER_ISOTIME,
afterIsoTime
);
}
PCFMessage[] responses = agent.send(request);
String lastIsoTime = null;
for (PCFMessage response : responses) {
String record = optionalString(
response,
CMQCFC.MQCACF_ERROR_LOG_RECORD
);
if (record != null) {
System.out.print(record);
if (!record.endsWith(System.lineSeparator())) {
System.out.println();
}
}
String responseTime = optionalString(
response,
CMQCFC.MQCACF_ERROR_LOG_ISOTIME
);
if (responseTime != null && !responseTime.isBlank()) {
lastIsoTime = responseTime;
}
}
if (lastIsoTime != null) {
System.err.println("LAST_ISOTIME=" + lastIsoTime);
if (cursorFile != null) {
Files.writeString(
cursorFile,
lastIsoTime + System.lineSeparator(),
StandardCharsets.UTF_8,
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING
);
}
}
} catch (MQException e) {
System.err.printf(
"MQ failure: completionCode=%d reasonCode=%d%n",
e.completionCode,
e.reasonCode
);
throw e;
} finally {
if (agent != null) {
agent.disconnect();
}
if (queueManager != null && queueManager.isConnected()) {
queueManager.disconnect();
}
}
}
private static String optionalString(PCFMessage message, int parameter) {
try {
return message.getStringParameterValue(parameter);
} catch (Exception absent) {
return null;
}
}
}
JAVA8. Compilar o cliente no Docker
Inicie o container do cliente PCF:
docker compose --profile tools up -d pcf-clientEste passo é necessário para o resto do laboratório. O perfil tools mantém o container do cliente fora da inicialização inicial do Queue Manager. Habilitá-lo aqui compila e inicia o ambiente que fornece javac, a JVM Java e as bibliotecas cliente do IBM MQ. Você só precisa executar o comando novamente após desligar ou remover o container.
Confirme que o JDK e o JAR all-client foram obtidos e estão presentes:
docker compose exec pcf-client javac -version
docker compose exec pcf-client \
find /opt/mq -name '*.jar' -printCompile o programa Java:
docker compose exec pcf-client bash -lc '
javac -cp "/opt/mq/*" \
ErrorLogReader.java
'O container do cliente é separado do Queue Manager. O seu diretório /work é o diretório client do host, e sua conexão com mq(1414) atravessa a rede Compose através do canal MQI DEV.ADMIN.SVRCONN.
9. Obter o log de erro ativo
Execute o cliente:
docker compose exec pcf-client bash -lc '
java -cp ".:/opt/mq/*" \
ErrorLogReader AMQERR01.LOG
'A saída padrão contém o texto retornado do Queue Manager. O erro padrão termina com um cursor semelhante a:
LAST_ISOTIME=2026-07-22T10:15:00.123456ZO comando não montou /mnt/mqm do container do Queue Manager. Ele obteve o log através de uma conexão cliente MQ autenticada e uma solicitação PCF.
Para efeitos de comparação, inspecione o arquivo localmente dentro do container do Queue Manager:
docker compose exec mq \
tail -40 /var/mqm/qmgrs/LOGQM/errors/AMQERR01.LOGO texto retornado pelo PCF deve corresponder ao log de erro do Queue Manager.
10. Gerar um evento diagnóstico
Crie um canal SENDER cujo destino seja a porta TCP local intencionalmente fechada 1. Iniciá-lo produzirá uma falha de conexão de canal no lado do servidor que será tratada pelo Queue Manager.
docker compose exec -T mq runmqsc LOGQM <<'MQSC'
DEFINE QLOCAL(BAD.XMITQ) USAGE(XMITQ)
DEFINE CHANNEL(BAD.SDR) CHLTYPE(SDR) TRPTYPE(TCP) XMITQ(BAD.XMITQ) CONNAME('127.0.0.1(1)') SHORTTMR(30) SHORTRTY(3) LONGRTY(0)
START CHANNEL(BAD.SDR)
MQSC
sleep 5Confirme que o canal está aguardando para tentar de novo (retry):
docker compose exec -T mq runmqsc LOGQM <<'MQSC'
DISPLAY CHSTATUS(BAD.SDR) ALL
MQSCO resultado esperado é STATUS(RETRYING). SHORTTMR(30) deixa um intervalo de 30 segundos entre tentativas curtas, enquanto SHORTRTY(3) permite um máximo de três tentativas. Isso dá tempo suficiente para executar o comando de exibição após a espera de cinco segundos.
Obtenha novamente o conteúdo do log:
docker compose exec pcf-client bash -lc '
java -cp ".:/opt/mq/*" \
ErrorLogReader AMQERR01.LOG
'Procure uma mensagem de conexão de canal referenciando BAD.SDR ou 127.0.0.1(1), juntamente com suas seções de explicação e ação. Os identificadores exatos da mensagem AMQ podem variar com a plataforma e o tempo de falha.
11. Implementar recolha incremental
Baixar repetidamente todo o log ativo é desperdiçar recursos. O timestamp da resposta permite que um coletor peça apenas registros a partir ou após seu último ponto de verificação.
Comece capturando um cursor:
docker compose exec pcf-client bash -lc '
java -cp ".:/opt/mq/*" \
ErrorLogReader AMQERR01.LOG "" last-isotime.txt \
> first-read.log
'
cat client/last-isotime.txtPare e reinicie o canal SENDER a fim de gerar outro evento diagnóstico do Queue Manager:
docker compose exec -T mq runmqsc LOGQM <<'MQSC'
STOP CHANNEL(BAD.SDR) MODE(FORCE)
START CHANNEL(BAD.SDR)
MQSC
sleep 5Use o cursor guardado na próxima solicitação:
CURSOR=$(tr -d '\r\n' < client/last-isotime.txt)
docker compose exec pcf-client bash -lc "
java -cp \".:/opt/mq/*\" \
ErrorLogReader AMQERR01.LOG '$CURSOR' last-isotime.txt \
> incremental-read.log
"
cat client/incremental-read.log
cat client/last-isotime.txtO IBM MQ aplica semântica de comparação “maior-ou-igual” ao timestamp. Portanto, o registo no ponto de verificação pode aparecer novamente. Um coletor em produção deve ser idempotente: retenha informações suficientes para suprimir um registro de fronteira duplicado ou aceite duplicados e deduplique-os a jusante.
Nunca avance o cursor armazenado antes que todos os fragmentos de resposta PCF tenham sido processados com sucesso. Caso contrário, uma falha entre atualizar o cursor e persistir os registos pode criar uma lacuna de monitoramento.
12. Selecionar um log por nome
O IBM MQ escreve erros atuais do Queue Manager no log AMQERR01.LOG. Em AIX, Linux e Windows, quando esse arquivo atinge seu limite de rotação, dados mais antigos movem-se para AMQERR02.LOG e AMQERR03.LOG.
O laboratório não produziu dados de erro suficientes para rodar o log e por isso o AMQERR02.LOG ainda não existe. Para obter o arquivo ativo executamos:
docker compose exec pcf-client bash -lc '
java -cp ".:/opt/mq/*" \
ErrorLogReader AMQERR01.LOG
'Num Queue Manager onde a rotação ocorreu, usamos o mesmo comando com AMQERR02.LOG ou AMQERR03.LOG. Um resultado vazio para qualquer nome pode simplesmente significar que o arquivo correspondente ainda não foi criado.
São válidos apenas os três nomes de log de erro do Queue Manager. O comando não é um leitor de arquivos remoto genérico, o que é uma parte importante de seu limite de segurança.
13. Design de coletor em produção
Um coletor útil é mais do que um loop que imprime texto. Tenha em conta estas considerações:
| Consideração | Orientação para produção |
|---|---|
| Checkpointing | Armazene um cursor por Queue Manager e nome de log. Atualize-o apenas após todos os fragmentos retornados terem sido entregues. |
| Rotação | Consultar apenas AMQERR01.LOG pode perder registos se o arquivo rodar enquanto um coletor está offline. Monitorize Queue Managers continuamente e defina uma política de recuperação que possa inspecionar AMQERR02.LOG quando um cursor não esteja situado no log ativo. |
| Tratamento de duplicados | Como a comparação AfterIsoTime é inclusiva, torne a ingestão a jusante idempotente. Os timestamps podem não identificar unicamente um registro de erro. |
| Back pressure | Cada resposta pode conter até 1 MB de texto. Processe ou envie respostas tão rapidamente quanto a API do cliente permite e aplique limites razoáveis em memória, re-tentativas e buferização de saída. |
| Segurança | Use uma identidade de monitorização dedicada; conceda +ctrl apenas onde a recuperação de log é necessária; habilite TLS com validação de pares; crie regras CHLAUTH para o coletor; proteja credenciais ou use autenticação baseada em tokens; e aplique controles de rede ao redor do canal administrativo. |
| Parsing | A resposta PCF contém texto de log em bruto. Preserve o texto original para diagnóstico. Se campos estruturados forem necessários, efetue parsing a jusante e retenha o registo fonte para que mudanças no parser não destruam evidências. |
14. Solução de problemas
O comando não é reconhecido
Confirme que a versão MQ do Queue Manager é IBM MQ 9.4.5 ou posterior:
docker compose exec mq dspmqverMantenha as bibliotecas PCF do cliente em um nível atual compatível.
Reason Code 2035
MQRC_NOT_AUTHORIZED significa que a identidade da conexão, mapeamento de canal ou autoridades de objeto são insuficientes. Verifique:
- O utilizador que chega ao Queue Manager após o mapeamento efetuado por regras de autenticação de canal (CHLAUTH)
- Autorizações
+connect,+inqe especialmente+ctrlno Queue Manager - Acessos necessários para que a mensagem PCF e as suas respostas cheguem aos destinos
- Se uma identidade privilegiada é bloqueada por regras de canal
Não desabilite autenticação de canal como correção permanente.
Não aparece nenhum registo novo
Nem todo erro do lado do cliente cria uma entrada no log de erro do Queue Manager. Uma falha que ocorre antes de alcançar o MQ, como resolução DNS ou conexão TCP recusada, é local ao cliente. Efetue a geração de uma falha que atinja o Queue Manager e depois inspecione diretamente o log do container e o AMQERR01.LOG.
Saída incremental repete uma entrada
Isso é consistente com o comportamento de comparação “maior-ou-igual” usado para os timestamp. Remova o registro de fronteira ou tolere-o a jusante.
O container de ferramentas sai imediatamente
Inicie-o com o perfil Compose usado no artigo:
docker compose --profile tools up -d pcf-client15. O que o laboratório demonstra
O resultado importante não é simplesmente a obtenção do log a partir de um cliente Java. O laboratório estabelece um modelo operacional:
- O coletor conecta-se através do cliente MQ
- As autorizações do MQ controlam o acesso
- O comando expõe apenas logs de erro do Queue Manager
- Resultados grandes são retornados como múltiplas respostas PCF
- Um timestamp fornecido pelo servidor suporta recolha incremental
- O coletor não precisa de acesso ao host ou a dados partilhados
16. Documentação útil
- What's new in IBM MQ 9.4.5 for Multiplatforms
MQCMD_INQUIRE_ERROR_LOGrequestMQCMD_INQUIRE_ERROR_LOGresponse- Error logs on AIX, Linux, and Windows
- Introduction to IBM MQ Programmable Command Formats
17. Limpeza do ambiente
Pare os containers e remova o volume do Queue Manager:
cd "$HOME/mq-pcf-error-log-lab"
docker compose --profile tools down -vRemova os arquivos do laboratório quando eles não forem mais necessários:
cd "$HOME"
rm -rf "$HOME/mq-pcf-error-log-lab"