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).
=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.
| Panel | Code | Shows |
|---|---|---|
| Status | ST | All jobs (active, held, output, input) |
| Display Active | DA | Address spaces currently executing |
| Held Output | H | SYSOUT held for review or print |
| Output | O | SYSOUT ready for printing or download |
| Input | I | Initiators and the jobs they own |
| Job Class | JC | Job class definitions and limits |
| Lines | LI | Output line counts per job |
| Nodes | NO | NJE node definitions |
| Printers | PR | Printer devices and their queues |
| Punch | PUN | Punch devices |
| Readers | RDR | Card-reader (internal-reader) devices |
| Initiators | INIT | Initiator status (drained, halted, active) |
| System Log | LOG | SYSLOG — operator and system messages |
| Action Messages | SR | Outstanding WTORs awaiting reply |
| User Log | ULOG | This session's TSO/SDSF command echoes |
| MAS | MAS | JES2 multi-access spool members |
| Sysplex | SYS | All systems in the sysplex |
| Resource Monitor | RM | DASD, CPU, paging snapshots |
| SE | SE | Scheduling environments |
| Enclaves | ENC | WLM enclaves |
| Network Servers | NS | NJE/SNA connections |
| Spool Offload | SO | Spool offload jobs |
| Spool Volumes | SP | Spool DASD volumes |
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 additively — PREFIX ALICE* OWNER ALICE is a tighter filter than either alone.
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):
PREFIX ALICEJ* ; OWNER ALICE ; ST
Output:
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:
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.
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.
| Cmd | What it does |
|---|---|
S | Select / browse — open the job's combined SYSOUT |
SE | SDSF Edit — same as S but in edit mode (read-only by default) |
SJ | Show JCL — display the converted JCL the system actually ran |
? | Expand — show the job's individual SYSOUT datasets (one row per DDname) |
X | Print/cancel — context-dependent (purges on O, cancels on DA) |
XD | Download the SYSOUT to a dataset |
XDC | Download with confirmation panel |
C | Cancel the job (active jobs only) |
P | Purge — discard the job and all its SYSOUT |
O | Release (output queue) or change class (held queue) |
H | Hold the job's output |
A | Release held output (action) |
E | Restart the job from a step (with RESTART=) |
Z | Zap — modify selected fields inline |
D | Display — show full attributes |
= | Repeat the last command on this row |
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.
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:
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:
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).
| Command | What it does |
|---|---|
/$DA | Display all active initiators and the jobs they hold |
/$DI | Display all initiators with status |
/$DI1 | Display initiator 1 only |
/$SI1 | Start initiator 1 |
/$PI1 | Drain initiator 1 (finish current job, then stop) |
/$EI1 | Halt initiator 1 immediately |
/$DJ | Display all jobs in JES2 |
/$DJALICEJ01 | Display one job by name |
/$DJQ | Job queue summary |
/$DSPL | Spool volume status |
/$DJOBCLASS(A) | Display JOBCLASS A definition |
/$TJOBCLASS(A),QHELD=N | Toggle JOBCLASS A's held attribute off |
/$DPRT1 | Display printer 1 status |
/$SPRT1 | Start printer 1 |
/$PPRT1 | Drain printer 1 |
/$VS,'cmd' | Pass cmd to MVS (e.g. /$VS,'D A,L') |
/$N | Display NJE node table |
/$DA (* what's running right now *)
/$DI (* initiator status *)
/$DSPL (* spool volumes — capacity check *)
Output:
$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.
=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.
=SR
NP REPLY TIME SYSNAME MSG
01 0014 12:31:23 SY1 *14 IEF238D ALICEJ01 - REPLY DEVICE OR CANCEL
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.
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.
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
PREFIX *after a busy night — you'll see thousands of jobs and SDSF gets slow. Always re-narrow withPREFIX ALICE*before scrolling.- Forgetting
PRINT CLOSE— leaves the print dataset partially written and locked. Always close after aPRINT ODSN. - Confusing
H(Hold) panel with theHrow command — typingHin the panel command field opens the held-output panel; typingHin a row prefix holds that job's output. Same letter, very different actions. - Slash commands rejected — RACF in the
OPERCMDSclass controls who can issue what. A silent reject usually means your userid lacksJES2.<verb>.<noun>access; ask the security admin forREADon the specific resource. SET SAVE OFFand lost filters — if your prefixes never persist across sessions, you have save mode off. Turn it on once and forget about it.?then forgetting where you are — after expanding a job into individual datasets,F3returns to the job list, not to the original panel.=STis the safer "go home" key.- 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.
P(purge) is irreversible — there is no undo. Hold (H) instead of purging if you're not sure you're done with the output.OWNER ALICEshows nothing — userid is uppercase on z/OS.owner aliceis the same query, butOWNER ALIC(truncated) silently matches nothing because OWNER is exact-match by default. UseOWNER ALICE*for prefix-match./$DSPLshows spool nearly full — JES2 will start refusing new jobs at 80% by default. Notify the operator and consider/$P JES2is 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.
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:
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:
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:
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.
=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.
S JESYSMSG (* browse it *)
FIND ABEND (* find the abend line *)
FIND S0C7 (* find data-exception code *)
Output:
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.
=DA
PREFIX ALICEJ*
Output:
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
C ALICEJ01 JOB12351 (* cancel *)
Output:
$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".
=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.
=INIT
NP INIT Status JobName Class
P 5 ACTIVE ALICEJ02 A
P 5
Output:
$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.
=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:
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:
/$P JOBQ,QUEUE=OUTPUT,OWNER=ALICE (* JES2 bulk-purge via slash *)
Output:
$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.
=SR
NP REPLY TIME MSG
01 0023 14:02:11 *23 IEF233A M 0A40,TAPE01,SL,ALICEJ02,STEP01,TAPEIN
R 23,'0A40,TAPE01' (* mounted on the indicated drive *)
Output:
$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.
=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.
/* 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:
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.
# 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:
jobname jobid status retcode
ALICEJ01 JOB12345 OUTPUT CC 0000
ALICEJ02 JOB12346 ACTIVE null