JCL: The JOB Statement
Learn the syntax of the JOB card in detail: accounting information, the CLASS and MSGCLASS parameters, NOTIFY, and how to read a fully labeled JOB statement.
Introduction
Every JCL job stream begins with exactly one JOB statement, often called the "JOB card" — a term left over from the punch card era, still used constantly today. This single statement establishes the identity of the entire job: who owns it, how it should be billed, how important it is relative to other work, and where its messages should end up. Get comfortable reading and writing it, because everything else in a job stream sits underneath it.
The Job Statement's Job
The JOB statement does not run a program and does not reference any application data directly — that is the responsibility of the EXEC and DD statements you will study in the next two lessons. Instead, the JOB statement answers questions that apply to the entire job as a whole: what is this job called, who is responsible for it, how should the organization's accounting system bill for the resources it consumes, what scheduling priority (class) should it receive, and how much diagnostic output should it produce.
If the rest of a job stream is about what to do, the JOB statement is about the job itself as an accountable unit of work: identity, ownership, billing, and priority. Nothing about the actual processing logic belongs on the JOB card.
Anatomy of the JOB Card
A JOB statement has a fixed shape: the job name, the literal word JOB, then a set of positional and keyword parameters.
//jobname JOB (accounting-info),'programmer-name',// CLASS=class,MSGCLASS=class,MSGLEVEL=(1,1),// NOTIFY=&SYSUID| Part | Meaning |
|---|---|
| jobname | A 1-8 character name identifying the job, often coded with a naming convention (e.g. a userid prefix) required by the shop |
| (accounting-info) | A positional parameter, typically an account number used to bill the resources the job consumes |
| 'programmer-name' | A positional parameter naming the person or team responsible for the job, shown in job output listings |
| CLASS= | A keyword parameter selecting the job class, which influences scheduling priority and resource limits |
| MSGCLASS= | A keyword parameter selecting where the job's system messages (the JES log) are routed |
| MSGLEVEL= | A keyword parameter controlling how much JCL statement and message detail appears in the output |
| NOTIFY= | A keyword parameter identifying a TSO userid to receive a completion notification |
Accounting Information
The first positional parameter on a JOB statement is typically accounting information — most often an account number, and sometimes additional sub-fields depending on the shop's standards (room number, department code, and so on). z/OS itself does not interpret this information for scheduling purposes; it exists so the mainframe's system management facilities can attribute CPU time, I/O, and other resource usage back to the correct cost center. In large organizations running thousands of jobs a day across many departments, this is how the bill for shared mainframe capacity gets divided fairly.
The exact format and required content of the accounting field is defined locally by each installation, sometimes enforced strictly through the job entry subsystem's exit routines. Always check local standards documentation rather than assuming a format from a different shop or from a training exercise will be accepted.
CLASS: Where This Job Runs
CLASS assigns a job to one of a set of job classes (typically single letters or digits, such as A, B, or 9) that the installation has defined with specific characteristics: how many jobs in that class may run concurrently, what priority they receive relative to other classes, and sometimes resource limits like maximum CPU time. A shop might, for example, reserve class A for short, high-priority jobs and route long-running batch cycles to a different class with looser time limits but lower priority, so that quick jobs are not stuck waiting behind hours-long ones.
As a learner, the specific letter or number assigned to a class carries no universal meaning — CLASS=A means something different at every installation. What matters is understanding that CLASS exists to let an installation manage competing demands for shared processor and initiator resources.
MSGCLASS and MSGLEVEL
MSGCLASS controls where the job's SYSOUT output — system messages, the JES job log, and any SYSOUT datasets not otherwise redirected — is routed, again using an installation-defined single character (commonly things like A for a printer-bound class, or X for output intended to be browsed online through SDSF). MSGLEVEL controls how much detail is captured: the first value controls whether JCL statements themselves are included in the output, and the second controls whether allocation and termination messages are included.
MSGLEVEL=(1,1) -> Include JCL statements AND allocation/termination messages (most common for troubleshooting)MSGLEVEL=(0,0) -> Minimal output: no JCL echo, no allocation messagesMSGLEVEL=(1,0) -> Show JCL statements, but suppress allocation messagesOther Common Parameters
Beyond accounting, CLASS, and MSGCLASS, a handful of other JOB statement parameters show up constantly in real-world job streams.
| Parameter | Purpose |
|---|---|
| NOTIFY=&SYSUID | Sends a TSO message to the submitting user (using the built-in &SYSUID symbol for "my own userid") when the job completes |
| TIME=(m,s) | Sets a CPU time limit for the job; the job is cancelled if it runs longer, protecting the system from runaway work |
| REGION=nnnnK | Requests a virtual storage region size for the job's address space |
| TYPRUN=SCAN | Requests a JCL syntax check only, without actually executing the job — useful for validating new JCL safely |
A Fully Labeled Example
//PAYRJ010 JOB (ACCT77,DEPT4),'M PATEL',// CLASS=B,// MSGCLASS=X,// MSGLEVEL=(1,1),// NOTIFY=&SYSUID,// TIME=(0,30)Click Run to see what this code prints.
Common Mistakes
- Assuming CLASS or MSGCLASS values are universal — they are locally defined per installation and mean nothing consistent across different shops.
- Forgetting the comma after each parameter that is continued to the next line, which breaks the statement.
- Omitting NOTIFY and then having no easy way to find out a submitted job has completed or failed without manually checking the job queue.
- Setting an unrealistically low TIME= limit out of habit and having otherwise-healthy long-running jobs cancelled prematurely.
Best Practices
- Always include NOTIFY=&SYSUID on jobs you submit interactively, so you are told immediately when they finish.
- Learn your specific shop's CLASS and MSGCLASS standards early — they are documented locally and enforced by real scheduling behavior.
- Use MSGLEVEL=(1,1) while learning or troubleshooting, since it gives you the most diagnostic detail; production jobs may use leaner settings once proven stable.
- Consider TYPRUN=SCAN when testing unfamiliar or heavily modified JCL, to validate syntax before actually consuming execution resources.
Frequently Asked Questions
No. Exactly one JOB statement appears at the top of a single job stream. If you need to submit another unit of work, it is a separate job with its own JOB statement, even if submitted from the same JCL member or PDS.
It is a system symbol that automatically resolves to the userid of whoever submitted the job, so you do not have to hardcode your own userid into every JOB card you write.
This is usually related to CLASS — if the job class you are using already has its maximum number of concurrently executing jobs (its initiators) busy, your job waits until one frees up, based on relative priority.
In most shops, yes, in some form — it is how resource usage gets billed internally. The exact required format is defined locally, so check your installation's standards rather than guessing.
Key Takeaways
- The JOB statement establishes job-level identity, accounting, scheduling class, and message routing — never processing logic.
- CLASS controls scheduling priority and concurrency limits, and its meaning is defined locally by each installation.
- MSGCLASS routes system output, while MSGLEVEL controls how much JCL and allocation detail appears in that output.
- NOTIFY=&SYSUID is a small but extremely useful habit for knowing when your submitted jobs finish.
- Every job stream has exactly one JOB statement, positioned first.
Summary
The JOB statement is the identity card for an entire job stream: who it belongs to, how it is billed, how it is prioritized, and where its output goes. With that foundation in place, the next lesson moves to the statement that actually decides what runs: the EXEC statement, and the important distinction between running a program directly and calling a reusable procedure.