- JCL 教程
- JCL 首页
- JCL - 概述
- JCL - 环境
- JCL - JOB 语句
- JCL - EXEC 语句
- JCL - DD 语句
- JCL - 基础库
- JCL - 过程
- JCL - 条件处理
- JCL - 定义数据集
- JCL - 输入/输出方法
- JCL - 运行 COBOL 程序
- JCL - 实用程序
- JCL - 基本排序技巧
- JCL 有用资源
- JCL - 常见问题解答
- JCL - 快速指南
- JCL - 有用资源
- JCL - 讨论
JCL - 条件处理
作业输入系统使用两种方法在 JCL 中执行条件处理。作业完成后,将根据执行状态设置返回码。返回码可以是 0(成功执行)到 4095(非零表示错误条件)之间的数字。最常见的约定值是:
0 = 正常 -一切正常
4 = 警告 - 出现轻微错误或问题。
8 = 错误 - 出现重大错误或问题。
12 = 严重错误 - 出现主要错误或问题,结果不可靠。
16 = 终止错误 - 出现非常严重的问题,请勿使用结果。
可以使用 **COND** 参数和 **IF-THEN-ELSE** 结构来控制作业步骤的执行,本教程已对此进行了解释。
COND 参数
可以在 JCL 的 JOB 或 EXEC 语句中编写 **COND** 参数。它是对前面作业步骤返回码的测试。如果测试结果为真,则当前作业步骤的执行将被跳过。跳过只是省略作业步骤,而不是异常终止。单个测试中最多可以组合八个条件。
语法
以下是 JCL COND 参数的基本语法:
COND=(rc,logical-operator) or COND=(rc,logical-operator,stepname) or COND=EVEN or COND=ONLY
以下是所用参数的说明:
**rc**: 这是返回码
**逻辑运算符**: 可以是 GT(大于)、GE(大于或等于)、EQ(等于)、LT(小于)、LE(小于或等于)或 NE(不等于)。
**stepname**: 这是测试中使用其返回码的作业步骤。
最后两个条件 (a) COND=EVEN 和 (b) COND=ONLY,已在本教程中进行了解释。
COND 可以写在 JOB 语句或 EXEC 语句中,这两种情况下其行为都不同,如下所述:
JOB 语句中的 COND
当在 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.
EXEC 语句中的 COND
当在作业步骤的 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 结构
控制作业处理的另一种方法是使用 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**: 条件将具有以下格式:**KEYWORD OPERATOR VALUE**,其中 **KEYWORDS** 可以是 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
让我们尝试查看上述程序,以便更详细地理解它:
在 IF1 中测试 STP01 的返回码。如果为 0,则执行 STP02。否则,处理将转到下一个 IF 语句 (IF2)。
在 IF2 中,如果 STP01 已开始执行,则执行 STP03a 和 STP03b。
在 IF3 中,如果 STP03b 未 ABEND,则执行 STP04。在 ELSE 中,没有语句。这称为 NULL ELSE 语句。
在 IF4 中,如果 STP01.RC = 0 和 STP02.RC <=4 为真,则执行 STP05。
在 IF5 中,如果作业步骤 STP05 中过程 PRC1 中的 proc-step PST1 ABEND,则执行 STP06。否则执行 STP07。
如果 IF4 的值为假,则不执行 STP05。在这种情况下,不测试 IF5,也不执行步骤 STP06、STP07。
如果作业异常终止(例如用户取消作业、作业时间到期或数据集向后引用被跳过的步骤),则不会执行 IF-THEN-ELSE。
设置检查点
可以使用 **SYSCKEOV**(这是一个 DD 语句)在 JCL 程序中设置检查点数据集。
**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** 禁止自动重新启动和检查点处理。
如果只需要对特定 abend 代码进行自动重新启动,则可以在 IBM 系统 parmlib 库的 **SCHEDxx** 成员中指定。
**RESTART 参数** 编写在 JOB 或 EXEC 语句中,它有助于在作业失败后手动重新启动 JOB/STEP。RESTART 可以与 checkid 结合使用,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 语句。