“JCL…is, I am convinced, the worst computer programming language ever devised by anybody, anywhere. It was developed under my supervision; there is blame enough to go around among all the supervisory levels” (bit.ly/1OiYJ15). That was Fred Brooks, the person who led the creation of IBM’s System/360 Mainframe including its job control language (JCL).
When I first read that, I was surprised: I never thought of JCL as a computer programming language. Then I realized: that’s been part of the problem all along. It was seen as an afterthought—a text wrapper for the stuff that actually happens. And that’s been the case since before the first System/360 mainframe: people had been wrapping the real stuff that got things done (i.e., programs and data) with a few lines of text-based control statements to tell the computer how to run it.
Available on z/OS (as well as z/VSE in a similar form), MVS JCL for z/OS is one of those things you have to learn about and use if you’re going to call yourself a “real mainframer”—even if you never compose it from scratch.
For that matter, I’m not sure I’ve ever composed it completely from scratch and I wouldn’t be surprised if no one I know has. You have to at least begin by copying a JOBCARD that works properly in your local context and modifying it as needed. While you’re at it, why not copy a job that works and does something similar to what you need, modifying it as little as possible on the way? Isn’t that how everyone writes JCL?
I’ll tell you right now: that’s not how I write C or REXX, and not always how I write COBOL (OK, except for the Identification and Environment Divisions).
But that’s how it’s done with JCL: Start every line with two slashes (or sometimes a slash and an asterisk), unless it’s a line that contains input data such as program source code. Let’s make this clear right now: JCL lines begin with slashes to distinguish them from the stuff that actually matters. It doesn’t matter that the JCL matters too, and often is the only text in a JCL JOB. It’s the second-class citizen, serving the program and data that must be dealt with. That’s the attitude it came from, and while history has shown that to be a dysfunctional perspective, it became embedded in how we do things on the mainframe.
Like anyone who’s going to pains to not seem important, so the JCL does things in an apologetic, backward manner to make sure you know that it’s merely here to serve something better, which is a shame, because it has become the workhorse of the mainframe, and would be so much nicer if it could be slapped together like a CLIST, REXX EXEC or Perl script.
Be that as it may, you can eventually get more-or-less used to JCL, and it’s getting easier with the introduction of IF-THEN-ELSE statements, even though traditional program flow such as iterative loops still eludes this “language.”
There are two kinds of JCL: JOBs and PROCs (or PROCedures). The main difference between the two is that a JOB is submitted by a user (or other running task) and begins with a JOBCARD, a control statement at the beginning of every job that identifies it to the system with a JOBNAME and tells the system other things about how the job is to run. A PROC has a PROCNAME but not a JOBNAME, and can be run as part of a job or directly by the system.
CARDs and DECKs, gotta mention those: Every line of JCL is 80 characters long, and only the first 72 characters (or “columns”) count, because the remaining 8 are used for counting. That’s because, in the earliest days, everything was on punched cards that were 80 characters wide. All together, a group of punch cards that made up a JOB or program (often wrapped in a JOB) was known as a DECK, and if you dropped it, putting it back in order was nearly impossible unless you had line numbers to allow you to resort to re-sorting everything.
It turns out that many control statements, such as the “JOBCARD,” can have more information than could fit in 72 characters (plus, the first two characters have to be “//” and be followed by at least one space and an optional label). So, they can go multiple lines, as long as each non-final line has a comma (“,”) at the end of its parameters to continue it. Which doesn’t keep us from calling the whole thing a “card” even though it can span multiple “cards.”
Begin a JOB with a JOBCARD. And you begin a PROC with a PROC statement (unless it’s implied in a system PROCLIB member; don’t worry about that exception, I had to identify it so I don’t get heck from readers). Call PROCs from within JOBs if you wish (you can even define them inside JOBs for use in those JOBs, but only if you choose).
After all that, it’s made entirely of STEPs, which begin with a line giving the step a name and specifying which program or PROC will be called as part of that step (and other stuff that we can talk about if you come to my session at SHARE).
Every step has at least one line: the “EXEC” line which says what to run. After that are optional other lines that create the context for that step to run, listing data sets it will use, containing inline input it may process (the original “important stuff” that the JCL wrapped around) and indicating where to send the output.
Delete Data Set
The example is a minimal JCL JOB for deleting a data set, using the JCL features for doing so while running a program that effectively does nothing (except for setting a return code of zero) called IEFBR14 as an excuse for the data set handling:
//DPOSRH1 JOB ACCT,'DELETE DATASET',MSGCLASS=J,CLASS=A
//NOTHING EXEC PGM=IEFBR14
//DELETEME DD DSN=DPOSRH.OBSOLETE.DATASET,
Congratulations: you’re now one step closer to being a real mainframer! To learn and discuss more, stop by my session “What the Heck is JCL and Why Does It Look so Funny?” at SHARE in San Antonio Thursday at 3:15 where we’ll talk all about this bizarre but necessary “language.”
Reg Harbeck has been working in IT and mainframes for more than 25 years, and is very involved in the mainframe culture and ecosystem, particularly with the SHARE Board and zNextGen and Security projects. He may be reached at Reg@Harbeck.ca.