On Fri, 2 May 2008 16:37:19 -0700, Howard Rifkind <[EMAIL PROTECTED]> wrote:
>Brian, would you be good enough to share the code for the process you >mention below? >>On Thu, 1 May 2008 15:20:04 -0500, Brian Nielsen <[EMAIL PROTECTED]> >wrote: >> >>I recently setup an automated process to FTP to z/OS data extracted fro m >>DISKACNT's ACCOUNT files every day. No RSCS or human intervention >>required. Here is a sanitized version of the code and environment in which sanitize d parts have been replaced with: {comment about what should be here} The environment is described first, followed by the code. --------------- User directory for service machine: USER {userid} LBYONLY 16M 128M G INCLUDE IBMDFLT MACH ESA IPL CMS MDISK 191 3390 {start cyl} 001 {volid} MR MDISK 192 3390 {start cyl} 020 {volid} MR LINK DISKACNT 191 291 RR Service machine requirements and notes: - all files below must reside on the {userid} 191 MDISK - the 192 disk will hold all files created by this process - 20 cyls for the 192 disk will hold about 20 months worth of data (for this site, ymmv) z/OS requirements: - TCP/IP connection with sending side - pre-allocated PDSE to receive FTP transfers (2 cyls holds about 150 days worth of data for this site, ymmv) - userid for sending side to use for FTP, with authority to write into the PDSE General Process requirements and notes: - VM accounting records are closed every day just before midnight (by a scheduling service machine) - {userid} is XAUTOLOG'd just after midnight (by a scheduling service machine) - PDSE members DAYdd contain the accounting data from that day of the month - Alternate code in BILL-DAT EXEC can name PDSE members $Ammddyy instea d of DAYdd - The PDSE is self-cleaning if members are named DAYdd, but not if name d $Ammddyy - PDSE member TODAY contains yesterday's accounting data (to be processed today by a z/OS process at this site) - The z/OS process must erase the TODAY member when it is done with it - PDSE member $TODAY will only exist if the z/OS process didn't erase member TODAY - If PDSE member REQUESTS exists, it will be retrieved and later rename d $Rmmddyy - The contents of the REQUESTS member is one or more lines of: mmddyy - The sending side will send accounting data from all dates listed in REQUESTS - Any ACCOUNT files on DISKACNT 191 but not on {userid} 192 are processed & sent to z/OS - An automated process for deleting old DISKACNT 191 files and {userid} 192 files needs to be implemented. - The EXPIRE EXEC will find files older than a threshold, but currently does nothing else. -------------- PROFILE EXEC: /* */ 'set pf1 filel * * ' 'set pf3 q disk' 'set pf12 retrieve' 'set pf24 retrieve forward' 'access 291 z' /* DISKACNT 191 */ 'CP LINK TCPMAINT 592 592 RR' /* has FTP command */ 'ACCESS 592 U' /* If connected, prompt user for action */ connected=substr( diag(24, -1), 13, 1 ) <> 2 IF connected THEN DO say 'Press ENTER to run normally, or any input to cancel.' pull response IF response<>'' THEN EXIT 1 END /* run the billing process */ 'EXEC BILLING' 'CP LOGOFF' ------------------------ BILLING EXEC: /* This exec ties together the execs that do the sub-functions. */ 'COPY FTP REQUESTS A = INPUT D (REP' /* prep the ftp commands file */ 'EXEC FTP-PRD1' /* get requests file from zOS */ 'EXEC BILL-CHK' /* add unprocessed files to TODO LIST * / 'EXEC BILL-DO' /* process TODO LIST file */ 'EXEC FTP-PRD1' /* send data file to zOS */ ------------------------ FTP REQUESTS (this has been sanitized): cd '{fully qualified name of z/OS PDSE}' get requests todo.list.d (replace quit ------------------------ FTP-PRD1 EXEC (this has been sanitized to remove an IP address): /* This exec FTPs data to/from z/OS on PROD1. */ /* FTP commands are in an input file. */ /* FTP ouput will be saved to a file, then appended to a log. */ fm='D' in_file='FTP INPUT' fm out_file='FTP OUTPUT' fm today=DATE('U',,,'') /* get todays date as mmddyy */ ftp_log ='FTP-LOG' today fm 'FILEDEF INPUT DISK' in_file 'FILEDEF OUTPUT DISK' out_file z_os_ip_addr='{IP address of z/OS system}' 'FTP' z_os_ip_addr ftp_rc=rc IF ftp_rc<>0 THEN say 'FTP rc='ftp_rc 'FILEDEF INPUT CLEAR' 'FILEDEF OUTPUT CLEAR' 'PIPE (ENDCHAR ?)', /* append the ftp output to the log file */ '<' out_file, '| >>' ftp_log ---------------------- BILL-CHK EXEC: /* This exec determines which VM accounting files have not been */ /* processed yet. */ fm_new='Z' /* unprocessed files - DISKACNT 191 * / fm_old='D' /* processed files */ todo_fid='TODO LIST' fm_old yesterday_fid='YESTERDY LIST' fm_old 'PIPE (ENDCHAR ?)', /* make RECFM of todo file be V instead of F */ 'CMS COPY' todo_fid todo_fid '(oldd rep recfm V', '| HOLE' 'PIPE (ENDCHAR ?)', /* erase old file if it exists */ 'CMS ERASE' yesterday_fid, '| HOLE' base=DATE('B') today =DATE('U',base ,'B','') /* today's date in mmddyy format */ yesterday=DATE('U',base-1,'B','') /* yesterday's date in mmddyy format */ 'PIPE (ENDCHAR ?)', 'CMS LISTF ACCOUNT $A*' fm_new '(DATE NOH', /* list ACCOUNT files on DISKACNT 191 */ '| NFIND DMS', /* discard CMS error msgs */ '| NLOCATE W2 \$A'today'\', /* discard today's accounting file */ '| SPECS /STATE/ 1 W1-2 NW /'fm_old'/ NW', /* build command to see if file is on processed disk */ '| CMS', /* issue command */ '| SPECS W4 1', /* keep ft from NOT FOUND msg */ '| SPECS 3-* 1', /* strip $A from ft */ '| y: NLOCATE W1 \'yesterday'\', /* find yesterday's accounting file */ '| f: FANINANY', /* append to list of files to send */ '| >>' todo_fid, /* append to list of files to send */ '?', 'y:', '| >' yesterday_fid, '| f:' /* append to list of files to send */ --------------------------- BILL-DO EXEC: /* This exec reads the TODO LIST file and for each entry calls the */ /* BILL-DAT exec to process that dates data. */ fm_old='D' /* processed files */ in_file='TODO LIST' fm_old ftp_fid='FTP INPUT' fm_old /* file to hold FTP commands */ yesterday_fid='YESTERDY LIST' fm_old today=DATE('U',,,'') /* get todays date as mmddyy */ 'COPY FTP HEADER A' ftp_fid '(REP' /* initialize FTP command fil e */ 'STATE' in_file /* verify that input file exists */ IF rc<>0 THEN EXIT rc 'PIPE (ENDCHAR ?)', '<' in_file, /* read in the file */ '| NLOCATE W1 /'today'/', /* discard files with today's date */ '| SPECS /EXEC BILL-DAT ACCOUNT $A/' 1 W1 N, /* build call to BILL-DA T EXEC */ '| CMS' /* call BILL-DAT EXEC */ 'PIPE (ENDCHAR ?)', /* add to FTP command file */ 'LITERAL rename requests $r'today, '| >>' ftp_fid 'RENAME' in_file 'TODO' today fm_old /* preserve TODO list */ 'STATE' yesterday_fid /* verify that input file exists */ IF rc<>0 THEN EXIT rc 'PIPE (ENDCHAR ?)', /* add to FTP command file */ '<' yesterday_fid, /* read in the file */ '| SPECS /put billdata.$A/ 1 W1 N /.'fm_old '$TODAY/ N', '| APPEND LITERAL rename $TODAY TODAY', '| >>' ftp_fid ----------------------------- FTP HEADER (this has been sanitized): cd '{same fully qualified z/OS PDSE name as in FTP REQUESTS file}' ----------------------------- NETRC DATA (this has been sanitized): machine {same IP address as in FTP-PRD1 EXEC} login {z/OS userid for this FTP process} password {password for same} ----------------------------- BILL-DAT EXEC (this has been sanitized to remove reformatting of the accounting records): /* This exec reads a file containing VM accounting records and */ /* filters and transforms the data into the format required by the */ /* billing system on z/OS. */ arg fname ftype . in_file=fname ftype in_fm='Z' /* unprocessed files - DISKACNT 191 */ out_fm='D' /* processed files */ 'PIPE (ENDCHAR ?)', /* copy input file to processed disk */ 'CMS COPY' in_file in_fm '= =' out_fm '(OLDD REP', '| HOLE' in_file=fname ftype out_fm /* use the copied file */ 'STATE' in_file /* verify that input file exists */ IF rc<>0 THEN EXIT rc out_file='BILLDATA' ftype out_fm ftp_fid='FTP INPUT' out_fm zos_name='DAY'substr(ftype,5,2) /* zos_name='$A'delstr(ftype,1,2) */ /* use this for non-overwrite mode */ 'PIPE (ENDCHAR ?)', 'LITERAL put billdata.'ftype'.'out_fm zos_name, '| >>' ftp_fid {sanitized variables being initialized for use in pipe below} 'pipe (endchar ?)', 'f:', /* reformatted records come here */ 'FANINANY', '| >' out_file, '?', '<' in_file, /* read input file */ {sanitized pipe stages which manipulate the accounting records} '| f:' EXIT --------------------------- EXPIRE EXEC: /* This EXEC finds files older than a specified number of days. */ arg fn ft fm threshold . IF ^DATATYPE(threshold,'W') THEN DO say '"'threshold'" is not a whole number.' EXIT 4 END base_date=DATE('B') /* today's date */ cutoff_date=base_date-threshold /* date of old files */ 'PIPE (ENDCHAR ?)', 'CMS LISTF' fn ft fm '(DATE NOH', '| SPECS W1-3 1.21 PAD 0 W8 22.8 RIGHT', /* fn ft fm mm/dd/yy */ '| DATECONV W4 REXXU REXXB', /* put date in base date format */ '| PICK W4 <<= /'cutoff_date'/', /* keep only old files */ '| SPECS W1-3 1', /* fn ft fm */ '| CONS' --------------------------- Brian Nielsen