Recent from talks
Contribute something
Nothing was collected or created yet.
Job Control Language
View on WikipediaJob Control Language (JCL) is a programming language for scripting and launching batch jobs on IBM mainframe computers.[1] JCL code determines which programs to run, and with which files and devices for input and output.[2] Parameters in the JCL can also provide accounting information for tracking the resources used by a job and can set which machine the job should run on.
There are two major variants based on host platform and associated lineage. One version is available on the platform lineage that starts with DOS/360 and has progressed to z/VSE. The other version starts with OS/360 and continues to z/OS which includes JES extensions, Job Entry Control Language (JECL). The variants share basic syntax and concepts but have significant differences.[3] The VM operating system does not have JCL as such; the CP and CMS components each have command languages.
Generically, a job control language is any programming language for job control; not just the IBM mainframe one.[4]
Terminology
[edit]JCL-specific terminology includes:
- Data set
A file; either temporary or permanent; located on a disk drive, tape storage, or other device.[5][6]
- Partitioned data set (PDS)
A collection of files; commonly used to store textual data such as source code, assembler macros (SYS1.MACLIB), system configuration (SYS1.PARMLIB), reusable JCL procedures (SYS1.PROCLIB), etc. As a collection of files, a PDS is like to an archive file (ZIP, TAR, etc.) which in turn is like a file system directory. A PDS can contain executable code (load modules or program objects) which makes a PDS like a Unix-based static library. A member, once stored, cannot be updated although a member can be deleted and replaced, such as via the IEBUPDTE utility.[7] Since the 1989 release of MVS DFP 3.2, an enhanced version, partitioned data set extended (PDSE) has been available.[8]
- Member
A file (data set) in a PDS. A member can be accessed by specifying the name of the PDS with the member name in parentheses. For example, the system macro GETMAIN in SYS1.MACLIB can be referenced as SYS1.MACLIB(GETMAIN).[7]
- Unix system services (USS)
A complete Unix environment running as part of the MVS base control program. It allows Unix files, scripts, tasks, and programs to run on a mainframe in a POSIX-compliant Unix environment without virtualization.
Motivation
[edit]Originally, mainframe systems were oriented toward batch processing. Many batch jobs require setup, with specific requirements for main storage, and dedicated devices such as magnetic tapes, private disk volumes, and printers set up with special forms.[9] JCL was developed as a means of ensuring that all required resources are available before a job is scheduled to run. For example, many systems, such as Linux allow identification of required datasets to be specified on the command line, and therefore subject to substitution by the shell, or generated by the program at run-time.
On these systems the operating system job scheduler has little or no idea of the requirements of the job. In contrast, JCL explicitly specifies all required datasets and devices. The scheduler can pre-allocate the resources prior to releasing the job to run. This helps to avoid "deadlock", where job A holds resource R1 and requests resource R2, while concurrently running job B holds resource R2 and requests R1. In such cases the only solution is for the computer operator to terminate one of the jobs, which then needs to be restarted. With job control, if job A is scheduled to run, job B will not be started until job A completes or releases the required resources.
Features common to DOS and OS JCL
[edit]Jobs, steps and procedures
[edit]For both DOS and OS the unit of work is the job. A job consists of one or several steps, each of which is a request to run one specific program. For example, before the days of relational databases, a job to produce a printed report for management might consist of the following steps: a user-written program to select the appropriate records and copy them to a temporary file; sort the temporary file into the required order, usually using a general-purpose utility; a user-written program to present the information in a way that is easy for the end-users to read and includes other useful information such as sub-totals; and a user-written program to format selected pages of the end-user information for display on a monitor or terminal.
In both DOS and OS JCL the first "card" must be the JOB card, which:[10]
- Identifies the job.
- Usually provides information to enable the computer services department to bill the appropriate user department.
- Defines how the job as a whole is to be run, e.g. its priority relative to other jobs in the queue.
Procedures (commonly called procs) are pre-written JCL for steps or groups of steps, inserted into a job. Both JCLs allow such procedures. Procs are used for repeating steps which are used several times in one job, or in several different jobs. They save programmer time and reduce the risk of errors. To run a procedure one simply includes in the JCL file a single "card" which copies the procedure from a specified file, and inserts it into the jobstream. Also, procs can include parameters to customize the procedure for each use.
Basic syntax
[edit]Both DOS and OS JCL have a maximum usable line length of 80 characters, because when DOS/360 and OS/360 were first used the main method of providing new input to a computer system was 80-column punched cards.[11] It later became possible to submit jobs via disk or tape files with longer record lengths, but the operating system's job submission components ignored everything after character 80.
Strictly speaking both operating system families use only 71 characters per line. Characters 73-80 are usually card sequence numbers which the system printed on the end-of-job report and are useful for identifying the locations of any errors reported by the operating system. Character 72 is usually left blank, but it can contain a nonblank character to indicate that the JCL statement is continued onto the next card.
All commands, parameter names and values have to be in capitals, except for USS filenames.
All lines except for in-stream input (see below) have to begin with a slash "/", and all lines which the operating system processes have to begin with two slashes // - always starting in the first column. However, there are two exceptions: the delimiter statement and the comment statement. A delimiter statements begins with a slash and an asterisk (/*), and a comment statement in OS JCL begins with a pair of slashes and asterisk (//*) or an asterisk in DOS JCL.
Many JCL statements are too long to fit within 71 characters, but can be extended on to an indefinite number of continuation cards by:
| OS JCL | DOS JCL |
|---|---|
Ending all actual JCL cards except the last at a point where the syntax requires a comma (,) |
Ending all actual JCL cards except the last at a point where the syntax requires a comma (,) and a non-blank character in column 72
|
Starting each continuation card with // in column 1 and then at least 1 space |
Starting each continuation card with spaces and continuing in column 15 |
The structure of the most common types of card is:[12]
| OS JCL | DOS JCL |
|---|---|
|
|
In-stream input
[edit]DOS and OS JCL both allow in-stream input, i.e. "cards" which are to be processed by the application program rather than the operating system. Data which is to be kept for a long time will normally be stored on disk, but before the use of interactive terminals became common the only way to create and edit such disk files was by supplying the new data on cards.
DOS and OS JCL have different ways of signaling the start of in-stream input, but both end in-stream input with /* at column 1 of the card following the last in-stream data card. This makes the operating system resume processing JCL in the card following the /* card.[13]
- OS JCL: DD statements can be used to describe in-stream data, as well as data sets. A DD statement dealing with in-stream data has an asterisk (*) following the DD identifier, e.g.
//SYSIN DD *. JCL statements can be included as part of in-stream data by using the DD DATA statements.
- An operand named DLM allowed specifying a delimiter (default is "/*"). Specifying an alternate delimiter allows JCL to be read as data, for example to copy procedures to a library member or to submit a job to the internal reader.
- An example,[14] which submits a job to the Internal Reader (INTRDR) and then deletes two files is:
//SUBM EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=Z
//SYSUT2 DD SYSOUT=(A,INTRDR)
//SYSIN DD DUMMY
//SYSUT1 DD DATA,DLM=ZZ
//RUNLATR JOB ACCT,MANIX,CLASS=A.TYPRUN=HOLD
//* ^ a JOB to run later
//CPUHOG EXEC PGM=PICALC1K
//OUTPUT DD DSN=PICALC.1000DGTS,SPACE=(TRK,1),DISP=(,KEEP)
ZZ
//* ^ as specified by DLM=ZZ
//DROPOLDR EXEC PGM=IEFBR14
//DELETE4 DD DSN=PICALC.4DGTS,DISP=(OLD,DELETE)
//DELETE5 DD DSN=PICALC.5DGTS,DISP=(OLD,DELETE)
- The program called PICALC1K will await (TYPRUN=HOLD) being released manually
- The program called IEFBR14 will run NOW and upon completion, the two existing files, PICALC.4DGTS and PICALC.5DGTS will be deleted.
- DOS JCL: Simply enter the in-stream data after the EXEC card for the program.
Complexity
[edit]Fred Brooks, who supervised the OS/360 project in which JCL was created, called it "the worst computer programming language ever devised by anybody, anywhere" in The Design of Design, where he used it as the example in the chapter "How Expert Designers Go Wrong".[15] He attributed this to the failure of the designers to realize that JCL is, in fact, a programming language.
Much of the complexity of OS JCL, in particular, derives from the large number of options for specifying dataset information. While files on Unix-like operating systems are abstracted into ordered streams of bytes, with the task of reading and writing structured data belonging exclusively with user-level programs (which, ultimately, ingest and emit such streams), and the practical details of data storage and access handled in large part by the operating system without the knowledge of user programs; datasets on OS/360 and its successors expose their file types and sizes, record types and lengths, block sizes, device-specific information like magnetic tape density, and label information. Although there are system defaults for many options, there is still a lot to be specified by the programmer, through a combination of JCL and information coded in the program. The more information coded in the program, the less flexible it is, since information in the program overrides anything in the JCL; thus, most information is usually supplied through JCL.
For example, to copy a file on Unix operating system, the user would enter a command like:
cp oldFile newFile
The following example, using JCL, might be used to copy a file on OS/360:
//IS198CPY JOB (IS198T30500),'COPY JOB',CLASS=L,MSGCLASS=X
//COPY01 EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DSN=OLDFILE,DISP=SHR
//SYSUT2 DD DSN=NEWFILE,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(40,5),RLSE),
// DCB=(LRECL=115,BLKSIZE=1150)
//SYSIN DD DUMMY
A second explanation for the complexity of JCL is the different expectations for running a job from those found in a PC or Unix-like environment.
- Low-end System/360 CPUs were less powerful and more expensive than the mid-1980s PCs for which MS-DOS was designed. OS/360 was intended for systems with a minimum memory size of 32 KB and DOS/360 for systems with a minimum of 16 KB. A 360/30 CPU—low-end when System/360 was announced in 1964—processed 1.8K to 34.5K instructions per second.[16] The first IBM PC in 1981 had 16 KB or 64 KB of memory and would process about 330K instructions per second.[17][18] As a result, JCL had to be easy for the computer to process, and ease of use by programmers was a much lower priority. In this era, programmers were much cheaper than computers.
- JCL was designed for batch processing. As such, it has to tell the operating system everything, including what to do depending on the result of a step. For example,
DISP=(NEW,CATLG,DELETE)means "if the program runs successfully, create a new file and catalog it; otherwise delete the new file." Programs run on a PC frequently depend on the user to clean up after processing problems. - System/360 machines were designed to be shared by all the users in an organization. So the
JOBcard tells the operating system how to bill the user's account (IS198T30500), what predefined amount of storage and other resources may be allocated (CLASS=L), and several other things.//SYSPRINT DD SYSOUT=*tells the computer to print the program's report on the default printer which is loaded with ordinary paper, not on some other printer which might be loaded with blank checks.DISP=SHRtells the operating system that other programs can readOLDFILEat the same time.
Later versions of the DOS/360 and OS/360 operating systems retain most features of the original JCL—although some simplification has been made, to avoid forcing customers to rewrite all their JCL files.[citation needed] Many users save as a procedure any set of JCL statements which is likely to be used more than once or twice.[19]
The syntax of OS JCL is similar to the syntax of macros in System/360 assembly language, and would therefore have been familiar to programmers at a time when many programs were coded in assembly language.
DOS JCL
[edit]Positional parameters
[edit]//TLBL TAPEFIL,'COPYTAPE.JOB',,,,2
//ASSGN SYS005,200
//DLBL DISKFIL,'COPYTAPE.JOB',0,SD
//EXTENT SYS005,VOL01,1,0,800,1600
DOS JCL parameters are positional, which makes them harder to read and write, but easier for the system to parse.
- The programmer must remember which item goes in which position in every type of statement.
- If some optional parameters are omitted but later ones are included, the omitted parameters must be represented by commas with no spaces, as in the TLBL statement above.
DOS JCL to some extent mitigates the difficulties of positional parameters by using more statements with fewer parameters than OS JCL. In the example the ASSGN, DLBL and EXTENT statements do the same work (specifying where a new disk file should be stored) as a single DD statement in OS JCL.
Device dependence
[edit]In the original DOS/360 and in most versions of DOS/VS one had to specify the model number of the device which was to be used for each disk or tape file—even for existing files and for temporary files which would be deleted at the end of the job. This meant that, if a customer upgraded to more modern equipment, many JCL files had to be changed.
Later members of the DOS/360 family reduced the number of situations in which device model numbers were required.
Manual file allocation
[edit]DOS/360 originally required the programmer to specify the location and size of all files on DASD. The EXTENT card specifies the volume on which the extent resides, the starting absolute track, and the number of tracks. For z/VSE a file can have up to 256 extents on different volumes.
OS JCL
[edit]OS JCL consists of three basic statement types:[20]
JOBstatement, which identifies the start of the job, and information about the whole job, such as billing, run priority, and time and space limits.EXECstatement, which identifies the program or procedure[21] to be executed in this step of the job,
and information about the step, including CONDitions for running or skipping a step.DD(Data Definition) statements, which identify a data file to be used in a step, and detailed info about that file.DDstatements can be in any order within the step.
Right from the start, JCL for the OS family (up to and including z/OS) was more flexible and easier to use.
The following examples use the old style of syntax which was provided right from the launch of System/360 in 1964. The old syntax is still quite common in jobs that have been running for decades with only minor changes.
Rules for coding JCL statements
[edit]Each JCL statement is divided into five fields:[22]
Identifier-Field Name-Field Operation-Field Parameter-Field Comments-Field
^ ^ ^ ^
no space space space space
Identifier-Field should be concatenated with Name-Field, i.e. there should be no spaces between them.
- Identifier-Field (
//): The identifier field indicates to the system that a statement is a JCL statement rather than data. The identifier field consists of the following:- Columns 1 and 2 of all JCL statements, except the delimiter statement, contain
// - Columns 1 and 2 of the delimiter statement contain
/* - Columns 1, 2, and 3 of a JCL comment statement contain
//*
- Columns 1 and 2 of all JCL statements, except the delimiter statement, contain
- Name-Field: The name field identifies a particular statement so that other statements and the system can refer to it. For JCL statements, it should be coded as follows:
- The name must begin in column 3.
- The name is 1 through 8 alphanumeric or national (
$,#,@) characters. - The first character must be an alphabetic.
- The name must be followed by at least one blank.
- Operation-Field: The operation field specifies the type of statement, or, for the command statement, the command. Operation-Field should be coded as follows:
- The operation field consists of the characters in the syntax box for the statement.
- The operation follows the name field.
- The operation must be preceded and followed by at least one blank.
- The operation will be one of
JOB,EXECandDD.
- Parameter-Field: The parameter field, also sometimes referred to as the operand field, contains parameters separated by commas. Parameter field should be coded as follows:
- The parameter field follows the operation field.
- The parameter field must be preceded by at least one blank.
- The parameter field contains parameters which are keywords that used in the statement to provide information such as the program or dataset name.
- Comments-Field: This contains comments. Comments-Field should be coded as Follows:
- The comments field follows the parameter field.
- The comments field must be preceded by at least one blank.
Keyword parameters
[edit]//NEWFILE DD DSN=MYFILE01,UNIT=DISK,SPACE=(TRK,80,10),
// DCB=(LRECL=100,BLKSIZE=1000),
// DISP=(NEW,CATLG,DELETE)
All of the major parameters of OS JCL statements are identified by keywords and can be presented in any order. A few of these contain two or more sub-parameters, such as SPACE (how much disk space to allocate to a new file) and DCB (detailed specification of a file's layout) in the example above. Sub-parameters are sometimes positional, as in SPACE, but the most complex parameters, such as DCB, have keyword sub-parameters.
Positional parameter must precede keyword parameters. Keyword parameters always assign values to a keyword using the equals sign (=).[23]
Data access (DD statement)
[edit]The DD statement is used to reference data. This statement links a program's internal description of a dataset to the data on external devices: disks, tapes, cards, printers, etc. The DD may provide information such as a device type (e.g. '181','2400-5','TAPE'), a volume serial number for tapes or disks, and the description of the data file, called the DCB subparameter after the Data Control Block (DCB) in the program used to identify the file.
Information describing the file can come from three sources: The DD card information, the dataset label information for an existing file stored on tape or disk, and the DCB macro coded in the program. When the file is opened this data is merged, with the DD information taking precedence over the label information, and the DCB information taking precedence over both. The updated description is then written back to the dataset label. This can lead to unintended consequences if incorrect DCB information is provided.[24]
Because of the parameters listed above and specific information for various access methods and devices the DD statement is the most complex JCL statement. In one IBM reference manual description of the DD statement occupies over 130 pages—more than twice as much as the JOB and EXEC statements combined.[25]
The DD statement allows inline data to be injected into the job stream. This is useful for providing control information to utilities such as IDCAMS, SORT, etc. as well as providing input data to programs.
Device independence
[edit]From the very beginning, the JCL for the OS family of operating systems offered a high degree of device independence. Even for new files which were to be kept after the end of the job one could specify the device type in generic terms, e.g., UNIT=DISK, UNIT=TAPE, or UNIT=SYSSQ (tape or disk). Of course, if it mattered one could specify a model number or even a specific device address.[26]
Procedures
[edit]Procedures permit grouping one or more "EXEC PGM=" and DD statements and then invoking them with "EXEC PROC=procname" -or- simply "EXEC procname" [27]
A facility called a Procedure Library allowed pre-storing procedures.
PROC & PEND
[edit]Procedures can also be included in the job stream by terminating the procedure with a // PEND statement, then invoking it by name the same way as if it were in a procedure library.
For example:
//SUMPRINT PROC
//PRINT EXEC PGM=IEBGENER
//SYSUT1 DD DSN=CEO.FILES.DAYEND.RPT24A,DISP=SHR
//SYSUT2 DD SYSOUT=A
//SYSIN DD DUMMY
// PEND
// EXEC SUMPRINT
Parameterized procedures
[edit]OS JCL procedures were parameterized from the start, making them rather like macros or even simple subroutines and thus increasing their reusability in a wide range of situations.[28]
//MYPROC PROC FNAME=MYFILE01,SPTYPE=TRK,SPINIT=50,SPEXT=10,LR=100,BLK=1000
.....
//NEWFILE DD DSN=&FNAME,UNIT=DISK,SPACE=(&SPTYPE,&SPINIT,&SPEXT),
// DCB=(LRECL=&LR,BLKSIZE=&BLK),DISP=(NEW,CATLG,DELETE)
....
In this example, all the values beginning with ampersands "&" are parameters which will be specified when a job requests that the procedure be used. The PROC statement, in addition to giving the procedure a name, allows the programmer to specify default values for each parameter. So one could use the one procedure in this example to create new files of many different sizes and layouts. For example:
//JOB01 JOB ..........
//STEP01 EXEC MYPROC FNAME=JOESFILE,SPTYPE=CYL,SPINIT=10,SPEXT=2,LR=100,BLK=2000
or
//JOB02 JOB ..........
//STEP01 EXEC MYPROC FNAME=SUESFILE,SPTYPE=TRK,SPINIT=500,SPEXT=100,LR=100,BLK=5000
Referbacks
[edit]In multi-step jobs, a later step can use a referback instead of specifying in full a file which has already been specified in an earlier step. For example:
//MYPROC ................
//MYPR01 EXEC PGM=..........
//NEWFILE DD DSN=&MYFILE,UNIT=DISK,SPACE=(TRK,50,10),
// DCB=(LRECL=100,BLKSIZE=1000),DISP=(NEW,CATLG,DELETE)
....
//MYPR02 EXEC PGM=..........
//INPUT01 DD DSN=*.MYPR01.NEWFILE
Here, MYPR02 uses the file identified as NEWFILE in step MYPR01 (DSN means "dataset name" and specifies the name of the file; a DSN could not exceed 44 characters[29]).
In jobs which contain a mixture of job-specific JCL and procedure calls, a job-specific step can refer back to a file which was fully specified in a procedure, for example:
//MYJOB JOB ..........
//STEP01 EXEC MYPROC Using a procedure
//STEP02 EXEC PGM=......... Step which is specific to this job
//INPUT01 DD DSN=*.STEP01.MYPR01.NEWFILE
where DSN=*.STEP01.MYPR01.NEWFILE means "use the file identified as NEWFILE in step MYPR01 of the procedure used by step STEP01 of this job". Using the name of the step which called the procedure rather than the name of the procedure allows a programmer to use the same procedure several times in the same job without confusion about which instance of the procedure is used in the referback.
Comments
[edit]JCL files can be long and complex, and the language is not easy to read. OS JCL allows programmers to include two types of explanatory comment:
- On the same line as a JCL statement. They can be extended by placing a continuation character (conventionally "
X") in column 72, followed by "//" in columns 1–3 of the next line. - Lines which contain only comment, often used to explain major points about the overall structure of the JCL rather than local details. Comment-only lines are also used to divide long, complex JCL files into sections.
//MYJOB JOB ..........
//* Lines containing only comments.
//******** Often used to divide JCL listing into sections ********
//STEP01 EXEC MYPROC Comment 2 on same line as statement
//STEP02 EXEC PGM=......... Comment 3 has been extended and X
// overflows into another line.
//INPUT01 DD DSN=STEP01.MYPR01.NEWFILE
Concatenating input files
[edit]OS JCL allows programmers to concatenate ("chain") input files so that they appear to the program as one file, for example
//INPUT01 DD DSN=MYFILE01,DISP=SHR
// DD DSN=JOESFILE,DISP=SHR
// DD DSN=SUESFILE,DISP=SHR
The 2nd and third statements have no value in the name field, so OS treats them as concatenations. The files must be of the same basic type (almost always sequential), and must have the same record length, however the block length need not be the same.
In early versions of the OS (certainly before OS/360 R21.8) the block length must be in decreasing order, or the user must inspect each instance and append to the named DD statement the maximum block length found, as in, for example,
//INPUT01 DD DSN=MYFILE01,DISP=SHR,BLKSIZE=800
// DD DSN=JOESFILE,DISP=SHR (BLKSIZE assumed to be equal to or less than 800)
// DD DSN=SUESFILE,DISP=SHR (BLKSIZE assumed to be equal to or less than 800)
In later versions of the OS (certainly after OS/MVS R3.7 with the appropriate "selectable units") the OS itself, during allocation, would inspect each instance in a concatenation and would substitute the maximum block length which was found.
A usual fallback was to simply determine the maximum possible block length on the device, and specify that on the named DD statement, as in, for example,
//INPUT01 DD DSN=MYFILE01,DISP=SHR,BLKSIZE=8000
// DD DSN=JOESFILE,DISP=SHR (BLKSIZE assumed to be equal to or less than 8000)
// DD DSN=SUESFILE,DISP=SHR (BLKSIZE assumed to be equal to or less than 8000)
The purpose of this fallback was to ensure that the access method would allocate an input buffer set which was large enough to accommodate any and all of the specified datasets.
Conditional processing
[edit]OS expects programs to set a return code which specifies how successful the program thought it was. The most common conventional values are:[30]: p.87
- 0 = Normal - all OK
- 4 = Warning - minor errors or problems
- 8 = Error - significant errors or problems
- 12 = Severe error - major errors or problems, the results (e.g. files or reports produced) should not be trusted.
- 16 = Terminal error - very serious problems, do not use the results!
OS JCL refers to the return code as COND ("condition code"), and can use it to decide whether to run subsequent steps. However, unlike most modern programming languages, conditional steps in OS JCL are not executed if the specified condition is true—thus giving rise to the mnemonic, "If it's true, pass on through [without running the code]." To complicate matters further, the condition can only be specified after the step to which it refers. For example:
//MYJOB JOB ...........
//STEP01 EXEC PGM=PROG01
....
//STEP02 EXEC PGM=PROG02,COND=(4,GT,STEP01)
....
//STEP03 EXEC PGM=PROG03,COND=(8,LE)
....
//STEP04 EXEC PGM=PROG04,COND=(ONLY,STEP01)
....
//STEP05 EXEC PGM=PROG05,COND=(EVEN,STEP03)
....
means:
- Run
STEP01, and collect its return code. - Don't run
STEP02if the number 4 is greater thanSTEP01's return code. - Don't run
STEP03if the number 8 is less than or equal to any previous return code. - Run
STEP04only ifSTEP01abnormally ended. - Run
STEP05, even ifSTEP03abnormally ended.
This translates to the following pseudocode:
run STEP01
if STEP01's return code is greater than or equal to 4 then
run STEP02
end if
if any previous return code is less than 8 then
run STEP03
end if
if STEP01 abnormally ended then
run STEP04
end if
if STEP03 abnormally ended then
run STEP05
else
run STEP05
end if
Note that by reading the steps containing COND statements backwards, one can understand them fairly easily. This is an example of logical transposition.
However, IBM later introduced IF condition in JCL thereby making coding somewhat easier for programmers while retaining the COND parameter (to avoid making changes to the existing JCLs where COND parm is used).
The COND parameter may also be specified on the JOB statement. If so the system "performs the same return code tests for every step in a job. If a JOB statement return code test is satisfied, the job terminates."[31]
Utilities
[edit]Jobs use a number of IBM utility programs to assist in the processing of data. Utilities are most useful in batch processing. The utilities can be grouped into three sets:
- Data Set Utilities - Create, print, copy, move and delete data sets.
- System Utilities - Maintain and manage catalogs and other system information.
- Access Method Services - Process Virtual Storage Access Method (VSAM) and non-VSAM data sets.
Difficulty of use
[edit]OS JCL is undeniably complex[32] and has been described as "user hostile".[33][34] As one instructional book on JCL asked, "Why do even sophisticated programmers hesitate when it comes to Job Control Language?"[35] The book stated that many programmers either copied control cards without really understanding what they did, or "believed the prevalent rumors that JCL was horrible, and only 'die-hard' computer-types ever understood it" and handed the task of figuring out the JCL statements to someone else.[35] Such an attitude could be found in programming language textbooks, which preferred to focus on the language itself and not how programs in it were run. As one Fortran IV textbook said when listing possible error messages from the WATFOR compiler: "Have you been so foolish as to try to write your own 'DD' system control cards? Cease and desist forthwith; run, do not walk, for help."[36]
Nevertheless, some books that went into JCL in detail emphasized that once it was learned to an at least somewhat proficient degree, one gained freedom from installation-wide defaults and much better control over how an IBM system processed your workload.[35][32] Another book commented on the complexity but said, "take heart. The JCL capability you will gain from [the preceding chapter] is all that most programmers will ever need."[32]
Job Entry Control Language
[edit]On IBM mainframe systems Job Entry Control Language or JECL is the set of command language control statements that provide information for the spooling subsystem – JES2 or JES3 on z/OS or VSE/POWER for z/VSE. JECL statements may "specify on which network computer to run the job, when to run the job, and where to send the resulting output."[30]
JECL is distinct from job control language (JCL), which instructs the operating system how to run the job.
There are different versions of JECL for the three environments.
OS/360
[edit]An early version of Job Entry Control Language for OS/360 Remote Job Entry (Program Number 360S-RC-536) used the identifier .. in columns 1–2 of the input record and consisted of a single control statement: JED (Job Entry Definition). "Workstation Commands" such as LOGON, LOGOFF, and STATUS also began with .. .[37]
pre-JES JECL
[edit]Although the term had not yet been developed, HASP did have similar functionality to what would become the JECL of JES, including /* syntax.
z/OS
[edit]For JES2 JECL statements start with /*, for JES3 they start with //*, except for remote /*SIGNON and /*SIGNOFF commands. The commands for the two systems are completely different.
JES2 JECL
[edit]The following JES2 JECL statements are used in z/OS 1.2.0.[38]
| JECL statement | Function | Example |
|---|---|---|
/*$command |
Enters an operator (console) command | /*$S PRINTER3[39]
|
/*JOBPARM |
Specifies values for job-related parameters | /*JOBPARM TIME=10
|
/*MESSAGE |
Sends a message to the operator console | /*MESSAGE CALL JOE AT HOME IF JOB ABENDS
|
/*NETACCT |
Specifies account number for network job | /*NETACCT 12345
|
/*NOTIFY |
Specifies destination for notification messages | /*NOTIFY SAM
|
/*OUTPUT |
Specifies SYSOUT dataset options | /*OUTPUT FORMS=BILL
|
/*PRIORITY |
Sets job selection priority | /*PRIORITY 15
|
/*ROUTE |
Specifies output destination or execution node | /*ROUTE PRT RMT5
|
/*SETUP |
Requests volume mounting or other offline operation | /*SETUP TAPE01,TAPE02
|
/*SIGNOFF |
Ends remote session | /*SIGNOFF
|
/*SIGNON |
Begins remote session | /*SIGNON REMOTE5 password
|
/*XEQ |
Specifies execution node | /*XEQ DENVER
|
/*XMIT |
Indicates job or dataset to be transmitted to another network node | /*XMIT NYC
|
JES3 JECL
[edit]The following JES3 JECL statements are used in z/OS 1.2.0[40]
| JECL statement | Function | Example |
|---|---|---|
//**command |
Enters a JES3 operator (console) command | |
//*DATASET |
Marks the beginning of an in-stream dataset | |
//*ENDDATASET |
Marks the end of an in-stream dataset | |
//*ENDPROCESS |
Marks the end of a series of //*PROCESS statements |
|
//*FORMAT |
Specifies SYSOUT dataset options |
|
//*MAIN |
Specifies values for job-related parameters | |
//*NET |
Identifies relationships among jobs using JES3 dependent job control | |
//*NETACCT |
Specifies account number for network job | |
//*OPERATOR |
Sends a message to the operator console | |
//*PAUSE |
Stops the input reader | |
//*PROCESS |
Identifies a non-standard job | |
//*ROUTE |
Specifies the execution node for the job | |
/*SIGNOFF |
Ends remote session | /*SIGNOFF
|
/*SIGNON |
Begins remote session |
z/VSE
[edit]For VSE JECL statements start with '* $$' (note the single space). The Job Entry Control Language defines the start and end lines of JCL jobs. It advises VSE/POWER how this job is handled. JECL statements define the job name (used by VSE/POWER), the class in which the job is processed, and the disposition of the job (i.e. D, L, K, H).
| JECL statement[41] | Function | Example |
|---|---|---|
* $$ CTL |
Establishes a default input class | * $$ CTL CLASS=A
|
* $$ JOB |
Specifies attributes of a job | * $$ JOB JNM=PYRL,PRI=9
|
* $$ EOJ |
Marks the end of a job | * $$ EOJ
|
* $$ RDR |
Inserts a file from a 3540 diskette into the input stream | * $$ RDR SYS005,'fname',2
|
* $$ PRT |
Specifies characteristics of spooled print files "LST' is a synonym for "PRT" |
* $$ PRT FNO=STD,COPY=2
|
* $$ PUN |
Specifies characteristics of spooled punch files | * $$ PUN DISP=T,TADDR=280
|
* $$ SLI |
Inserts data ("book") from source statement library into the input stream | * $$ SLI A.JCL1
|
* $$ DATA |
Inserts data from the card reader into a book retrieved from the source statement library | * $$ DATA INPUT1
|
Example:
* $$ JOB JNM=NAME,DISP=K,CLASS=2
[some JCL statements here]
* $$ EOJ
Other systems
[edit]Other mainframe batch systems had some form of job control language, whether called that[4] or not; their syntax was completely different from IBM versions, but they usually provided similar capabilities. Such a language would have control cards with a special indicator, such as an initial dollar sign with $JOB being the first such card, interspersed with cards containing program code, data to be run, and so on.[4]
Interactive systems include "command languages"—command files (such as PCDOS ".bat" files) can be run non-interactively, but these usually do not provide as robust an environment for running unattended jobs as JCL. On some computer systems the job control language and the interactive command language may be different. For example, TSO on z/OS systems uses CLIST or Rexx as command languages along with JCL for batch work. On other systems these may be the same.
See also
[edit]- dd (Unix), Unix program inspired by
DD - IBM mainframe utility programs
- Batch processing
- Data set (IBM mainframe)#Generation Data Group
References
[edit]- ^ "Every job submitted for execution ... must include JCL statements" – ibm.com
- ^ and many more aspects such as whether the file is to be retained or deleted, the maximum disk space to which it can grow, the name of a tape to be pre-mounted, and indicate under what conditions to skip a step.
- ^ Ashley and Fernandez, Job Control Language, p. 1.
- ^ a b c Stallings, William (1996). Computer Organization and Architecture: Designing for Performance (Fourth ed.). Upper Saddle River, New Jersey: Prentice-Hall. p. 228. ISBN 0-13-359985-X.
- ^ Ashley and Fernandez, Job Control Language, p. 5.
- ^ McQuillen, System/360–370 Assembler Language, pp. 385–386.
- ^ a b McQuillen, System/360–370 Assembler Language, pp. 288–289, 400.
- ^ Lewis, Cecilia (August 8, 2011). "What We've Done for You Lately With PDSE" (PDF). SHARE in Orlando. Retrieved 2023-03-03.
- ^ McQuillen, System/360–370 Assembler Language, pp. 22–24.
- ^ McQuillen, System/360–370 Assembler Language, pp. 380–382.
- ^ Stern and Stern, Structured COBOL Programming, pp. 528–529.
- ^ Stern and Stern, Structured COBOL Programming, pp. 529, 531.
- ^ Stern and Stern, Structured COBOL Programming, pp. 529, 537.
- ^ modeled on https://www.ibm.com/support/knowledgecenter/SSLTBW_2.2.0/com.ibm.zos.v2r2.hasc300/has2z1_Submitting_to_the_internal_reader_from_jobs_or_tasks.htm, using knowledge dating back to when Green Cards came from IBM, and Manix worked for a company owning an IBM card sorter
- ^ Brooks, Frederick P. (2010). The Design Of Design. Addison-Wesley. pp. 167–173. ISBN 978-0-201-36298-5.
- ^ "IBM Archives: System/360 Model 30". www-03.ibm.com. 2003-01-23. Archived from the original on December 17, 2004. Retrieved 2016-04-25.
- ^ "IBM PC". Archived from the original on 2006-07-05. Retrieved 2007-10-21.
- ^ IBM-compatible computers History of PCs Archived August 14, 2007, at the Wayback Machine
- ^ Brown, Gary DeWard (2002). zOS JCL (fifth ed.). John Wiley & Sons. p. 248. ISBN 0471-236357.
- ^ Ashley and Fernandez, Job Control Language, pp. 8, 23. There are also two additional statements, PROC and PEND, used to test JCL procedures.
- ^ A pre-stored set of "EXEC PGM=" and "DD" JCL commands which could be parameterized
- ^ Ashley and Fernandez, Job Control Language, pp. 12–16.
- ^ Ashley and Fernandez, Job Control Language, pp. 13–15.
- ^ IBM Corporation (August 1978). OS/VS MVS Data Management Services Guide (PDF). Retrieved Oct 17, 2014.
- ^ IBM Corporation (June 1971). IBM System/360 Operating System: Job Control Language Reference (PDF). Retrieved June 25, 2019.
- ^ McQuillen, System/360–370 Assembler Language, pp. 297, 406–407.
- ^ the default for the EXEC statement is PROC=
- ^ Ashley and Fernandez, Job Control Language, pp. 129–131.
- ^ "Data set names". IBM. 27 March 2014.
Data set names must not exceed 44 characters, including all name segments and periods.
- ^ a b Brown, Gary DeWard (2002). zOS JCL. John Wiley & Sons. ISBN 9780471426738. Retrieved 2014-05-05.
- ^ IBM Corporation. "Relationship of the COND parameters on JOB and EXEC statements". IBM Knowledge Center. Retrieved Feb 21, 2018.
- ^ a b c McQuillen, System/360–370 Assembler Language, pp. 406–407.
- ^ Charley, Alfred (1993). NetView: IBM's Network Management Product. New York: Van Nostrand Reinhold. p. 93. ISBN 0-442-01407-4.
- ^ Mathew W. Blode (April 6, 2020). "Newly unemployed New Yorkers are being frustrated by 1970s-era technology(nytimes.com)". Retrieved May 7, 2020.
JCL in particular is notoriously user hostile and has been called "the worst programming language ever designed" by Fred Brooks ... (http://dtsc.dfw.ibm.com/MVSDS/'HTTPD2.APPS.ZOSCLASS.PDF(ZCLA...)[link in original].
- ^ a b c Ashley and Fernandez, Job Control Language, pp. vii–viii, back cover.
- ^ Blatt, John M. (1971). Introduction to FORTRAN IV Programming: Using the WATFOR/WATFIV Compilers. Pacific Palisades, California: Goodyear Publishing Company. p. 276. ISBN 0-87620-440-X.
- ^ IBM Corporation (1968). IBM System/360 Operating System Remote Job Entry (PDF). Retrieved 2014-05-05.
- ^ IBM Corporation. "Job Entry Subsystem 2 (JES2) Control Statements". z/OS V1R2.0 MVS JCL. Archived from the original on October 18, 2015. Retrieved February 25, 2013.
- ^ other examples can be viewed at Houston Automatic Spooling Priority#Operator Commands
- ^ IBM Corporation. "Job Entry Subsystem 3 (JES3) Control Statements". z/OS V1R2.0 MVS JCL. Archived from the original on October 18, 2015. Retrieved February 25, 2013.
- ^ IBM Corporation (1974). DOS/VS POWER/VS Installation and Operations (PDF).
Sources
[edit]- "z/OS V1R6.0 MVS JCL User's Guide" (PDF) (5th ed.). IBM. September 2004. Archived from the original (PDF) on 2013-08-19. Retrieved 2006-10-12.
- "z/OS V1R7.0 MVS JCL Reference" (PDF) (11th ed.). IBM. April 2006. Archived from the original (PDF) on 2013-08-19. Retrieved 2006-10-12.
- Johnston, Jerry (1 April 2005). "VSE: A Look at the Past 40 Years". z/Journal. Thomas Communications. Archived from the original on 4 March 2009.
- "Computer Chronicles: 1972 - 1981". ThinkQuest. Oracle Corporation. 1998. Archived from the original on 21 June 2009.
- DeWard Brown, Gary (7 June 2002). zOS JCL (5th ed.). Wiley. ISBN 978-0-471-23635-1.
- "JCL Statement Fields". z/OS V1R11.0 MVS JCL Reference z/OS V1R10.0-V1R11.0. IBM. 2010.
- IBM Corporation (March 2007). Introduction to the New Mainframe: z/VSE Basics (PDF). IBM, International Technical Support Organization. ISBN 978-0-73-848624-6. Retrieved 2017-12-06.
- Ashley, Ruth; Fernandez, Judi N. (1978). Job Control Language: A Self-Teaching Guide. New York: John Wiley & Sons. ISBN 0-471-03205-0.
- McQuillen, Kevin (1975). System/360–370 Assembler Language (OS). Fresno, California: Mike Murach & Associates. LCCN 74-29645.
- Stern, Nancy; Stern, Robert A. (1980). Structured COBOL Programming (3rd ed.). New York: John Wiley & Sons. ISBN 0-471-04913-1.
Job Control Language
View on GrokipediaOverview
Definition and Purpose
Job Control Language (JCL) is a high-level scripting language developed by IBM for use on mainframe operating systems, including DOS/360 and OS/360, to submit, control, and manage batch jobs. It functions as a declarative set of statements that instructs the operating system on the execution of non-interactive workloads, focusing on system-level coordination rather than application programming. Unlike imperative programming languages, JCL specifies what resources and actions are required without embedding such logic directly into the source code of the programs being run.[5] The primary purpose of JCL is to facilitate the allocation and management of system resources for batch processing, such as identifying input/output devices, datasets, and the programs or utilities to execute within a job sequence. It enables users to define job steps, establish logical connections between those steps and data resources, and sequence multiple tasks to run automatically in a controlled environment, all while preserving the integrity of the underlying application code. This approach supports efficient handling of large-scale data processing tasks on IBM mainframes, where jobs are submitted for background execution without requiring real-time user intervention.[5] JCL distinguishes itself from command-line interfaces, such as Time Sharing Option (TSO), or application programming interfaces (APIs), by being inherently batch-oriented and non-interactive; it automates resource setup and job flow in a declarative manner, contrasting with the immediate, user-driven responses typical of online or interactive systems. Initially developed by IBM in the 1960s as part of the System/360 architecture—launched in 1964—JCL addressed the need for standardized job control amid the transition from punched-card-based inputs to more flexible disk-oriented storage systems.[5]Historical Development
Job Control Language (JCL) originated in the mid-1960s as a standardized mechanism for managing batch jobs on IBM mainframe systems, building on precursors like the job control features in IBSYS, the operating system for the IBM 7090 and 1401 computers, which used control cards to sequence program execution and resource allocation.[6] JCL was formally introduced in 1964 alongside the announcement of the IBM System/360 family, serving as the primary interface for submitting and controlling jobs under OS/360 for larger configurations and DOS/360 for smaller, disk-based systems.[5] This development marked a shift toward a unified, declarative language that automated job setup, data set handling, and system resource requests, addressing the limitations of manual operator interventions in earlier computing environments.[7] The evolution of JCL began with its initial implementations: DOS JCL, tailored for resource-constrained smaller systems, was first delivered with DOS/360 in June 1966, emphasizing simplicity for single-tasking environments.[5] In parallel, OS JCL saw enhancements through the 1970s with the release of OS/MVS (Multiple Virtual Storage) in 1974, which introduced support for virtual memory, multiprogramming, and more complex job streams, allowing JCL to handle dynamic allocation and conditional execution more efficiently.[8] A pivotal advancement came with the integration of JCL into the Job Entry Subsystem (JES) framework in the early 1970s—JES2 was announced in 1972 and JES3 in 1973—enabling centralized job queuing, spooling, and scheduling across networked mainframes, which significantly improved throughput and reduced operator dependency.[9][10] Key milestones in JCL's history include the transition to z/OS in October 2000, which preserved core JCL syntax while extending support for 64-bit addressing, Unicode, and sysplex environments, ensuring backward compatibility for decades of legacy applications.[5] Continued refinements through the 2010s and into the 2020s focused on enhancing JCL's interoperability with modern infrastructures, such as minor updates in z/OS 2.4 (2019) and z/OS 3.1 (2023) for better integration with hybrid cloud services via tools like z/OS Connect, allowing JCL-defined jobs to interface with API-based workloads without fundamental syntax changes.[11][12] By 2025, z/OS 3.2 further supported cloud-native data access and AI-driven automation in batch processing, with JCL remaining a stable cornerstone for mission-critical operations.[13]Motivation for Use
Job Control Language (JCL) emerged as a critical tool in early mainframe computing to separate job control instructions from the application logic embedded in programs, allowing non-programmer operators to efficiently manage and submit batch workflows without altering source code.[5][14] This separation enhanced modularity, maintainability, and security by isolating resource requests and execution parameters in a dedicated scripting layer, which was essential for the multi-user, multi-programming environments of systems like OS/360.[5] In batch-oriented setups, where jobs processed large volumes of data sequentially without interactive user input, JCL enabled operators to handle scheduling and execution independently of developers, streamlining operations in data centers.[15] Developed amid the challenges of 1960s computing, JCL addressed key limitations in pre-System/360 environments, such as manual tape mounting by operators, which disrupted workflows and increased downtime, and resource contention among competing jobs on shared hardware.[5][14] It provided a standardized mechanism to pre-specify devices, volumes, and data sets, reducing operator intervention and enabling automated allocation in multi-programming configurations like Multiprogramming with a Variable Number of Tasks (MVT).[14] Additionally, JCL facilitated error recovery through structured job steps and conditional processing, mitigating issues where failures in one task halted entire sequences and required manual restarts.[5] These features optimized throughput in centralized batch systems, where jobs were submitted via card decks or tapes and processed unattended overnight.[15] The advantages of JCL included automation of multi-step jobs, which chained programs and data handling into cohesive workflows, and resource optimization by specifying priorities, storage limits, and device assignments to balance system load.[14] It also promoted portability across hardware configurations, a core goal of the System/360 architecture shift in 1964, by using abstract parameters rather than machine-specific details.[5] This design supported scalable batch processing for business applications, such as payroll or inventory updates, handling terabyte-scale data with high reliability.[15] However, JCL introduced trade-offs, particularly increased complexity for simple, single-step tasks compared to later interactive systems, where direct commands sufficed without the verbose structure needed for unattended batch execution.[5] While effective for its era's demands, this rigidity reflected the priorities of resource-constrained mainframes over user-friendly scripting.[14]Core Concepts and Terminology
Key Terms and Definitions
Job Control Language (JCL) employs a set of standardized terms to describe the components and processes involved in submitting and executing batch jobs on IBM mainframe systems. These terms form the foundational vocabulary for users interacting with operating systems such as z/OS and z/VSE, enabling precise specification of job structure, resource allocation, and data handling. Understanding these terms is essential for constructing valid JCL statements that direct the system in processing workloads efficiently.[1] The following glossary outlines key JCL terms with brief definitions, highlighting core elements applicable across variants while noting significant differences between OS (e.g., z/OS) and DOS/VS (e.g., z/VSE) implementations where relevant. These definitions draw from official IBM documentation to ensure accuracy.- JOB: A statement that initiates a unit of work, identifying the job with a unique name and optional parameters such as accounting information, class, and resource limits for the entire job submission. In both OS and DOS/VS JCL, it marks the beginning of job processing.[1][16]
- EXEC: A statement that defines a job step by specifying the program (via PGM=) or cataloged procedure (via PROC=) to execute, along with step-specific parameters like time limits or input arguments. It is common to both OS and DOS/VS JCL, serving as the entry point for each processing phase within a job.[1][16]
- DD (Data Definition): In OS JCL (e.g., z/OS), a statement that allocates and describes input/output data sets or devices for a job step, including parameters for dataset name (DSNAME), disposition (DISP), and unit type (UNIT). It consolidates device, label, and extent information into a single statement.[1][14]
- ASSGN (Assign): In DOS/VS JCL (e.g., z/VSE), a statement that assigns a logical unit (e.g., SYS005) to a physical device (e.g., DISK or a channel unit address), enabling I/O operations; it replaces device allocation aspects of the OS DD statement and supports temporary or permanent assignments.[16][17]
- DLBL (Disk Label): In DOS/VS JCL, a statement that defines the label and attributes for a DASD file, including the file ID, expiration date, and access mode; it corresponds to dataset naming and labeling in the OS DD statement's DSNAME and VOL parameters.[16][17]
- EXTENT: In DOS/VS JCL, a statement that specifies the physical location and size of a dataset on a volume, including cylinder ranges and track counts; it handles extent mapping separately from OS JCL, where such details are embedded in the DD statement's SPACE parameter.[16][17]
- SYSIN: A predefined logical unit or DD name for inline input data or control statements provided directly in the job stream, often following a DD * or ASSGN statement; used in both OS and DOS/VS for program control cards.[1][16]
- SYSOUT: A predefined logical unit or DD name for directing system-generated output (e.g., print files or messages) to external devices like printers, specified via SYSOUT= class in OS or ASSGN in DOS/VS; it manages job output routing in both variants.[1][16]
- Cataloged Procedure: A reusable set of JCL statements (including EXEC and DD/ASSGN equivalents) stored in a system library (e.g., SYS1.PROCLIB in OS or procedure libraries in DOS/VS), invoked by name in an EXEC statement to standardize multi-step operations.[14][16]
- In-Stream Procedure: A procedure defined within the job stream using PROC and PEND statements in OS JCL, or equivalent inline definitions in DOS/VS; it allows temporary, job-specific reusable JCL without library storage.[14]
- Symbolic Parameter: A variable (denoted by &name in both OS and z/VSE JCL, with $$ used in specific z/VSE contexts such as TAILOR statements) within procedures that allows dynamic substitution of values at invocation time, enhancing reusability by customizing elements like dataset names or limits.[14][16]
- Generation Data Group (GDG): In OS JCL, a collection of chronologically related, cataloged non-VSAM datasets sharing a base name, referenced by generation number (e.g., (+1) for the newest); DOS/VS lacks native GDG support, relying on versioned labels in DLBL instead.[18][16]
- Job Step: An individual processing unit within a JOB, initiated by an EXEC statement and consisting of program execution plus associated data definitions; it represents a modular building block in both OS and DOS/VS JCL structures.[1][16]
- Data Set: A named collection of related data (e.g., files or catalogs) referenced in JCL statements; in OS, allocated via DD with DSNAME; in DOS/VS, defined via DLBL and EXTENT for precise volume placement.[14][16]
- Disposition (DISP): A parameter in OS DD statements specifying the status and final state of a data set (e.g., NEW, OLD, SHR, DELETE); DOS/VS equivalents are handled via DLBL expiration dates and file attributes rather than a unified parameter.[14][16]
Jobs, Steps, and Procedures
In Job Control Language (JCL), a job represents a complete unit of work submitted to IBM mainframe operating systems such as z/OS and z/VSE for execution, encompassing one or more processing tasks that achieve a specific objective, such as batch processing or data transformation.[19][20] Each job begins with a JOB statement that identifies the submission and provides essential control information, allowing the system to allocate resources and track the job's progress through the system.[19] A step within a job constitutes a single program execution or invocation of a procedure, serving as the fundamental building block for performing discrete operations.[19][20] Defined by an EXEC statement, a step specifies the program to run or the procedure to call, along with any necessary parameters, and is executed sequentially unless conditional logic alters the flow.[19] Jobs can contain multiple steps to handle complex workflows, where each step processes input from prior steps or external sources, enabling modular construction of larger tasks.[20] Procedures enhance JCL's efficiency by providing reusable sequences of one or more steps, allowing users to define common patterns once and invoke them across multiple jobs without duplication.[19][20] There are two primary types: cataloged procedures, which are stored in system procedure libraries for broad accessibility and maintenance, and in-stream procedures, which are embedded directly within a job's JCL for ad-hoc or job-specific reuse.[19] Invoked via an EXEC statement, procedures promote standardization in environments with repetitive operations.[19] The typical flow of a JCL job starts with the JOB statement to initiate the unit of work, followed by one or more EXEC statements delineating the steps or procedure calls, and may conclude with an optional END statement to explicitly terminate the job definition.[19][20] This structure supports common use cases like multi-step jobs in data processing pipelines, where initial steps might extract and sort data, subsequent steps transform it, and final steps output results to datasets or reports, ensuring orderly execution in high-volume mainframe environments.[19][20]Basic Syntax Elements
Job Control Language (JCL) statements follow a fixed-format structure derived from the 80-column punched-card heritage of IBM mainframe systems, where each statement is confined to 80 columns to maintain compatibility with legacy input methods.[21] This format ensures consistent parsing by the operating system, with columns 73-80 traditionally reserved for optional sequence numbers used in editing and debugging.[21] All JCL statements, except comments and delimiters, begin with// in columns 1 and 2, signaling the start of a valid control statement.[21]
The core fields of a JCL statement are the name field, operation field, parameter field, and optional comments field, separated by at least one blank space. The name field, occupying columns 3 through 11 (up to 8 characters), identifies the statement for reference within jobs or steps, such as naming a dataset in a DD statement; it must start with an alphabetic or national character followed by alphanumerics or special characters like $, #, or @.[21] The operation field, starting in column 12 and spanning up to 8 characters, specifies the statement type, such as JOB for initiating a job, EXEC for executing a program or procedure, or DD for defining data.[21] The parameter field, beginning after the operation field and extending to column 71, contains the operands that provide details for the operation, while the comments field follows thereafter for non-executable annotations.[21] For example, a basic OS JCL JOB statement might appear as:
//MYJOB JOB (ACCT),'PROGRAMMER',CLASS=A,MSGCLASS=X
//MYJOB JOB (ACCT),'PROGRAMMER',CLASS=A,MSGCLASS=X
MYJOB is the name, JOB the operation, and the parenthesized items the parameters, with no comments included. For DOS/VS JCL, parameters are positional only.[1]
In OS JCL, parameters in the parameter field are categorized as positional or keyword; DOS/VS JCL uses only positional parameters. Positional parameters must appear in a fixed sequence as defined by the statement's syntax, without explicit labels, and are used for essential, order-dependent values like accounting information in a JOB statement; omitting one typically requires a comma placeholder unless it is the final positional parameter.[22] Keyword parameters, which follow all positional ones in OS JCL, are explicitly named using an equals sign (e.g., CLASS=A), allowing flexible ordering and easier readability for optional or conditional specifications.[22] This approach in OS JCL balances rigidity for core elements with adaptability for extensions, though mixing them incorrectly can lead to parsing errors.[22]
Field delimitations and punctuation enforce precise separation to prevent ambiguity in processing. Blanks separate the major fields (name, operation, parameters, comments), while within the parameter field, commas delineate individual parameters or subparameters, and parentheses group related values, such as multiple dataset specifications.[22] For instance, in a DD statement, parameters like DSN=MYDATA,DISP=(NEW,CATLG) use commas to separate the dataset name from disposition details and parentheses to nest subparameters.[23] Strings containing commas or blanks must be enclosed in apostrophes to avoid misinterpretation as delimiters.[22]
When a statement exceeds column 71, continuation lines allow extension across multiple records, a mechanism essential for complex parameter lists in jobs and steps. To continue, end the first line with a comma (if separating parameters) or ensure no unresolved enclosure like parentheses or apostrophes, place a nonblank character (often a comma or period) in column 72, and begin the next line with // in columns 1-2 followed by the continuation in column 16, ignoring columns 3-15.[24] For example:
//STEP1 EXEC PGM=MYPROG,PARM='PARAM1,PARAM2',
REGION=0M
//STEP1 EXEC PGM=MYPROG,PARM='PARAM1,PARAM2',
REGION=0M
PARAM2 and a nonblank in column 72 signal continuation, with REGION=0M resuming in column 16.[24] Unclosed parentheses or apostrophes on the prior line also imply continuation without needing column 72 marked.[25] Comments and certain statements like delimiters cannot be continued, requiring separate lines if needed.[25]
JCL's syntax includes error-prone aspects stemming from its historical design, notably complete case insensitivity, where uppercase, lowercase, or mixed cases are treated identically (e.g., JOB equals job), potentially leading to overlooked typos in modern editors without case enforcement.[21] The rigid 80-column constraint, while allowing longer effective lines via continuations up to 8194 characters, demands careful column alignment to avoid truncation or invalid field overlaps, a common pitfall when adapting code from variable-length environments.[21] These elements collectively ensure reliable batch processing but require meticulous coding to mitigate parsing failures.[21]
Common Features Across Variants
In-Stream Input Handling
In-stream input handling in Job Control Language (JCL) allows users to embed small amounts of data or control statements directly within the job stream, avoiding the need for separate external files. This feature is particularly useful for providing concise input to utilities or programs during job execution, and it is supported across variants like OS and DOS JCL through Data Definition (DD) statements or equivalents. The primary mechanism involves the SYSIN DD statement, which designates the input stream for the executing step.[26] The SYSIN DD statement is coded immediately after the EXEC statement in a job step and uses the format//SYSIN DD * to initiate in-stream data, followed by the data lines and terminated by a delimiter such as /* in column 1. This approach supplies input directly from the JCL input stream to the program or utility, such as control statements for processing. For instance, in a simple copy utility like IEBGENER, the SYSIN can contain records to be copied to an output dataset. Alternatively, the //SYSIN DD DATA format is used, with data lines terminated by a comment statement //* in column 1, offering a structured way to delimit inline content especially in procedures or when avoiding conflicts with default terminators.[26][27]
Limitations on in-stream input ensure system efficiency, restricting it to small datasets only; records are typically limited to 80 bytes per line when submitted via TSO, though JES2 supports up to 32,768 bytes for fixed- or variable-length records. Exceeding these constraints can lead to job failures or unread data being discarded, making in-stream handling unsuitable for large volumes that should instead reference external datasets via DD statements. Custom delimiters can be specified with the DLM parameter (e.g., DLM=XX) to prevent conflicts if the data contains default terminators like /*.[26]
A representative example for a SORT utility involves embedding control statements in SYSIN to define sorting criteria:
//SORTSTEP EXEC PGM=SORT
//SYSIN DD *
SORT FIELDS=(1,10,CH,A)
OUTFIL FNAMES=SORT.OUT,BUILD=(1:10)
/*
//SORTSTEP EXEC PGM=SORT
//SYSIN DD *
SORT FIELDS=(1,10,CH,A)
OUTFIL FNAMES=SORT.OUT,BUILD=(1:10)
/*
File Allocation Basics
In Job Control Language (JCL), file allocation is managed through control statements to specify datasets, volumes, and storage units required by job steps, though the exact syntax varies across variants. In OS JCL, this is primarily handled through Data Definition (DD) statements, which define the physical and logical attributes of files, enabling the operating system to reserve resources such as disk space or tape drives before program execution. For instance, a DD statement outlines whether a dataset is to be created, accessed, or shared, ensuring proper integration with the executing program. In DOS/zVSE variants, equivalent functionality is provided by statements like ASSGN, DLBL, and EXTENT, which are more device-dependent and use positional parameters.[23][17] Datasets in JCL are categorized as temporary or permanent based on their naming and lifecycle, with variant-specific conventions. In OS JCL, temporary datasets are denoted by a DSN parameter prefixed with two ampersands (e.g., DSN=&&TEMP), allocated dynamically for the duration of a single job and automatically deleted upon job completion, making them suitable for intermediate processing without permanent storage overhead.[28] In DOS/zVSE, temporary files may use system-managed areas or unlabeled media without the && prefix. In contrast, permanent datasets in OS JCL use a qualified name (DSN=QUALIFIER.DATASET.NAME) that can be cataloged in the system catalog for repeated access across jobs, allowing persistence beyond the current execution; similar cataloging occurs in DOS variants via sub-libraries. The disposition parameter in OS JCL (DISP) further governs dataset handling: DISP=NEW creates a new dataset with exclusive access; DISP=OLD provides exclusive access to an existing dataset; and DISP=MOD allows modification (e.g., appending) to an existing dataset, also with exclusive control to maintain data integrity. Equivalent disposition controls exist in DOS JCL through parameters on DLBL statements.[29] Key parameters in OS JCL DD statements include DSN for the dataset name, UNIT for the device type (e.g., UNIT=SYSDA for system disk allocation or UNIT=TAPE for sequential media), and SPACE for reserving storage on direct-access volumes. The SPACE parameter requests primary and secondary extents in units such as cylinders (CYL), tracks (TRK), or blocks (BLK), for example, SPACE=(CYL,(10,5)) to allocate 10 primary cylinders with 5 secondary if needed, preventing fragmentation during growth. Volumes are specified via the VOL parameter to indicate specific serial numbers (e.g., VOL=SER=ABC123) or request system-assigned volumes for new datasets. In DOS/zVSE, space and volume are managed via EXTENT statements with track/cylinder specifications and device assignments.[30][31][32] If allocation fails—due to insufficient space, invalid volume, or device unavailability—the system issues an error, halting the step. In OS/zOS, this may result in abends like SB37 (space exhaustion) or SE37 (end-of-volume without specification), reported via messages like IEC000I. In DOS/zVSE variants, errors are indicated through different system messages and abend types. These errors prompt review of allocation parameters, and the job's condition code reflects the failure for conditional processing.[33][34]Complexity and Learning Curve
Job Control Language (JCL) is renowned for its inherent complexity, stemming primarily from its verbose syntax and the sheer number of parameters required to define job execution details on IBM mainframe systems. Each JCL statement, such as JOB, EXEC, or DD, demands precise specification of elements like program names, resource allocations, and disposition rules, often involving interdependent subparameters (e.g., UNIT, VOLUME, and DISP in DD statements) that can span multiple lines and require careful sequencing across up to 255 job steps. This verbosity, designed for the batch-oriented processing of the 1960s, results in lengthy scripts that are prone to errors if even minor details, such as device affinity or space calculations, are overlooked.[35] The learning curve for JCL is steep due to its origins in the mid-1960s era of computing, when graphical user interfaces were nonexistent and users relied heavily on printed manuals and punch-card input for coding and submission. New users often struggle with misconceptions, such as treating JCL as a full programming language rather than a declarative control mechanism for resource management, compounded by the need to grasp z/OS-specific concepts like data set attributes and subsystem interactions. Error messages further exacerbate difficulties, as they frequently lack modern diagnostic clarity; for instance, system outputs may not clearly indicate which step triggered an issue, leaving users to sift through logs with cryptic codes like IEF278I for unit affinity problems.[36][35][37] IBM has implemented several mitigations to address these challenges, including built-in syntax checking tools like the TYPRUN=SCAN parameter, which scans JCL for errors without executing the job, and utilities such as IEFBR14 for testing allocations in isolation. Reference summaries and educational aids, like the z/OS MVS JCL User's Guide, provide structured overviews of parameters and examples to reduce reliance on trial-and-error. Despite alternatives like REXX for scripting tasks, JCL remains a core skill in mainframe education because it underpins essential batch processing in industries reliant on z/OS stability, where replacing legacy JCL workflows would incur significant costs and disruptions.[35][38][39]DOS JCL Specifics
Positional Parameters
In DOS JCL, positional parameters are specified in a strict, fixed order without accompanying keywords in early implementations, requiring programmers to adhere to predefined positions for each element. This approach was designed for the simpler architecture of DOS/360, introduced in the mid-1960s. For the JOB statement in DOS/360, the first (and only) positional parameter is the job name (1-8 alphanumeric characters). An example is// JOB PAYRL01.[40]
Successors like DOS/VS introduced optional keyword parameters such as CLASS (a single character indicating scheduling category) and PRTY (a number from 0 to 15 determining execution order within the class). An example is // JOB PAYRL01 CLASS=A,PRTY=5.[16]
The EXEC statement in DOS/360 relies on a positional parameter for the program name (1-8 alphanumeric characters). For instance, // EXEC SORT executes the SORT program. Program-specific parameters, such as sort keys, are handled via separate control statements like PARM (in later variants) or utility-specific DD definitions, rather than inline positional elements. This fixed ordering simplifies parsing by the DOS supervisor, as no keyword matching is needed, making it efficient for basic job submissions on resource-constrained systems of the era.[40]
While this method offers advantages in brevity and ease for short statements—reducing coding overhead and verbosity in environments with limited card or line input—it introduces drawbacks in readability and maintenance. Programmers must memorize the exact sequence, leading to error-prone entries for longer parameter lists, where omitting or misplacing an item can cause job failures without clear diagnostic feedback. These limitations were inherent to DOS/360's design philosophy, prioritizing system simplicity over user flexibility, with later variants like DOS/VS adding keywords to address some issues.[40]
Device Dependence
In DOS JCL, device dependence is manifested through statements that explicitly specify physical hardware configurations, such as the ASSIGN statement, which maps logical input/output units to specific devices using hexadecimal channel/unit addresses (e.g., X'cuu') or device types with unit numbers. For instance, an ASSIGN statement like// ASSGN SYS001,X'380',PERM permanently allocates the logical unit SYS001 to the physical device at address X'380', often a tape or disk unit, while // ASSGN SYS003,2314 designates a 2314 disk drive for SYS003. Similarly, the TLBL statement defines tape labels in conjunction with these assignments, requiring prior specification of tape unit numbers (e.g., // TLBL FILE01,'DATASET',,,00E for unit 00E), and the LINK statement relies on assigned devices like SYSLNK for linkage editor output. This hardware-specific binding ensures direct control over I/O paths but ties jobs rigidly to the system's physical layout.[16]
This explicit approach arose from the resource constraints of smaller IBM systems in the 1960s, such as the System/360 series, which featured limited memory (e.g., as low as 128 KB), modest processing power, and diverse I/O hardware like 2311 disks or 2400-series tapes. In these environments, abstraction layers were minimal to conserve overhead, necessitating precise device addressing (e.g., via channel, control unit, and device identifiers like 132) to optimize slow I/O operations relative to CPU speed and prevent resource conflicts in single-tasking setups. Such design prioritized efficiency in batch processing for resource-scarce installations over flexibility.[5]
The resulting issues include limited portability, as hardware upgrades or reconfigurations—such as replacing a 3390 DASD with a modern equivalent—often require manual revisions to multiple JCL statements to update device addresses or types, potentially affecting thousands of jobs. Device failures further demand operator intervention, including console monitoring, reassignment via updated ASSIGN statements, or troubleshooting with tools like dumps, without automated failover in early DOS variants. This dependence contrasts with manual file allocation practices, where dataset extents are defined alongside device specs but add another layer of hardware-specific control.[41]
Despite these challenges, DOS JCL's device-dependent model persists in legacy environments like z/VSE, where it supports mission-critical batch workloads for industries requiring compatibility with 1970s-era applications, often through emulation of older hardware (e.g., 3390 drives) to maintain operational continuity without full rewrites.[41]
Manual File Allocation
In DOS JCL, manual file allocation for direct access storage devices (DASD) relies on explicit control statements to define and assign physical storage without the benefit of dynamic or catalog-based automation. The primary methods involve the DLBL statement to specify dataset labels and attributes, and the EXTENT statement to delineate the precise tracks or cylinders allocated for the file. Unlike later systems, DOS JCL lacks dynamic allocation, requiring programmers to predefine all storage details in the job stream, which ties allocation closely to device dependence.[42] The DLBL statement identifies the file by its symbolic name, dataset identifier (up to 44 characters), expiration date (in YY/DDD format, up to 366 days), and label codes such as SD for standard disk labels or DA for data. For example, a typical DLBL might read// DLBL 'MYFILE','DATASET NAME',75/100,SD, establishing the file's metadata before any I/O access. This is followed by one or more EXTENT statements that specify the volume serial number (VOL/SER, a 1-6 character identifier), extent type (e.g., 1 for data), sequence number (starting at 0), starting relative track address, and number of tracks. An example EXTENT could be // EXTENT SYS001,123456,1,0,0100,0500, allocating 500 tracks beginning at track 100 on volume 123456. These statements must precede the EXEC statement for the program using the file, ensuring the system verifies labels and mounts volumes accordingly.[42][43]
For uncataloged files, the process demands operator intervention, as the system does not maintain a central catalog for automatic volume location. Upon encountering the DLBL and EXTENT, the operator console receives a request to mount the specified VOL/SER; if omitted, the system performs no volume validation, increasing the risk of overwriting unintended data. In multi-volume scenarios, multiple EXTENT statements (up to 125 per file) are required, each potentially triggering additional operator mounts without automatic switching, making the process labor-intensive and prone to errors such as extent overlaps or insufficient space (e.g., error message 8075A). This manual handling suits low-volume systems where datasets are small and operator oversight is readily available, minimizing the need for complex automation.[42][43]
Overall, DOS JCL's manual file allocation approach, while precise for its era, represents a precursor to the device-independent automation in OS JCL, where cataloged datasets reduce operator dependency. Its limitations in scalability highlight its design for simpler, resource-constrained environments typical of early System/360 installations.[42]
OS JCL Specifics
Coding Rules and Keyword Parameters
Job Control Language (JCL) in OS/360 and its successors adheres to a fixed 80-column record format, mimicking traditional punched-card input, where each statement occupies one or more such records. Columns 1 and 2 must contain// to identify a JCL statement, with the name field (optional, 1-8 alphanumeric characters starting in column 3), operation field (e.g., JOB, EXEC, or DD), and parameter field following, separated by blanks; content is limited to columns 3 through 71, while columns 73 through 80 are reserved for sequence numbers and ignored during processing. Parameters within the operand field are coded as comma-separated entries, with continuation lines starting with // in columns 1-2 followed by content beginning in column 16. This structured format ensures compatibility with the system's input reader and interpreter, facilitating reliable job submission and execution.[44]
OS JCL emphasizes keyword parameters, coded as keyword=value pairs (e.g., DISP=SHR for shared disposition or DSN=MYDATASET for dataset name specification), which can appear in any order within the parameter field and may include subparameters enclosed in parentheses, such as DISP=(NEW,CATLG,DELETE). This approach contrasts with legacy positional parameters, which require strict sequencing, by providing greater flexibility and reducing coding errors through explicit naming. Keyword parameters enhance maintenance, as modifications to specific options do not affect others, and support overriding in procedures or steps without resequencing the entire statement. Common examples include REGION=0M for virtual storage allocation and TIME=5 for CPU time limits, allowing precise resource control.[45][44]
Introduced with OS/360 to address limitations in earlier systems like DOS JCL, which relied heavily on rigid positional notation, the keyword-based syntax promotes device independence, multiprogramming support, and modular job design through features like cataloged procedures. This evolution enabled more efficient resource allocation in multi-user environments, with defaults provided for omitted parameters—such as DISP=NEW for temporary datasets, UNIT=SYSDA for system-assigned devices, or installation-defined values for MSGCLASS—to streamline common operations without explicit specification. Validation of JCL syntax and semantics occurs at job submission by the job management components, such as the input reader and interpreter in OS/360, or the Job Entry Subsystem (JES) in later systems, which checks for format adherence, keyword validity, and parameter consistency before queuing the job; errors result in immediate rejection or flushing to prevent invalid execution.[45][44]
Data Access via DD Statements
In OS JCL, the DD (data definition) statement serves as the primary mechanism for specifying and allocating data sets and input/output resources required by executing programs or procedures.[46] It enables the system to link logical dataset references within application code to physical storage or devices, ensuring proper data access during job steps.[47] Each DD statement corresponds to one dataset or resource, and multiple statements can appear within a job step to handle various inputs and outputs.[46] The basic structure of a DD statement follows the format//ddname DD parameters, where ddname is a user-assigned logical name (1 to 8 alphanumeric characters) that programs reference via file control blocks or similar mechanisms to access the defined data.[46] This logical name provides device independence, allowing programs to interact with data without specifying physical details in the code itself.[47] Common functions of the DD statement include defining sequential or partitioned datasets on disk, allocating tape volumes for sequential processing, directing output to printers or sysout classes, generating system dumps with SYSUDUMP for diagnostic purposes, and simulating datasets with DUMMY to bypass actual I/O operations during testing.[46][47]
Key parameters in the DD statement control allocation and attributes. The DSN parameter specifies the dataset name, such as DSN=MYLIB.DATASET, identifying the data for input, output, or both.[46] The DISP parameter defines the dataset's disposition, for example, DISP=(NEW,CATLG,DELETE), which indicates creation of a new dataset, cataloging it upon normal completion, and deletion if the job abends.[46] The UNIT parameter requests a device type, like UNIT=SYSDA for direct access storage or UNIT=TAPE for magnetic tapes.[46]
The VOL parameter identifies the specific volume or volumes holding the dataset, using syntax such as VOL=SER=VOL001 for a single volume or VOL=(SER,VOL001,VOL002) for multi-volume datasets, ensuring precise allocation on DASD or tape devices.[48] The SPACE parameter allocates primary and secondary extents of storage, typically in cylinders, tracks, or blocks; for instance, SPACE=(CYL,(10,5),RLSE) requests 10 cylinders initially, adds 5 more if needed, and releases unused space at completion.[48] This parameter is essential for new or expanding datasets to prevent allocation failures due to insufficient space.[48]
The DCB (data control block) parameter describes the dataset's record format and processing attributes, overriding any defaults from the dataset's data class.[48] Common subparameters include RECFM for record format (e.g., RECFM=FB for fixed-block records), LRECL for logical record length (e.g., LRECL=80), and BLKSIZE for physical block size (e.g., BLKSIZE=8000), which collectively define how records are organized, read, and written to optimize I/O efficiency.[48] For example, a full DCB might appear as DCB=(RECFM=FB,LRECL=80,BLKSIZE=8000), ensuring compatibility between the program and the dataset structure.[48]
DD statements employ keyword parameters, allowing flexible specification of attributes in any order after the DD keyword.[46] Through the logical ddname, the DD statement integrates seamlessly with executing programs, where application code opens files using the ddname to map to the allocated resources managed by the operating system.[47] This abstraction supports both batch and utility jobs, from simple file copies to complex data processing workflows.[46]
Device Independence
In OS JCL, device independence is facilitated by the UNIT parameter in DD statements, which allows users to specify generic device types such as UNIT=SYSDA for direct access storage devices (disks) or UNIT=TAPE for magnetic tape units, without referencing specific hardware addresses. The operating system then dynamically allocates an available device matching the generic type from the pool of configured units, leveraging Unit Control Blocks (UCBs) to manage device descriptions and ensure proper allocation during job execution. This design principle originated in OS/360 to enable device-independent input/output (I/O) methods, supporting the integration of diverse peripherals for business data processing without tying applications to particular hardware.[23][49][50] A primary benefit of this abstraction is enhanced portability, as jobs can execute across varying system configurations—such as different models of disk or tape drives—without requiring JCL modifications, provided the generic types are supported. It also minimizes operator intervention by automating device selection, allowing the Job Entry Subsystem (JES) to handle assignments based on availability and system policies. For output datasets, the SYSOUT parameter further promotes independence by routing data to predefined output classes managed by JES, which abstract physical destinations like printers or punches and direct them via external writers.[23][51] Despite these advantages, device independence has limitations in performance-critical scenarios, where generic allocations may result in suboptimal device selection, such as slower units or increased contention; tuning often involves specifying esoteric unit names or specific device addresses to optimize throughput and resource utilization. DD statements provide the mechanism for these device references, integrating them with dataset definitions to maintain overall flexibility.[52]Advanced OS JCL Features
Procedures and PROC/PEND
In OS JCL, procedures provide a mechanism for code reuse by encapsulating a sequence of job steps and data definitions that can be invoked across multiple jobs, reducing redundancy in job streams.[19] A procedure begins with the PROC statement, which includes a required name to identify it (e.g., //MYPROC PROC), and ends with the PEND statement (e.g., // PEND), which delimits the procedure's content.[53] These statements are essential for defining the boundaries of the procedure logic.[45] Procedures can be created as in-stream, embedded directly within a job's JCL between the JOB and any EXEC statements, or as cataloged, stored as members in a procedure library such as SYS1.PROCLIB for system-wide access.[19] In-stream procedures require the PROC and PEND statements to explicitly bound the code, ensuring it is recognized and processed correctly within the job.[45] Cataloged procedures, by contrast, optionally include PROC and PEND, as the procedure is retrieved by its member name from the library during job execution.[45] Both types consist of EXEC statements to define job steps and DD statements to specify datasets, volumes, and devices, which are expanded inline when the procedure is called.[19] To invoke a procedure, an EXEC statement in the job uses the PROC= parameter followed by the procedure name, such as //STEP1 EXEC PROC=MYPROC, which substitutes the procedure's contents at that point in the job stream.[19] Additional DD statements or overrides can follow the EXEC to modify or extend the procedure's data definitions without altering the original.[19] Procedures form a key component alongside jobs and steps, enabling modular JCL design where steps within procedures execute programs or utilities in a predefined order.[54] A primary use case for procedures is standardizing compile-link-go sequences in program development workflows, where a single procedure automates the compilation of source code, linkage editing to produce an executable load module, and immediate execution of the program.[55] For instance, IBM supplies the cataloged procedure IGYWCLG for COBOL programs, structured as follows://IGYWCLG PROC LNGPRFX='IGY.V2R1M0',SYSLBLK=3200,
LIBPRFX='CEE',GOPGM=GO
//COBOL EXEC PGM=IGYCRCTL,REGION=2048K
//STEPLIB DD DSNAME=&LNGPRFX..SIGYCOMP,DISP=SHR
//SYSPRINT DD SYSOUT=*
// ... (additional DD statements for compiler work files)
//LKED EXEC PGM=HEWL,COND=(8,LT,COBOL),REGION=1024K
//SYSLIB DD DSNAME=&LIBPRFX..SCEELKED,DISP=SHR
// ... (DD statements for link-edit input and output)
//GO EXEC PGM=*.LKED.SYSLMOD,COND=((8,LT,COBOL),(4,LT,LKED)),REGION=2048K
//STEPLIB DD DSNAME=&LIBPRFX..SCEERUN,DISP=SHR
// ... (DD statements for execution)
// PEND
//IGYWCLG PROC LNGPRFX='IGY.V2R1M0',SYSLBLK=3200,
LIBPRFX='CEE',GOPGM=GO
//COBOL EXEC PGM=IGYCRCTL,REGION=2048K
//STEPLIB DD DSNAME=&LNGPRFX..SIGYCOMP,DISP=SHR
//SYSPRINT DD SYSOUT=*
// ... (additional DD statements for compiler work files)
//LKED EXEC PGM=HEWL,COND=(8,LT,COBOL),REGION=1024K
//SYSLIB DD DSNAME=&LIBPRFX..SCEELKED,DISP=SHR
// ... (DD statements for link-edit input and output)
//GO EXEC PGM=*.LKED.SYSLMOD,COND=((8,LT,COBOL),(4,LT,LKED)),REGION=2048K
//STEPLIB DD DSNAME=&LIBPRFX..SCEERUN,DISP=SHR
// ... (DD statements for execution)
// PEND
Parameterized Procedures and Referbacks
In OS JCL, parameterized procedures enhance reusability by incorporating symbolic parameters, which allow dynamic substitution of values at procedure invocation. These parameters are denoted by an ampersand (&) followed by an alphanumeric name of up to 8 characters, such as &DSN for a dataset name or &STEP for a step identifier. They are defined within the procedure using the PROC statement or SET statements, where a default substitution text is assigned, for example://MYPROC PROC DSN=DEFAULT.DSN. When invoking the procedure via an EXEC statement, users can override these defaults by specifying new values positionally or by keyword, such as //STEP1 EXEC PROC=MYPROC,DSN=MYDATA.DSN1. This mechanism ensures the procedure adapts to job-specific requirements without modification.[56]
Referbacks in parameterized procedures involve using symbolic parameters to reference previously defined values or elements, promoting consistency and reducing redundancy. For instance, a symbol like &MEMBER can be substituted into a dataset specification, such as //SYSUT1 DD DSN=PROCLIB.&MEMBER,DISP=SHR, where &MEMBER is overridden at invocation to specify a procedure library member dynamically. This referback syntax extends to backward references within DD statements, but in procedures, it primarily facilitates self-referential constructs by resolving symbols sequentially during JCL processing. Default values ensure referbacks function even if overrides are omitted, with substitution occurring before execution to generate equivalent static JCL.[57][58]
Advanced usage includes conditional referbacks within IF/THEN constructs, where symbolic parameters enable logic based on runtime values. For example, an IF statement might evaluate IF (&FLAG = 'UPDATE') THEN followed by steps using referbacks like &DSN, allowing the procedure to branch dynamically while maintaining parameter flexibility. Symbols in conditions are resolved prior to evaluation, supporting nested procedures and ensuring overrides propagate correctly. This feature, introduced in later OS/360 releases and refined in z/OS, underscores the procedural nature of JCL for complex job flows.[57]
The following example illustrates a simple parameterized procedure with referbacks:
//PARMPROC PROC DSN=BASE.DSN,STEP=MAIN
//STEP1 EXEC PGM=PROG1,PARM=&STEP
//INPUT DD DSN=&DSN,DISP=SHR
//OUTPUT DD DSN=&DSN.OUT,DISP=(NEW,CATLG),UNIT=SYSDA
// PEND
//PARMPROC PROC DSN=BASE.DSN,STEP=MAIN
//STEP1 EXEC PGM=PROG1,PARM=&STEP
//INPUT DD DSN=&DSN,DISP=SHR
//OUTPUT DD DSN=&DSN.OUT,DISP=(NEW,CATLG),UNIT=SYSDA
// PEND
//JOB1 JOB ...
//STEPX EXEC PROC=PARMPROC,DSN=USER.DATA,STEP=UPDATE
//JOB1 JOB ...
//STEPX EXEC PROC=PARMPROC,DSN=USER.DATA,STEP=UPDATE
Comments, Concatenation, and Conditional Processing
In Job Control Language (JCL) for IBM z/OS, comments serve to document job streams without affecting execution, aiding maintenance and operator instructions. The primary method for full-line comments is coding//* in columns 1 through 3, followed by the comment text in columns 4 through 71; each such line is treated as a standalone comment and cannot be continued. Inline comments can be added after a JCL statement using /* to introduce the remark, which extends to the end of the line but cannot span multiple lines. These comment formats are ignored by the system during processing and may appear in the job log if the MSGLEVEL parameter requests statement printing.[59]
Concatenation in JCL allows multiple sequential data sets to be treated as a single logical input file for a job step, primarily using DD statements for input processing. To implement concatenation, code a series of consecutive DD statements where only the first includes a ddname, and subsequent ones omit it while specifying their data sets via parameters like DSN; the data sets are accessed sequentially in the order listed. This technique applies to sequential disk or tape files, partitioned data set members, or in-stream input, but requires compatible logical record lengths (LRECL) and record formats (RECFM) across all concatenated sets, though block sizes (BLKSIZE) may vary. Output data sets cannot be concatenated, and the application program must handle any differences in physical characteristics. For example:
//INPUT DD DSN=PROD.LIB1,DISP=SHR
// DD DSN=PROD.LIB2,DISP=SHR
// DD DSN=PROD.LIB3,DISP=SHR
//INPUT DD DSN=PROD.LIB1,DISP=SHR
// DD DSN=PROD.LIB2,DISP=SHR
// DD DSN=PROD.LIB3,DISP=SHR
COND=(4,GT,STEP1) skips the step if STEP1's return code exceeds 4. Introduced in early OS/360 versions, COND supports up to eight comparison tests and can reference steps within procedures using stepname.procstepname notation.[61]
The IF/THEN/ELSE/ENDIF construct, added in z/OS 1.9 for more flexible logic, evaluates relational expressions involving return codes (RC), abend codes (ABEND), step execution status (RUN), or symbolic parameters at the job step level. Syntax begins with //name IF condition THEN, followed by JCL statements in the THEN block, an optional //name ELSE for the alternative block, and ends with //name ENDIF; conditions use operators like GT, LE, AND, and support nesting up to 15 levels. An example is:
//IFSTEP IF RC=0 THEN
//STEP1 EXEC PGM=SUCCESS
// ELSE
//STEP2 EXEC PGM=FAILURE
// ENDIF
//IFSTEP IF RC=0 THEN
//STEP1 EXEC PGM=SUCCESS
// ELSE
//STEP2 EXEC PGM=FAILURE
// ENDIF
EXEC PROC=TEST,COND.PSTEP1=(8,LT)), ensuring logic flows across cataloged or in-stream procedures. Similarly, IF/THEN/ELSE can enclose procedure invocations, evaluating outcomes to control subsequent steps or nested procedures, enhancing modularity in complex job streams.[63]
Job Entry Control Language (JECL)
Pre-JES JECL in OS/360
In the OS/360 environment prior to the introduction of Job Entry Subsystems (JES), Job Entry Control Language (JECL) served as an extension to standard OS JCL, enabling enhanced control over job submission and processing through spooling programs like the Houston Automatic Spooling Priority (HASP). These JECL statements, prefixed with /*, were processed in the system's reader/interpreter mode, where jobs were submitted directly without intermediate queuing, allowing immediate interpretation and execution by the operating system. HASP, developed as an add-on to OS/360, facilitated this direct mode while providing basic spooling for input and output, bridging the gap between basic OS/360 job handling and more advanced subsystem capabilities.[9] Key JECL statements included /*JOBPARM, which specified job-related parameters such as estimated execution time (via ESTLNCT), and punched card output ($ESTPUN) to aid HASP in resource allocation and scheduling. The /*SIGNON statement supported remote job entry by allowing terminals to connect to HASP, often specifying line numbers or passwords for secure access to the system. For accounting purposes, /*NETACCT provided network and resource usage details, interpreted by HASP's input processor to track billing and resource consumption. Additionally, /*ROUTE directed output destinations, such as routing print or punch data to specific remote printers or local devices, enhancing flexibility in multi-site environments.[64] This pre-JES JECL approach was integral to HASP's operation in OS/360, where it handled job flow without a dedicated queuing subsystem, relying instead on direct reader processing for efficiency in batch environments. However, as IBM transitioned to more sophisticated job management, these HASP-based JECL elements were gradually phased out following the introduction of JES in the mid-1970s, with full integration occurring around 1976 alongside OS/VS2 MVS releases.[65]JES2 and JES3 JECL in z/OS
In z/OS environments, JES2 and JES3 employ Job Entry Control Language (JECL) statements to extend JCL capabilities for job submission, routing, prioritization, and resource management, with JES3 emphasizing centralized control in multi-system complexes while JES2 supports more distributed, independent processing across nodes.[26][66] JECL statements begin with/* and are typically placed after the JOB statement but before the first EXEC statement, allowing users to specify JES-specific options without altering core JCL.[26]
JES2 JECL includes the /*JOBPARM statement, which defines job attributes such as system affinity (SYSAFF), output class (CLASS), priority, number of copies (COPIES), forms type (FORMS), and resource limits like lines (LINES) or bytes (BYTES); its syntax is /*JOBPARM [parameter](/page/Parameter)=value, for example, /*JOBPARM SYSAFF=CFH1,CLASS=A,COPIES=2.[26] This statement overrides system defaults for job scheduling and output handling in JES2's decentralized model, where each node manages its own resources independently.[66] Additionally, /*XSUM requests a job execution summary report detailing step completion, resource usage, and return codes, invoked simply as /*XSUM at the job's end to aid in performance analysis without requiring operator intervention.[26] JES2 also extends dynamic allocation through JECL integration, allowing runtime adjustments to datasets and devices via parameters like PROCLIB for procedure libraries.[26]
In contrast, JES3 JECL supports centralized management in sysplex environments, featuring the /*NETSERV statement to configure network job entry parameters such as destination (DEST) for routing across systems, with syntax /*NETSERV DEST=NY to direct jobs or output to a remote JES3 node.[26][66] The /*SIGNON statement authenticates users or initiates sessions in multi-CPU setups, using syntax like /*SIGNON userid,password or /*SIGNON workstation-name A R passwd1 passwd2 new-passwd to establish secure access and override local controls from a global JES3 main.[26] These statements enable JES3's hierarchical control, where a single global instance schedules resources across local systems, differing from JES2's peer-to-peer approach.[66]
Both JES2 and JES3 share /*ROUTE and /*PRIORITY for spooling integration with JCL. The /*ROUTE statement directs job execution or output to specific nodes, printers, or systems, with variants like /*ROUTE XEQ=node for execution routing or /*ROUTE PRINT=dest for output, supporting multi-statement sequences for complex paths.[26] The /*PRIORITY statement assigns a numeric priority (0-15 in JES2, 0-14 in JES3) to influence queue positioning, as in /*PRIORITY 10, and works alongside JCL's JOB statement for unified spooling of sysout datasets.[26] These shared elements ensure compatibility for basic job flow while leveraging JES-specific extensions for advanced environments.
As of z/OS 3.2 (September 2025), JECL core functionality remains unchanged, but enhancements include expanded JES2 support for JES3 statements (initiated in V2R2) via INPUTDEF and JECLDEF parameters, along with API hooks in installation exits for custom JECL processing and integration with z/OS management facilities.[26][67][68] This convergence facilitates migrations between JES2 and JES3 without full JCL rewrites, maintaining backward compatibility for legacy pre-JES precursors.[69]
JECL in z/VSE
Job Entry Control Language (JECL) in z/VSE extends the core JCL framework with POWER statements to manage job submission, execution, and output in IBM's z/Virtual Storage Extended (z/VSE) operating system, which evolved from DOS/360 influences for efficient resource handling in smaller-scale environments.[70] These POWER statements, prefixed with* $$, integrate seamlessly with standard JCL (using // for job steps) to provide subsystem-level control, such as assigning execution classes and priorities. For instance, the * $$ CTL statement assigns a default execution class (e.g., CLASS=A) and manages job flow, overriding defaults set by the PSTART command, while * $$ JOB delimits the start of a job with attributes like name (JNM=jobname), priority (PRI=5), and disposition (DISP=D).[70] This integration allows JECL to handle both batch processing and interaction with online subsystems, distinguishing it from the more expansive OS/360 JCL by emphasizing compact, DOS-like device addressing (e.g., using control unit address cuu for queues).[70]
Key features of JECL in z/VSE include robust subsystem queuing for input (RDR), output (LST and PUN), and transmission (XMT) queues, supporting up to 36 classes (A-Z, 0-9) and 10 priority levels (0-9) to optimize resource allocation in multi-partition setups.[70] The // PAUSE statement suspends job processing for operator intervention by halting execution and issuing messages on SYSLOG (e.g., for manual actions like error resolution or disposition changes), with the operator resuming by pressing END/ENTER.[17] Output management is handled via statements like * $$ LST for print attributes (e.g., CLASS=B, DISP=K, ROUTE=[WORKSTATION](/page/Workstation)) and * $$ PUN for punch output, with options for tape offloading (POFFLOAD SAVE,LST,280) and token tracking (TKN=00000105) to segment and route data efficiently.[70] These capabilities support dynamic partitioning and shared spooling, making JECL suitable for environments with limited resources compared to the enterprise-scale queuing in OS/360 derivatives.[70]
Following the end-of-service for IBM z/VSE Version 6 Release 2, in 2025 JECL remains integral to compatible systems like 21CS VSEn 6.4 (available October 2025), facilitating hybrid batch and online workloads through features like remote job entry and time-based scheduling (e.g., * $$ JOB DUETIME=1330, DUEDAY=DAILY).[71][72] It supports ongoing operations on IBM Z hardware, including integration with networking for distributed processing, while maintaining backward compatibility with DOS-era conventions for device independence.[73] An example JECL snippet might appear as:
* $$ JOB JNM=EXAMPLE, CLASS=A, PRI=5
* $$ CTL CLASS=A
// JOB EXAMPLE
// EXEC PGM=MYPROG
* $$ LST CLASS=B, DISP=H
* $$ EOJ
* $$ JOB JNM=EXAMPLE, CLASS=A, PRI=5
* $$ CTL CLASS=A
// JOB EXAMPLE
// EXEC PGM=MYPROG
* $$ LST CLASS=B, DISP=H
* $$ EOJ
