cheat sheet

JCL DD Statement

Comprehensive reference for the JCL DD statement: DSN, DISP, DCB, SPACE, UNIT, VOL=SER, concatenation, DUMMY, SYSOUT, KEYLEN.

JCL DD Statement — Deep Reference

What it is

The DD (Data Definition) statement is the JCL card that binds a ddname inside a program — the logical file the program opens — to a real dataset, in-stream data, SYSOUT class, or no-op. It is the single most parameter-dense statement in JCL, controlling allocation (SPACE, UNIT, VOL=SER), lifecycle (DISP), record format (DCB), and routing (SYSOUT, DUMMY, NULLFILE). JCL quick reference covers the surrounding JOB and EXEC syntax; this page goes deep on every DD keyword you will encounter in production batch.

Install

DD statements are part of the JCL language and ship with z/OS — there is nothing to install. Code them in any sequential dataset, PDS member, or in-stream and run them through JES2 / JES3 with the TSO SUBMIT command, the SDSF SE action, or zowe jobs submit.

text
SUBMIT 'ALICE.JCL.LIB(SAMPLEJOB)'

Output: (none — exits 0 on success)

Syntax

A DD statement starts in column 1 with //, a 1–8 character ddname in columns 3–10, the keyword DD, and then a list of keyword sub-parameters separated by commas. Continuation onto the next card requires // in columns 1–2 and a non-blank character no earlier than column 4; long parameter lists are usually split after a comma.

text
//ddname   DD param1=value1,
//             param2=value2,
//             param3=(sub1,sub2)

Output: (none — exits 0 on success)

Essential keywords

KeywordMeaning
DSN= (or DSNAME=)Dataset name — cataloged, uncataloged, temp, GDG, member
DISP=Status, normal-end, abnormal-end disposition
DCB=Data Control Block — RECFM, LRECL, BLKSIZE, DSORG, KEYLEN
SPACE=Primary, secondary, directory blocks
UNIT=Device type (SYSDA, TAPE, 3390, …)
VOL=SER=Specific volume serial(s)
LABEL=Tape label / file position
RECFM= / LRECL= / BLKSIZE=DCB sub-parameters when given directly
DSNTYPE=LIBRARY (PDSE), PDS, HFS, LARGE, EXTREQ, EXTPREF
EXPDT= / RETPD=Expiration date / retention period
SYSOUT=Route to JES spool (class, optional output dest)
DUMMY / DSN=NULLFILENo I/O — open succeeds, EOF on first read
KEYLEN= / KEYOFF=Sequenced-key length and offset (VSAM, extended-format)
STORCLAS= / MGMTCLAS= / DATACLAS=SMS class overrides
AVGREC=SPACE primary/secondary measured in records (U/K/M units)
FREE=When to deallocate (END, CLOSE)

DSN — dataset naming patterns

The DSN parameter names what the ddname refers to. Names follow the standard z/OS dataset naming rules — up to 44 characters, 1–22 qualifiers separated by ., each qualifier 1–8 characters of alphanumeric plus @#$, the first qualifier (HLQ) used by RACF to find the matching profile. Temporary, GDG, and PDS-member forms add syntax on top.

Cataloged dataset

When the dataset is in the master/user catalog (the normal case), give the name alone — z/OS resolves the unit and volume from the catalog.

text
//INFILE   DD DSN=ALICE.PAYROLL.MASTER,DISP=SHR

Output: (none — exits 0 on success)

Uncataloged dataset

For a dataset that exists on a volume but is not cataloged, include UNIT and VOL=SER so the system can find it without consulting the catalog.

text
//INFILE   DD DSN=ALICE.PAYROLL.MASTER,
//             DISP=SHR,
//             UNIT=SYSDA,
//             VOL=SER=PRD001

Output: (none — exits 0 on success)

Generation Data Group (GDG) reference

GDG members are referenced by relative number — (0) is the current generation, (-1) the previous, (+1) a new generation created by this job. The base must already exist (defined with IDCAMS DEFINE GENERATIONDATAGROUP).

text
//* Most recent existing generation
//INFILE   DD DSN=ALICE.SALES.HISTORY(0),DISP=SHR

//* Two generations back
//INFILE2  DD DSN=ALICE.SALES.HISTORY(-2),DISP=SHR

//* Create a new generation
//OUTFILE  DD DSN=ALICE.SALES.HISTORY(+1),
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(50,10),RLSE),
//             DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)

//* Absolute generation name (rarely needed)
//INFILE3  DD DSN=ALICE.SALES.HISTORY.G0042V00,DISP=SHR

Output: (none — exits 0 on success)

Temporary datasets

A name beginning with && is a job-temporary dataset; allocated when the step needs it, kept until the disposition says otherwise, deleted automatically when the job ends if the system has nothing else holding it. Use them to pass data between steps in the same job.

text
//STEP01   EXEC PGM=SORT
//SORTIN   DD DSN=ALICE.INPUT,DISP=SHR
//SORTOUT  DD DSN=&&SORTED,
//             DISP=(NEW,PASS),
//             SPACE=(CYL,(5,5)),
//             DCB=(RECFM=FB,LRECL=80)
//STEP02   EXEC PGM=ALICEPGM
//INFILE   DD DSN=&&SORTED,DISP=(OLD,DELETE)

Output: (none — exits 0 on success)

PDS / PDSE member

DSN=lib(member) opens one member of a partitioned dataset. The library can be a PDS, a PDSE (DSNTYPE=LIBRARY), or a load library; the member name is 1–8 chars.

text
//SYSPROC  DD DSN=ALICE.REXX.LIB(ALICEX01),DISP=SHR
//SYSIN    DD DSN=ALICE.JCL.LIB(SAMPLE),DISP=SHR

Output: (none — exits 0 on success)

Names with special characters

Quoted DSN with single quotes lets you embed special characters; uncommon outside test rigs but required when migrating from non-mainframe naming. Lowercase is allowed inside the quotes but z/OS folds the qualifiers to uppercase at allocation unless the dataset is SMS-managed and explicitly tagged for mixed case.

text
//ODD      DD DSN='ALICE.QUOTED-NAME.DATA',DISP=SHR

Output: (none — exits 0 on success)

DISP — disposition

DISP is a three-part keyword giving the dataset's current status, what to do at normal step end, and what to do at abnormal step end. The first sub-parameter affects allocation; the second and third affect cleanup at step exit.

text
DISP=(status, normal-end, abnormal-end)
StatusMeaning
NEWAllocate a new dataset; fails if it already exists
OLDExclusive access to an existing dataset
SHRShared (read) access — multiple jobs allowed
MODAppend to an existing dataset (or create if NEW)
Normal / abnormalMeaning
DELETEUncatalog and scratch (frees DASD)
KEEPLeave dataset on disk; do not change catalog state
CATLGCatalog the dataset (default for NEW with no second sub-parameter on SMS volumes)
UNCATLGRemove catalog entry, leave dataset on disk
PASSHand off to a later step in the same job

DISP truth table

DISP=First stepAfter normal step end
(NEW,CATLG,DELETE)Allocate new, catalogKeep + catalog on success, scratch on failure
(NEW,KEEP)Allocate new, uncatalogedKeep on disk, no catalog entry
(OLD,DELETE)ExclusiveScratch the dataset
(OLD,KEEP)ExclusiveLeave alone
(SHR,KEEP)Shared readLeave alone
(MOD,CATLG)Append (create if NEW)Catalog if newly created
(NEW,PASS)Allocate, exclusivePass to next step (still NEW until terminal disp)
text
//* Pattern: build a new output, keep on success, throw away on fail
//OUT      DD DSN=ALICE.WORK.NEW,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(10,5)),
//             DCB=(RECFM=FB,LRECL=80)

//* Pattern: read shared (multiple jobs may open it)
//IN       DD DSN=ALICE.MASTER,DISP=SHR

//* Pattern: append to a log
//LOG      DD DSN=ALICE.AUDIT.LOG,DISP=MOD

//* Pattern: pass a temp file between steps
//STEP1    EXEC PGM=PROG1
//OUT      DD DSN=&&PASS,DISP=(NEW,PASS),
//             SPACE=(CYL,(1,1)),DCB=(RECFM=FB,LRECL=80)
//STEP2    EXEC PGM=PROG2
//IN       DD DSN=&&PASS,DISP=(OLD,DELETE)

Output: (none — exits 0 on success)

DCB — data control block

DCB describes the record format, length, and blocking. SMS-managed datasets pick up the missing pieces from the data class; non-SMS datasets and tape need everything explicit. Modern shops usually let BLKSIZE=0 so the system picks a half-track optimum.

text
DCB=(RECFM=FB,LRECL=80,BLKSIZE=0,DSORG=PS)
Sub-parameterMeaning
RECFM=FFixed-length records
RECFM=VVariable-length records
RECFM=FBFixed Blocked — multiple records per block
RECFM=VBVariable Blocked
RECFM=FBAFB + ANSI carriage control (first byte = print control)
RECFM=VBAVB + ANSI carriage control
RECFM=UUndefined — block = record (load libraries)
LRECL=nRecord length in bytes (max 32760 for non-LARGE, 32756 for V)
BLKSIZE=nBlock size; 0 lets the system pick system-determined
DSORG=PSPhysical sequential
DSORG=POPartitioned organisation (PDS)
DSORG=DADirect
DSORG=ISIndexed sequential (legacy)

Common DCB recipes

text
(* 80-byte source/JCL - classic *)
DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)

(* 132-byte print/report *)
DCB=(RECFM=FBA,LRECL=133,BLKSIZE=0)

(* Variable data - typical EDI / text *)
DCB=(RECFM=VB,LRECL=255,BLKSIZE=0)

(* Long variable - max 32756 / 32760 minus 4 RDW *)
DCB=(RECFM=VB,LRECL=32756,BLKSIZE=0)

(* Load library *)
DCB=(RECFM=U,BLKSIZE=32760)

(* PDS source *)
DCB=(RECFM=FB,LRECL=80,DSORG=PO)

Output: (none — exits 0 on success)

Referencing another dataset's DCB

DCB=*.stepname.ddname copies DCB attributes from a previously-allocated DD in the same job; DCB=ALICE.MODEL.DS copies from a model dataset on disk.

text
//OUT      DD DSN=ALICE.WORK.COPY,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(5,5)),
//             DCB=*.STEP01.INFILE

Output: (none — exits 0 on success)

SPACE — DASD allocation

SPACE= requests primary and secondary allocations and (for PDS) a directory-block count. The unit is TRK (tracks), CYL (cylinders — recommended for anything non-trivial), or a record length for AVGREC-style allocation. Always code a secondary extent — a missing one is the most common cause of B37 / D37 abends.

text
SPACE=(unit, (primary, secondary, directory), RLSE, CONTIG, ROUND)
Sub-parameterMeaning
TRKAllocate in tracks
CYLAllocate in cylinders (1 cyl = 15 tracks on 3390)
nRecord-length unit when AVGREC= is given
(prim,sec)Primary + secondary extents
(prim,sec,dir)Primary + secondary + PDS directory blocks
RLSERelease unused space at close (return to free pool)
CONTIGPrimary must be one contiguous extent
ROUNDRound to whole cylinders when AVGREC is in use
MXIGTake the largest available extent
ALXTake up to five largest extents

Common SPACE recipes

text
(* Small sequential, release leftovers *)
SPACE=(TRK,(5,5),RLSE)

(* Medium sequential *)
SPACE=(CYL,(50,10),RLSE)

(* Large dataset, 16K records average *)
AVGREC=K,SPACE=(160,(100,50),RLSE)
(* Allocates space for ~100K records of 160 bytes *)

(* PDS with 100 directory blocks *)
SPACE=(CYL,(10,5,100))

(* Empty PDSE - directory count is meaningless *)
SPACE=(CYL,(10,5,0)),DSNTYPE=LIBRARY

Output: (none — exits 0 on success)

B37 / D37 / E37 abends

These are the three space-related allocation failures every batch programmer learns the hard way: B37 = no more secondary extents and the volume is full, D37 = primary too small and no secondary specified, E37 = volume has run out of extents and the dataset has reached the 16-extent (or 123-extent for SMS) limit. The fix is RLSE to free unused space, a larger primary, or splitting across multiple volumes.

text
(* Multi-volume on shared DASD *)
//BIG      DD DSN=ALICE.HUGE.FILE,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(900,200),RLSE),
//             UNIT=(SYSDA,4),         (* up to 4 volumes *)
//             VOL=(,,,4),
//             DCB=(RECFM=FB,LRECL=80)

Output: (none — exits 0 on success)

UNIT and VOL=SER

UNIT= names a device class (esoteric name like SYSDA, or generic like 3390, or specific address 181); VOL=SER= pins the dataset to a specific volume. SMS-managed allocations use storage and management classes instead and you can omit both.

text
//* Allocate on a specific volume
//OUT      DD DSN=ALICE.WORK,
//             DISP=(NEW,CATLG,DELETE),
//             UNIT=SYSDA,
//             VOL=SER=WRK001,
//             SPACE=(CYL,(10,5))

//* Multi-volume preallocation
//BIG      DD DSN=ALICE.HUGE,
//             DISP=(NEW,CATLG,DELETE),
//             UNIT=(SYSDA,3),
//             VOL=SER=(WRK001,WRK002,WRK003),
//             SPACE=(CYL,(500,100))

//* Specific device address - rare
//TAPE     DD DSN=ALICE.BACKUP,
//             DISP=(NEW,CATLG,DELETE),
//             UNIT=(0A80,DEFER),
//             VOL=SER=ALICE1,
//             LABEL=(1,SL)

Output: (none — exits 0 on success)

Device classes you will see

UNIT valueDevices it covers
SYSDAGeneric DASD (3390)
SYSALLDAAll DASD types
33903390 disk family
TAPETape — installation-defined esoteric
CARTCartridge tape
VIOVirtual I/O (in-storage) — temp datasets only

In-stream data (DD *) and DD DATA

For small inputs you can put records right in the JCL. DD * ends at the next JCL card or the /* delimiter; DD DATA is identical except it does not stop at //, which is useful when the in-stream data itself contains JCL-looking records.

text
//SYSIN    DD *
  LISTCAT ENT(ALICE.PAYROLL.MASTER) ALL
/*

//* Custom delimiter when default conflicts with data
//SYSIN    DD *,DLM=@@
  // some text that starts like JCL
  //*  also fine
@@

//* Plain DD DATA - reads until //END
//SYSIN    DD DATA
//STEP01 EXEC PGM=IEFBR14
//SYSPRINT DD SYSOUT=*
//END

Output: (none — exits 0 on success)

Concatenation

Multiple datasets can be concatenated to a single ddname so the program sees them as one logical input. Code the first DD with the ddname and parameters, then subsequent DDs with blank ddnames; all DSNs must have compatible attributes (matching RECFM/LRECL, or the largest must come first).

text
//* Three input datasets read as one
//SYSPROC  DD DSN=ALICE.REXX.SITE,DISP=SHR
//         DD DSN=SYS1.SBPXEXEC,DISP=SHR
//         DD DSN=SYS1.SAXREXEC,DISP=SHR

//* Concatenating in-stream data and a dataset
//SYSIN    DD *
   LISTCAT ENT(ALICE.PAYROLL.MASTER) ALL
/*
//         DD DSN=ALICE.IDCAMS.COMMANDS(MORE),DISP=SHR

Output: (none — exits 0 on success)

Concatenation rules

  1. Maximum 16 datasets per DD chain (255 for PDSE/USS files in some cases).
  2. Mix PDS and PS — the result is read as if it were one logical sequential file.
  3. Different LRECL is allowed only when the largest is in the first concatenation.
  4. DCB is taken from the first DD unless overridden.
  5. Concatenating DUMMY short-circuits the rest — never useful, but worth knowing.

DUMMY and NULLFILE

DUMMY (or DSN=NULLFILE) makes the OPEN succeed and every read return EOF, every write succeed silently. Use it to stub out optional inputs during testing or to discard an unused output.

text
//* Skip an input
//INFILE   DD DUMMY

//* Equivalent
//INFILE   DD DSN=NULLFILE

//* DCB attributes still apply (some programs check them)
//INFILE   DD DUMMY,DCB=(RECFM=FB,LRECL=80)

//* Discard output
//OUTFILE  DD DUMMY,DCB=(RECFM=FB,LRECL=80)

Output: (none — exits 0 on success)

SYSOUT — JES spool

SYSOUT= routes the output to the JES2/JES3 spool instead of a dataset. The class (a single letter usually A through Z or 0 through 9) selects the JES output queue; * inherits the MSGCLASS on the JOB card.

text
(* Default class = MSGCLASS *)
//SYSPRINT DD SYSOUT=*

(* Specific class - H is held output in most shops *)
//REPORT   DD SYSOUT=H

(* With JES output writer and form *)
//PRINT    DD SYSOUT=(A,,STD1)

(* Route to internal reader - submits the dataset as a job *)
//RDR      DD SYSOUT=(*,INTRDR)

(* Hold for browse without printing *)
//HELD     DD SYSOUT=*,OUTPUT=*.HELD
//HELD     OUTPUT  CLASS=X,DEST=HOLD

Output: (none — exits 0 on success)

Useful SYSOUT extras

ParameterMeaning
COPIES=nPrint N copies
DEST=Route to a specific destination
FORMS=Specify a form ID
FCB=Forms Control Buffer
CHARS=Print character set (XEROX/3800 era)
BURST=YBurst output (paper printers)
HOLD=YESHold output for browse
OUTLIM=Limit lines before JES forces termination
FREE=CLOSESpool to JES at CLOSE instead of step end

KEYLEN / KEYOFF

These DCB sub-parameters describe a key field for indexed-sequential, VSAM-emulated, or extended-format sequential datasets. KEYLEN is the key length in bytes, KEYOFF is the byte offset from the start of the record where the key begins.

text
(* Sequential dataset with extended format and a key for use with SORTKEYS *)
//OUT      DD DSN=ALICE.KEYED.DS,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(10,5)),
//             DCB=(RECFM=FB,LRECL=100),
//             KEYLEN=8,KEYOFF=0,
//             DSNTYPE=EXTREQ

(* IDCAMS uses these on DEFINE CLUSTER instead - DD-level KEYLEN
   is the rare case for non-VSAM indexed access *)

Output: (none — exits 0 on success)

SMS classes

When SMS (Storage Management Subsystem) is active most allocation decisions move from JCL to installation-defined classes. SMS uses ACS routines on the dataset name to pick STORCLAS (where on disk it goes), MGMTCLAS (backup, migration, retention) and DATACLAS (RECFM, LRECL, BLKSIZE, KEYLEN, KEYOFF, SPACE defaults). You can override any of them at JCL level.

text
//OUT      DD DSN=ALICE.SMS.OUTPUT,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(10,5),RLSE),
//             DATACLAS=DC80FB,
//             STORCLAS=SCSTD,
//             MGMTCLAS=MCRETN90

Output: (none — exits 0 on success)

EXPDT and RETPD

Retention controls let JES (and DFHSM) know when the dataset becomes eligible for deletion. EXPDT is an explicit expiration date; RETPD is a retention period in days. Common pattern for production data is RETPD=14 with HSM ML2 migration after 7 idle days.

text
//OUT      DD DSN=ALICE.DAILY.BACKUP(+1),
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(50,10),RLSE),
//             RETPD=14

(* "Never expire" - the convention *)
//OUT      DD DSN=ALICE.PERMANENT,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(5,5)),
//             EXPDT=99000

(* Never expire post-2000 - new convention *)
EXPDT=1999/365

Output: (none — exits 0 on success)

Common pitfalls

  1. Forgetting the secondary extentSPACE=(CYL,(10)) with no secondary gets a B37/D37 the first time the data outgrows ten cylinders. Always code (prim,sec).
  2. DISP=NEW on a dataset that already exists — gets a JCL error IGD17001I or IEC141I 013. Use DISP=OLD (or MOD) to reuse, or delete first with an IEFBR14 step.
  3. DISP=SHR to write — z/OS allows write through a SHR allocation; another job may corrupt your data. Use OLD for any write-mode open.
  4. In-stream DD * and lowercase data — column 1 of in-stream data must be uppercase unless the JES2 parameter LOWERCASE=YES is in effect, otherwise the JES card scanner may flag it. Use DD DATA,DLM=@@ for free-form text.
  5. Mismatched LRECL in concatenation — opens succeed but reads truncate to the first DD's LRECL. Always put the largest LRECL first or use DCB=(LRECL=largest) on the head DD.
  6. BLKSIZE=0 on a non-SMS dataset — system-determined BLKSIZE only works for SMS-managed datasets or when IGGCAS00/half-track defaults are enabled in PARMLIB. Outside SMS, code an explicit blocksize.
  7. DUMMY doesn't satisfy a required input check — programs that re-verify their input via DSCB will see "no real DSN" and fail. Use a small empty dataset instead.
  8. GDG (+1) referenced in a later step without DISP=PASS — the new generation isn't catalogued until the job ends. Code DISP=(NEW,PASS) then DISP=(OLD,CATLG) (or rely on RETAIN for newer LE).
  9. Tape datasets and EXPDT=99000 — on some shops this is interpreted as "never scratch", on others as a fixed-date in 1999. Use the unambiguous EXPDT=1999/365 form.
  10. UNIT=AFF=otherdd — affinity makes the new DD use the same volume as another allocation. Forgetting it means a second tape mount; remembering it the wrong way means jobs block each other on the same drive.
  11. FREE=CLOSE and re-opening — once the dataset is freed at CLOSE, opening it again in the same step requires re-allocation. Most programs assume the DD stays bound for the step's life.
  12. GDG generations and DISP=MOD — never use MOD on a GDG (+1); the generation is created on first allocation, and the next step that references (+1) gets the same one (one generation, not two).

Sources

References consulted while writing this article. Links open in a new tab.

  • IBM Documentation — DD statement (z/OS MVS JCL Reference) — Authoritative reference for DD parameters (DSN, DISP, SPACE, DCB, FREE, UNIT, VOL) used in this article.

Real-world recipes

Allocate a new performance-tuned PS dataset

A daily ingest job needs a large fixed-block sequential dataset with system-optimised blocking, generous secondary extents, and release-on-close to avoid wasted DASD.

text
//ALICEJ01 JOB (ACCT),'DAILY INGEST',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//STEP01   EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN    DD DUMMY
//SYSUT1   DD DSN=ALICE.SRC.INPUT,DISP=SHR
//SYSUT2   DD DSN=ALICE.DAILY.LOAD,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(300,100),RLSE),
//             DCB=(RECFM=FB,LRECL=200,BLKSIZE=0),
//             DATACLAS=DC200FB,
//             MGMTCLAS=MCRETN30,
//             AVGREC=K

Output:

text
IEB352I  WARNING: ONE OR MORE OF THE OUTPUT DCB PARMS COPIED FROM INPUT
IEB1135I IEBGENER  PROCESSING ENDED AT EOD

Build then read a GDG with PASS

A two-step job creates a new generation in step 1 and reads it in step 2 without going through the catalog (which would only be updated at job end).

text
//ALICEJ02 JOB (ACCT),'GDG PIPELINE',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//STEP01   EXEC PGM=SORT
//SORTIN   DD DSN=ALICE.SRC.DAILY,DISP=SHR
//SORTOUT  DD DSN=ALICE.SALES.HISTORY(+1),
//             DISP=(NEW,PASS),
//             SPACE=(CYL,(50,10),RLSE),
//             DCB=(RECFM=FB,LRECL=80)
//SYSIN    DD *
   SORT FIELDS=(1,8,CH,A)
/*
//SYSOUT   DD SYSOUT=*
//STEP02   EXEC PGM=ALICEPGM
//INFILE   DD DSN=ALICE.SALES.HISTORY(+1),DISP=(OLD,CATLG)
//SYSOUT   DD SYSOUT=*

Output:

text
ICE000I 1 -  CONTROL STATEMENTS FOR SORT - LEVEL 12.0
ICE201I H RECORD TYPE IS F - DATA STARTS IN POSITION 1
ICE751I 1 -  EFL-K06032: 0 IN: 142811 OUT: 142811

Multi-volume large dataset

A retention archive needs to span up to four DASD volumes; use UNIT=(SYSDA,4) and VOL=(,,,4) for the volume count.

text
//ARCHIVE  DD DSN=ALICE.ARCHIVE.HUGE,
//             DISP=(NEW,CATLG,DELETE),
//             UNIT=(SYSDA,4),
//             VOL=(,,,4),
//             SPACE=(CYL,(2000,500),RLSE),
//             DCB=(RECFM=VB,LRECL=32756,BLKSIZE=0),
//             MGMTCLAS=MCARCHV

Output: (none — exits 0 on success)

Submit a downstream job via internal reader

A scheduler job builds a child JCL on the fly and pushes it to the internal reader; JES picks it up and queues it like any other submission.

text
//ALICEJ03 JOB (ACCT),'SUBMIT CHILD',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//SUB      EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN    DD DUMMY
//SYSUT1   DD *
//ALICEJ04 JOB (ACCT),'CHILD',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//STEP01   EXEC PGM=IEFBR14
//DD1      DD DSN=ALICE.CHILD.SCRATCH,
//             DISP=(NEW,DELETE,DELETE),
//             SPACE=(TRK,(1,1)),
//             DCB=(RECFM=FB,LRECL=80)
/*
//SYSUT2   DD SYSOUT=(*,INTRDR)

Output:

text
IEB352I  WARNING: ONE OR MORE OF THE OUTPUT DCB PARMS COPIED FROM INPUT
IEB1135I IEBGENER  PROCESSING ENDED AT EOD
$HASP100 ALICEJ04 ON INTRDR     CHILD

Discover the optimal BLKSIZE for an existing dataset

Use IDCAMS LISTCAT to inspect the actual block size SMS picked for a similar dataset, then reuse it on the next allocation.

text
//LISTCAT  EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
   LISTCAT ENT('ALICE.MODEL.DS') ALL
/*

Output:

text
NONVSAM ------- ALICE.MODEL.DS
     IN-CAT --- CATALOG.MASTER
     HISTORY
       DATASET-OWNER-----ALICE        CREATION-----------26.140
       RELEASE----------------2       EXPIRATION----------00.000
     SMSDATA
       STORAGECLASS ---SCSTD          MANAGEMENTCLASS-MCRETN30
       DATACLASS ------DC200FB        LBACKUP ---0000.000.0000
     ATTRIBUTES
       RECORG---NULL                  RECFM----FB
       LRECL------------200           BLKSIZE--------27800
       KEYLEN----------NULL           RKP-------------NULL
       EXTENTS-----------1            EXTHIGH-----------12

Concatenate a per-job override library in front of the site library

A common DevOps pattern — let the developer's PDS take precedence over the site library so a hotfix can be tested without changing the shared copy.

text
//SYSPROC  DD DSN=ALICE.MY.REXX,DISP=SHR        (* developer override *)
//         DD DSN=SYS1.SBPXEXEC,DISP=SHR
//         DD DSN=SYS1.SAXREXEC,DISP=SHR

Output: (none — exits 0 on success)

Capture step output even if the step abends

Wrap a problem job with FREE=CLOSE and a SYSOUT class that doesn't get purged on abend so you can still read the spool.

text
//STEP01   EXEC PGM=ALICEPGM
//SYSPRINT DD SYSOUT=X,FREE=CLOSE
//SYSUDUMP DD SYSOUT=X,FREE=CLOSE
//SYSIN    DD DSN=ALICE.INPUT,DISP=SHR
//OUTFILE  DD DSN=ALICE.OUTPUT,
//             DISP=(NEW,CATLG,KEEP),       (* KEEP on abend so partial output stays *)
//             SPACE=(CYL,(10,5),RLSE),
//             DCB=(RECFM=FB,LRECL=200)

Output: (none — exits 0 on success)