cheat sheet

SDSF

Browse, filter, and act on JES2 spool from inside ISPF — find your job, read SYSOUT, cancel, purge, and issue operator commands.

SDSF — Spool Display and Search Facility

What it is

SDSF (Spool Display and Search Facility) is IBM's panel-driven viewer over the JES2 (and, with limitations, JES3) spool on z/OS — the window through which every mainframer watches their jobs run, reads SYSOUT, and pokes at the system. It runs as an ISPF application (option S from the primary menu) and as a TSO command, and exposes the same data that the operator console sees: every job's status, every SYSOUT dataset, every initiator, every printer, plus a slash-command channel to JES2 itself. Reach for SDSF whenever you submit a job and want to know what happened — it is the daily-driver answer to "where is my output". A read-only alternative is IOF, common at some sites; for fully scripted spool access from a workstation, use Zowe CLI (zowe jobs list jobs, zowe jobs view job-status-by-jobid, zowe jobs view spool-file-by-id) — the same JES2 spool that SDSF panels show, exposed as a JSON-emitting CLI. Zowe-based workflows depend on SDSF being configured under the hood; on z/OS 3.1 and z/OS 3.2 (GA September 2025) the REXX-on-SDSF interface (ISFEXEC, ISFCALLS) remains the canonical scripted access path.

Entering SDSF

SDSF launches from ISPF or as a standalone TSO command. From the ISPF primary menu type S (or =S from anywhere) — that takes you to the SDSF primary menu. From any ISPF panel you can also type TSO SDSF to start it directly, or run SDSF from option 6 (TSO command shell).

text
=S                        (* from any ISPF panel *)
TSO SDSF                  (* from option 6 *)
SDSF                      (* from a TSO READY prompt *)

Output: (none — opens the SDSF primary menu)

The primary menu is a numbered list of panels (DA, I, ST, H, O, LOG, SR, ULOG, MAS, JC, SE, …). You jump to a panel by typing its two-letter code; from inside any panel, =panel (e.g. =ST) jumps without going through the menu first. F3 ends and returns one level; =X exits SDSF and ISPF together.

Panel cheatsheet

Each SDSF panel is a tabular view over one kind of JES2 object. The most commonly used panels are ST (your jobs) and DA (active address spaces); operators live in LOG, SR, and I.

PanelCodeShows
StatusSTAll jobs (active, held, output, input)
Display ActiveDAAddress spaces currently executing
Held OutputHSYSOUT held for review or print
OutputOSYSOUT ready for printing or download
InputIInitiators and the jobs they own
Job ClassJCJob class definitions and limits
LinesLIOutput line counts per job
NodesNONJE node definitions
PrintersPRPrinter devices and their queues
PunchPUNPunch devices
ReadersRDRCard-reader (internal-reader) devices
InitiatorsINITInitiator status (drained, halted, active)
System LogLOGSYSLOG — operator and system messages
Action MessagesSROutstanding WTORs awaiting reply
User LogULOGThis session's TSO/SDSF command echoes
MASMASJES2 multi-access spool members
SysplexSYSAll systems in the sysplex
Resource MonitorRMDASD, CPU, paging snapshots
SESEScheduling environments
EnclavesENCWLM enclaves
Network ServersNSNJE/SNA connections
Spool OffloadSOSpool offload jobs
Spool VolumesSPSpool DASD volumes
text
ST                        (* go to Status panel *)
=DA                       (* jump directly to active *)
=LOG                      (* jump directly to system log *)

Output: (none — selected panel opens)

Filtering the view

Three commands narrow what each panel shows: PREFIX (filter by jobname), OWNER (filter by submitting userid), and DEST (filter SYSOUT by destination). They persist across panels for the duration of the session until you change them, and they apply additivelyPREFIX ALICE* OWNER ALICE is a tighter filter than either alone.

text
PREFIX ALICEJ*            (* only jobnames starting ALICEJ *)
PREFIX *                  (* clear — show all jobnames *)
OWNER ALICE               (* only jobs submitted by user ALICE *)
OWNER *                   (* clear owner filter *)
DEST LOCAL                (* only output destined for LOCAL *)
DEST *                    (* clear destination filter *)

Output: (none — visible row set narrows)

You can stack them in one go using the command-delimiter (; by default):

text
PREFIX ALICEJ* ; OWNER ALICE ; ST

Output:

text
SDSF STATUS DISPLAY ALL CLASSES                  LINE 1-3 (3)
COMMAND INPUT ===>                              SCROLL ===> CSR
NP   JOBNAME  JobID    Owner    Prty Queue      C  Pos SAff
     ALICEJ01 JOB12345 ALICE      15 OUTPUT     X
     ALICEJ02 JOB12346 ALICE       9 ACTIVE        SY1
     ALICEJ03 JOB12347 ALICE       1 INPUT

PREFIX accepts asterisk wildcards (* matches any string, % matches any single character). Saving filters to your profile means they survive across SDSF sessions:

text
SET SAVE ON               (* persist current filters to ISPF profile *)
SET SAVE OFF              (* stop persisting *)

Output: (none — preference stored)

Sorting and arranging

The view is freely sortable by any visible column with SORT, and column order/visibility is editable with ARRANGE. Both write into your SDSF profile when SET SAVE ON is in effect.

text
SORT JOBNAME A            (* ascending by jobname *)
SORT JOBID D              (* descending by JOBID — newest first *)
SORT QUEUE,JOBNAME        (* multi-key *)
ARRANGE                   (* opens column editor *)

Output: (none — rows resort or column editor opens)

A common operator habit is SORT JOBID D on ST so the most recently submitted job is always the first row.

Prefix-area (row) commands

The leftmost column of every row is the prefix area — type a one- or two-letter command there, hit Enter, and it acts on that job, dataset, initiator, printer, or message. The character set varies slightly by panel, but the table below covers ST, DA, H, and O.

CmdWhat it does
SSelect / browse — open the job's combined SYSOUT
SESDSF Edit — same as S but in edit mode (read-only by default)
SJShow JCL — display the converted JCL the system actually ran
?Expand — show the job's individual SYSOUT datasets (one row per DDname)
XPrint/cancel — context-dependent (purges on O, cancels on DA)
XDDownload the SYSOUT to a dataset
XDCDownload with confirmation panel
CCancel the job (active jobs only)
PPurge — discard the job and all its SYSOUT
ORelease (output queue) or change class (held queue)
HHold the job's output
ARelease held output (action)
ERestart the job from a step (with RESTART=)
ZZap — modify selected fields inline
DDisplay — show full attributes
=Repeat the last command on this row
text
NP   JOBNAME  JobID
S    ALICEJ01 JOB12345        (* browse combined SYSOUT *)
?    ALICEJ02 JOB12346        (* expand into individual DDs *)
SJ   ALICEJ03 JOB12347        (* view converted JCL *)
P    ALICEJ04 JOB12348        (* purge the job *)

Output: (none — actions execute and update the panel)

When you ?-expand a job you land in a second view listing each DD: JESMSGLG, JESJCL, JESYSMSG, then each user SYSOUT DD in order. Select any one with S to read just that piece. To page across multiple datasets at once, type S next to several rows and hit Enter — SDSF browses them in sequence, separated by header pages.

Browsing SYSOUT

Inside a SYSOUT browse you have the standard ISPF-style scroll and search keys plus a few SDSF-specific ones. Search is anchored by line; FIND wraps at end-of-file.

text
FIND ABEND                (* search forward *)
FIND ABEND PREV           (* search backward *)
FIND IEF373I ALL          (* count and highlight all matches *)
RFIND                     (* repeat last find (PF5) *)
FIND X'40' HEX            (* find hex byte *)
TOP / BOTTOM              (* jump to start / end *)
UP n / DOWN n             (* scroll n lines *)
LEFT / RIGHT              (* horizontal scroll *)
HEX ON|OFF                (* toggle hex display *)
PRINT                     (* spawn print-to-dataset dialog *)
PRINT ODSN(ALICE.OUT)     (* print to a specific dataset *)

Output: (none — view updates or print dialog opens)

PRINT ODSN is the scripted form of XD from the row level — it writes the visible browse to a sequential dataset. Add NEW, CATLG, and SPACE parameters to allocate on the fly:

text
PRINT ODSN(ALICE.JOB12345.SYSOUT) NEW CATLG SPACE(5,5) TRK RECFM(V,B) LRECL(255)
PRINT CLOSE               (* close the print file when done *)

Output:

text
PRINT CLOSED              0 LINE

Forgetting PRINT CLOSE leaves the dataset open and partially written; the next browse you print will append to it.

Slash commands — JES2 from inside SDSF

Any command prefixed with / is passed straight to JES2 as a console command. This is the same channel an operator uses at the console; your authority is bounded by RACF profiles in the OPERCMDS class. The results appear in the ULOG panel (=ULOG).

CommandWhat it does
/$DADisplay all active initiators and the jobs they hold
/$DIDisplay all initiators with status
/$DI1Display initiator 1 only
/$SI1Start initiator 1
/$PI1Drain initiator 1 (finish current job, then stop)
/$EI1Halt initiator 1 immediately
/$DJDisplay all jobs in JES2
/$DJALICEJ01Display one job by name
/$DJQJob queue summary
/$DSPLSpool volume status
/$DJOBCLASS(A)Display JOBCLASS A definition
/$TJOBCLASS(A),QHELD=NToggle JOBCLASS A's held attribute off
/$DPRT1Display printer 1 status
/$SPRT1Start printer 1
/$PPRT1Drain printer 1
/$VS,'cmd'Pass cmd to MVS (e.g. /$VS,'D A,L')
/$NDisplay NJE node table
text
/$DA                      (* what's running right now *)
/$DI                      (* initiator status *)
/$DSPL                    (* spool volumes — capacity check *)

Output:

text
$HASP890 JOBCLASS(A)  STATUS=ACTIVE,MODE=JES,
$HASP890              QHELD=NO,JOURNAL=YES

The =ULOG panel records every slash command and its reply with a timestamp. It's the only place to find the exact text of an operator response after the fact — once you scroll past it on the command line, it's gone unless ULOG captured it.

The LOG panel

LOG shows the SYSLOG — the system's running record of console messages from every address space, in chronological order. It is huge (multiple gigabytes a day on a busy system) and pre-filtered to the current operlog or syslog.

text
=LOG                      (* open the log *)
FIND IEF403I              (* find all 'job started' messages *)
FIND IEF404I ALICEJ01     (* find 'job ended' for one jobname *)
BOOK 5M                   (* jump back 5 minutes *)
BOOK 2H                   (* jump back 2 hours *)
TOP / BOTTOM              (* jump to oldest / newest *)

Output: (none — log scrolls)

BOOK is the SDSF way of saying "rewind by relative time" — accepts nS, nM, nH, nD. Operators use it to look at "what happened during the incident" without scrolling. The O panel and LOG panel both honor an optional SYSNAME filter — SYSNAME SY1 in a sysplex shows messages from member SY1 only.

The SR panel — outstanding WTORs

SR (System Requests) lists every WTOR — Write-to-Operator-with-Reply — that the system is waiting on. Each row is a numbered reply; type the reply text in the prefix area or use R nn,text from the command line.

text
=SR
NP    REPLY    TIME       SYSNAME  MSG
01    0014     12:31:23   SY1      *14 IEF238D ALICEJ01 - REPLY DEVICE OR CANCEL
text
R 14,CANCEL               (* answer reply ID 14 with CANCEL *)
R 14,'/dev/tape1'         (* answer with a literal string *)

Output: (none — JES2 dispatches the reply)

Forgetting to scan SR after a job pauses is a classic stuck-batch cause — the job is waiting on a mount or a console reply and nothing else will happen until someone answers.

Issuing TSO commands from SDSF

/cmd goes to JES2; bare commands (no slash) typed on the SDSF command line go to TSO. This lets you launch ISPF utilities and one-liners without leaving SDSF.

text
LISTC ENT('ALICE.*') ALL              (* TSO LISTCAT *)
SUBMIT 'ALICE.JCL.LIB(ALICEJ01)'      (* submit a job *)
TSO STATUS ALICE*                     (* explicit TSO scope *)

Output: (none — TSO command executes; replies appear in ULOG)

Action characters and overtypes

Many panels let you change a field by overtyping it directly — type the new value on top of the old one and Enter. This is how operators change SYSOUT class, swap initiators between job classes, or release single sysout datasets.

text
NP   JOBNAME  Class
     ALICEJ01 X            (* overtype X -> A on the O panel to change class *)

Output: (none — class changed)

Whether overtype is enabled depends on the panel and your SAF authority. Greyed-out fields are read-only for your userid.

Common pitfalls

  1. PREFIX * after a busy night — you'll see thousands of jobs and SDSF gets slow. Always re-narrow with PREFIX ALICE* before scrolling.
  2. Forgetting PRINT CLOSE — leaves the print dataset partially written and locked. Always close after a PRINT ODSN.
  3. Confusing H (Hold) panel with the H row command — typing H in the panel command field opens the held-output panel; typing H in a row prefix holds that job's output. Same letter, very different actions.
  4. Slash commands rejected — RACF in the OPERCMDS class controls who can issue what. A silent reject usually means your userid lacks JES2.<verb>.<noun> access; ask the security admin for READ on the specific resource.
  5. SET SAVE OFF and lost filters — if your prefixes never persist across sessions, you have save mode off. Turn it on once and forget about it.
  6. ? then forgetting where you are — after expanding a job into individual datasets, F3 returns to the job list, not to the original panel. =ST is the safer "go home" key.
  7. Browsing a still-running job — SDSF shows SYSOUT as JES2 has spooled it so far. The job may not have flushed its OS buffers yet, so the last few lines of a running job's SYSOUT can lag reality by seconds.
  8. P (purge) is irreversible — there is no undo. Hold (H) instead of purging if you're not sure you're done with the output.
  9. OWNER ALICE shows nothing — userid is uppercase on z/OS. owner alice is the same query, but OWNER ALIC (truncated) silently matches nothing because OWNER is exact-match by default. Use OWNER ALICE* for prefix-match.
  10. /$DSPL shows spool nearly full — JES2 will start refusing new jobs at 80% by default. Notify the operator and consider /$P JES2 is not the answer.

Real-world recipes

Find and download the SYSOUT of the last job I submitted

The most common workflow: submit a JCL, jump to SDSF, locate the job, read it, and save it locally.

text
SUBMIT 'ALICE.JCL.LIB(ALICEJ01)'        (* from TSO option 6 *)
=ST                                      (* jump to SDSF Status *)
PREFIX ALICEJ*                           (* narrow to my jobs *)
SORT JOBID D                             (* newest first *)

Land on ST with the most recent row at the top. Browse it with S:

text
NP   JOBNAME   JobID    Owner Prty Queue C
S    ALICEJ01  JOB12345 ALICE   15 OUTPUT R

Output: (browser opens the combined SYSOUT for JOB12345)

Inside the browse, save the combined output to a dataset:

text
PRINT ODSN(ALICE.JOB12345.SYSOUT) NEW CATLG SPACE(5,5) TRK RECFM(V,B) LRECL(255)
PRINT *                                  (* prints visible content *)
PRINT CLOSE                              (* closes the dataset *)

Output:

text
PRINT CLOSED   142 LINE

F3 back to ST. From here, XD next to the row would have done the same thing in one step — PRINT is the long form when you want to inspect first.

Triage a batch failure

A job ABENDed overnight. Find it, get the return code chain, and read JESYSMSG to find the failing step.

text
=ST ; PREFIX ALICEJ01 ; SORT JOBID D
?    ALICEJ01 JOB12350                   (* expand into datasets *)

The first three DDs of every job are JES-owned: JESMSGLG, JESJCL, JESYSMSG. JESYSMSG is the one with the per-step return codes and any allocation failures.

text
S    JESYSMSG                            (* browse it *)
FIND ABEND                               (* find the abend line *)
FIND S0C7                                (* find data-exception code *)

Output:

text
IEF142I ALICEJ01 STEP02 - STEP WAS EXECUTED - COND CODE 0000
IEF142I ALICEJ01 STEP03 - STEP WAS EXECUTED - SYSTEM ABEND CODE = 0C7

F3 back, S JESJCL to read the converted JCL of STEP03 to find the dataset that broke. From JESJCL, the inline IEFC653I lines show JES's symbol resolution which is invaluable when symbols disagree with what you expected.

Cancel a runaway job

A job is consuming CPU and won't stop. DA shows it; C cancels.

text
=DA
PREFIX ALICEJ*

Output:

text
NP   JOBNAME  StepName ProcStep JobID     Owner   C Pos DP Real Paging  SIO  CPU%
     ALICEJ01 RUNAWAY  GO       JOB12351  ALICE   X   1 D7 1234      0 1432  98.7
text
C    ALICEJ01 JOB12351                   (* cancel *)

Output:

text
$HASP890 ALICEJ01  CANCELLED

If the cancel doesn't take, escalate to P (purge — drops the job and any output) or, for genuinely stuck address spaces, use the /$VS,'C ALICEJ01,DUMP' slash command to force-cancel with a dump for postmortem.

Release a held output class for printing

Held SYSOUT (MSGCLASS=H or routed to a held class) sits on H until someone releases it. Operators do this with O for "release output".

text
=H
PREFIX ALICEJ*
O    ALICEJ01 JOB12345                   (* release back to output queue *)
=O                                        (* confirm it landed *)

Output: (released output now appears on the O panel with status READY)

For a whole class at once, the JES2 equivalent is /$TOQ,Q=H,Q=A which moves everything from class H to class A.

Drain initiator 5 for maintenance

You need to take initiator 5 offline before patching, but you want it to finish whatever it's running first.

text
=INIT
NP   INIT  Status   JobName    Class
P    5     ACTIVE   ALICEJ02   A
text
P    5

Output:

text
$HASP000 INIT 5  IS NOW DRAINING

Initiator 5 finishes ALICEJ02 then stops accepting new work. /$DI5 confirms DRAINED. Restart with /$SI5 when the maintenance window closes.

Bulk-purge old job output

End-of-day cleanup: purge every owned job older than today that still has output around.

text
=O
OWNER ALICE
SORT DATE A

Visually identify the cutoff row, then enter P in the prefix of every row above it (you can type P repeatedly down the column and press Enter once). Or, for a one-shot purge by jobname pattern from the command line:

text
P ALICEJ*                                (* prefix-area command applied by pattern is not supported *)

That last form does not work in stock SDSF — bulk-purge by pattern requires either a CLIST/REXX driver against SDSF REXX API or operator slash commands:

text
/$P JOBQ,QUEUE=OUTPUT,OWNER=ALICE        (* JES2 bulk-purge via slash *)

Output:

text
$HASP890 6 JOBS PURGED

Reply to a tape-mount WTOR

A job is paused waiting for a tape mount. SR shows the request; reply with the volume serial.

text
=SR
NP    REPLY    TIME       MSG
01    0023     14:02:11   *23 IEF233A M 0A40,TAPE01,SL,ALICEJ02,STEP01,TAPEIN
text
R 23,'0A40,TAPE01'                       (* mounted on the indicated drive *)

Output:

text
$HASP893 REPLY 23 ACCEPTED

WTORs disappear from SR once answered; the job resumes immediately.

Watch the log for a specific event

You're chasing a recurring error. Open LOG, sit at the bottom, and let new lines stream in.

text
=LOG
BOTTOM
FIND IEF450I                              (* abend message *)
RFIND                                     (* repeat — finds the next *)

Output: (cursor jumps to next match each press of PF5)

For continuous monitoring use the & macro suffix on a sysplex log query, or set INPUT ON so the log auto-scrolls. The BOOK command (BOOK 30M) lets you back up half an hour without losing your place.

Use SDSF in batch via REXX

SDSF exposes a REXX API (ISFEXEC + ISFCALLS) that drives the same panels programmatically. Useful for unattended health checks.

text
/* List my held output as a REXX exec */
rc = isfcalls("ON")
isfprefix = "ALICEJ*"
isfowner  = "ALICE"
Address SDSF "ISFEXEC H"
do i = 1 to JNAME.0
   say JNAME.i JOBID.i "queue=" QUEUE.i
end
rc = isfcalls("OFF")

Output:

text
ALICEJ01 JOB12345 queue=HELD
ALICEJ02 JOB12346 queue=HELD

The same idea works for any panel — set ISFPREFIX, ISFOWNER, ISFDEST, call ISFEXEC <panel>, then walk the stem variables it returns (JNAME., JOBID., OWNER., QUEUE., etc.). Combined with Address SDSF "++<action>" you can fully automate "purge everything in the output queue older than 7 days from a nightly batch job".

Drive SDSF from off-platform via Zowe CLI

For pipelines and IDE-resident workflows on z/OS 3.1+ the Zowe CLI is the modern equivalent of SDSF's REXX API. It connects via z/OSMF (preferred) or FTP, returns JSON, and pipes naturally into shell tooling. The mapping is one-to-one with the SDSF panels covered above.

bash
# What ST panel shows for my prefix
zowe jobs list jobs --owner ALICE --prefix "ALICEJ*"

# Combined SYSOUT (== S on the ST row)
zowe jobs view all-spool-content --jobid JOB12345

# JESYSMSG only (== S JESYSMSG inside ? expansion)
zowe jobs view spool-file-by-id --jobid JOB12345 --spool-file-id 3

# Cancel and purge (== C / P row commands)
zowe jobs cancel job --jobid JOB12345
zowe jobs delete  job --jobid JOB12345

# Submit + wait
zowe jobs submit data-set "ALICE.JCL.LIB(ALICEJ01)" --wait-for-output

Output:

text
jobname  jobid     status   retcode
ALICEJ01 JOB12345  OUTPUT   CC 0000
ALICEJ02 JOB12346  ACTIVE   null

Sources