1. EXEC — o que é e sintaxe
O EXEC statement inicia um step dentro do job. Cada step executa um programa ou procedure. Um job pode ter até 255 steps.
//[stepname] EXEC PGM=nome-programa * executa programa //[stepname] EXEC PROC=nome-procedure * chama procedure //[stepname] EXEC nome-procedure * PROC= é opcional
💗 Stepname é opcional, mas use sempre
O nome do step (colunas 3–10) é tecnicamente opcional, mas sempre dê um nome descritivo. Sem nome, você não consegue usar RESTART= para reiniciar a partir de um step específico, nem referenciar o step em condicionais. Nomes como STEP01, COMPILE, EXEC, RELAT são convenções comuns.
2. PGM vs. PROC
| PGM= | PROC= | |
|---|---|---|
| O que executa | Um programa compilado diretamente | Uma procedure JCL (conjunto reutilizável de steps) |
| Onde está | Em uma load library (STEPLIB, JOBLIB) | No PROCLIB do JES ou definida inline |
| Quando usar | Para rodar seu programa COBOL ou um utilitário IBM | Para reutilizar um conjunto de steps padrão |
| Exemplo | EXEC PGM=IEFBR14 | EXEC PROC=COBUCL |
🦕 Analogia — PGM é o chef, PROC é a receita
PGM= é como ligar diretamente para um chef: "Fulano, venha cozinhar aqui agora". PROC= é como pedir uma receita padrão da cozinha: "Me manda o combo de compilação do COBOL". A procedure já sabe quais passos seguir, você só precisa chamar pelo nome.
3. Parâmetros do EXEC
| Parâmetro | Descrição | Exemplo |
|---|---|---|
PGM | Nome do programa a executar | PGM=CALC-SAL |
PARM | Parâmetro passado ao programa (acesso via LINKAGE SECTION) | PARM='2024-12' |
REGION | Memória máxima para este step (sobrepõe o do JOB) | REGION=128M |
TIME | Tempo de CPU máximo para este step | TIME=(2,0) |
COND | Condição para executar ou pular este step | COND=(0,NE) |
PARM — passando parâmetros para o programa
//STEP01 EXEC PGM=RELAT-MES, // PARM='202412' * mes/ano de referencia
LINKAGE SECTION. 01 PARM-RECEBIDO. 05 PARM-TAMANHO PIC S9(04) COMP. 05 PARM-MES-ANO PIC X(06). * '202412' PROCEDURE DIVISION USING PARM-RECEBIDO. DISPLAY 'MES DE REFERENCIA: ' PARM-MES-ANO
4. DD — o que é e sintaxe
O DD statement (Data Definition) conecta nomes lógicos usados no programa com os datasets físicos do mainframe. É o "elo" entre o SELECT ... ASSIGN TO DDNAME no COBOL e o arquivo real no disco.
//ddname DD parâmetros * Exemplos comuns: //ENTRADA DD DSN=PROD.FUNC.DADOS,DISP=SHR //SAIDA DD DSN=PROD.RELAT.OUT,DISP=(NEW,CATLG,DELETE), // UNIT=SYSDA,SPACE=(TRK,(10,5)), // DCB=(DSORG=PS,RECFM=FB,LRECL=133)
🦕 Analogia — DD é como conectar tomadas
Seu programa COBOL faz SELECT ARQ-ENTRADA ASSIGN TO ENTRADA. Isso é como um plug de três pinos: o programa sabe que precisa de energia (dados), mas não sabe de onde vem. O DD é a tomada na parede — //ENTRADA DD DSN=PROD.FUNC.DADOS conecta o plug de "ENTRADA" no arquivo real PROD.FUNC.DADOS. O nome tem que casar exatamente entre o ASSIGN do COBOL e o DDname do JCL.
5. DDs especiais obrigatórios
Alguns DDnames têm significado especial para o sistema e o programa:
| DDname | Finalidade |
|---|---|
STEPLIB | Library onde o sistema procura o programa executável deste step |
JOBLIB | Library padrão para todos os steps (no nível do JOB, antes do primeiro EXEC) |
SYSOUT | Mensagens de DISPLAY do programa e saída padrão do sistema |
SYSPRINT | Relatório principal de utilitários IBM (IDCAMS, IEBGENER, etc.) |
SYSIN | Dados de controle para utilitários (parâmetros do SORT, comandos IDCAMS) |
SYSABEND | Dump de memória quando o programa sofre abend (para diagnóstico) |
✅ STEPLIB vs. JOBLIB
JOBLIB vale para todos os steps do job — coloque antes do primeiro EXEC. STEPLIB vale apenas para o step onde está declarado e sobrepõe o JOBLIB para aquele step. Use STEPLIB quando steps diferentes precisam de versões diferentes do mesmo programa (ex: STEP01 usa a versão de teste, STEP02 usa a de produção).
6. Dados inline com DD *
Para passar pequenos volumes de dados ou parâmetros de controle diretamente no JCL, sem precisar de um arquivo separado, use DD * (in-stream data):
//SORTSTEP EXEC PGM=DFSORT //SORTIN DD DSN=PROD.FUNC.DADOS,DISP=SHR //SORTOUT DD DSN=PROD.FUNC.SORTED, // DISP=(NEW,CATLG,DELETE),UNIT=SYSDA, // SPACE=(CYL,(5,2)),LIKE=PROD.FUNC.DADOS //SYSOUT DD SYSOUT=* //SYSIN DD * * dados de controle do SORT vêm aqui SORT FIELDS=(1,11,CH,A) * ordena pelo campo pos 1, tam 11, asc /* * fim dos dados inline
⚠️ /* vs. // — fim de dados inline
/* (sem segundo /) encerra os dados inline do DD *. Ele é opcional quando o próximo statement já começa com // (o sistema entende que os dados acabaram), mas é boa prática incluí-lo explicitamente para deixar o JCL mais legível. Não confunda /* com //* (que é comentário).
7. DD DUMMY
DD DUMMY cria um dataset "nulo" — o programa enxerga o arquivo como se existisse, mas qualquer leitura retorna EOF e qualquer escrita é descartada. Muito útil para:
- Desativar um arquivo de saída sem alterar o programa
- Testes onde você não quer gerar output real
- SYSIN de utilitários que não precisam de parâmetros
//STEP01 EXEC PGM=IEBGENER //SYSUT1 DD DSN=PROD.FUNC.DADOS,DISP=SHR //SYSUT2 DD SYSOUT=* //SYSIN DD DUMMY * IEBGENER nao precisa de SYSIN //SYSPRINT DD SYSOUT=*
8. Step completo comentado
Veja um step realista com múltiplos DDs, comentado linha a linha:
//*-----------------------------------------------------------* //* STEP01: Calcula folha de pagamento do mes * //*-----------------------------------------------------------* //CALCFOL EXEC PGM=CALCFOL, // PARM='202412', * mes de referencia // REGION=128M //* Load library com o executavel do programa //STEPLIB DD DSN=PROD.LOAD.LIB,DISP=SHR // DD DSN=DB2.LOAD.LIB,DISP=SHR * concatenacao de libs //* Arquivo de entrada: cadastro de funcionarios //FUNC DD DSN=PROD.FUNC.CADAS,DISP=SHR //* Arquivo de saida: folha calculada (novo dataset) //FOLHA DD DSN=PROD.FOLHA.202412, // DISP=(NEW,CATLG,DELETE), // UNIT=SYSDA, // SPACE=(CYL,(10,5)), // DCB=(DSORG=PS,RECFM=FB,LRECL=200) //* Relatorio de erros e inconsistencias //ERROS DD SYSOUT=* //* Dump para debug em caso de abend //SYSABEND DD SYSOUT=* //* Saida padrao (DISPLAY do COBOL vai aqui) //SYSOUT DD SYSOUT=*
🟣 Concatenação de datasets no STEPLIB
No exemplo acima, o STEPLIB tem dois DDs consecutivos sem nome (o segundo não tem DDname). Isso é uma concatenação: o sistema procura o programa primeiro em PROD.LOAD.LIB, depois em DB2.LOAD.LIB. Útil quando o executável precisa de bibliotecas de runtime de diferentes produtos (DB2, CICS, IMS). A ordem importa — o sistema usa o primeiro que encontrar.