1. Sintaxe geral
//jobname JOB [parâmetros-posicionais],[parâmetros-palavra-chave]
🦕 Analogia — o JOB statement é como uma ficha de admissão
Quando você entra numa empresa, preenche uma ficha: nome, CPF, cargo, salário, departamento. O JOB statement é a "ficha de admissão" do job no mainframe: nome do job, conta de cobrança, programador responsável, classe de execução, prioridade. Sem a ficha, ninguém te deixa entrar.
2. Nome do job
O nome do job fica nas colunas 3 a 10, imediatamente após as barras //, sem espaço:
- De 1 a 8 caracteres
- Deve começar com letra ou
$,#,@ - Pode conter letras, números e esses três caracteres especiais
- Deve ser único no sistema (muitas instalações exigem que comece com o userid)
//LCJOB001 JOB ... * LC = Lady Cobol, convencao de userid //CALCFOL JOB ... * nome descritivo da funcao //$DIARIO JOB ... * com caractere especial
3. Parâmetros posicionais
Os parâmetros posicionais vêm logo após o JOB, em ordem obrigatória. São dois e ambos opcionais — mas se omitir o primeiro e incluir o segundo, você precisa deixar a vírgula no lugar.
1º posicional — Informações de conta
Identifica a conta que será cobrada pelo uso de CPU e recursos. O formato varia por instalação.
* Conta simples //MEUJOB JOB ACCT001, ... * Conta com subparâmetros (conta, departamento, projeto) //MEUJOB JOB (ACCT001,DEPTO,PROJ), ... * Omitindo conta mas mantendo o 2o posicional //MEUJOB JOB ,'LADY COBOL', ...
2º posicional — Nome do programador
Nome do responsável pelo job. Vai entre aspas simples se contiver espaços ou caracteres especiais.
//MEUJOB JOB ACCT001,LADYCOBOL, ... * sem espaco: sem aspas //MEUJOB JOB ACCT001,'LADY COBOL', ... * com espaco: com aspas
4. Parâmetros de palavra-chave
Vêm depois dos posicionais, em qualquer ordem. Estes são os mais importantes:
| Parâmetro | O que faz | Valores comuns |
|---|---|---|
CLASS | Classe de iniciadores — define em qual fila o job entra | A, B, C… (definido pelo site) |
MSGCLASS | Classe de saída para o log de mensagens do job | X (spool), A (impressora) |
MSGLEVEL | Nível de detalhe das mensagens JCL no output | (1,1) = tudo; (0,0) = mínimo |
NOTIFY | Userid a notificar quando o job terminar | &SYSUID (usuário atual) |
REGION | Memória máxima para o job inteiro | 0M (ilimitado), 64M, 128M |
TIME | Tempo máximo de CPU (aborts com S522 se exceder) | 1440 (24h), (5,30) = 5min30s |
TYPRUN | Modo de execução especial | SCAN (só valida JCL) |
RESTART | Reinicia o job a partir de um step específico | STEP02 |
CLASS e MSGCLASS — os mais usados no dia a dia
🦕 Analogia — CLASS como caixa do supermercado
O mainframe tem várias "caixas de checkout" (iniciadores) com diferentes funções: Caixa A = jobs de desenvolvimento (menos prioridade), Caixa B = jobs de teste, Caixa P = produção (alta prioridade). Você escolhe a caixa com o parâmetro CLASS. Cada instalação define quantas caixas existem e o que cada letra significa.
MSGLEVEL=(x,y) — entendendo os dois valores
| MSGLEVEL=(x,y) | x — Statements JCL | y — Mensagens do sistema |
|---|---|---|
| (0,0) | Só o JOB card | Só se houver erro |
| (1,0) | Todo o JCL | Só se houver erro |
| (1,1) | Todo o JCL | Sempre (mais verboso) |
| (2,0) | Só os statements do JCL do job (não de proc) | Só se houver erro |
✅ MSGLEVEL no dia a dia
Em desenvolvimento: use MSGLEVEL=(1,1) para ver tudo e facilitar o diagnóstico de erros.
Em produção: use MSGLEVEL=(1,0) ou (0,0) para reduzir o volume de log e economizar spool.
TIME — evitando loops infinitos
* Tempo ilimitado (cuidado em producao!) //MEUJOB JOB ...,TIME=1440 * Maximo de 5 minutos e 30 segundos de CPU //MEUJOB JOB ...,TIME=(5,30) * Apenas 45 segundos //MEUJOB JOB ...,TIME=(0,45)
⚠️ Abend S522 — tempo de CPU excedido
Se o job ultrapassar o TIME definido, ele é cancelado pelo sistema com o abend S522. Em produção, definir um TIME razoável é uma boa prática de proteção contra loops infinitos. Se você viu um S522 no SDSF e não esperava, o programa está em loop ou o TIME está muito baixo para o volume de dados.
TYPRUN=SCAN — validar JCL sem executar
Um dos recursos mais úteis para quem está aprendendo: com TYPRUN=SCAN, o JES valida a sintaxe do JCL sem executar nenhum programa. Ótimo para verificar erros antes de submeter em produção.
//TESTJOB JOB ACCT001,'LADY COBOL', // CLASS=A,MSGCLASS=X, // MSGLEVEL=(1,1), // TYPRUN=SCAN * valida o JCL, nao executa
5. Continuação de linha
O JOB statement (e qualquer statement JCL) pode ser continuado em múltiplas linhas. A regra é: terminar a linha na coluna 71 ou antes, com vírgula, e começar a próxima linha com // e pelo menos um espaço antes dos parâmetros.
//MEUJOB JOB (ACCT001,DEPTO),'LADY COBOL', // CLASS=A, // MSGCLASS=X, // MSGLEVEL=(1,1), // NOTIFY=&SYSUID, // REGION=0M, // TIME=1440
⚠️ Regras de continuação
- A linha que continua deve terminar com vírgula antes da coluna 72
- A linha de continuação começa com
//seguido de pelo menos um espaço (colunas 3 em diante) - Não pode haver nada entre a coluna 72 e o fim da linha (colunas 73–80 são ignoradas)
- Esquecer a vírgula é um dos erros mais comuns — o JES interpreta como fim dos parâmetros
6. Exemplos completos
JOB card de desenvolvimento
//LCDEV01 JOB (DEVACCT),'LADY COBOL', // CLASS=D, * classe de dev // MSGCLASS=X, * spool // MSGLEVEL=(1,1), * log completo // NOTIFY=&SYSUID * avisa ao terminar
JOB card de produção
//PRDCALFO JOB (PRDACCT,FOLHAPAG),'FOLHA PAGAMENTO', // CLASS=P, * alta prioridade // MSGCLASS=A, * imprime log // MSGLEVEL=(0,0), * log minimo // REGION=256M, * memoria maxima // TIME=(30,0) * max 30 min de CPU
JOB card com TYPRUN=SCAN para validar
//VALJOB JOB ACCT001,'TESTE DE SINTAXE', // CLASS=A,MSGCLASS=X, // MSGLEVEL=(1,1), // TYPRUN=SCAN
🟣 RESTART — retomando um job com falha
Se um job de produção falhar no STEP03 (após STEP01 e STEP02 terem rodado com sucesso), você pode reiniciá-lo a partir do STEP03 sem reprocessar os passos anteriores:
RESTART=STEP03
Mas cuidado: os datasets de saída criados nos passos anteriores ainda existem. Se o STEP03 tentar criar o mesmo dataset, vai dar erro de "dataset already exists". Nesse caso, você precisa deletar os datasets intermediários antes de reiniciar — ou usar DISP=(MOD,...) no lugar de DISP=(NEW,...).