| Bellacosa Maifnrame e o caso do return code que decidiu quem viveria no batch |
☕ Um Café no Bellacosa Mainframe
O Caso do Return Code que Decidiu Quem Viveria no Batch
JCL IF/THEN/ELSE: o detetive invisível que interroga programas, examina falhas e escolhe o próximo passo
A chuva caía sobre o data center como uma sequência interminável de registros gravados em fita.
Do lado de fora, a cidade dormia. Dentro da sala de operações, milhares de luzes piscavam em silêncio, enquanto o z/OS processava folhas de pagamento, transferências bancárias, seguros, cartões de crédito, estoques, relatórios fiscais e uma quantidade de dinheiro que faria qualquer contador perder o sono.
Eram duas horas e dezessete da madrugada quando o telefone tocou.
— Bellacosa, temos um problema.
Do outro lado da linha, um jovem programador COBOL parecia nervoso.
— O relatório não foi enviado. O programa de geração terminou, mas o passo seguinte não executou. No spool aparece uma coisa chamada IF/THEN/ELSE. Acho que o JCL decidiu ignorar meu programa.
Acendi o abajur, empurrei para o lado uma velha revista de mistério dos anos 1950 e observei o copo de café frio sobre a mesa.
O rapaz ainda não sabia, mas havia acabado de encontrar uma das figuras mais discretas e poderosas do mundo batch.
O JCL não era apenas uma lista de programas.
Ele também podia tomar decisões.
E, em algum lugar daquele JOB, uma condição havia interrogado um Return Code, analisado as evidências e decidido que determinado passo não merecia executar.
O nome do suspeito?
IF / THEN / ELSE
Esta é a história de como o JCL aprendeu a escolher caminhos.
1. O JCL não é apenas um carregador de programas
Para um programador COBOL iniciante, o JCL costuma parecer uma espécie de porteiro do mainframe.
Ele informa:
qual programa será executado;
quais arquivos serão utilizados;
onde os relatórios serão gravados;
quais parâmetros serão enviados;
quais recursos o JOB precisará.
Um exemplo simples poderia ser:
//RELATOR JOB (1234),'BELLACOSA',CLASS=A,MSGCLASS=X
//STEP01 EXEC PGM=GERAREL
//ENTRADA DD DSN=EMPRESA.VENDAS.DIARIO,DISP=SHR
//SAIDA DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
Nesse caso, o JCL solicita ao sistema que execute o programa GERAREL.
Durante algum tempo, o iniciante imagina que o JCL faz apenas isso: chama programas e associa arquivos.
Mas existe um nível mais profundo.
Um JOB pode conter vários passos:
//STEP01 EXEC PGM=VALIDA
//STEP02 EXEC PGM=ATUALIZA
//STEP03 EXEC PGM=RELATOR
//STEP04 EXEC PGM=ENVIA
Agora surge uma pergunta crítica:
todos os passos devem executar mesmo quando um dos anteriores falhar?
Naturalmente, não.
Se o programa de validação descobrir que o arquivo de entrada está inválido, não faz sentido atualizar o banco de dados.
Se a atualização não for concluída, não é seguro gerar um relatório afirmando que tudo terminou corretamente.
Se o relatório não existir, não há motivo para tentar enviá-lo.
Foi para controlar decisões como essas que o JCL recebeu estruturas condicionais.
2. O que é IF/THEN/ELSE no JCL?
O IF/THEN/ELSE permite que o JOB escolha quais passos deverão executar com base no resultado de passos anteriores.
A ideia fundamental é a mesma encontrada no COBOL.
Em COBOL, podemos escrever:
IF WS-SALDO > 0
DISPLAY 'CONTA POSITIVA'
ELSE
DISPLAY 'CONTA SEM SALDO'
END-IF
O programa examina uma condição e escolhe uma ação.
No JCL, entretanto, a decisão é maior.
O JCL não escolhe apenas uma instrução.
Ele pode decidir se um programa inteiro será ou não executado.
Veja o exemplo básico:
//STEP01 EXEC PGM=PROGA
//TESTE01 IF (STEP01.RC = 0) THEN
//STEP02 EXEC PGM=PROGB
// ELSE
//STEP03 EXEC PGM=PROGC
// ENDIF
O fluxo é o seguinte:
STEP01executa o programaPROGA.O sistema registra o Return Code produzido por esse passo.
O JCL avalia a condição
STEP01.RC = 0.Se a condição for verdadeira, executa
STEP02.Caso contrário, executa
STEP03.Ao encontrar
ENDIF, o fluxo condicional termina.
Visualmente:
STEP01
|
STEP01.RC é igual a 0?
/ \
SIM NÃO
| |
STEP02 STEP03
\ /
CONTINUA
É uma bifurcação na estrada do batch.
Um caminho será percorrido.
O outro ficará registrado no spool como um passo não executado por causa da lógica condicional.
3. O Return Code: a testemunha principal
O coração dessa história não é o IF.
É o Return Code.
O Return Code, geralmente abreviado como RC, é um valor devolvido por um programa ao terminar.
Ele comunica ao sistema o resultado da execução.
Uma convenção comum é:
| Return Code | Significado habitual |
|---|---|
| 0 | Processamento concluído com sucesso |
| 4 | Sucesso com advertência |
| 8 | Erro de processamento |
| 12 | Erro grave |
| 16 | Falha severa |
Mas existe uma regra fundamental:
O significado do Return Code pertence ao programa ou ao utilitário que o produziu.
Não existe uma lei universal determinando que RC=4 seja sempre aceitável ou que RC=8 represente exatamente o mesmo erro em todos os programas.
No IDCAMS, no DFSORT, em programas COBOL internos ou em produtos de terceiros, os significados podem variar.
Por isso, o programador deve conhecer o contrato de retorno do programa executado.
Imagine um programa de validação de clientes:
RC=0 Todos os registros são válidos
RC=4 Existem registros com advertências
RC=8 Existem registros rejeitados
RC=12 O arquivo não pôde ser processado
Nesse caso, talvez seja permitido continuar com RC=4.
A condição poderia ser:
//CHKVALID IF (STEP01.RC <= 4) THEN
//STEP02 EXEC PGM=ATUALIZA
// ELSE
//STEPERRO EXEC PGM=TRATAERR
// ENDIF
Agora o JOB aceita retorno zero ou quatro.
Isso demonstra por que o teste simplista RC = 0 nem sempre é suficiente.
4. Como um programa COBOL define o Return Code?
Em COBOL, o programa pode atribuir um valor ao registrador especial RETURN-CODE.
Exemplo:
IDENTIFICATION DIVISION.
PROGRAM-ID. VALIDA01.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-QTD-ERROS PIC 9(05) VALUE ZERO.
PROCEDURE DIVISION.
PERFORM PROCESSAR-ARQUIVO
IF WS-QTD-ERROS = ZERO
MOVE 0 TO RETURN-CODE
ELSE
MOVE 8 TO RETURN-CODE
END-IF
GOBACK.
Quando o programa termina com:
MOVE 0 TO RETURN-CODE
o passo pode aparecer no spool com retorno zero.
Quando termina com:
MOVE 8 TO RETURN-CODE
o JCL poderá testar esse valor em um passo posterior.
Essa comunicação é extremamente importante.
O programa COBOL conhece o resultado funcional do processamento.
O JCL conhece o fluxo completo do JOB.
O Return Code é a ponte entre os dois.
É como se o programa deixasse um bilhete sobre a mesa:
“Terminei. Este é o estado do caso.”
O JCL lê o bilhete e decide o que fazer.
5. A anatomia correta de uma estrutura condicional
Observe este exemplo mais completo:
//FECHAMEN JOB (ACCT),'FECHAMENTO',CLASS=A,MSGCLASS=X
//*
//VALIDA EXEC PGM=PGMVALID
//ARQENT DD DSN=EMPRESA.MOVIMENTO.DIA,DISP=SHR
//RELERR DD SYSOUT=*
//*
//IFVALID IF (VALIDA.RC <= 4) THEN
//*
//ATUALIZA EXEC PGM=PGMATU
//ARQENT DD DSN=EMPRESA.MOVIMENTO.DIA,DISP=SHR
//CADASTRO DD DSN=EMPRESA.CLIENTES.MASTER,DISP=OLD
//*
//IFATU IF (ATUALIZA.RC = 0) THEN
//RELATOR EXEC PGM=PGMREL
//SAIDA DD SYSOUT=*
// ELSE
//ERROATU EXEC PGM=PGMERRO
// ENDIF
//*
// ELSE
//ERROVAL EXEC PGM=PGMERRO
// ENDIF
Temos dois níveis de decisão.
Primeiro:
IF (VALIDA.RC <= 4) THEN
Se a validação for aceitável, o JOB executa ATUALIZA.
Depois:
IF (ATUALIZA.RC = 0) THEN
Se a atualização terminar com sucesso, o relatório será gerado.
Caso contrário, ERROATU será executado.
Se a validação inicial falhar, o JOB nem chega à atualização. Ele segue diretamente para ERROVAL.
Esse é um exemplo de IF aninhado.
Funciona bem, mas exige disciplina.
Quanto mais níveis de aninhamento existirem, mais difícil será compreender o JOB.
Um JCL com sete ou oito IFs dentro de outros IFs pode se transformar em uma mansão noir cheia de corredores, portas falsas e quartos onde ninguém se lembra de ter entrado.
6. Operadores de comparação
O JCL permite comparar Return Codes de diferentes maneiras.
Igualdade
//TESTE IF (STEP01.RC = 0) THEN
Também pode ser encontrada a forma mnemônica:
//TESTE IF (STEP01.RC EQ 0) THEN
Diferente
//TESTE IF (STEP01.RC NE 0) THEN
Dependendo do ambiente e da codificação disponível, símbolos como ¬= podem aparecer, mas as formas mnemônicas são frequentemente mais claras e evitam problemas de caracteres.
Maior que
//TESTE IF (STEP01.RC GT 4) THEN
Menor que
//TESTE IF (STEP01.RC LT 8) THEN
Maior ou igual
//TESTE IF (STEP01.RC GE 8) THEN
Menor ou igual
//TESTE IF (STEP01.RC LE 4) THEN
As formas mnemônicas são:
| Operador | Significado |
|---|---|
| EQ | Igual |
| NE | Diferente |
| GT | Maior que |
| LT | Menor que |
| GE | Maior ou igual |
| LE | Menor ou igual |
7. Condições compostas com AND e OR
O JCL pode analisar mais de uma evidência.
Utilizando AND
//TESTE IF (STEP01.RC = 0 & STEP02.RC = 0) THEN
Ou, conforme a forma adotada:
//TESTE IF (STEP01.RC EQ 0 AND STEP02.RC EQ 0) THEN
A condição será verdadeira somente se os dois passos terminarem com retorno zero.
Exemplo prático:
STEP01valida o arquivo de clientes;STEP02valida o arquivo de contratos;STEP03executa apenas quando os dois arquivos são válidos.
//IFOK IF (STEP01.RC EQ 0 AND STEP02.RC EQ 0) THEN
//STEP03 EXEC PGM=ATUALIZA
// ENDIF
Utilizando OR
//IFERRO IF (STEP01.RC GE 8 OR STEP02.RC GE 8) THEN
//TRATAERR EXEC PGM=ERROGER
// ENDIF
Aqui, o tratamento será executado se qualquer um dos passos retornar oito ou mais.
A importância dos parênteses
Em condições complexas, use parênteses para deixar a intenção visível:
//TESTE IF ((STEP01.RC LE 4) AND
// (STEP02.RC EQ 0)) THEN
O JOB não é lugar para jogos de adivinhação.
Um programador pode compreender uma expressão hoje e esquecê-la seis meses depois. Um colega chamado às três da madrugada terá ainda menos paciência.
Escreva para a manutenção, não apenas para o interpretador.
8. RC não é a mesma coisa que ABEND
Essa é uma das distinções mais importantes para um iniciante.
Um Return Code significa que o programa chegou a uma conclusão normal e devolveu um resultado.
Um ABEND significa que ocorreu uma terminação anormal.
Exemplos de ABEND:
S0C7
S0C4
S806
U4038
Um S0C7, por exemplo, frequentemente está relacionado a uma operação numérica inválida, como tentar tratar conteúdo não numérico como número.
Um S806 pode indicar que o programa não foi encontrado em uma biblioteca de carga acessível.
Nesses casos, não estamos simplesmente diante de um RC=8.
O programa sofreu uma interrupção anormal.
O JCL permite testar situações de ABEND.
Exemplo:
//STEP01 EXEC PGM=PROGA
//IFABEND IF (STEP01.ABEND) THEN
//DUMP EXEC PGM=GERADUMP
// ENDIF
Também é possível testar se um passo executou normalmente:
//IFNORMAL IF (STEP01.RUN AND NOT STEP01.ABEND) THEN
//STEP02 EXEC PGM=PROGB
// ENDIF
A disponibilidade e a forma exata dos testes devem ser verificadas de acordo com os padrões do ambiente e a documentação utilizada pela instalação, mas o conceito central permanece:
RCtrata o resultado de uma conclusão normal;ABENDtrata uma terminação anormal;um passo pode não executar por causa de uma condição anterior;
um passo não executado não deve ser confundido com um programa que executou e retornou erro.
No spool, essas diferenças contam a história real do JOB.
9. O que acontece quando não existe ELSE?
O ELSE é opcional.
Podemos escrever:
//STEP01 EXEC PGM=PROGA
//SEOK IF (STEP01.RC EQ 0) THEN
//STEP02 EXEC PGM=PROGB
// ENDIF
Se STEP01.RC for zero, STEP02 executará.
Caso contrário, o bloco será ignorado e o JOB continuará depois do ENDIF.
Isso é útil quando existe uma ação necessária apenas em uma situação específica.
Exemplo:
//AVISO IF (VALIDA.RC EQ 4) THEN
//EMAIL EXEC PGM=ENVIAAV
// ENDIF
O e-mail será enviado somente quando houver advertências.
10. Vários passos dentro do THEN e do ELSE
Um erro comum é imaginar que cada bloco pode conter apenas um EXEC.
Na verdade, vários passos podem ser agrupados.
//STEP01 EXEC PGM=VALIDA
//FLUXOOK IF (STEP01.RC LE 4) THEN
//STEP02 EXEC PGM=ATUALIZA
//STEP03 EXEC PGM=RELATOR
//STEP04 EXEC PGM=ENVIA
// ELSE
//STEP90 EXEC PGM=LOGERRO
//STEP91 EXEC PGM=NOTIFICA
// ENDIF
Se a validação for aceitável, três programas serão executados.
Se não for, dois programas de tratamento serão acionados.
Esse tipo de construção aparece com frequência em ambientes de produção.
11. Exemplo realista: fechamento de vendas
Considere o seguinte processo noturno:
Receber arquivo de vendas.
Validar estrutura.
Atualizar banco de dados.
Gerar relatório.
Enviar relatório.
Em caso de erro, registrar ocorrência e notificar o suporte.
O JCL poderia ser:
//VENDAS JOB (FIN),'FECHAMENTO',CLASS=A,MSGCLASS=X
//*
//VALIDA EXEC PGM=VALVEND
//ARQVEN DD DSN=LOJA.VENDAS.DIARIA,DISP=SHR
//RELERR DD SYSOUT=*
//*
//IFVAL IF (VALIDA.RC LE 4) THEN
//*
//ATUALIZA EXEC PGM=ATUVEND
//ARQVEN DD DSN=LOJA.VENDAS.DIARIA,DISP=SHR
//BASEVEN DD DSN=LOJA.VENDAS.MASTER,DISP=OLD
//*
//IFATU IF (ATUALIZA.RC EQ 0) THEN
//RELATOR EXEC PGM=RELVEND
//RELATORI DD DSN=LOJA.RELATORIO.DIARIO,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(5,2)),
// DCB=(RECFM=FB,LRECL=133,BLKSIZE=0)
//*
//ENVIA EXEC PGM=MAILBAT
//ARQMAIL DD DSN=LOJA.RELATORIO.DIARIO,DISP=SHR
// ELSE
//LOGATU EXEC PGM=LOGERRO
//AVISAATU EXEC PGM=AVISOPS
// ENDIF
//*
// ELSE
//LOGVAL EXEC PGM=LOGERRO
//AVISAVAL EXEC PGM=AVISOPS
// ENDIF
Agora examine a lógica.
Cenário 1: validação retorna zero
O arquivo está correto.
O JOB entra no primeiro THEN.
Cenário 2: validação retorna quatro
O arquivo contém advertências permitidas.
Como a condição é LE 4, o processamento continua.
Cenário 3: validação retorna oito
O JOB ignora atualização, relatório e envio.
Executa LOGVAL e AVISAVAL.
Cenário 4: atualização retorna oito
A validação foi aceita, mas a atualização falhou.
O relatório e o envio não executam.
O JOB chama LOGATU e AVISAATU.
Esse desenho impede que um relatório aparentemente correto seja enviado após uma atualização malsucedida.
É assim que uma estrutura condicional protege a integridade operacional.
12. IF/THEN/ELSE versus COND
Antes da popularização das estruturas condicionais explícitas, muitos JOBs utilizavam intensamente o parâmetro COND.
Exemplo:
//STEP02 EXEC PGM=PROGB,COND=(0,NE,STEP01)
O problema é que COND trabalha com uma lógica que muitos iniciantes consideram invertida.
O parâmetro indica uma condição para ignorar o passo.
Em outras palavras, quando a condição do COND é verdadeira, o passo não executa.
Isso exige atenção.
No exemplo:
COND=(0,NE,STEP01)
a interpretação é aproximadamente:
Ignore
STEP02se o Return Code deSTEP01for diferente de zero.
Portanto, STEP02 executa apenas quando STEP01.RC é zero.
O equivalente com IF é mais legível:
//TESTE IF (STEP01.RC EQ 0) THEN
//STEP02 EXEC PGM=PROGB
// ENDIF
Compare:
COND=(0,NE,STEP01)
com:
IF (STEP01.RC EQ 0) THEN
A segunda forma parece uma frase.
Por isso, em fluxos complexos, o IF/THEN/ELSE geralmente facilita a leitura e a manutenção.
Isso não significa que COND esteja morto.
Muitos JOBs antigos e novos ainda o utilizam.
Um profissional de mainframe precisa compreender os dois.
Mas deve evitar misturar COND e estruturas IF sem necessidade, pois a combinação pode criar comportamentos difíceis de analisar.
13. Passo a passo para investigar um JOB condicional
Quando você encontrar um JCL grande, não tente compreender tudo ao mesmo tempo.
Use o método Bellacosa de investigação batch.
Passo 1 — Localize todos os EXEC
Anote cada step:
VALIDA
ATUALIZA
RELATOR
ENVIA
LOGERRO
AVISOPS
Isso revela os atores da história.
Passo 2 — Localize todos os IF
Procure:
IF
ELSE
ENDIF
Marque o início e o fim de cada bloco.
Passo 3 — Descubra qual step está sendo testado
Exemplo:
IF (VALIDA.RC LE 4) THEN
O suspeito interrogado é VALIDA.
Passo 4 — Consulte o significado dos Return Codes
Descubra o contrato do programa.
Talvez:
0 = sucesso
4 = aviso
8 = arquivo inválido
12 = falha de abertura
Sem essa informação, a condição é apenas um número sem contexto.
Passo 5 — Desenhe o fluxo
Use papel, quadro ou editor de texto:
VALIDA
|
RC <= 4?
/ \
SIM NÃO
| |
ATUALIZA LOGERRO
|
RC = 0?
/ \
SIM NÃO
| |
RELATOR AVISOPS
ENVIA
Passo 6 — Compare com o spool
Verifique:
quais passos realmente executaram;
quais foram ignorados;
quais retornaram código;
se houve ABEND;
qual foi o maior Return Code do JOB;
se alguma condição alterou o fluxo.
O spool é a cena do crime.
Não confie apenas no que o desenvolvedor acredita que aconteceu.
Leia as evidências.
14. Erros comuns de iniciantes
Considerar qualquer valor diferente de zero como desastre
Nem sempre RC=4 representa falha.
Pode ser apenas uma advertência.
O contrato do programa deve definir isso.
Testar o step errado
IF (STEP02.RC EQ 0) THEN
não funciona como esperado se STEP02 não executou ou se a intenção era testar STEP01.
Nomes claros reduzem esse risco.
Esquecer o ENDIF
Cada estrutura precisa ser encerrada corretamente.
Em fluxos aninhados, identação e comentários ajudam muito.
Criar condições excessivamente complexas
Uma expressão com muitos AND, OR, NOT e parênteses pode funcionar, mas se tornar impossível de manter.
Às vezes, dividir o processamento em mais de um bloco é melhor.
Confundir step ignorado com erro
Um passo dentro de um ramo não escolhido pode aparecer como não executado.
Isso não significa que seu programa falhou.
Significa que o JCL decidiu não chamá-lo.
Tratar ABEND como Return Code comum
Um S0C7 não é simplesmente RC=7.
ABENDs possuem outra natureza e exigem tratamento apropriado.
Não documentar Return Codes funcionais
Um programa COBOL que retorna RC=6, RC=20 ou RC=32 sem documentação está deixando uma bomba-relógio para a equipe de produção.
15. Boas práticas para JCL de produção
Use nomes significativos
Evite:
//STEP1
//STEP2
//STEP3
Prefira:
//VALIDA
//ATUALIZA
//GERAREL
//ENVIA
O nome do step deve ajudar a contar a história do JOB.
Nomeie os blocos condicionais
//IFVALID IF (VALIDA.RC LE 4) THEN
Isso facilita localizar mensagens e interpretar o fluxo.
Comente decisões incomuns
//* RC=4 INDICA REGISTROS REJEITADOS, MAS PROCESSAMENTO PODE CONTINUAR
Um bom comentário economiza horas de investigação.
Padronize Return Codes
A equipe deve saber o que cada faixa representa.
Por exemplo:
0 Sucesso
4 Advertência
8 Erro funcional
12 Erro técnico
16+ Falha severa
Evite aninhamento profundo
Se o JOB parecer uma boneca russa de IFs, talvez seja hora de redesenhar o fluxo.
Sempre pense no tratamento de erro
Não basta impedir a execução de passos posteriores.
Pergunte:
quem será notificado?
onde o erro será registrado?
o arquivo será preservado?
será necessário restart?
o operador saberá qual ação tomar?
o scheduler interpretará o resultado corretamente?
Um bom IF não apenas impede problemas.
Ele orienta a recuperação.
16. Curiosidades do mundo batch
O JOB pode terminar “bem”, mas o negócio ter falhado
Tecnicamente, um programa pode terminar com RC=0 mesmo quando não processou nada útil.
Por exemplo, o arquivo estava vazio, mas o programa considerou isso normal.
O sistema operacional vê sucesso.
O negócio talvez veja um desastre.
Por isso, Return Codes devem representar estados relevantes para a operação.
O maior RC costuma chamar atenção
Ferramentas de operação e schedulers frequentemente analisam o maior Return Code encontrado no JOB.
Mas o comportamento exato depende das regras da instalação e da automação utilizada.
Schedulers também tomam decisões
Produtos como IBM Workload Scheduler, Control-M e outras soluções podem avaliar status de JOBs, Return Codes, dependências, horários e recursos.
Nesse cenário, existe uma cadeia de inteligência:
Programa COBOL
↓
Return Code
↓
JCL IF/THEN/ELSE
↓
Resultado do JOB
↓
Scheduler
↓
Próximo processamento
Um pequeno número devolvido por um programa pode impedir a execução de uma cadeia inteira de processamento corporativo.
Um RC mal definido pode custar caro
Imagine um programa que detecta inconsistência financeira, grava uma mensagem no relatório, mas termina com RC=0.
O JCL entende que tudo ocorreu corretamente.
O relatório é enviado.
O scheduler libera os próximos JOBs.
Horas depois, alguém descobre que os dados estavam errados.
O problema não foi apenas técnico.
Foi uma falha de comunicação entre programa e operação.
17. O exemplo definitivo para um Padawan COBOL
Vamos construir um fluxo simples e completo.
O objetivo é:
validar um arquivo;
processá-lo se estiver correto;
gerar relatório se o processamento terminar bem;
executar tratamento se algo falhar.
//PEDIDOS JOB (1234),'PEDIDOS',CLASS=A,MSGCLASS=X
//*
//VALIDA EXEC PGM=VALPED
//ARQPED DD DSN=EMPRESA.PEDIDOS.ENTRADA,DISP=SHR
//SYSOUT DD SYSOUT=*
//*
//IFVAL IF (VALIDA.RC LE 4) THEN
//*
//PROCESSA EXEC PGM=PROCPED
//ARQPED DD DSN=EMPRESA.PEDIDOS.ENTRADA,DISP=SHR
//CADPED DD DSN=EMPRESA.PEDIDOS.MASTER,DISP=OLD
//SYSOUT DD SYSOUT=*
//*
//IFPROC IF (PROCESSA.RC EQ 0) THEN
//RELATOR EXEC PGM=RELPED
//RELATORI DD SYSOUT=*
// ELSE
//ERROPROC EXEC PGM=TRATPED
//MOTIVO DD *
FALHA NO PROCESSAMENTO DE PEDIDOS
/*
// ENDIF
//*
// ELSE
//ERROVAL EXEC PGM=TRATPED
//MOTIVO DD *
ARQUIVO DE PEDIDOS REPROVADO NA VALIDACAO
/*
// ENDIF
O raciocínio é:
VALIDA
|
+-- RC 0 ou 4?
|
+-- SIM → PROCESSA
| |
| +-- RC 0?
| |
| +-- SIM → RELATOR
| |
| +-- NÃO → ERROPROC
|
+-- NÃO → ERROVAL
O iniciante que aprende a desenhar esse fluxo já está deixando de apenas “ler JCL”.
Ele começa a pensar como alguém de produção.
18. O easter egg do velho operador
Dizem que, em um data center antigo, havia um operador chamado Moretti.
Ninguém sabia sua idade. Alguns juravam que ele já trabalhava ali quando os discos ainda pareciam máquinas de lavar.
Moretti tinha um ritual.
Sempre que um JOB terminava, ele não olhava primeiro para o programa, para o consumo de CPU ou para o horário.
Ele procurava o Return Code.
Certa madrugada, um novato perguntou:
— Por que o senhor olha primeiro para um número tão pequeno?
Moretti respondeu:
— Porque os programas falam muito nos relatórios, mas dizem a verdade no retorno.
Anos depois, quando Moretti se aposentou, encontraram um cartão perfurado em sua gaveta.
Nele havia apenas uma frase:
RC=0 NÃO SIGNIFICA QUE O UNIVERSO ESTÁ CORRETO.
SIGNIFICA APENAS QUE O PROGRAMA DISSE QUE ESTÁ.
Ninguém sabe se a história é verdadeira.
Mas todo programador mainframe deveria guardar a frase.
19. A conclusão do caso
Naquela madrugada, o jovem programador voltou ao telefone.
— Bellacosa, encontrei o problema. O primeiro programa terminou com RC=4. O IF estava testando apenas RC=0. Por isso o passo de envio não executou.
— E o que significa RC=4 nesse programa?
Houve silêncio.
Depois, ouvi o som de páginas sendo folheadas.
— Significa que o relatório foi gerado, mas alguns registros foram ignorados. Ainda é permitido enviá-lo.
— Então o erro não estava no programa.
— Estava na condição.
Exatamente.
O programa havia feito seu trabalho.
O JCL também.
O problema era que alguém havia escrito uma regra incompleta.
A condição dizia:
IF (STEP01.RC EQ 0) THEN
Mas a regra de negócio deveria aceitar zero e quatro:
IF (STEP01.RC LE 4) THEN
Uma pequena diferença.
Dois caracteres.
Uma decisão completamente diferente.
No mainframe, muitas catástrofes não começam com explosões, fumaça ou mensagens dramáticas.
Elas começam com detalhes.
Um dataset com o DISP errado.
Um campo numérico mal inicializado.
Uma biblioteca ausente no STEPLIB.
Um Return Code não documentado.
Ou um IF que pergunta a coisa errada.
O IF/THEN/ELSE transforma o JCL em algo muito maior do que uma sequência estática de comandos. Ele permite que o JOB observe resultados, escolha caminhos, evite processamentos inúteis, proteja dados, acione tratamentos e automatize decisões operacionais.
Para quem trabalha com COBOL, produção, suporte, operações ou sistemas, dominar esse recurso não é opcional.
É parte da alfabetização batch.
Quando você compreender o Return Code, começará a entender o programa.
Quando compreender o IF, começará a entender o JOB.
E quando conseguir seguir o fluxo inteiro pelo spool, examinando cada passo, cada retorno, cada desvio e cada programa ignorado...
Bem...
Nesse momento, jovem Padawan, você já não estará apenas executando JCL.
Estará investigando o mainframe.
E em uma madrugada chuvosa, quando um JOB de milhões de reais parar sem explicação aparente, talvez alguém ligue para você.
Na tela, uma única linha estará esperando:
//MISTERIO IF (STEP01.RC GT 4) THEN
O café estará frio.
A sala estará escura.
E o caso será seu.
Sem comentários:
Enviar um comentário