Jcl 简明教程

JCL - Conditional Processing

作业入口系统使用两种方法在 JCL 中执行条件处理。当作业完成时,会根据执行状态设置返回码。返回码可以是介于 0(执行成功)到 4095(非零表示错误状况)之间的数字。最常见的约定值有:

  1. 0 = 正常 - 一切正常

  2. 4 = 警告 - 轻微错误或问题。

  3. 8 = 错误 - 重大错误或问题。

  4. 12 = 严重错误 - 重大错误或问题,结果不可靠。

  5. 16 = 终止错误 - 非常严重的问题,请勿使用结果。

作业步骤执行可以根据 COND * parameter and *IF-THEN-ELSE 结构中解释的先前的步骤的返回码进行控制。

COND parameter

可以在 JCL 的 JOB 或 EXEC 语句中对 COND 参数进行编码。这是对前一个作业步骤返回码的测试。如果对测试评估结果为真,则会绕过当前的作业步骤执行。绕过只是省略作业步骤,而不是执行异常终止。单次测试最多可以合并八个条件。

Syntax

以下是 JCL COND 参数的基本语法:

COND=(rc,logical-operator)
or
COND=(rc,logical-operator,stepname)
or
COND=EVEN
or
COND=ONLY

下面是对所用参数的描述:

  1. rc :此返回值

  2. logical-operator :可能是 GT(大于)、GE(大于或等于)、EQ(等于)、LT(小于)、LE(小于或等于)或 NE(不等于)。

  3. stepname :用于测试的作业步骤的返回码。

最后两个条件 (a) COND=EVEN 和 (b) COND=ONLY 已在本教程中进行了说明。

可以在 JOB 语句或 EXEC 语句中对 COND 进行编码,并且在两种情况下,它都会表现出不同的行为,如下所示:

COND inside JOB statement

当在 JOB 语句中对 COND 进行编码时,会对每个作业步骤测试条件。当条件在任何特定作业步骤中为真时,将会跳过它以及随后的作业步骤。以下是一个示例:

//CNDSAMP JOB CLASS=6,NOTIFY=&SYSUID,COND=(5,LE)
//*
//STEP10 EXEC PGM=FIRSTP
//* STEP10 executes without any test being performed.

//STEP20 EXEC PGM=SECONDP
//* STEP20 is bypassed, if RC of STEP10 is 5 or above.
//* Say STEP10 ends with RC4 and hence test is false.
//* So STEP20 executes and lets say it ends with RC16.

//STEP30 EXEC PGM=SORT
//* STEP30 is bypassed since 5 <= 16.

COND inside EXEC statement

当在作业步骤的 EXEC 语句中对 COND 进行编码并发现为真时,只跳过该作业步骤,并且从下一个作业步骤继续执行。

//CNDSAMP JOB CLASS=6,NOTIFY=&SYSUID
//*
//STP01 EXEC PGM=SORT
//* Assuming STP01 ends with RC0.

//STP02 EXEC PGM=MYCOBB,COND=(0,EQ,STP01)
//* In STP02, condition evaluates to TRUE and step bypassed.

//STP03 EXEC PGM=IEBGENER,COND=((10,LT,STP01),(10,GT,STP02))
//* In STP03, first condition fails and hence STP03 executes.
//* Since STP02 is bypassed, the condition (10,GT,STP02) in
//* STP03 is not tested.

COND=EVEN

当对 COND=EVEN 进行编码时,即使任何以前的步骤异常终止,也将执行当前作业步骤。如果对 COND=EVEN 编码任何其他 RC 条件,那么只有当没有 RC 条件为真时,作业步骤才会执行。

//CNDSAMP JOB CLASS=6,NOTIFY=&SYSUID
//*
//STP01 EXEC PGM=SORT
//* Assuming STP01 ends with RC0.

//STP02 EXEC PGM=MYCOBB,COND=(0,EQ,STP01)
//* In STP02, condition evaluates to TRUE and step bypassed.

//STP03 EXEC PGM=IEBGENER,COND=((10,LT,STP01),EVEN)
//* In STP03, condition (10,LT,STP01) evaluates to true,
//* hence the step is bypassed.

COND=ONLY

当对 COND=ONLY 进行编码时,只有当任何以前的步骤异常终止时,才执行当前作业步骤。如果对 COND=ONLY 编码任何其他 RC 条件,那么只有当没有 RC 条件为真,并且任何以前的作业步骤异常失败时,作业步骤才会执行。

//CNDSAMP JOB CLASS=6,NOTIFY=&SYSUID
//*
//STP01 EXEC PGM=SORT
//* Assuming STP01 ends with RC0.

//STP02 EXEC PGM=MYCOBB,COND=(4,EQ,STP01)
//* In STP02, condition evaluates to FALSE, step is executed
//* and assume the step abends.

//STP03 EXEC PGM=IEBGENER,COND=((0,EQ,STP01),ONLY)
//* In STP03, though the STP02 abends, the condition
//* (0,EQ,STP01) is met. Hence STP03 is bypassed.

IF-THEN-ELSE Construct

控制作业处理的另一种方法是使用 IF-THEN-ELSE 构造。这提供了更灵活和用户友好的条件处理方式。

Syntax

以下是 JCL IF-THEN-ELSE 构造的基本语法:

//name IF condition THEN
list of statements //* action to be taken when condition is true
//name ELSE
list of statements //* action to be taken when condition is false
//name ENDIF

以下是上述 IF-THEN-ELSE 构造中所用术语的描述:

  1. name :这是可选的,名称可以有 1 到 8 个以字母、#、$ 或 @ 开头的字母数字字符。

  2. Condition :条件将具有以下格式: KEYWORD OPERATOR VALUE ,其中 KEYWORDS 可以是 RC(返回码)、ABENDCC(系统或用户完成码)、ABEND、RUN(步骤启动执行)。 OPERATOR 可以是逻辑运算符(AND (&)、OR (|))或关系运算符(<、⇐、>、>=、<>)。

Example

以下是一个显示 IF-THEN-ELSE 用法的简单示例:

//CNDSAMP JOB CLASS=6,NOTIFY=&SYSUID
//*
//PRC1   PROC
//PST1	   EXEC PGM=SORT
//PST2	   EXEC PGM=IEBGENER
//       PEND
//STP01  EXEC PGM=SORT
//IF1    IF STP01.RC = 0 THEN
//STP02     EXEC PGM=MYCOBB1,PARM=123
//       ENDIF
//IF2    IF STP01.RUN THEN
//STP03a    EXEC PGM=IEBGENER
//STP03b    EXEC PGM=SORT
//       ENDIF
//IF3    IF STP03b.!ABEND THEN
//STP04     EXEC PGM=MYCOBB1,PARM=456
//       ELSE
//       ENDIF
//IF4    IF (STP01.RC = 0 & STP02.RC <= 4) THEN
//STP05     EXEC PROC=PRC1
//       ENDIF
//IF5    IF STP05.PRC1.PST1.ABEND THEN
//STP06     EXEC PGM=MYABD
//       ELSE
//STP07     EXEC PGM=SORT
//       ENDIF

让我们尝试深入了解上述程序以更详细地理解它:

  1. STP01 的返回码在 IF1 中进行测试。如果是 0,则执行 STP02。否则,处理转到下一个 IF 语句(IF2)。

  2. 在 IF2 中,如果 STP01 已经开始执行,那么 STP03a 和 STP03b 将被执行。

  3. 在 IF3 中,如果 STP03b 没有 ABEND,那么 STP04 将被执行。在 ELSE 中没有语句。它被称为一个 NULL ELSE 语句。

  4. 在 IF4 中,如果 STP01.RC = 0 且 STP02.RC ⇐4 为 TRUE,那么 STP05 将被执行。

  5. 在 IF5 中,如果 jobstep STP05 中的 PROC PRC1 中的 proc-step PST1 ABEND,那么 STP06 将被执行。否则执行 STP07。

  6. 如果 IF4 求值为 false,那么 STP05 将不会被执行。在这种情况下,IF5 将不会被测试,并且步骤 STP06、STP07 也不会被执行。

如果作业异常终止(例如用户取消作业、作业超时,或者数据集因反向引用被绕过的步骤),那么 IF-THEN-ELSE 将不会被执行。

Setting Checkpoints

你可以在 JCL 程序中使用 SYSCKEOV, 设置检查点数据集,它是一个 DD 语句。

CHKPT 是在 DD 语句中为多卷 QSAM 数据集编码的参数。当 CHKPT 被编码为 CHKPT=EOV 时,将在输入/输出多卷数据集的每个卷的末尾写入一个检查点,该检查点将被写入 SYSCKEOV 语句中指定的数据集中。

//CHKSAMP JOB CLASS=6,NOTIFY=&SYSUID
//*
//STP01     EXEC PGM=MYCOBB
//SYSCKEOV  DD DSNAME=SAMPLE.CHK,DISP=MOD
//IN1       DD DSN=SAMPLE.IN,DISP=SHR
//OUT1      DD DSN=SAMPLE.OUT,DISP=(,CATLG,CATLG)
//          CHKPT=EOV,LRECL=80,RECFM=FB

在上例中,检查点将写入到输出数据集 SAMPLE.OUT 的每个卷的末尾的 SAMPLE.CHK 数据集中。

Restart Processing

你可以在使用 RD parameter 的自动化方式或使用 RESTART parameter 的手动方式重新启动处理。

RD parameter 被编码在 JOB 或 EXEC 语句中,它有助于自动化 JOB/STEP 重新启动,并且可以保存四个值之中的一个值:R、RNC、NR 或 NC。

  1. RD=R 允许自动化重新启动,并且会考虑在 DD 语句的 CHKPT 参数中编码的检查点。

  2. RD=RNC 允许自动化重新启动,但是会覆盖(忽略)CHKPT 参数。

  3. RD=NR 指定作业/步骤无法被自动化重新启动。但是,当它使用 RESTART 参数被手动重新启动时,CHKPT 参数(如果有任何)将被考虑。

  4. RD=NC 不允许自动化重新启动和检查点处理。

如果只需要对指定的异常代码进行自动化重新启动,那么可以在 IBM 系统 parmlib 库的 SCHEDxx 成员中指定该代码。

RESTART parameter 被编码在 JOB 或 EXEC 语句中,它有助于作业/步骤在作业失败后手动重新启动。RESTART 可以附带 checkid,即写入到 SYSCKEOV DD 语句中编码的数据集的检查点。当编码 checkid 时,SYSCHK DD 语句应该被编码为在 JOBLIB 语句(如有任何)之后引用检查点数据集,否则在 JOB 语句之后引用。

//CHKSAMP JOB CLASS=6,NOTIFY=&SYSUID,RESTART=(STP01,chk5)
//*
//SYSCHK    DD DSN=SAMPLE.CHK,DISP=OLD
//STP01     EXEC PGM=MYCOBB
//*SYSCKEOV	DD DSNAME=SAMPLE.CHK,DISP=MOD
//IN1       DD DSN=SAMPLE.IN,DISP=SHR
//OUT1      DD DSN=SAMPLE.OUT,DISP=(,CATLG,CATLG)
//          CHKPT=EOV,LRECL=80,RECFM=FB

在上例中,chk5 是 checkid,即 STP01 在 checkpoint5 处重新启动。请注意,在设置检查点部分解释的先前程序中,添加了一个 SYSCHK 语句,并且 SYSCKEOV 语句被注释掉了。