JCL - 条件处理

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

  • 0 = 正常 - 一切正常

  • 4 = 警告 - 小错误或问题。

  • 8 = 错误 - 重大错误或问题。

  • 12 = 严重错误 - 重大错误或问题,结果不应可信。

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

可以使用 COND 参数和IF-THEN-ELSE构造根据前一步骤的返回代码来控制作业步骤执行,本教程已对此进行了说明。

COND参数

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

语法

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

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

以下是所使用参数的说明:

  • rc:这是返回码

  • logical-operator(逻辑运算符):这可以是 GT(大于)、GE(大于或等于)、EQ(等于)、LT(小于)、LE(小于) 大于或等于)或 NE(不等于)。

  • stepname:这是测试中使用其返回码的作业步骤。

最后两个条件 (a) COND=EVEN 和 (b) COND=ONLY,已在本教程下面进行了解释。

COND 可以在 JOB 语句或 EXEC 语句内进行编码,在这两种情况下,它的行为都不同,如下所述:

JOB 语句中的 COND

当 COND 编码在 JOB 语句中时,会针对每个作业步骤测试条件。 当任何特定作业步骤的条件为真时,该条件及其后面的作业步骤都会被绕过。 下面是一个例子:

//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.

EXEC 语句中的 COND

当 COND 被编码在作业步骤的 EXEC 语句中并且被发现为 true 时,仅绕过该作业步骤,并从下一个作业步骤继续执行。

//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 时,即使前面的任何步骤异常终止,也会执行当前作业步骤。 如果任何其他 RC 条件与 COND=EVEN 一起编码,则当没有 RC 条件为 true 时,作业步骤将执行。

//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 时,仅当前面的任何步骤异常终止时,才会执行当前作业步骤。 如果任何其他 RC 条件与 COND=ONLY 一起编码,则当没有任何 RC 条件为 true 并且之前的任何作业步骤异常失败时,作业步骤将执行。

//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 构造

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

语法

以下是 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 结构中所用术语的描述:

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

  • condition(条件):条件的格式为:关键字运算符值,其中关键字可以是 RC(返回代码), ABENDCC(系统或用户完成代码)、ABEND、RUN(步骤开始执行)。 OPERATOR 可以是逻辑运算符(AND (&)、OR (|))或关系运算符(<、<=、>、>=、<>)。

示例

下面是一个简单的例子,展示了 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

让我们尝试研究一下上面的程序以更详细地理解它:

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

  • 在IF2中,如果STP01已经开始执行,则执行STP03a和STP03b。

  • 在 IF3 中,如果 STP03b 没有 ABEND,则执行 STP04。 在 ELSE 中,没有任何语句。 它称为 NULL ELSE 语句。

  • 在 IF4 中,如果 STP01.RC = 0 且 STP02.RC <=4 为 TRUE,则执行 STP05。

  • 在 IF5 中,如果作业步骤 STP05 中的 PROC PRC1 中的过程步骤 PST1 ABEND,则执行 STP06。 否则执行STP07。

  • 如果 IF4 的计算结果为 false,则不执行 STP05。 在这种情况下,不会测试 IF5,并且不会执行步骤 STP06、STP07。

如果作业异常终止,例如用户取消作业、作业时间到期或数据集向后引用到被绕过的步骤,则不会执行 IF-THEN-ELSE。

设置检查点

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

A 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 中写入了一个检查点。

重新开始处理

您可以使用RD参数以自动方式重新启动处理,或使用RESTART参数手动重新启动处理。

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

  • RD=R 允许自动重新启动并考虑 DD 语句的 CHKPT 参数中编码的检查点。

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

  • RD=NR 指定作业/步骤无法自动重新启动。 但当使用RESTART参数手动重启时,会考虑CHKPT参数(如果有)。

  • RD=NC 不允许自动重启和检查点处理。

如果需要仅对特定异常结束代码进行自动重新启动,则可以在 IBM 系统 parmlib 库的 SCHEDxx 成员中指定。

RESTART 参数 编码在 JOB 或 EXEC 语句中,它有助于在作业失败后手动重新启动 JOB/STEP。 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 语句。