Setting PATH in IEBGENER from file - mainframe

I'm trying to set the PATH parameter in a IEBGENER step in a JCL from a file. But I can't seem to get it to work.
Here is what the original step, that works just fine, looks like:
//COPY EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT1 DD *
Some text
//SYSUT2 DD PATH='/local/Folder1/File1',
// PATHDISP=(KEEP,KEEP),
// PATHOPTS=(OWRONLY,OCREAT,OEXCL),
// PATHMODE=(SIRUSR,SIWUSR)
What I want to do is set the PATH parameter in SYSUT2 from a file that is written in some previous step. Something like this:
BROWSE TEST.FILE1 Line 0000000000 Col 001 080
Command ===> Scroll ===> CSR
********************************* Top of Data **********************************
TPATH='/local/Folder1/File1'
******************************** Bottom of Data ********************************
//SETPATH SET DSN=TEST.FILE1,DISP=SHR
//*
//COPY EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT1 DD *
Some text
//SYSUT2 DD PATH='&TPATH',
// PATHDISP=(KEEP,KEEP),
// PATHOPTS=(OWRONLY,OCREAT,OEXCL),
// PATHMODE=(SIRUSR,SIWUSR)
This of course complains about no variable TPATH in the JCL, which logically makes sense as it can't find the variable name in the JCL.
Also tried putting the entire SYSUT2 in a separate file, but without success.
A "good enough" compromise would be to concatenate a file prefix with a date and time parameter, but that would only work in production when the job is run via a scheduler (with OPCSCAN or similar). Not in test where I submit the job myself, or is it possible to do that without a scheduler?
'/local/Folder1/File' & iDate & iTime -- You get the point.
Any ideas much appreciated!

One way to do this would be to write the SYSUT2 DD statement to a member in a separate PDS or PDSE, then INCLUDE that member in your IEBGENER step. The separate PDS or PDSE must be specified in a JCLLIB statement.
You could also run BPXBATCH and use cp instead of IEBGENER to copy your data.
If you have the Dovetail Technologies Co:Z Toolkit installed, fromdsn might be what you're looking for.

Related

copying and pasting information between datasets

How to copy data fully from one dataset to another dataset when one of the dataset consists of dots as shown bllow ?
The dots you are seeing are most likely undisplayable data so a utility is the best bet.
There are many ways to move data around on z/OS. If you are simply trying to copy an existing dataset to another to make a copy you could use a batch utility like IEBGENER. Here is some sample JCL
//IEBGENER JOB (CCCCCCCC),'HOGSTROM',
// MSGLEVEL=(1,1),
// MSGCLASS=O,
// CLASS=A,
// NOTIFY=&SYSUID
//*
//*----------------------------------------------------------
//* IEBGENER
//*----------------------------------------------------------
//GENER02 EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DSN=USER1.TEST.DATA,DISP=SHR
//SYSUT2 DD DSN=USER1.TEST.ODATA,DISP=(,CATLG,DELETE),
// UNIT=SYSDA,SPACE=(CYL,5,RLSE),DCB=USER1.TEST.DATA
//SYSIN DD DUMMY
//
You could also use online tools like ISPF Option 3.2 to create the new dataset
and 3.3 to move / copy it.
It's not clear to me what question you're asking, or why you'd do such a thing by hand. I'd instead suggest using one of the built in z/OS tools. Specifically, IEBCOPY.
//COPYLIKE JOB MSGCLASS=H,TIME=1440
//COPYREP EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DSN=SYS1.LPALIB,DISP=SHR,UNIT=3390,VOL=SER=D83RL2
//SYSUT2 DD DSN=SYS1.LPALIB.ORIG,
// LIKE=SYS1.LPALIB,
// DISP=(NEW,KEEP),VOL=SER=D83RL2,UNIT=3390
//SYSIN DD *
/*
Also, as a note, the source dataset doesn't consist of dots, it consists of undisplayable data.

How to secure store password in a JCL FTP?

I have the following code to send a file through FTP using JCL:
//FTP00001 EXEC PGM=IKJEFT01,DYNAMNBR=50
//OUT DD SYSOUT=*
//AMSDUMP DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSPRINT DD DUMMY
//OUTPUT DD SYSOUT=*
//SYSTSIN DD *
123.234.345.67
myuser1
p4ssw0rd
ascii
cd infos
PUT 'EF35.LMINFO.D180203' info_180203.txt
QUIT
/*
It works like a charm, the problem is that I don't want to put the credentials hardcoded inside the JCL. How could we hide them so anyone who has access to the JCL can't see the connection details? I'd like to hide the credentials from the output too, but note I still want to see the rest of the info: bytes transferred, possible error messages, and so on.
I thought in putting the SYSTSIN content inside a file, but I'd face the same problem: anyone who has access to the file, will see the user and pass. Therefore, what is the best method to sort this out?
The way I have seen it done is like this:
//FTP00001 EXEC PGM=IKJEFT01,DYNAMNBR=50
//OUT DD SYSOUT=*
//AMSDUMP DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSPRINT DD DUMMY
//OUTPUT DD SYSOUT=*
//SYSTSIN DD DSN=AA.SOMETHING.LOGIN,DISP=SHR
// DD DSN=AA.SOMETHING.FTP,DISP=SHR
// DD DSN=AA.SOMETHING.LOGOFF,DISP=SHR
where AA.SOMETHING.LOGIN would contain
123.234.345.67
myuser1 <- replace with ACID for this job
p4ssw0rd <- replace with password for the ACID
AA.SOMETHING.FTP would conatin
ascii
cd infos
PUT 'EF35.LMINFO.D180203' info_180203.txt
AA.SOMETHING.LOGOFF would contain
QUIT
This JCL would run via a batch ACID and only the ACID would have read/write access to the AA.SOMETHING.LOGIN file. So the FTP server would need to add the ACID as a user. That is really the only way to do it. You are right though, anyone with access to AA.SOMETHING.LOGIN can see the credentials, but because we separated the login information from the FTP commands, there is no reason to need access to the login files unless the username/pass or the IP address changes. So you would be able to change anything in the files you have access to. You could also take it a step further than put the IP address in a separate dataset so then you can edit/view literally anything except the login credentials. That would look like this:
//FTP00001 EXEC PGM=IKJEFT01,DYNAMNBR=50
//OUT DD SYSOUT=*
//AMSDUMP DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSPRINT DD DUMMY
//OUTPUT DD SYSOUT=*
//SYSTSIN DD DSN=AA.SOMETHING.SERVER,DISP=SHR
// DD DSN=AA.SOMETHING.LOGIN,DISP=SHR
// DD DSN=AA.SOMETHING.FTP,DISP=SHR
// DD DSN=AA.SOMETHING.LOGOFF,DISP=SHR
This also allows you to change the server, FTP commands and logout/cleanup all without having access to the login credentials.
The only real downside to this is if you ever need to update the login credentials, you either need to:
Request access to the file
Write another JCL that will run with the ACID that has access to that file to update it
Even with that in mind, I still think this is the best way.
harrison4 pointed out that the IBM Communications Server has an architected form of this solution that can use either a dataset or a USS file. It is documented in the "z/OS Communications Server: IP User's Guide and Commands" manual to which harrison4 linked in his comment:
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.halu001/netftp.htm
It may go without saying, but I'll say it anyway. It is always bad practice to store passwords in datasets or files unless they are encrypted (not encoded, encrypted). If you must do this, be sure that the file permissions or security manager profiles restrict access to the file/dataset as much as possible.

Take the last file and use it as jcl variable

I have to do a job that uses the last file from a base name. For example, if I am having:
FILE.140115
FILE.140111
FILE.140101
I need to catch FILE.140115 wich has the closest date from today.
So, I would use:
//TEST010 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//OUTDD DD DSN=FILE.LISTFILE,
// DISP=(NEW,CATLG,DELETE),
// DATACLAS=(MED),
// DCB=(RECFM=VB,LRECL=125)
//SYSIN DD *
LISTCAT ENT(FILE.*) -
NAME -
OUTFILE(OUTDD)
Then, using a sort I can obtain a single file with the name of the file that I need inside. But I dont know how to use the content of this file as a variable to use it as parameter in another step.
Is there a way to do this without using CLIST? Or other ways to do what I want.
Thanks in advance!
Have you tried using a GDG? Many problems normally solved in a distributed environment with date/timestamps in file names are readily solved in a mainframe environment with GDGs.

How to create a member in an existing pds using jcl

I've used the below jcl:
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DUMMY,RECFM=FB,LRECL=80
//SYSUT2 DD DSN=RK.MYDIR.FILES(NEW1),DISP=(SHR)
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
I was able to create it. But i can't understand the code here. Is there any possibility to create using IEFBR14. If not this is the nly way. Please kindly explain me the code. Thank you
It can't be done with IEFBR14
IEBCOPY is more appropriate:
http://publib.boulder.ibm.com/infocenter/zos/basics/index.jsp?topic=/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBCOPY.htm
This is the reference which helps explain IEBGENER:
http://publib.boulder.ibm.com/infocenter/zos/basics/index.jsp?topic=/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBGENER.htm
If you're interested in the reason why, understand that IEFBR14 doesn't actually open any of the DD statements you code in your JCL. Rather, it's just a shorthand way to drive the system allocation (and deallocation) routines. Indeed, if you were to look at an assembler listing of iEFBR14, you'd find it's only two instructions: set the R15 return code to zero, and exit.
With batch processing, the idea is that the system (JES plus the batch initiator) should do a lot of the work before an application even starts. Thus, if you allocate a new dataset, or reference (say) a tape device that takes time for the operator to mount, the system does all this for you before your program even starts. IEFBR14 is a convenient way to use the system allocation routines to allocate files using these capabilities of JCL.
But there's a catch when it comes to accessing PDS datasets in JCL, like you're trying to do.
When you specify DSN(MEMBER) syntax in JCL, the allocation routines don't particularly care about the MEMBER part - turns out, this isn't a function of the initiator, but is instead implemented in OPEN/CLOSE. In your example, allocation verifies that the dataset exists (since you coded DISP=SHR), and when a program OPENs the DD statement, the OPEN routines automatically issue BPAM FIND/POINT/STOW to get you to the PDS member you specified. This is how your PDS member gets created, and so you need to use a program that actually OPENs the file (IEBGENR, IEBUPDTE, IEBCOPY, IDCAMS, etc would all work).
One small unrelated comment is that you might want to be careful about updating datasets (especially PDS) using DISP=SHR. If you manage to get the timing wrong, two of these jobs could in theory run at exactly the same time, and this would likely cause corruption to your dataset. Unless you're certain you're the only task accessing the PDS, it's safer to use DISP=OLD in this case.
If you'd like to create multiple members at once, I suggest IEBUPDTE.
From IBM:
This basic example uses IEBUPDTE to add two JCL procedures to the data set named MY.PROCLIB:
//ADDPROC1 JOB 1,SMCHUGH,MSGCLASS=X
// EXEC PGM=IEBUPDTE
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DISP=OLD,DSN=MY.PROCLIB
//SYSUT2 DD DISP=OLD,DSN=MY.PROCLIB
//SYSIN DD DATA
./ ADD LIST=ALL,NAME=MYJOB1
//STEP1 EXEC=SUZNX1
//PRINT DD SYSOUT=A
// (more JCL for MYJOB1)
//SYSUDUMP DD SYSOUT=* (last JCL for MYJOB1)
./ REPL LIST=ALL,NAME=LASTJOB
//LIST EXEC PGM=SUZNLIST
// (more JCL for this procedure)
//* LAST JCL STATEMENT FOR LASTJOB
./ ENDUP
/*
This creates one new member, MYJOB1, but you can see that it can also replace members (LASTJOB).
http://publib.boulder.ibm.com/infocenter/zos/basics/topic/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBUPDTE.htm
If you are copying the contents of a DSN into the new member, use IEBGENER.
To set the attributes of the new DSN dynamically use the LIKE parameter.
For example (using Mikes example above)
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset
//SYSUT2 DD DISP=(,CATLG,DELETE),DSN=your.output.dataset,
// LIKE=your.input.dataset
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY <-- no CONTROL statements
The LIKE attribute lets you easily create a new dataset, using the attributes of the dataset you specify, I also changed the disposition to reflect what a new DSN should be set to.
Warning! -- in re using IEBGENER with SYSUT2 DD DSN=PDS(MEMBER): Don't forget to specify the MEMBER name -- if you do, IEBGENER will overwrite your PDS from the beginning with whatever it finds in SYSUT1, starting with ruining your PDS directory!
The IEBGENER utility is used to copy a single file.
The SYSUT1 DD name is used to supply the INPUT or file to be copied from.
The SYSUT2 DD name is the OUTPUT file.
The SYSIN DD provides the CONTROL statements (if any).
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset
//SYSUT2 DD DISP=SHR,DSN=your.output.dataset
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY <-- no CONTROL statements
Note that the file/dataset can be a sequential dataset or a member of a partitioned dataset.
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset(member)
//SYSUT2 DD DISP=SHR,DSN=your.output.dataset(member)

Can we add symbolic parameters in PDS members used in cataloged procedures?

I have JCL, which is executing one catalog procedure.
In catalog procesdure one COBOL-DB2 pgm is being executed.
Below is my JCL
//A JOB (#),'CALL DB2',NOTIFY=&SYSUID
//JS010 EXEC TESTPROC
Below is my TESTPROC
//TESTPROC
//PS010 EXEC PGM=IKJEFT01,,DYNAMNBR=20
//STEPLIB DD DSN=TEST.LOADLIB,DISP=SHR
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD DSN=TEST.PDS(TESTPGM),
// DISP=SHR
//SYSOUT DD SYSOUT=*
below is my SYSTIN data --TESTPGM
DSN SYSTEM(TEST)
RUN PROGRAM(TESTPGM) PLAN(TESTPLAN)
END
My query is can I use symbolic parameters in place of TESTPGM and TESTPLAN in SYSTIN data member TESTPGM?
Regards,
Saisha :)
As mentioned below you could have the PDS Member name become a symbolic value and then define each member in the PDS to point to a different program. Using your JCL as an example:
//TESTPROC PROC MYPGM=
//PS010 EXEC PGM=IKJEFT01,,DYNAMNBR=20
//STEPLIB DD DSN=TEST.LOADLIB,DISP=SHR
//SYSTSPRT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSTSIN DD DSN=TEST.PDS(&MYPGM),
// DISP=SHR
//SYSOUT DD SYSOUT=*
In the above example your EXEC statement would envoke the proc as:
//JS010 EXEC TESTPROC,MYPGM=TESTPGM
Another option, you could over-ride the SYSTSIN DD directly as follows:
//A JOB (#),'CALL DB2',NOTIFY=&SYSUID
//JS010 EXEC TESTPROC
//PS010.SYSTSIN DD *
DSN SYSTEM(TEST)
RUN PROGRAM(TESTPGM) PLAN(TESTPLAN)
END
/*
//
One other suggestion...
In your final implementation you might want to consider separating the
DSN SYSTEM(TEST)
from the
RUN PROGRAM(TESTPGM) PLAN(TESTPLAN)
END
The reason is that you may find you want to run the program in multiple DB2 environments, not just SYSTEM(TEST). To do this, simply add another parameter DB2SYS= and modify as follows:
//TESTPROC PROC DB2SYS=MYTEST,MYPGM=
...
//SYSTSIN DD DSN=TEST.PDS(&DB2SYS),DISP=SHR
// DD DSN=TEST.PDS(&MYPGM),DISP=SHR
where PDS Member MYTEST has the DSN SYSTEM(TEST) statement already coded.
The short answer is no. If you have symbolic parameters in the control cards in the PDS your SYSTSIN DD statement references, they (the symbolic parameters) will not be resolved.
One way around this is to have a separate program, executing in a separate step within your procedure prior to your PS010 step, that takes in parameters and text and writes a temporary file. The symbolic parameters will be resolved in that program's PARM=.
//PS001 EXEC PGM=LOADPARM,PARM='DSN SYSTEM(&DSNSYS)'
//SYSPRINT DD SYSOUT=*
//OUTPUT01 DD DISP=(,PASS),
// DSN=&&DSNSYS,
// AVGREC=U,
// LRECL=80,
// RECFM=FB,
// SPACE=(80,1)
//****
The hypothetical program LOADPARM would simply take its input parm and write it to OUTPUT01, being careful to pad it on the right with blanks. In PS010 you would then have a SYSTSIN that looks like...
//SYSTSIN DD DISP=(OLD,DELETE),DSN=&&DSNSYS
// DD DISP=SHR,DSN=TEST.PDS(TESTPGM)
...where the TESTPGM member looks like...
RUN PROGRAM(TESTPGM) PLAN(TESTPLAN)
END
In this manner, your cataloged procedure is ignorant of which DB2 subsystem it is accessing. That information is supplied in the execution JCL with the DSNSYS symbolic parameter.
There are other ways to approach this problem, for instance you could have a symbolic parameter that resolves to a known member in a shared PDS, having one member per DB2 subsystem.
Nope, we cant use the symbolic parameters inside SYSTSIN. Instead of bifurcating the SYSTSIN card into two and generalizing the DB2 subsytem i prefer to maintain separate test datacards with symbolic parameter for that member name and switch it whenever needed.
But the automating the DB2 subsystem may not result desired values all the times. Anyhow thats good effort made.

Resources