Mainframe batch job - return code RC 8 from IEBCOPY - mainframe

//VENKATBK JOB (3322332),'KRISHNA',TIME=(1,0),
// CLASS=A,NOTIFY=VENKATB,MSGLEVEL=(1,1),PRTY=1
//STEP2 EXEC PGM=IEBCOPY
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSDUMP DD SYSOUT=*
//SYSUT1 DD DSN=VENKATB.KK.INPUT.COPY,DISP=SHR
//SYSUT2 DD DISP=SHR,DSN=VENKATB.KK.INPUT.COPY1
//SYSIN DD *
COPY INDD=SYSUT1,
OUTDD=SYSUT2
/*
THE MESSEGE FROM THE SPOOL IS..,
i have got return code maxcc=8.
i have wrote this program in different types by modifications still I am getting this maxcc=8 return code.
I don't know where did made a mistake. please help.
IEB1135I IEBCOPY FMID HDZ1A10 SERVICE LEVEL NONE DATED 20080414 DFP
IEB1035I VENKATBK STEP2 06:40:28 SUN 25 DEC 2022 PARM=''
COPY INDD=SYSUT1,
IEB107I INVALID CONTINUATION
IEB118I CONTROL STATEMENT ERROR
OUTDD=SYSUT2
IEB115I END OF FILE ON SYSIN
IEB151I JOB HAS TERMINATED WITH ERROR(S)
IEB147I END OF JOB - 8 WAS HIGHEST SEVERITY CODE

z/OS DFSMSdfp Utilities are a very old beast, and so is their syntax. Have a look at Continuing utility control statements in manual z/OS DFSMSdfp Utilities, chapter Introduction, topic Control:
Utility control statements are contained in columns 1 through 71. A statement that exceeds 71 characters must be continued on one or more additional records. A nonblank character must be placed in column 72 to indicate continuation.
The important part in your case is: A nonblank character must be placed in column 72 to indicate continuation.
=COLS> ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8
000011 //SYSIN DD *
000012 COPY INDD=SYSUT1, *
000013 OUTDD=SYSUT2
000014 /*

Related

How can I "hard code" a header into my output using EASYTRIEVE as part of a JCL file?

My goal is to have three headers appear at the top of my output. The headers will be "Title", "Genre", and "Rating". The JCL file inputs data from a dataset, a list of movies, their genres (which are numbered and later translated into words using IF logic), and the ratings (using packed data). I am not supposed to use any programs like SORT. My solution needs to be "hard coded".
I expect the results to look like this:
snapshot of the expected results
The actual results look like this:
snapshot of the actual results
The job submits successfully, without any error. However, the JCL file does not produce the desired output.
I understand that the JCL file is following a list of instructions for each record from the data set, and looping over the instructions for each record, which is why the Title, Genre, and Ratings headers repeat. I've tried using "GOTO" and labels to alter where the loop resumes from, so that the JCL file only executes the header parameters on the first execution. Unfortunately, it doesn't seem to work.
I linked screenshots of my JCL file below. As you can see, I redefined my OHEAD variable to be blank (' '), which prevents the headers from overlapping the movie data. If I could find a way to have the JCL instructions loop, and restart from AFTER the first "OHEAD" statement, then I would only need to define OHEAD once. Conceptually, that's what I'm trying to do.
I started training on JCL a few days ago, so I appreciate your patience and any input you can offer.
JCL file screenshot 1
JCL file screenshot 2
JCL file screenshot 3
JCL file screenshot 4
JCL file screenshot 5
I copied the JCL file text below.
000001 //DSINC01C JOB (0000,1178),'TRAINING',NOTIFY=DSINC01,
000002 // MSGCLASS=E
000003 //*
000004 //* DELETE STEP FOR EASIER RE-RUNS
000005 //*
000006 //S01 EXEC PGM=IDCAMS,REGION=40M
000007 //SYSPRINT DD SYSOUT=*
000008 //SYSIN DD *
000009 DELETE DSINC01.TRAINING.OUTPUT
000010 IF MAXCC=8 THEN SET MAXCC = 0
000011 /*
000012 //*
000013 //* EASYTRIEVE STEP
000014 //*
000015 //S02 EXEC PGM=EZTPA00,REGION=4M
000016 //SYSLIB DD DSN=ALCHAN.TEST.EMAC,DISP=SHR
000017 // DD DSN=SYS3.EASYPLUS.CAIMAC,DISP=SHR
000018 //FILEI DD DISP=SHR,DSN=DSINC01.TRAINING.MDATA
000019 //FILEO DD DSN=DSINC01.TRAINING.OUTPUT,
000020 // DISP=(,CATLG),
000021 // UNIT=PUBLIC,SPACE=(CYL,(500,250),RLSE),
000022 // DCB=(LRECL=80,RECFM=FB,BLKSIZE=0,DSORG=PS)
000023 //EZTVFM DD UNIT=WORK,SPACE=(CYL,(10,5))
000024 //SORTWK01 DD UNIT=WORK,SPACE=(CYL,(10,5))
000025 //SORTWK02 DD UNIT=WORK,SPACE=(CYL,(1,1))
000026 //SORTWK03 DD UNIT=WORK,SPACE=(CYL,(1,1))
000027 //SYSOUT DD SYSOUT=*
000028 //SYSPRINT DD SYSOUT=*
000029 //SYSLIZ DD SYSOUT=*
000030 //SYSLZ1 DD SYSOUT=*
000031 //SYUDUMP DD SYSOUT=*
000032 //*
000033 //SYSIN DD *
000034 FILE SYSLIZ PRINTER
000035 *
000036 * INPUT FILE LAYOUT
000037 *
000038 FILE FILEI
000039 IMNAME 1 40 A
000040 IMGENRE 41 1 N
000041 IMRATE 42 2 P
000042 * OUTPUT FILE LAYOUT
000043 *
000044 FILE FILEO
000045 OHEAD 1 80 A
000046 OMNAME 1 30 A
000047 OMGENRE 32 7 A
000048 OMRATE 40 3 N
000049 *--------------------------------------------------------------------
000050 * MAIN LINE
000051 *--------------------------------------------------------------------
000052 JOB INPUT FILEI NAME DATA
000053 OHEAD = 'TITLE GENRE RATING'
000054 PUT FILEO
000055 OHEAD = ' '
000056 OMNAME = IMNAME
000057 OMGENRE = ' '
000058 IF IMGENRE = 1
000059 OMGENRE = 'FANTASY'
000060 END-IF
000061 IF IMGENRE = 2
000062 OMGENRE = 'ACTION'
000063 END-IF
000064 IF IMGENRE = 3
000065 OMGENRE = 'COMEDY'
000066 END-IF
000067 IF IMGENRE = 4
000068 OMGENRE = 'HORROR'
000069 END-IF
000070 IF IMGENRE = 5
000071 OMGENRE = 'DRAMA'
000072 END-IF
000073 OMRATE = IMRATE
000074 PUT FILEO
000075 GO TO JOB
000076 /*
Copying just the Easytrieve code, add a label, and change the GO TO.
Edited: I modified the Easytrieve again. I don't know if this will work, as I don't have a mainframe to test with.
Get an online Easytrieve manual and learn the language.
000034 FILE SYSLIZ PRINTER
000035 *
000036 * INPUT FILE LAYOUT
000037 *
000038 FILE FILEI
000039 IMNAME 1 40 A
000040 IMGENRE 41 1 N
000041 IMRATE 42 2 P
000042 * OUTPUT FILE LAYOUT
000043 *
000044 FILE FILEO
000045 OHEAD 1 80 A
000046 OMNAME 1 30 A
000047 OMGENRE 32 7 A
000048 OMRATE 40 3 N
000049 *--------------------------------------------------------------------
000050 * MAIN LINE
000051 *--------------------------------------------------------------------
000052 JOB INPUT FILEI NAME DATA
000053 OHEAD = 'TITLE GENRE RATING'
000054 PUT FILEO
GET FILEI
DO WHILE NOT EOF FILEI
000055 OHEAD = ' '
000056 OMNAME = IMNAME
000057 OMGENRE = ' '
000058 IF IMGENRE = 1
000059 OMGENRE = 'FANTASY'
000060 END-IF
000061 IF IMGENRE = 2
000062 OMGENRE = 'ACTION'
000063 END-IF
000064 IF IMGENRE = 3
000065 OMGENRE = 'COMEDY'
000066 END-IF
000067 IF IMGENRE = 4
000068 OMGENRE = 'HORROR'
000069 END-IF
000070 IF IMGENRE = 5
000071 OMGENRE = 'DRAMA'
000072 END-IF
000073 OMRATE = IMRATE
000074 PUT FILEO
000075 GET FILEI
000076 END-DO
000077 /*
This solution also works, though the concept differs from my original thought.
000001 //DSINC01C JOB (0000,1178),'TRAINING',NOTIFY=DSINC01,
000002 // MSGCLASS=E
000003 //*
000004 //* DELETE STEP FOR EASIER RE-RUNS
000005 //*
000006 //S01 EXEC PGM=IDCAMS,REGION=40M
000007 //SYSPRINT DD SYSOUT=*
000008 //SYSIN DD *
000009 DELETE DSINC01.TRAINING.OUTPUT
000010 IF MAXCC=8 THEN SET MAXCC = 0
000011 /*
000012 //*
000013 //* EASYTRIEVE STEP
000014 //*
000015 //S02 EXEC PGM=EZTPA00,REGION=4M
000016 //SYSLIB DD DSN=ALCHAN.TEST.EMAC,DISP=SHR
000017 // DD DSN=SYS3.EASYPLUS.CAIMAC,DISP=SHR
000018 //FILEI DD DISP=SHR,DSN=DSINC01.TRAINING.MDATA
000019 //FILEO DD DSN=DSINC01.TRAINING.OUTPUT,
000020 // DISP=(,CATLG),
000021 // UNIT=PUBLIC,SPACE=(CYL,(500,250),RLSE),
000022 // DCB=(LRECL=80,RECFM=FB,BLKSIZE=0,DSORG=PS)
000023 //EZTVFM DD UNIT=WORK,SPACE=(CYL,(10,5))
000024 //SORTWK01 DD UNIT=WORK,SPACE=(CYL,(10,5))
000025 //SORTWK02 DD UNIT=WORK,SPACE=(CYL,(1,1))
000026 //SORTWK03 DD UNIT=WORK,SPACE=(CYL,(1,1))
000027 //SYSOUT DD SYSOUT=*
000028 //SYSPRINT DD SYSOUT=*
000029 //SYSLIZ DD SYSOUT=*
000030 //SYSLZ1 DD SYSOUT=*
000031 //SYUDUMP DD SYSOUT=*
000032 //*
000033 //SYSIN DD *
000034 FILE SYSLIZ PRINTER
000035 *
000036 * INPUT FILE LAYOUT
000037 *
000038 FILE FILEI
000039 IMNAME 1 40 A
000040 IMGENRE 41 1 N
000041 IMRATE 42 2 P
000042 * OUTPUT FILE LAYOUT
000043 *
000044 FILE FILEO
000045 OMNAME 1 30 A
000046 OMGENRE 32 7 A
000047 OMRATE 40 6 A
000048 *
000049 DEFINE HEADER 1 1 A
000050 *--------------------------------------------------------------------
000051 * MAIN LINE
000052 *--------------------------------------------------------------------
000053 JOB INPUT FILEI NAME DATA
000054 IF HEADER = ' '
000055 OMNAME = 'TITLE'
000056 OMGENRE = 'GENRE'
000057 OMRATE = 'RATING'
000058 PUT FILEO
000059 HEADER = 'Y'
000060 END-IF
000061 OMNAME = IMNAME
000062 OMGENRE = ' '
000063 IF IMGENRE = 1
000064 OMGENRE = 'FANTASY'
000065 END-IF
000066 IF IMGENRE = 2
000067 OMGENRE = 'ACTION'
000068 END-IF
000069 IF IMGENRE = 3
000070 OMGENRE = 'COMEDY'
000071 END-IF
000072 IF IMGENRE = 4
000073 OMGENRE = 'HORROR'
000074 END-IF
000075 IF IMGENRE = 5
000076 OMGENRE = 'DRAMA'
000077 END-IF
000078 OMRATE = IMRATE
000079 PUT FILEO
000080 GO TO JOB
000081 /*
Your header prints every time because you printed it inside of JOB INPUT FILEI. Instead, move this logic to a JOB INPUT NULL proc (or write a STARTER proc for this). Then it will only run when the program is launched.

How do I fix USER FATAL MESSAGE 740?

How do I fix USER FATAL MESSAGE 740? This error is generated by Nastran when I try to run a BDF/DAT file of mine.
*** USER FATAL MESSAGE 740 (RDASGN)
UNIT NUMBER 5 HAS ALREADY BEEN ASSIGNED TO THE LOGICAL NAME INPUT
USER ACTION: CHANGE THE UNIT NUMBER ON THE ASSIGN STATEMENT AND IF THE UNIT IS USED FOR
PARAM,POST,<0 THEN SPECIFY PARAM,OUNIT2 WITH THE NEW UNIT NUMBER.
AVOID USING THE FOLLOWING UNIT NUMBERS THAT ARE ASSIGNED TO SPECIAL FILES IN MSC.NASTRAN:
1 THRU 12, 14 THRU 22, 40, 50, 51, 91, 92. SEE THE MSC.NASTRAN INSTALLATIONS/OPERATIONS
GUIDE SECTION ON MAKING FILE ASSIGNMENTS OR MSC.NASTRAN QUICK REFERENCE GUIDE ON
ASSIGN PHYSICAL FILE FOR REFERENCE.
Below is the head of my BDF file.
assign userfile='SUB1_PLATE.csv', status=UNKNOWN, form=formatted, unit=52
SOL 200
CEND
ECHO = NONE
DESOBJ(MIN) = 35
set 30=1008,1007,1015,1016
DESMOD=SUB1_PLATE
SUBCASE 1
$! Subcase name : DefaultLoadCase
$LBCSET SUBCASE1 DefaultLbcSet
ANALYSIS = STATICS
SPC = 1
LOAD = 6
DESSUB = 99
DISPLACEMENT(SORT1,PLOT,REAL)=ALL
STRESS(SORT1,PLOT,VONMISES,CORNER)=ALL
BEGIN BULK
param,xyunit,52
[...]
ENDDATA
Below is the solution
Correct
assign userfile='SUB1_PLAT.csv', status=UNKNOWN, form=formatted, unit=52
I shortened the name of CSV file to SUB1_PLAT.csv. This reduced the length of the line to 72 characters.
Incorrect
assign userfile='SUB1_PLATE.csv', status=UNKNOWN, form=formatted, unit=52
The file management section is limited to 72 characters, spaces included. The incorrect line stretches 73 characters. The nastran reader ignores the 73rd character and on. Instead of reading "unit=52" the reader reads "unit=5" which triggers the error.
|<--------------------- 72 Characters -------------------------------->||<- Characters are ignored truncated ->
assign userfile='SUB1_PLATE.csv', status=UNKNOWN, form=formatted, unit=52
References
MSC Nastran Reference Guide
The records of the first four sections are input in free-field format
and only columns 1 through 72 are used for data. Any information in
columns 73 through 80 may appear in the printed echo, but will not be
used by the program. If the last character in a record is a comma,
then the record is continued to the next record.

How to join records in Easytrieve internal SORT?

I've a requirement, where I need to extract 2 types of records from a single input file & join them for EZT report processing.
Currently, I've written an ICETOOL step to perform the extraction followed by the join. The output of the ICETOOL step is fed to the Easytrieve report step.
Extraction card is as below -
SORT FIELDS=(14,07,PD,A)
OUTFILE FNAMES=FILE010,INCLUDE=(25,03,CH,EQ,C'010')
OUTFILE FNAMES=FILE011,INCLUDE=(25,04,CH,EQ,C'011')
OPTION DYNALLOC=(SYSDA,05)
Here is the join card -
SORT FIELDS=(14,07,PD,A)
JOINKEYS F1=FILE010,FIELDS=(14,07,A),SORTED,NOSEQCHK
JOINKEYS F2=FILE011,FIELDS=(14,07,A),SORTED,NOSEQCHK
REFORMAT FIELDS=(F1:14,07,
F2,25,10)
OUTREC BUILD=(1,17,80:X),VTOF
OPTION DYNALLOC=(SYSDA,05)
I'm wondering if it was possible to perform the above SORT/ICETOOL operations within EasyTrive. I've used the Easytrieve internal SORT but it was for the simple extractions. Can we perform the join operation within the Easytrieve?
Note - The idea is to have a single EZT step.
You can make use Synchronized File Processing facility (SFP) in Easytrieve to acheive the task. Read more about it here.
FILE FILE010
KEY1 14 7 N
*
FILE FILE011
KEY2 14 7 N
FIELD1 25 10 A
*
FILE OUTFILE FB(80 0)
OKEY 1 7 N
OFIELD 8 10 A
*
WS-COUNT W 5 N VALUE 0
*
JOB INPUT FILE010 KEY KEY1 FILE011 KEY KEY2 FINISH(DIS)
*
IF EOF FILE010
STOP
END-IF
*
IF MATCHED
OKEY = KEY1
OFIELD = FIELD1
WS-COUNT = WS-COUNT + 1
PUT OUTFILE
END-IF
*
DIS. PROC
DISPLAY 'RECORDS WRITTEN: ' WS-COUNT
END-PROC
Please note,
Above code isn't tested, it's just a draft showing the idea on
file matching using Easytrieve to achieve the task.
Data types to the data items are assumed. You may have to change them suitably.
You may have to define the variable input datasets in the FILE
statement.
You may add more statements within the IF MATCHED condition for the
creation of report.
Hope this helps!

Search multiline error log for error code and then some of it's parameters on Linux

What command would give me the output I need for each instance of an error code in a very large log file? The file has records marked by a begin and end with number of characters. Such as:
SR 120
1414760452 0 1 Fri Oct 31 13:00:52 2014 2218714 4
GROVEMR2 scn
../SrxParamIF.m 284
New Exam Started
EN 120
The 5th field is the error code, 2218714 in previous example.
I thought of just grep'ing for the error code and outputting -A lines afterwards; then picking what I needed from that rather than parsing the entire file. That seems easy but my grep/awk/sed usage isn't to that level.
ONLY when error 2274021 is encountered as in the following example I'd like some output as shown.
Show me output such as: egrep ‘Coil:|Connector:|Channels faulted:| First channel:’ ERRORLOG|less
Part of input file of interest:
Mon Nov 24 13:43:37 2014 2274021 1
AWHMRGE3T NSP
SCP:RfHubCanHWO::RfBias 4101
^MException Class: Unknown Severity: Unknown
Function: RF: RF Bias
PSD: VIBRANT Coil: Breast SMI Scan: 1106/14
Coil Fault - Short Circuit
A multicoil bias fault was detected.
.
Connector: Port 1 (P1)
Channels faulted: 0x200
First channel: 10 of 32, counting from 1
Fault value: -2499 mV, Channel: 10->
Output:
Coil: Breast SMI
Connector: Port 1 (P1)
Channels faulted: 0x200
First channel: 10 of 32, counting from 1
Thanks in advance for any pointers!
Try the following (with the convenient adaptations)
#!/usr/bin/perl
use strict;
$/="\nEN "; # register separated by "\nEN "
my $error=2274021; # the error!
while(<>){ # for all registers
next unless /\b$error\b/; # ignore unless error
for my $line ( split(/\n/,$_)){
print "$line\n" if ($line =~ /Coil:|Connector:|Channels faulted:|First channel:/);
}
print "====\n"
}
Is this what you need?

Run Cron Job every 45 minutes with Node-Cron

I'm using node-cron to run scheduled jobs.
I want the jobs to run every 45 minutes, but its acting strangely
Here's the pattern I'm using
'00 */45 * * * *'
I started my script at
Tue Jun 17 2014 08:17:39 GMT+0000 (GMT)
Here's are the first couple of times the job was executed
1. Tue Jun 17 2014 08:45:03 GMT+0000 (GMT)
2. Tue Jun 17 2014 09:00:01 GMT+0000 (GMT)
3. Tue Jun 17 2014 09:45:02 GMT+0000 (GMT)
This is definitely not what I expected or want.
All I want is to run the Jobs every 45 minutes.
Can anyone help me with the pattern?
Thanks :)
You're probably looking for
0 */45 * * * *
The ranges are here.
Seconds: 0-59
Minutes: 0-59
Hours: 0-23
Day of Month: 1-31
Months: 0-11
Day of Week: 0-6
I'm more familiar with cron than with node-cron, but I've taken a quick look at the documentation.
If I understand it correctly, node-cron uses a syntax similar to that used by cron, but with an additional "seconds" field. So where a cron job might have:
# min hour mday month wday command
*/15 * * * * some-command
to schedule some-command to run every 15 minutes, node-cron would use a similar syntax to specify the time to run:
'0 */15 * * * *'
(with an additional field to specify seconds), but it executes a specified JavaScript function, not an external command.
In standard cron, there is no syntax to specify running a job every 45 minutes. A specification of 0/45 * * * * would run a job twice each hour, at 0 and 45 minutes after the hour. To run a job every 45 minutes (at 00:00, 00:45, 01:30, 02:15, ..., i.e., 32 times per day) you'd have to schedule it to run every 15 minutes, and then invoke a script that checks the current time to decide whether to do anything.
Or you can write an exhaustive list of all the times you want the job to run:
0 0 * * * some-command
45 0 * * * some_command
30 1 * * * some_command
15 2 * * * some_command
# 28 lines omitted
I'd definitely want to write a script to generate this list.
(This is workable because 24 hours happens to be a multiple of 45 minutes.
You couldn't run something every 35 minutes this way.)
A similar approach should work for node-cron. Schedule the function to run every 15 minutes, and invoke a function that checks the current time to decide whether to run. For example, you can check whether the number of minutes since midnight modulo 45 is zero. (You might want to allow for a small variance in case the scheduling is not exact.)
I don't know JavaScript well enough to suggest the best way to write this function, but it should be reasonably straightforward.
Or write 32 lines to specify all the times you want it to run.
There is no direct way to do this. However, we can get the result by intercepting the schedule using a shell command within the target script.
First, run the script at every 15 minutes:
*/15 * * * * <target_script>
Then, within the target_script, place the following code before actual codes:
#!/bin/sh
# Exit except at 0:45, 1:30, 2:15, 3:00, 3:45 etc
if ! echo "((`date +%-H`*60)+`date +%-M`)/45" | bc -l | grep "\.0*$" &> /dev/null;
then exit 1;
fi
# Your actual code goes here;
I tried this string for a 45-second interval and it works well:
'*/45 * * * * *'
You need to write a script as a wrapper to decide if the actual command shall be executed at every 45 minutes. That's 0, 45, 30 (= 45 + 45 - 60), 15 (= 30 + 45 - 60), 0 (= 15 + 45 - 60). so, the minutes to run the script shall be 0,15,30,45.
The command date +%M may be helpful in the shell script.
you can use node-reel which is more readable, straight forward and awesome 😉.
const reel = require('node-reel')
reel().call(() => {
console.log(Date.now());
}).everyFortyFiveMinutes().run()
https://github.com/shakee93/node-reel
Answer: */45 * * * *
This will run every 45th minute
Have a look here for clear understanding 👇
https://crontab.guru/#/45_*_
use cron npm moduel something like this
var cronJob = require('cron').CronJob;
var job = new cronJob({
cronTime:'0 */45 * * * *',
onTick: function(){
var my_date = new Date();
var tomorrow_date = my_date.getFullYear() + "-" + ('0'+(my_date.getMonth()+1)) + "-" + (my_date.getDate()+1)
var condition = [{},{$set: {'plannedDeliveryDate' :tomorrow_date +'T00:00:00.000Z'}}]
dbQuery.updateMany(orderModel, condition, function(err, result){
if(result.nModified == result.n) console.log(err, result)
})
},
start:true,
timeZone:'Asia/Kolkata'
});
job.start();
You can refer to cronr, it supports all the macro pattern and provides online demo cronr -- online demo
Just recently (27|01|22) used Node Cron in my project
const TaskSchedulerTimeInterval = 45;
// Runs a job for every 45 mins asynchronously
const fetchYoutubeAPIScheduler = () => {
try {
nodeCron.schedule(`*/${TaskSchedulerTimeInterval} * * * *`, async () => {
console.log('Running');
})
} catch (error) {
console.log('error =', error);
}
};
Underlying Meaning (loved the explanations given by others, so referencing them together in one post) :
#sec min hour monthday month weekday
*/15 * * * * *
Above example runs every 15 secs
range of each field:
Sec: 0-59
Min: 0-59
Hour: 0-23
monthday(Day of Month): 1-31
Months: 0-11
weekDay(Day of Week): 0-6

Resources