cheat sheet

JES2

z/OS Job Entry Subsystem 2 operator slash-commands for jobs, initiators, output, classes, NJE, and spool — from the console and from SDSF.

JES2 — Operator commands and subsystem control

What it is

JES2 (Job Entry Subsystem 2) is the IBM-supplied component of z/OS that reads jobs into the system, schedules them across initiators, manages SYSOUT until it is printed or purged, and (with NJE) ships work between connected systems. The "2" distinguishes it from JES3 — a different scheduler with a more centralized design — but on the vast majority of z/OS installations today, JES2 is the running subsystem. All JES2 operator commands begin with a dollar-sign verb ($D, $P, $S, $T, $E, $C, $N, $M), are issued from a system console or via the SDSF command line prefixed with /, and operate on resources identified by single-letter type codes (J for job, I for initiator, O for output group, Q for output queue, JC for job class, PRT for printer, SPL for spool, and so on). Reach for JES2 commands when you need to display the state of work in flight, hold or release jobs, bring initiators online or offline, redirect output classes, or manage spool space; for the panel-driven equivalent of the same operations, drive these commands through SDSF, which surfaces the same JES2 verbs through its prefix and slash-command interface.

Command anatomy

Every JES2 command has the same general shape: a $ verb that says what to do, an object code that says what kind of resource, an optional identifier or range, and zero or more ,KEYWORD=VALUE modifiers.

text
$verb<object><id>,KEYWORD=value,...
VerbAction
$DDisplay — read-only status report.
$PStop / drain (gracefully).
$SStart.
$TSet / alter attributes.
$ERestart (release after a hold).
$CCancel (force termination).
$HHold (defer execution or output).
$ARelease (resume from held).
$ORelease output for processing.
$NSend a message over NJE.
$MSend a message between consoles.
$LList long form.
$ZHalt (immediate stop, dangerous).

A command may be issued from any of three places: the system console (master or alternate), an SDSF ===> line prefixed with /, or a console interface program like OPERLOG. The dollar-sign prefix is universal to JES2; JES3 used * (asterisk) and a different command grammar.

Display commands

$D is the safest place to start any session — it reports state without changing anything. Every other verb has a corresponding $D variant so you can preview what is currently configured before changing it.

Jobs in the system

$DJ (display job) is the most-used JES2 command after $DA. Without an identifier it lists every job currently known to JES2 — input, conversion, execution, output, and held queues all at once.

text
$DJ                             (* every job in the system *)
$DJ ALL                         (* same, but include print-queue jobs *)
$DJ ALICEJ01                    (* a single job by name *)
$DJ JOB00123                    (* a single job by JES JOBID *)
$DJ JOB00100-JOB00200           (* a range of JOBIDs *)
$DJ Q=XEQ                       (* jobs currently executing *)
$DJ Q=INPUT                     (* jobs queued for execution *)
$DJ Q=OUTPUT                    (* jobs awaiting print *)
$DJ Q=HELD                      (* jobs held *)
$DJ /ALICE*                     (* jobs whose name matches a pattern *)
$DJ A=YES                       (* active jobs only *)
$DJ /ALICEJ01,CC                (* completion code for ALICEJ01 *)
$DJ /ALICEJ01,STC               (* status, completion, queue *)

The display response is a $HASP890 message stream — one line per job — that names the job, the JOBID, the class, the current status, and the completion code if known.

Active jobs and initiators

$DA (display active) reports just the executing work — useful when you need to know what an initiator is running right now. The compact form fits on a console screen.

text
$DA                             (* every active job and TSO user *)
$DA ALL                         (* include initiators in wait state *)
$DA J=ALICEJ01                  (* one named job *)
$DA J=JOB00123                  (* one job by JOBID *)
$DA U=*                         (* TSO users only *)

Initiators

A JES2 initiator is the address space that selects a job from the input queue, runs it, and returns to wait for the next. Their count, classes, and status are core dispatch knobs.

text
$DI                             (* all initiators *)
$DI 1                           (* a single initiator by number *)
$DI 1-10                        (* a range of initiators *)
$DI ALL                         (* include drained initiators *)

Output identifies the initiator number, its current status (ACTIVE, INACTIVE, DRAINED, STOPPED), the job classes it services, and the job (if any) it is currently running.

Output and printers

$DO lists held and selectable output. $DPRT lists local printer devices defined to JES2.

text
$DO                             (* every output group *)
$DO Q=O                         (* output queue O *)
$DO /ALICEJ01                   (* output for one job name *)
$DPRT                           (* every printer device *)
$DPRT 1                         (* a single printer *)
$DPRT ALL                       (* include drained printers *)
$DPUN                           (* every punch device (rarely used) *)

Job classes and SYSOUT classes

Job classes (JOBCLASS(x)) control which initiators pick up a job. SYSOUT classes (OUTCLASS(x)) control how output is processed.

text
$DJOBCLASS(A)                   (* show settings for job class A *)
$DJOBCLASS(*)                   (* every job class *)
$DOUTCLASS(X)                   (* show settings for SYSOUT class X *)
$DOUTCLASS(*)                   (* every SYSOUT class *)

Spool

$DSPOOL reports spool volumes and their utilization — critical for capacity monitoring because a full spool stops all JES2 work.

text
$DSPOOL                         (* every spool volume, percentage used *)
$DSPOOL(SPOOL1)                 (* one spool volume *)
$DSPOOLDEF                      (* spool configuration parameters *)

NJE nodes

NJE (Network Job Entry) interconnects multiple JES2 systems for cross-system job submission and SYSOUT routing.

text
$DNODE                          (* every NJE node defined *)
$DNODE(N1)                      (* one node by name *)
$DLINE                          (* NJE communication lines *)
$DPATH                          (* routing paths *)
$DAPPL                          (* VTAM applications used for NJE *)

Subsystem-wide state

$DPARM reports JES2 initialization parameter values without restarting the subsystem; $DSYS reports the current member of a MAS (multi-access spool) configuration.

text
$DPARM                          (* every JES2 PARM= value *)
$DPARM,MEMNAME=JCLASSES         (* one parameter block *)
$DSYS                           (* this system's role in the MAS *)
$DMASDEF                        (* MAS definition *)
$DPERFDATA                      (* JES2 performance statistics *)

Job control

These are the commands you reach for during the working day: hold a job, release it, cancel it, change its class, requeue it. All apply equally to jobs in the input, execution, or output queue, although some make sense only for jobs in particular states.

Hold and release

$HJ holds a job; $AJ releases it. A held job in the input queue does not get selected by any initiator; a held job in the output queue does not get printed.

text
$HJ ALICEJ01                    (* hold by jobname *)
$HJ JOB00123                    (* hold by JOBID *)
$HJ ALICEJ01,ALL                (* hold this and any duplicates *)
$AJ ALICEJ01                    (* release for execution / printing *)
$AJ JOB00123

Change class or priority

$TJ (alter job) re-classes, re-prioritizes, or re-routes a job. The job must usually be held or queued (not executing) for the change to apply.

text
$TJ ALICEJ01,C=B                (* move to class B *)
$TJ JOB00123,P=10               (* change priority to 10 *)
$TJ ALICEJ01,Q=X                (* move output to class X *)
$TJ JOB00123,D=R1               (* route to destination node R1 *)

Cancel and purge

$CJ cancels a job. For an executing job this is roughly equivalent to issuing C jobname from a console — the address space is terminated with a 222 system completion code. For a job already done, $CJ purges its output from spool.

text
$CJ ALICEJ01                    (* cancel/purge *)
$CJ JOB00123,P                  (* purge without dumping *)
$CJ JOB00123,A                  (* cancel with ABEND dump *)
$CJ ALICEJ01,ARMRESTART         (* cancel with auto-restart *)

Restart and requeue

$EJ restarts a job at a named step; $N (the request form, not the NJE form) requeues a held job.

text
$EJ ALICEJ01                    (* restart this job *)
$EJ ALICEJ01,STEP=STEP02        (* restart at STEP02 *)

Initiator control

Initiators are JES2's worker pool. Bringing one up adds capacity for the classes it services; bringing one down releases its address space.

Start, stop, drain

text
$SI 1                           (* start initiator 1 immediately *)
$SI 1-5                         (* start initiators 1 through 5 *)
$SI ALL                         (* start every defined initiator *)
$PI 1                           (* drain initiator 1 — current job finishes, no new work *)
$PI 1,QUICK                     (* drain immediately when the job ends *)
$PI ALL                         (* drain every initiator (planned shutdown) *)

Alter classes serviced

$TI rebinds an initiator to a different set of job classes. The classes are a string of single letters; order determines priority within the initiator.

text
$TI 1,CLASS=A                   (* initiator 1 services class A *)
$TI 1,CLASS=AB                  (* class A, then class B *)
$TI 2,CLASS=ABCDE               (* multi-class *)
$TI ALL,CLASS=A                 (* every initiator services class A *)

Display the configured-vs-running state

$DJOBCLASS(A) reports class A's queue depth and the initiator pool that can pick it up; useful when a class is "stuck" because no initiator is configured for it.

text
$DJOBCLASS(A),L                 (* long form — class A configuration *)
$TJOBCLASS(A),COMMAND='S'       (* automatically start jobs in class A *)
$TJOBCLASS(A),HOLD=YES          (* hold every new class A submission *)
$TJOBCLASS(A),HOLD=NO           (* release *)

Output and printer control

Output device commands target printers (PRT), punches (PUN), and the abstract output groups (O) that link a job's SYSOUT to a device.

Bring a printer online

text
$SPRT1                          (* start printer PRT1 *)
$SPRT1,DELAY=0                  (* start immediately, no warm-up delay *)
$PPRT1                          (* drain PRT1 — finish current job, take offline *)
$PPRT1,FORCE                    (* drain immediately, requeue current *)

Alter a printer's class assignment

$TPRT changes what a printer prints. A printer can be assigned a string of one or more output classes; only output in those classes is dispatched to it.

text
$TPRT1,CLASS=AB                 (* PRT1 prints class A then B *)
$TPRT1,WS=(CL,F,T)              (* work selection: class, forms, train *)
$TPRT1,F=STD                    (* force forms STD *)
$TPRT1,UCS=PN                   (* universal character set PN *)

Release or hold output groups

An "output group" is a unit of SYSOUT — typically a job's complete SYSOUT collected by class.

text
$OO JOB00123,CLASS=X            (* release the X-class output of one job *)
$OO ALICEJ01                    (* release all output groups for jobname *)
$HO ALICEJ01                    (* hold all output groups for jobname *)
$HO JOB00123,CLASS=X            (* hold one class of output *)

Reroute output to a different destination

text
$TO JOB00123,D=R1               (* route output to NJE node R1 *)
$TO ALICEJ01,U=USERID           (* route to a specific TSO userid *)
$TO JOB00123,CLASS=A,F=LETTER   (* change class to A, forms to LETTER *)

Display output

$DSU shows SYSOUT records on the queue. Useful when a class appears to back up.

text
$DSU                            (* every SYSOUT record *)
$DSU /ALICEJ01                  (* one job's output records *)

SYSOUT class management

Each SYSOUT class is a configuration block defining where the output lands (queue), whether it is held, what forms it expects, and so on.

text
$DOUTCLASS(X)                   (* show settings for class X *)
$TOUTCLASS(X),OUTDISP=HOLD      (* class X output is held *)
$TOUTCLASS(X),OUTDISP=WRITE     (* class X output is print-ready *)
$TOUTCLASS(X),OUTPUT=YES        (* eligible for write processing *)

Spool management

Spool is the JES2-managed pool of work datasets that hold every job's JCL, SYSOUT, and intermediate data until purged. Spool exhaustion stops the subsystem — every JES2 command after $DSPOOL here is part of a spool emergency playbook.

Display utilization

text
$DSPOOL                         (* every volume, percentage used *)
$DSPOOL(SPOOL1)                 (* one volume *)
$DSPL                           (* SPOOL utilization report *)

Add a spool volume

When spool is filling, the fastest mitigation is to bring an additional volume online. The volume must have been initialized as a JES2 spool dataset.

text
$SSPL(SPOOL2)                   (* start spool volume SPOOL2 *)
$SSPL(SPOOL2),DELAY=NO          (* start immediately *)

Drain a spool volume

$P SPL(name) drains a spool volume so it can be taken offline for maintenance. JES2 stops allocating new spool space on that volume and frees it as jobs complete.

text
$P SPL(SPOOL2)                  (* drain *)
$Z SPL(SPOOL2)                  (* halt immediately — only if frozen *)

Purge old output to free space

The mass-purge commands $P with Q= and a SYSOUT class identifier reclaim space across many jobs at once.

text
$P J(JOB*),Q=Z                  (* purge every job's class Z output *)
$P O ALL,Q=H                    (* purge every output group in queue H *)

NJE (Network Job Entry)

NJE links multiple JES2 systems so a job submitted on one can run on another and its SYSOUT can land back at the origin. The peer nodes are configured statically in JES2 PARM, and the operator commands manage the runtime state of the connections.

Display nodes and lines

text
$DNODE                          (* every defined node *)
$DNODE(N1)                      (* one node *)
$DLINE                          (* communication lines *)
$DLINE(LINE1)                   (* one line *)
$DPATH                          (* routing paths between nodes *)

Start and stop a node

text
$SN N1                          (* start (logon) node N1 *)
$PN N1                          (* stop node N1 *)
$EN N1                          (* restart node N1 after a stop *)
$DN(N1),Q                       (* queue depth for jobs waiting to ship to N1 *)

Cross-system messaging

text
$M N1,'Spool maintenance starts at 18:00'         (* message to node N1 *)
$M ALL,'JES2 patch applied'                       (* broadcast to every NJE node *)
$N N1,'Backup job queued'                         (* send a quick line to node N1 *)

Driving JES2 from SDSF

SDSF surfaces JES2 commands through two paths: the panel commands (/ prefix on a command line) and the prefix commands on rows of ST, DA, H, I, and O panels. The slash form on the SDSF command line gives you the full JES2 verb set.

text
===> /$DJ                       (* same as $DJ from a console *)
===> /$DSPOOL                   (* spool report *)
===> /$DI                       (* initiator status *)
===> /$SI 1                     (* start initiator 1 *)
===> /$PJ ALICEJ01              (* purge ALICEJ01's output *)
===> /$HJ JOB00123              (* hold one job *)

For most day-to-day operations the SDSF panel prefix commands (e.g. H on a row of ST for "hold this job") issue the equivalent $HJ under the cover. Knowing the underlying JES2 verbs is what lets you do the same operation against a batch of jobs in one slash command, or operate without SDSF at all from a console during recovery.

Common pitfalls

  1. Issuing JES2 commands with a leading space in SDSF — the slash is consumed but the command is rejected as unknown. Type the slash immediately as the first character of the command line.
  2. Forgetting ,FORCE on $PPRT — a draining printer will not finish until its current job ends. For an immediately stuck printer, use $PPRT n,FORCE to requeue the current job.
  3. Drained initiators not restarting at IPL — initiators left in DRAINED state persist across an IPL only if the JES2 PARM is updated; otherwise the IPL restores them to their PARM-defined state. $SI ALL after IPL ensures everything is started.
  4. $DJ returning nothing for a "missing" job — the job either has not yet been read by JES2 (still in the spool reader), or has already been purged. Check the JES2 log via LOG panel or $D LOGSTREAM for a trace.
  5. $CJ jobname cancelling more than expected — without a JOBID, every job sharing that jobname is targeted. Always use JOBID for unambiguous cancels in a multi-user environment.
  6. $P JES2 is not the right shutdown — that command stops JES2 itself and brings the system to a halt for ordinary jobs. The graceful shutdown sequence is: $P INIT,ALL (drain initiators), wait, then $P JES2.
  7. Spool filling silently — JES2 emits $HASP050 warnings to the console, but they scroll fast. Schedule periodic $DSPOOL checks via an automation product or REXX exec; never rely on visual console monitoring alone.
  8. NJE jobs queued forever — the receiving node is logged off or unreachable. $DN(N1),Q shows the depth; $P N1 then $S N1 cycles the connection; if the remote system is down, reroute with $TJ jobid,D=newnode.
  9. Class change refused while executing$TJ cannot move a job that is currently running. Cancel and resubmit, or change the class in the JCL and resubmit.
  10. $Z (halt) instead of $P (drain)$Z is the JES2 equivalent of kill -9: in-flight work is abruptly stopped and may leave inconsistent state on spool. Reserve for genuine emergencies; default to $P for ordinary shutdowns.

Sources

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

  • IBM Documentation — JES2 Initialization and Tuning Reference — Authoritative reference for JES2 operator commands ($D, $T, $P, $C, $Z) and JOBCLAS/INITCLAS configuration covered in this article.

Real-world recipes

Bring up a fresh initiator for a new job class

A new application team needs class K to be serviced. Define class K (or confirm it exists in JOBCLAS(K) PARM), then start an idle initiator bound to it.

text
$DJOBCLASS(K)                                       (* confirm class K exists *)
$DI                                                 (* find an unused initiator number — say 12 *)
$TI 12,CLASS=K                                      (* bind initiator 12 to class K *)
$SI 12                                              (* start it *)
$DI 12                                              (* confirm ACTIVE *)

A site that wants the initiator to survive IPLs should also update the JES2 PARMLIB member that defines initiator 12; runtime $T commands are not persistent.

Drain initiators ahead of a planned outage

Before an IPL or planned JES2 maintenance, drain every initiator so currently running jobs complete normally and no new ones start. Then check that nothing is left active.

text
$PI ALL                                             (* drain — no new work picked up *)
$DA                                                 (* watch active jobs drain *)
$DJ Q=XEQ                                           (* should be empty when safe *)
$P JES2                                             (* clean shutdown *)

Free spool space in an emergency

Spool is at 90% and rising. Purge held SYSOUT first (output class H is held by definition; users won't notice it disappearing), then drain inactive jobs. As a last resort, bring an additional spool volume online.

text
$DSPOOL                                             (* assess — 91% on SPOOL1 *)
$P O ALL,Q=H                                        (* purge held output, class H *)
$P J(*),Q=Z                                         (* purge dump/scratch output class Z *)
$DSPOOL                                             (* re-check *)
$SSPL(SPOOL3),DELAY=NO                              (* add spool volume *)

After the immediate pressure is off, schedule normal purges (held output, old test output) and audit the largest jobs with $DJ /,L.

Reroute a job's output to a different node

A user finished a job on system LOCAL but needs the SYSOUT to land on REMOTE for printing on a department printer.

text
$DJ ALICEJ01                                        (* confirm the job is OUTPUT-queued *)
$TO ALICEJ01,D=REMOTE                               (* route to NJE node REMOTE *)
$DJ ALICEJ01                                        (* verify destination changed *)

If the output never arrives at REMOTE, check NJE state with $DN(REMOTE) and $DLINE — a stopped line is the usual culprit.

Hold every new submission in a class for a deploy window

During a deploy, no new application work should run. Hold class P (production) without stopping its initiators — already-running jobs finish; new submissions queue up.

text
$TJOBCLASS(P),HOLD=YES                              (* new class-P submissions held on arrival *)
$DJ Q=XEQ                                           (* watch running jobs drain *)
$TJOBCLASS(P),HOLD=NO                               (* release after the deploy is verified *)
$AJ J=*,C=P                                         (* release any jobs held during the window *)

Cancel a runaway job and salvage its output

A job is in a loop, consuming CPU. Cancel with a dump (,A) so the application team can post-mortem, but make sure the SYSOUT survives the cancel.

text
$DJ ALICEJ01                                        (* confirm it's executing *)
$CJ ALICEJ01,A                                      (* cancel with ABEND dump *)
$DJ ALICEJ01                                        (* should now be on output queue *)
$AJ ALICEJ01                                        (* release output for printing *)

Audit spool usage by job name pattern

Find the top consumers of spool — long-running TSO sessions and stale jobs that never purged their output.

text
$DJ /,L                                             (* long-form list, every job *)
$DJ J=*,L                                           (* same as above *)
$DSU /ALICEJ01                                      (* one user's SYSOUT records *)
$DJ Q=HELD,L                                        (* held jobs, long form *)

Once identified, purge: $P J(jobid),P for individuals or $P O ALL,U=USERID for everything under one TSO userid.

Restart a TSO user's hung session

A TSO user reports their session is unresponsive. Their LOGON job is just another initiator-driven job to JES2; cancel it from a console.

text
$DA U=*                                             (* find the TSO user's session *)
$CJ TSU00123                                        (* cancel — TSU jobids are TSO logons *)
$DA U=*                                             (* verify cleared *)

Daily JES2 health snapshot from REXX

A REXX exec can issue JES2 commands via the MVS command service and capture the responses. Drop this into a JCL automation job to mail a daily summary:

text
/* REXX */
ADDRESS MVS '$DSPOOL'
ADDRESS MVS '$DI'
ADDRESS MVS '$DJ Q=XEQ'
ADDRESS MVS '$DPRT ALL'

Pair the captured output with FTP delivery (see the ftp cheat sheet) to land a daily JES2 status report on a workstation or shared drive.

Issue commands from JCL via the internal reader

To drive JES2 from a batch job, use IEFBR14 with a console-issuing program — most commonly an external automation product (NetView, OPS/MVS) or REXX as above. The internal reader is for new job submission, not JES2 verbs:

text
//SUBMIT   JOB (ACCT),'AUTOMATION',CLASS=A,MSGCLASS=X
//*  Submit a new job to JES2 via INTRDR
//STEP1    EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSUT2   DD SYSOUT=(*,INTRDR)
//SYSIN    DD DUMMY
//SYSUT1   DD *
//SUBJOB   JOB (ACCT),'SUB',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//STEP1    EXEC PGM=IEFBR14
/*

JCL routed to SYSOUT=(*,INTRDR) is read by JES2 and submitted as a new job — useful for self-restarting and cascade automation patterns.