Est. 1964 Advanced

JCL (Job Control Language)

The scripting language that tells IBM mainframe operating systems which programs to run, in what order, and with which data sets and devices — the connective tissue of batch processing since the System/360 era.

Created by IBM (developed for the System/360 and OS/360)

Paradigm Procedural: declarative job/step control statements interpreted in sequence by the operating system and its job entry subsystem
Typing Not a typed general-purpose language; JCL describes jobs, steps, and data sets through positional and keyword parameters rather than typed values
First Appeared 1964 (announced with System/360; OS/360 and its JCL became generally available around 1966)
Latest Version No independent version; JCL evolves with its host operating systems — most notably z/OS, whose 3.1 release reached general availability on 29 September 2023, and z/VSE

Job Control Language (JCL) is the scripting language used to submit and control batch work on IBM mainframe operating systems. Rather than computing answers itself, JCL tells the operating system what to do: which program or procedure to run, in what sequence, where to find the input data, where to put the output, and which devices and resources each step requires. A JCL “job” is a unit of batch work made up of one or more steps, and for nearly six decades it has been the way enterprises stitch together COBOL, PL/I, Assembler, sort utilities, and database programs into the overnight and scheduled processing cycles that still run much of the world’s banking, insurance, and government infrastructure. It first appeared in 1964 with IBM’s OS/360 and survives, remarkably compatible with its origins, in today’s z/OS.

History & Origins

When IBM announced the System/360 in 1964, it promised a single, compatible family of computers spanning a wide range of sizes and prices. The operating system meant to unify them, OS/360, was one of the most ambitious software projects of its time — and one of the most troubled, immortalized in Fred Brooks’s The Mythical Man-Month. OS/360 was fundamentally a batch system: programs were submitted as decks of punched cards, queued, and run without interactive supervision. JCL was the language that described those submissions to the machine.

Because the System/360 was offered in radically different configurations, two JCL dialects emerged. OS/360 JCL, intended for larger systems, leaned on keyword parameters and offered a notable degree of device independence — a programmer could ask for UNIT=TAPE or UNIT=DISK and let the system pick a specific device. DOS/360 JCL, for smaller machines, used terser positional parameters that were harder for humans to read and write but easier for a constrained system to parse. That trade-off was deliberate and revealing of the era: in the mid-1960s, computer time was vastly more expensive than programmer time, so JCL was designed to be cheap for the machine to process rather than pleasant for people to write.

The two lineages persist to this day. OS/360 grew into OS/VS, then MVS, then OS/390, and finally z/OS. DOS/360 became DOS/VS, VSE/ESA, and today z/VSE. Each generation preserved backward compatibility, which is why JCL written for OS/360 in the 1960s is still broadly recognizable — and often still runnable — on a modern mainframe.

Design Philosophy

JCL is not a general-purpose programming language, and trying to use it as one exposes its rough edges. Its design reflects a handful of priorities specific to 1960s batch computing:

  • Describe the job, don’t compute it. JCL’s role is job control — declaring steps, data sets, and resources — not arithmetic or business logic, which lives in the programs JCL invokes.
  • Tell the system everything in advance. Because batch jobs ran unattended, JCL had to specify, up front, what to do at every branch: how much storage and time a step may use, what to do if a prior step fails, and how to dispose of each data set whether the step succeeds or not.
  • Machine-efficiency over human-readability. JCL’s terse syntax, its reliance on punched-card column conventions, and its positional parameters all favor easy parsing on small, slow hardware.
  • Backward compatibility above all. Decades of business-critical jobs depend on JCL behaving exactly as it always has, so the language has changed cautiously and additively.

This pragmatism came at a cost in usability. Fred Brooks, who managed the System/360 effort, later called JCL “the worst computer programming language ever devised by anybody, anywhere,” precisely because it was created without the discipline of treating it as a real language. Generations of programmers have shared the sentiment — and used it anyway, every day.

Key Features

The three core statements

OS-style JCL is built around three statement types, each beginning in the first columns with //:

StatementPurpose
JOBMarks the start of a job; carries accounting/billing information, run priority, and limits on time and space.
EXECIdentifies the program or procedure to run as a step, along with parameters and condition logic.
DD(Data Definition) Connects a file name used by the program to an actual data set, device, or in-stream data.

A minimal job might look like this:

//PAYROLL  JOB (ACCT123),'MONTHLY RUN',CLASS=A,MSGCLASS=X
//STEP01   EXEC PGM=PAYCALC
//INPUT    DD   DSN=PROD.PAYROLL.MASTER,DISP=SHR
//OUTPUT   DD   DSN=PROD.PAYROLL.REPORT,DISP=(NEW,CATLG,DELETE),
//              SPACE=(TRK,(10,5)),UNIT=SYSDA
//SYSOUT   DD   SYSOUT=*

Here a single step runs the program PAYCALC, reads an existing data set, writes a new one (cataloging it on success, deleting it on failure), and routes system messages to the printer/spool.

Data sets and DISP

The DD statement’s DISP (disposition) parameter captures JCL’s “say everything” philosophy in miniature: it declares the data set’s status at the start of the step (NEW, OLD, SHR, MOD) and what to do with it both when the step ends normally and when it abends — for example DISP=(NEW,CATLG,DELETE).

Procedures and symbolic parameters

To avoid rewriting common job structures, JCL supports procedures (PROCs). A cataloged procedure is stored in a procedure library (PROCLIB) and reused by name; an in-stream procedure is defined inline between PROC and PEND statements. Symbolic parameters, written with a leading ampersand (&DATE, &SYSUID), let a caller substitute values into a procedure at submission time, giving JCL a limited but heavily used form of parameterization.

Conditional execution

Steps can be guarded by condition codes returned by earlier steps — historically via the COND parameter and, in modern JCL, the more readable IF/THEN/ELSE/ENDIF construct — so that, say, a database-update step runs only if the validation step finished with a return code of zero.

The job entry subsystem

JCL does not run in a vacuum. On z/OS, a job entry subsystem — either JES2 or JES3 — reads the JCL, queues the job, manages its spooled input and output (SYSIN/SYSOUT), schedules it for execution, and handles printing. Much of what JCL expresses is ultimately instructions to JES.

Evolution

JCL’s evolution is best understood as the evolution of its host systems, because the language itself changes slowly and additively to protect existing workloads:

  • OS/360 → OS/VS → MVS (1974): Virtual storage and the JES2/JES3 subsystems matured around a stable JCL syntax.
  • MVS → OS/390 (1996) → z/OS (2000): The platform went 64-bit and absorbed networking, security, and Unix services (z/OS UNIX), while JCL gained quality-of-life additions such as IF/THEN/ELSE conditional execution, the INCLUDE statement for sharing common JCL fragments, and SET for defining symbolics.
  • DOS/360 → VSE/ESA → z/VSE (2005): The smaller-system lineage kept its more positional JCL style.
  • z/OS 3.1 (2023): The current release line continues to run JCL job streams while layering in modern capabilities, reportedly including AI-assisted operational features — a striking illustration of how durable the original design has proven.

Throughout, the guiding rule has been that old JCL should keep working. New keywords and statements are added; old ones are essentially never taken away.

Current Relevance

JCL is far from a museum piece. Mainframes still process a large share of the world’s high-volume transaction and batch workloads, and essentially all of that batch processing is launched and controlled by JCL. Enterprise schedulers — IBM Workload Scheduler, BMC Control-M, Broadcom CA-7 — orchestrate vast networks of interdependent JCL jobs, and skilled JCL practitioners remain in demand precisely because so much critical code depends on it and so few newcomers learn it.

For learners and hobbyists without access to commercial hardware, the Hercules open-source emulator can run the public-domain MVS 3.8j system, providing an authentic environment in which to write and submit real JCL. (Production z/OS and z/VSE remain proprietary IBM systems, so this page lists no official Docker image.) IBM’s own Master the Mainframe / Z education programs and the Open Mainframe Project have also worked to keep JCL skills alive among a new generation.

Why It Matters

JCL matters because it is the connective tissue of a computing tradition that never went away. It predates most modern programming languages, yet it still launches the batch jobs behind ATMs, paychecks, insurance policies, and tax returns. As a piece of language history it is instructive in the opposite direction from most: where later languages prize expressiveness and programmer comfort, JCL is a candid artifact of a time when the machine’s convenience came first — a design choice so consequential that it shaped how an entire industry thinks about “jobs,” “steps,” and “data sets” to this day. Loved by few and cursed by many, JCL endures as one of computing’s most quietly indispensable languages.

Timeline

1964
IBM announces the System/360 family of computers; its flagship batch operating system, OS/360, introduces Job Control Language as the means of describing batch work to the system
1966
OS/360 and DOS/360 reach general availability after a famously difficult development effort; two distinct JCL dialects emerge — OS/360 JCL, built around keyword parameters and device independence, and the more positional, hardware-specific DOS/360 JCL
1972
OS/VS1 and OS/VS2 bring virtual storage to the System/370 line, carrying JCL forward largely unchanged and cementing its backward-compatible design
1974
MVS (Multiple Virtual Storage) becomes the high-end successor to OS/360; its job entry subsystems, JES2 and JES3, handle the spooling, scheduling, and reading of JCL job streams
1990
IBM introduces the System/390 architecture and, in 1996, repackages MVS as OS/390, bundling JCL-driven batch processing with the broader operating-system stack
2000
z/OS debuts as the 64-bit successor to OS/390 on the IBM eServer zSeries; JCL remains the standard way to submit batch jobs, still recognizably compatible with OS/360-era statements
2005
z/VSE replaces VSE/ESA as the modern descendant of DOS/360, continuing the positional DOS-style JCL lineage on smaller mainframe installations
2023
z/OS 3.1 reaches general availability on 29 September, carrying JCL into a contemporary, increasingly AI-augmented mainframe operating system nearly six decades after its introduction

Notable Uses & Legacy

Banking and core financial processing

Banks and payment processors run overnight batch cycles — interest accrual, statement generation, settlement, reconciliation — as JCL job streams that chain together COBOL and PL/I programs, sort utilities, and database steps on z/OS.

Insurance and actuarial batch

Insurers use JCL to orchestrate policy administration, premium billing, and claims-processing runs, where each step's success or failure (via condition codes) governs whether subsequent steps execute.

Government and public-sector systems

Tax agencies, social-security systems, and other large public institutions schedule recurring data-processing jobs through JCL, often against decades-old application code still resident on the mainframe.

Data management with system utilities

JCL drives IBM utility programs such as IDCAMS (VSAM and catalog management), IEBGENER (copy/print), SORT/DFSORT, and the famous do-nothing IEFBR14, defining the data sets they read and write through DD statements.

Enterprise job scheduling

Schedulers such as IBM Workload Scheduler, BMC Control-M, and CA-7 submit and manage thousands of JCL jobs daily, making JCL the unit of work that automated batch operations are built around.

Language Influence

Influenced By

IBSYS

Influenced

z/VSE JCL

Running Today

Run examples using the official Docker image:

docker pull
Last updated: