skip to content

z/OS FTP Reference

FTP from TSO, batch FTP via JCL, SITE parameters, transfer modes, FTPS, FTP.DATA configuration, and JES spool transfers.

9 min read 34 snippets 2d ago

z/OS FTP Reference#

Starting FTP from TSO#

FTP hostname
FTP hostname(port)
FTP hostname PORT(2121)
FTP hostname SECURE                    (* explicit TLS/FTPS *)
FTP hostname VERBOSE                   (* show all server responses *)

After connecting you are prompted for userid and password. To skip the prompt, use a NETRC file (see below).

Interactive FTP subcommands#

USER userid password        (* re-authenticate or initial login *)
CD remotedir                (* change remote directory *)
LCD localdsn                (* change local dataset HLQ prefix *)
PWD                         (* print remote working directory *)
DIR [pattern]               (* detailed directory/member listing *)
LS  [pattern]               (* brief listing *)
GET remote local            (* download remote file to local dataset *)
PUT local remote            (* upload local dataset to remote file *)
MGET pattern                (* download multiple files matching pattern *)
MPUT pattern                (* upload multiple datasets matching pattern *)
APPEND local remote         (* append local data to remote file *)
DELETE remotefile           (* delete remote file *)
RENAME old new              (* rename remote file *)
MKDIR remotedir             (* create remote directory *)
RMDIR remotedir             (* remove remote directory *)
QUOTE cmd                   (* send raw FTP command to server *)
SITE params                 (* send SITE parameters to remote FTP server *)
PASSIVE                     (* toggle passive vs active mode *)
STATUS                      (* show current connection and settings *)
TYPE A                      (* ASCII transfer mode β€” EBCDIC↔ASCII translation *)
TYPE B                      (* BINARY / IMAGE β€” no translation *)
TYPE E                      (* EBCDIC β€” mainframe-to-mainframe, no translation *)
SENDSITE ON|OFF             (* auto-send SITE before each transfer *)
SENDPASV ON|OFF             (* passive mode toggle *)
LOCSITE params              (* set allocation defaults for local receives *)
LRECL nnn                   (* set local LRECL for incoming transfers *)
BLKSIZE nnn                 (* set local BLKSIZE for incoming transfers *)
RECFM type                  (* set local RECFM for incoming transfers *)
BLOCK nnn                   (* set block count for transfers *)
OPEN hostname               (* connect to a new host without restarting FTP *)
CLOSE                       (* disconnect from current host, stay in FTP *)
QUIT                        (* disconnect and exit FTP *)

Transfer types#

TypeCommandUse when
ASCIITYPE AText files between mainframe and non-mainframe; translates EBCDIC↔ASCII
Binary/ImageTYPE B or TYPE ILoad modules, compiled objects, binary data; no translation
EBCDICTYPE EMainframe-to-mainframe text transfers; no translation
TYPE A    (* ASCII β€” default for most z/OS FTP servers *)
TYPE B    (* Binary/Image *)
TYPE E    (* EBCDIC *)

Tip: Always set TYPE B before transferring load libraries, VSAM exports, or any non-text data. Forgetting this is the most common cause of corrupted transfers.

SITE subcommand β€” z/OS allocation parameters#

SITE passes dataset allocation instructions to the remote z/OS FTP server before PUT/MPUT. These parameters control how the destination dataset is created.

Record format and space:

SITE RECFM=FB LRECL=80 BLKSIZE=27920 SPACE=(TRK,(5,5)) UNIT=SYSDA
SITE RECFM=VB LRECL=255 BLKSIZE=32760 SPACE=(CYL,(1,1))
SITE RECFM=U  BLKSIZE=32760                               (* load modules *)
SITE RECFM=FB LRECL=133                                   (* print/report lines *)

Dataset organization:

SITE PDS                                                   (* allocate as PDS *)
SITE PDSE                                                  (* allocate as PDSE *)
SITE DSNTYPE=LIBRARY                                       (* PDSE via DSNTYPE keyword *)
SITE FILETYPE=SEQ                                          (* sequential dataset β€” default *)
SITE FILETYPE=JES                                          (* submit to JES / retrieve spool *)

SMS classes:

SITE MGMTCLAS=STANDARD STORCLAS=FAST DATACLAS=FB80
SITE DATACLAS=VB255
SITE STORCLAS=PREMIUM

Space units:

SITE CYLINDERS SPACE=(5,2)
SITE TRACKS    SPACE=(100,20)
SITE BLOCKS    SPACE=(27920,(100,20))
SITE BLOCKSIZE=0                                           (* let system determine optimal BLKSIZE *)

Translation and encoding:

SITE XLATE ON                                              (* enable translation table *)
SITE XLATE OFF
SITE ENCODING=IBM-1047                                     (* specific EBCDIC code page *)
SITE ENCODING=ISO8859-1                                    (* ASCII code page *)

Multiple parameters on one line:

SITE RECFM=FB LRECL=80 BLKSIZE=27920 SPACE=(TRK,(10,5)) UNIT=SYSDA
SITE RECFM=VB LRECL=255 BLKSIZE=32760 SPACE=(CYL,(2,1)) MGMTCLAS=STANDARD

Dataset naming β€” quoted vs unquoted#

Quoting dataset names with single quotes forces absolute naming (no prefix appended):

GET 'SYS1.PROCLIB(IEFBR14)' iefbr14.jcl      (* explicit absolute name *)
PUT localfile 'MY.TARGET.DATASET'              (* absolute β€” no userid prefix *)

Without quotes the FTP server prepends your TSO prefix (usually userid) as the high-level qualifier:

GET PROCLIB(IEFBR14)        (* becomes userid.PROCLIB(IEFBR14) *)
PUT myfile DATA             (* becomes userid.DATA *)

PDS member transfers#

Upload to a specific member:

PUT localfile 'MY.PDS.LIB(MEMBER)'

Upload multiple files β€” member names taken from filename stems:

MPUT *.cbl 'MY.COBOL.SRC(*)'
MPUT *.jcl 'MY.JCL.LIB(*)'

Download all members of a PDS:

CD 'MY.SOURCE.LIB'
DIR                          (* verify members *)
MGET *                       (* download all members as separate local files *)

Download one member:

GET 'MY.PDS.LIB(MEMBER)' member.txt

Submitting JCL and retrieving spool via FTP (FILETYPE=JES)#

Switch to JES mode, submit, and retrieve output:

SITE FILETYPE=JES
PUT myjob.jcl                (* submit β€” FTP returns JOBID e.g. JOB00123 *)
DIR                          (* list your jobs and their status *)
DIR JOB00123                 (* list sysout datasets for specific job *)
GET JOB00123.2 output.txt    (* retrieve sysout dataset 2 (JESMSGLG, JESJCL, etc.) *)
DELETE JOB00123              (* purge all sysout for this job *)
SITE FILETYPE=SEQ            (* switch back to normal sequential mode *)

JES dataset numbers:

Sysout DDMeaning
.1JESMSGLG β€” JES message log
.2JESJCL β€” expanded JCL
.3JESYSMSG β€” JES/system messages
.4+Application SYSOUT DD statements in step order

Batch FTP via JCL#

Standard batch download:

//FTPGET   JOB (ACCT),'FTP GET',CLASS=A,MSGCLASS=X
//FTP      EXEC PGM=FTP,PARM='remotehost'
//SYSPRINT DD SYSOUT=*
//OUTPUT   DD SYSOUT=*
//INPUT    DD *
ftpuser
ftppass
TYPE B
GET remotefile 'MY.RECEIVED.DATA'
QUIT
/*

Batch upload with SITE parameters:

//FTPPUT   JOB (ACCT),'FTP PUT',CLASS=A,MSGCLASS=X
//FTP      EXEC PGM=FTP,PARM='remotehost'
//SYSPRINT DD SYSOUT=*
//OUTPUT   DD SYSOUT=*
//INPUT    DD *
ftpuser
ftppass
SITE RECFM=FB LRECL=80 BLKSIZE=27920 SPACE=(TRK,(5,5))
PUT 'MY.JCL.LIB(MYJOB)' MYJOB.JCL
QUIT
/*

Batch submit JCL to remote system via JES mode:

//FTPSUBMT JOB (ACCT),'REMOTE SUBMIT',CLASS=A,MSGCLASS=X
//FTP      EXEC PGM=FTP,PARM='remotezos'
//SYSPRINT DD SYSOUT=*
//OUTPUT   DD SYSOUT=*
//INPUT    DD *
ftpuser
ftppass
SITE FILETYPE=JES
PUT 'MY.JCL.LIB(BATCHJOB)'
QUIT
/*

Batch FTP with NETRC auto-login:

//FTPNETRC JOB (ACCT),'FTP NETRC',CLASS=A,MSGCLASS=X
//FTP      EXEC PGM=FTP,PARM='remotehost'
//SYSPRINT DD SYSOUT=*
//OUTPUT   DD SYSOUT=*
//NETRC    DD DSN=MY.NETRC,DISP=SHR
//INPUT    DD *
TYPE B
GET remotefile 'MY.RECEIVED.DATA'
QUIT
/*

Multiple transfers in one batch job:

//FTPMULTI JOB (ACCT),'MULTI FTP',CLASS=A,MSGCLASS=X
//FTP      EXEC PGM=FTP,PARM='remotehost'
//SYSPRINT DD SYSOUT=*
//OUTPUT   DD SYSOUT=*
//INPUT    DD *
ftpuser
ftppass
TYPE B
SITE RECFM=FB LRECL=80 BLKSIZE=27920 SPACE=(TRK,(5,5))
PUT 'MY.FIRST.DATA'  first.dat
PUT 'MY.SECOND.DATA' second.dat
TYPE A
PUT 'MY.REPORT.DATA' report.txt
QUIT
/*

Specifying a non-default port:

//FTP      EXEC PGM=FTP,PARM='remotehost 2121'

FTP.DATA β€” client configuration#

FTP.DATA (or hlq.FTP.DATA) controls default FTP client settings. Search order at session start:

  1. userid.FTP.DATA (personal)
  2. FTP.DATA under current prefix
  3. SYS1.TCPPARMS(FTPDATA) (site-wide default)

Common FTP.DATA keywords:

FTPKEEPALIVE   60             (* send keepalive every 60 seconds *)
DATATYPE       ASCII          (* default transfer type: ASCII, BINARY, or EBCDIC *)
SENDSITE       TRUE           (* auto-send SITE params before each transfer *)
PASSIVE        FALSE          (* use active mode; TRUE for passive *)
SENDPASV       FALSE          (* do not send PASV by default *)
VERBOSE        FALSE          (* suppress server response display *)
NODNS          TRUE           (* use IP addresses only, skip DNS *)
PROXY          proxyhost(port) (* FTP proxy *)
AUTOLOCSITE    TRUE           (* mirror remote SITE params to local *)
SBDATACONN     TRUE           (* secondary data connection binding *)
LOCSITE RECFM=FB LRECL=80 BLKSIZE=27920   (* default local allocation for GET *)
LOCSITE SPACE=(TRK,(5,5)) UNIT=SYSDA
TLSMECHANISM   TLS            (* force TLS β€” see FTPS section *)
SECURE_CTRLCONN PRIVATE       (* require encrypted control connection *)
SECURE_DATACONN PRIVATE       (* require encrypted data connection *)

NETRC β€” automatic login#

NETRC (or userid.NETRC) stores credentials for password-free FTP sessions:

MACHINE remotehost LOGIN ftpuser PASSWORD ftppass
MACHINE prod.zos.example.com LOGIN produser PASSWORD s3cr3t
MACHINE default    LOGIN anonymous PASSWORD user@example.com

Reference in JCL with //NETRC DD DSN=MY.NETRC,DISP=SHR. Protect this dataset with RACF β€” it contains cleartext passwords.

FTPS β€” FTP over TLS (explicit)#

z/OS FTP supports explicit TLS (FTPS). This is not SFTP β€” it uses standard FTP protocol over a TLS channel.

From TSO:

FTP hostname SECURE
FTP hostname SECURE PORT(990)           (* implicit TLS on port 990 *)

In FTP.DATA for always-on TLS:

TLSMECHANISM  TLS
SECURE_CTRLCONN PRIVATE
SECURE_DATACONN PRIVATE

In batch JCL:

//FTP      EXEC PGM=FTP,PARM='hostname SECURE'

AT-TLS (Application Transparent TLS) can also be configured at the TCP/IP policy level to enforce TLS transparently without application changes β€” contact your network/security team.

LOCSITE β€” default allocation for incoming transfers#

LOCSITE sets allocation defaults for datasets created during GET/MGET on the local (z/OS) side. Can be set in FTP.DATA or issued interactively:

LOCSITE RECFM=FB LRECL=80 BLKSIZE=27920 SPACE=(TRK,(5,5))
LOCSITE RECFM=VB LRECL=255 BLKSIZE=32760 SPACE=(CYL,(1,1))
LOCSITE PDSE                            (* incoming PDS transfers become PDSE *)
LOCSITE UNIT=SYSDA STORCLAS=STANDARD

Common patterns#

Download a single member:

GET 'PROD.PROCLIB(STARTED)' started.proc

Upload and replace a member:

SITE RECFM=FB LRECL=80
PUT deploy.jcl 'MY.JCL.LIB(DEPLOY)'

Transfer between two z/OS systems (EBCDIC, no translation):

TYPE E
GET 'REMOTE.DS' 'LOCAL.DS'

Bulk download from remote directory:

CD /u/myuser/exports
MGET *.csv

Retrieve multiple spool outputs from a batch job:

SITE FILETYPE=JES
DIR JOB00456
GET JOB00456.3 sysmsgs.txt
GET JOB00456.4 sysprint.txt
DELETE JOB00456
SITE FILETYPE=SEQ

Passive mode for firewall-friendly transfers:

PASSIVE
GET remotefile localfile

FTP return codes#

RangeMeaning
1xxPositive preliminary β€” action initiated
2xxPositive completion β€” action succeeded
3xxPositive intermediate β€” more information needed
4xxTransient negative β€” temporary failure, retry may work
5xxPermanent negative β€” do not retry without fixing the cause

Common codes:

CodeMeaning
125Data connection open, transfer starting
150File status OK, opening data connection
200Command OK
220Service ready (server greeting)
226Transfer complete, closing data connection
230User logged in
250Requested action OK
257Pathname created
331Username OK, password required
425Can’t open data connection
426Connection closed, transfer aborted
500Syntax error / command unrecognized
501Syntax error in parameters
530Not logged in / authentication failed
550File unavailable β€” not found, no RACF access, or wrong filetype
553File name not allowed

Troubleshooting#

SymptomLikely causeFix
425 Can't open data connectionFirewall blocking data portIssue PASSIVE command or open FTP data port range
Garbled text after transferWrong transfer typeUse TYPE A for text, TYPE B for binary
Dataset not found (550)Missing quotes on absolute nameAdd single quotes around fully qualified names
Userid prefix appended unexpectedlyUnquoted dataset nameQuote the dataset name: 'SYS1.PROCLIB'
ABEND in batch FTPServer-side or allocation errorCheck SYSPRINT for response codes and messages
Permission denied (550)RACF access deniedVerify dataset profile and userid permissions
TLS handshake failureCertificate not trustedCheck AT-TLS policy; may need to add server cert to keyring
Transfer complete but data wrongBinary file sent as ASCIIRe-transfer with TYPE B
Member truncatedWrong LRECLUse SITE LRECL=nnn matching source LRECL
Batch job gets RC 12FTP authentication or allocation failureCheck SYSPRINT OUTPUT for 4xx/5xx response codes