Mainframe JCl for ans - mainframe

One Jcl question
We have 3 steps in jcl,
Step1
Step2
Step3
If step 1 output empty ,then step2 need to run else step 3 need to be run.
Any one know answer?
It should not be add any new steps and solution should be thru jcl only

if you would like to do that with JCL there are several possibilities. I give you my favorite one:
//* Using IDCAMS
//* -------------------------------------------------------------------
//* Sets RC=0000 if dataset has records. *
//* Sets RC=0004 if dataset is empty. *
//*-------------------------------------------------------------------*
//IDCAMS0 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//MYFILE DD DISP=SHR,DSN=<Dataset Name>
//SYSIN DD *
PRINT INFILE(MYFILE) CHARACTER COUNT(1)
Regards,
Andreas

I wouldn't call it an elegant solution, but one simple way to handle this is to write yourself a short program that runs after step 1 and before step 2. This program checks to see if the output file from step 1 is empty or not, setting the return code to indicate one from the other, and then you can use standard JCL COND checking on the subsequent steps to get the result you want.
There are lots of ways to check for empty files...I'd use stat() in C/C++, but it can be done in Java and even REXX or other scripting languages if you prefer. In worst case, you just open and read the input file, returning the empty return code if you get an immediate EOF, otherwise return the non-empty return code.

Related

How to display input wait queue details of job of all lpars with JCL

I'm trying to get the output of waiting jobs in all plexes by running a JCL, but I don't seem to get the desired results. My code used:
//SDSF EXEC PGM=SDSF
//SYSOUT DD SYSOUT=*
//ISFOUT DD DSN=<MY TEST FILE>,
// DISP=(,CATLG,DELETE),
// DCB=(RECFM=FBA,LRECL=133,BLKSIZE=0),
// SPACE=(CYL,(1,1)),UNIT=SYSDA
//ISFIN DD *
/$DQ,Q=XEQ
ULOG
/*
//*
What I get in my output file is just "RO ALL,$DQ,Q=XEQ" the results of that command don't seem to appear. But if I execute the same command in sdsf panel, I get all the details. Any help?
Two things come to my mind that might help.
#1. I would rather use PGM=IKJEFT01 here. Done it for years for tons of commands and never failed.
Something in the flavour of:
//STEP01 EXEC PGM=IKJEFT01
//SYSTOUT DD SYSOUT=*
//SYSTIN DD *
CONSOLE NAME(XXXXX)
$jes_command_here
END
/*
#2. When you submit jobs that invoke commands via console it usually wants to take hold of the one you have in the SDSF profile set as default. Therefore you might run into an error when you have your ulog open in sdsf(for this lpar or any other in the plex) on a split when you submit the job. So make sure to have the console/ulog not used when running jobs like these.
Jarek.

Cannot get SDSF to respond to TSO or batch commands

I am trying to write a JCL Job Step that will retrieve the JESMSGLG, JESJCL, and JESLOG datasets of the active (this) job. The idea here is that I need to collect the log (from the beginning of the job to now) and record it in a data set before it ends execution.
So I have:
// EXEC PGM=SDSF
//MYOUT DD SYSOUT=* (to changed to a dataset in the future)
//ISFOUT DD SYSOUT=*
//ISFIN DD *
SET CONSOLE BATCH
PREFIX *
OWNER myid
DA OJOB
++S
PRINT FILE MYOUT
FIND JESMSGLG FIRST
++X
FIND JESJCL FIRST
++X
FIND JESLOG FIRST
++X
PRINT CLOSE
When I run the job all I get is CC=0000 and a printout of the SDSF Primary panel in IFSOUT.
If I try this under TSO with the SDSF command, again, all I get is the primary panel. If I enter any command (even an invalid one) it just seems to take the command and silently ignore it.
I can do this under ISPF just fine.
Any ideas as to what to look for to see what I am doing wrong or missing? Its pretty clear to me that this may well be a setup/invocation/security issue but I don't know how to debug it when all I seem to get is CC=0000.
Yup, that was it! I added PARM='++24,80' to the // EXEC PGM=SDSF and it now works. I'm not entirely sure why but it may have been a local installation error of SDSF.
It turns out the the commands I listed above are not quite right, but that's not relevant to this question.
Thank you, Kevin, for your time and interest.

JCL - MVS: how to retrieve result from submiting MVS command in Batch

Morning guys,
After submitting a MVS command in Batch, I wonder if it is possible to print the result in a seq file. Thanks for your time.
//S02IEBG EXEC PGM=IEBGENER
//SYSUT2 DD SYSOUT=(A,INTRDR),DCB=BLKSIZE=23440
//SYSIN DD DUMMY
//SYSOUT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSUT1 DD *,DLM=$$
/*$VS,'$DQ'
$$
It isn't clear from your question, but if you mean "after submitting your job, can you capture output to a dataset", I would suggest you use the XDC line command in SDSF. If you want a specific part of the output, use the ? line command first to show each of the outputs, then XDC on the one you want to save.
Yes it is possible to write the SYSOUT to a sequential file. I have done this before, but I would not recommend it unless you absolutely need to.
Your system should have some SYSLOG management system (like SMR/JMR or similar), where you can browse the SYSOUTs that a job has produced. Don't get me wrong, I realize that this isn't fool proof. There are times when you may need to write the SYSOUT to a file. The reason I needed to was because I looping with a lot of debugging displays and needed to have a lot lines to help me debug.
If you want to make sure that the SYSOUT goes to a file all you need to do is put the file after the SYSOUT:
//S02IEBG EXEC PGM=IEBGENER
//SYSUT2 DD SYSOUT=(A,INTRDR),DCB=BLKSIZE=23440
//SYSIN DD DUMMY
//SYSOUT DD DSN=YOUR.SYSOUT.FILE,
// DISP=(NEW,CATLG,DELETE),
// UNIT=TEST,SPACE=(TRK,(2,1),RLSE),
// DCB=(LRECL=080,BLKSIZE=0,RECFM=FB)
//SYSUDUMP DD SYSOUT=*
//SYSUT1 DD *,DLM=$$
You can alter the size of the file if you need to by editing the SPACE parameter. If you plan on running this job more than once, you will need to add a delete step before this, or make your SYSOUT file a GDG that can be incremented. Otherwise, the DISP of NEW will not work.
This can be done with any DD name as long as you know what the proper file allocation is.
I believe that the following may work. That is assuming that you want to capture the output from the DQ command :-
//SDSF EXEC PGM=SDSF
//ISFOUT DD SYSOUT=*
//CMDOUT DD DSN=YOUR.DATASET,
// DISP=(,CATLG,DELETE),
// DCB=(RECFM=FBA,LRECL=133,BLKSIZE=0),
// SPACE=(CYL,(1,1)),UNIT=SYSDA
//ISFIN DD *
SET CONSOLE BATCH
SET DELAY 60
/$ DQ
PRINT FILE CMDOUT
ULOG
PRINT
PRINT CLOSE
/*
//
Obviously this may need to be tailored according to your site's requirement.
You may find Issuing MVS or JES commands helpful.
Addition Re Comment :-
I did try the SDSF but I am not authorized to use it, which is why I
am looking for another way.
Perhaps then using TSO/E (REXX) as per :-
From TSO/E, you can establish an extended MCS console session using
the TSO/E CONSOLE command. After you activate a console session, you
can issue MVS™ system and subsystem commands and obtain command
responses. This appendix describes the different commands and
functions you can use in REXX execs to set up and use a console
session.
Writing REXX Execs to perform MVS operator activities
However, authority may be an issue if not immediately perhaps as soon as someone cottons on to you getting around the doors already closed.
This may work (I don't have the facilities to test it) :-
/* REXX */
ADDRESS TSO 'CONSPROF SOLDISPLAY(NO)'
ADDRESS TSO 'CONSOLE ACTIVATE'
ADDRESS CONSOLE '$DQ'
/* retrieve output command */
max_iterations = 100
DO i = 1 to max_iterations
messages_remaining = GETMSG('line.','SOL',,,10)
IF messages_remaining = 0 THEN leave
END
/* Done so echo retrieved messages
say 'Messages Retrieved are :-'
DO i = 1 to line.0
say '*** ' line.i
END
ADDRESS TSO 'CONSOLE DEACTIVATE'
EXIT
You'd need to wrap that into your batch job, so you may find the following helpful
How can I run my Rexx program as a batch job?.
Method 2 would be appropriate, as you want a TSO/E environment
A solution could be speaking to those responsible for denying access to SDSF, This could result in authority being given. There again it may result in the open doors such as being able to issue JES commands being shut.
You probably have access to SDSF to view the output.
Next to the job you want to print type xdc this will pop up a panel for dataset allocation(or it can be already existing one). Once done it will print the output and close it.
If You need just a output of a certain step/sysout you can type ? next to the job in SDSF. This will give you the list of the outputs. Same as before type xdc next to the one you picked and allocate a dataset.
This can also be done to your TSO session if you use the commands directly and need to have a history of it. Although this will only work until you close the SDSF ULOG.

JCL to create dataset whether it already exists or not

I want to write some JCL to create a dataset, with the requirements that :
if the dataset doesn't exist, create it
and either:
if the dataset already exists, overwrite it
or
if the dataset already exists, do nothing
As I understand it, (1) can be accomplished with DISP=NEW, and (2) with DISP=OLD, but I can't figure out from the docs and my course material how to do both at the same time. NEW throws a JCL error if the dataset exists and OLD throws one if it doesn't. I have no idea how to do (3).
I understand there are ways to query if a dataset exists within JCL, but we haven't covered that yet, so I assume it's possible without?
I think you're looking for a generation data group. This wouldn't overwrite the existing dataset, but would give you a new dataset every time your JCL is executed.
Up front you must create the generation data group base entry with an IDCAMS command documented here. This is a one time operation.
//MAKEGDG1 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEFINE GDG (NAME(MY.DSN) LIMIT(255))
//*
To use this, you write JCL such as...
//USEGDG1 EXEC PGM=IEFBR14
//DD001 DD DISP=(NEW,CATLG,DELETE),
// DSN=MY.DSN(+1),
// SPACE=(...),
// and so on
...where the (+1) means to create a new generation within the group. What is actually created is a dataset with the name MY.DSN.G####V00, where #### is a sequential number managed for you by the system, but you can always get the most current generation with MY.DSN(0). You can use the previous to the most current generation with MY.DSN(-1).
Some care is required, if you code MY.DSN without specifying a generation number in parens you will get all extant generations.
If a GDG is not what you're looking for, you could also code an IDCAMS step in front of your step cataloging your new dataset. The purpose of the IDCAMS step would be to delete the dataset. The IDCAMS DELETE command will give you a bad return code (12, if memory serves) if the dataset doesn't exist, but you can modify that by coding IF MAXCC=12 THEN SET MAXCC=0 under those circumstances.
Update per additional restrictions on what's allowed
If what you want is to create the dataset if it doesn't already exist and append to it if it does, that can be accomplished with DISP=(MOD,CATLG). I don't believe there is a way to accomplish your goal as stated without using either IDCAMS or writing a clist or Rexx program that does essentially what the IDCAMS DELETE does.
You could code DISP=(NEW,CATLG) and let the job fail if the dataset already exists. It's a terrible thing to do, but I think it meets your criteria.
I'm not in a position to test this right now, but you might try...
//CKEXIST1 EXEC PGM=IEFBR14
//DD001 DD DISP=OLD,DSN=MY.DSN
//*
//IF001 IF CKEXIST.RUN=TRUE THEN
//* step with DISP=OLD
// ELSE
//* step with DISP=NEW
//IF001E ENDIF
...but even if it works I still think it's pretty ugly. The idea is the IEFBR14 step won't execute because the dataset allocation will fail. The IF001 statement is checking to see if the step ran, and I think that will test false if the dataset doesn't exist and true if it does. Not something I'd recommend for a production jobstream.
Generally I create a step prior to the creation of the dataset to delete the dataset. Although I use DISP=(MOD,DELETE). SPACE=(TRK,0) is effectively a null value for space because we’re going to delete the DSN or allocate with no space to delete it anyway. The difference between this and the answer by #bruce_martin is that the dataset creation is tied to the step actually writing the dataset.
This means that if the file does not exist it is created, if it exists it is used and the DELETE says delete it at step termination. The net effect is that the DSN is deleted whether it existed or not prior to the next step.
Here is an example,
//DEL0010 EXEC PGM=IEFBR14
//DSN2DEL DD DSN=dataset.to.write.to,DISP=(MOD,DELETE),
// SPACE=(TRK,0),UNIT=SYSALLDA
//*
//STEP0010 EXEC PGM=MYPROG
//DSN2CR8 DD DSN=dataset.to.write.to,DISP=(,CATLG,DELETE),
// SPACE=...,UNIT=...
Using this approach ensures there is no dataset for the next step so you don’t have to be concerned with condiditional restarts.
#cschneids is an excellent solution; but to do 1 & 2 you could do
//CREATE EXEC PGM=IEFBR14
//DD001 DD DISP=(MOD,CATLG,DELETE),
// DSN=MY.DSN,...
//*
//USEGDG1 EXEC PGM=MYPGM,COND=(0,NE)
//DD001 DD DISP=OLD,
// DSN=MY.DSN
for option 3 you could use IDCAMS
create a jcl with extra steps (it's 21 years since I wrote JCL so I'll leave the exact coding to you).
// step1 exec pgm=idcams
rename my.dsn in my.otherdsn
/*
//step2 exec pgm=idcams, cond=(0, eq, step1) rename successful: rename back
rename my.otherdsn in mydsn
/*
//step3 exec pgm=IEFBR14, cond=(0, ne, step1) did not exist, create it
//mydsn dd my.dsn,disp(new,catlg), etc
/*
//step4a exec pgm=myprogram, parm='EXISTS", cond=(0, eq, step1)
// ....
//step4b exec pgm=myprogram, parm='NEW", cond=(0, ne, step1)
// ....
use the parm of myprogram to work out your program logic!
Something like this worked for us too to automatically restore files: first step renames a in b. if this fails, the job had been aborted, so step2 restores the database. then the actual job jcl was included. the last step in the job renames b in a.

How to pass arguments to REXX program through JCL

Can we pass arguments to a REXX program from JCL?
I suppose, JCL PARM can be used as we use for passing arguments to COBOL programs.. Do put your ideas here...
You want EXEC PGM=IRXJCL,PARM='member_name exec_args'. SYSEXEC should point to the PDS containing member name. SYSTSIN is the input for PULL, SYSTSPRT is the output DD for SAY
Check out the "Using REXX in TSO/E and Other MVS Address Spaces" chapter in the "TSO/E Rexx User Guide" book (SA22-7791) for a full example.
An added note: If your REXX exec uses ISPF services, you can run it in batch with PGM=IKJEFTxx (xx being a variable suffix) and allocating ISPxLIB in the job step.
If the parameters together with the REXX member name exceeds 100 bytes, the method mentioned by Ron Patterson won't work as JCL syntax only allows a maximum paramater length of 100 bytes. In this case I recommend using IKJEFTxx (already posted by Tony). You then have to pass the REXX program name as instream data to SYSTSIN. The parameters to this program can simply written behind the program name. When you need more than one line, use the hyphen as last character of a line to indicate the concatenation with the following line.
Example:
//EXAMPLE EXEC PGM=IKJEFT01,REGION=4096K,DYNAMNBR=30
//SYSPRINT DD SYSOUT=*
//SYSEXEC DD DISP=SHR,DSN=YOUR.REXX.LIBRARY
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
SCHLABB PARAMETER1 PARAMETER2 PARAMETER3 -
VERY_LONG_PARAMETER4 -
LAST_PARAMETER5
/*
//
I was getting RC (-3) for basic EXECIO, LIBDEF, commands when I tried running IRXJCL. I wish there was better documentation on what IRXJCL can and can not do.
Finally followed the approach from the below link, to dynamically pass values to a REXX by writing them to a file and reading from the file. How to run dymanic SQL through IKJEFT01 Utility?

Resources