1

在 rexx 程序中,调用 COBOL 程序并使用临时数据集分配 (TSO alloc) 捕获它的 SYSOUT,然后使用 EXECIO 读取。它通常可以正常工作,没有任何问题。

我们的一位用户(使用不同的机器)在 EXECIO 读取时报告了一个问题。

 IRX0562E Abnormal completion of the GET Data Management macro.   
 IRX0565E SG0     ,$LOGON  ,3420,D,SYSOUT  ,GET    ,WRNG.LEN.RECORD,0000003500000 0,QSAM.     
 IEC020I      001-4,SG0,$LOGON,SYSOUT,3420,BWS858,     
 IEC020I      SYS15089.T170858.RA000.SG0.R0278041     
 IEC020I DCB EROPT=ABE OR AN      INVALID CODE, AND/OR NO SYNAD EXIT  SPECIFIED   
 IRX0250E System abend code 001, reason code 00000004.     
 IRX0255E Abend in host command EXECIO or address environment routine MVS.

我发现这个问题专门发生在 COBOL 程序在 SYSOUT 上有一些输出时。通过在 TSO 分配中指定“VB”属性,我可以在我的 z/OS 系统中重新创建类似的情况。在这种情况下,分配的数据集在 ISPF 中不可见。尝试在 ISPF 中查看时显示以下错误消息。

'I/O error occurred reading the edit data'

如果这个损坏的数据是使用共享/旧模式分配的,那么问题就解决了。所以这种问题发生在新分配和 COBOL 程序执行期间。

在 COBOL 程序执行后,进一步的 SHR/OLD 模式分配纠正了这个问题。关于这里到底出了什么问题的任何想法?

对于测试版本,我使用如下的编目文件。下面的 SYSOUT 分配,就在 COBOL 程序执行之前如下。看到只有当我将记录格式更改为“VB”时才会出现问题(这是重新创建用户在另一台 zos 机器上报告的相同错误)。

     if (existsDSN(tmpDS)) 然后做  
         ADDRESS TSO, /* 这里可以工作 */
         "ALLOC DS('"tmpDS"') F(SYSOUT) SHR 重用"  
     结尾  
     否则做  
         ADDRESS TSO /* 此处创建 ds 错误 */   
         "ALLOC DS('"tmpDS"') F(SYSOUT) NEW DSORG(PS)",  
         “BLKSIZE(121) 空间(5,15) 跟踪 RECFM(FBA) DIR(0)”  
     结尾

请注意,编目 SYSOUT 数据集在 ISPF 浏览模式下甚至不可读。


以下是bill 提到的COBOL 程序的输出,但是第一条记录在SYSOUT 中出现了两次(即总共4 条消息行)。

 0000000121
4FFFFFFFFFF
00000000121
   '   ` expected message text
4070007004
00D0009000
4

2 回答 2

1

好的,以下是手册对您的情况的说明:

企业 COBOL 编程指南

默认情况下,DFSORT 诊断消息被发送到 SYSOUT 数据集。如果要更改此默认值,请使用 DFSORT OPTION 控制卡的 MSGDDN 参数或使用 SORT-MESSAGE 专用寄存器。

企业 COBOL 语言参考

您可以使用 SORT-MESSAGE 特殊寄存器来指定数据集的 ddname,排序实用程序应使用该数据集代替 SYSOUT 数据集。在 SORT-MESSAGE 中指定的 ddname 等同于在排序控制文件中的 'MSGDDN=' 控制语句中指定的名称。

DFSORT 应用程序编程指南(我的重点)

//SYSOUT DD

标识 DFSORT 消息数据集。默认 ddname 是 SYSOUT,但您可以使用 MSGDDN 安装或运行时选项为消息数据集指定备用 ddname。如果不使用编目过程,请始终为消息数据集提供 DD 语句。(如果您从 COBOL 程序调用 DFSORT 并且使用 ddname SYSOUT 作为消息数据集,那么在您的 COBOL 程序中使用 DISPLAY 会产生不确定的打印结果。)

DFSORT 使用RECFM=FBA、LRECL=121 和为消息数据集指定的 BLKSIZE。如果您指定的 BLKSIZE 不是 121 的倍数,则 DFSORT 使用 BLKSIZE=121。如果不指定 BLKSIZE,DFSORT 会按照 SDBMSG 安装选项的指示选择块大小(请参阅 z/OS DFSORT 安装和定制)。 如果您使用临时或永久消息数据集,最好指定 MOD 的配置以确保您看到消息数据集中的所有消息和控制语句。

和:

MSGDDN

MSGDDN=ddname

临时覆盖 MSGDDN 安装选项,该选项指定消息数据集的备用 ddname。MSGDDN 必须在以下情况下生效:

v调用 DFSORT 的程序使用 SYSOUT(例如,COBOL 使用 SYSOUT)并且您不希望 DFSORT 消息与程序消息混合

v 您的 E15 和 E35 例程是用 COBOL 编写的,并且您不希望 DFSORT 消息与程序消息混合。

v 一个程序多次调用 DFSORT,并且您希望每次调用 DFSORT 时都有单独的消息。

ddname 可以是任何 1 到 8 个字符的名称,但在作业步骤中必须是唯一的;不要使用 DFSORT 使用的名称(例如,SORTIN)。如果指定的 ddname 在运行时不可用,则使用 SYSOUT。有关使用消息数据集的详细信息,请参阅 z/OS DFSORT 消息、代码和诊断指南 注意:只有在扩展参数列表或 DFSPARM 中的 OPTION 控制语句上传递 MSGDDN 时,才会处理它。

尽管手册中有建议,但您所做的是混合来自 COBOL 和 DFSORT 的 SYSOUT 输出(实际上是多次调用 DFSORT)。您在将 SYSOUT 定向到顺序数据集的同时完成了该操作,该数据集具有与 DFSORT 使用的不同特征。由于 DFSORT 将始终输出消息,因此如果 COBOL 程序在运行中至少在 DISPLAY 上使用,则可以保证您的数据集已损坏。

如果您在测试期间的任何时候将 SYSOUT DD 定向到 SYSOUT= (spool) 数据集(我猜接近 100% 的人都这样做),您会注意到 SYSOUT 数据集上的混合输出那一步。我不确定它的外观(从未这样做过,或者知道会这样做),但您至少能够识别多次使用的来源(同一个 COBOL 程序,做自己的 DISPLAY,并且还进行多个内部排序)。


您已经通过使用 DFSORT 的 MSGDD= 修改默认输出 DD (SYSOUT) 解决了您的问题。

值得注意的是,您还可以使用编译器选项 OUTDD(somedd) 将用于 COBOL DISPLAY 的 DD 的名称从其默认值 (SYSOUT) 更改为其他名称。

语言环境默认使用 SYSOUT,但您可以使用运行时选项 MSGFILE 来修改它(LE 运行时选项可以通过各种方式设置,请参阅语言环境文档(我发现最简单的是//CEEDOPT DD在 JCL对于批处理程序)。

确保从 Rexx 程序中为程序的一次执行分配的文件随后被取消分配,并且不重复使用数据集名称是每次都需要注意的事情。确保您始终检查 RC,只要有东西可以设置 RC。不要在不需要的语句上指定选项。


这是您在我将其粘贴到您的问题之前显示的数据,来自我提供的程序:

0000000121
4FFFFFFFFFF
00000000121
   '   ` expected message text
4070007004
00D0009000

第二次尝试:

预期的消息文本

44
00

我不确定“预期的消息文本”是什么意思,也不确定“第一条记录出现两次”,也不确定“总共 4 条消息行”。

数据没有排列。在您的问题中,我更正了 0000000121 部分,但没有更正其他记录。

忽略“预期消息文本”,您将以“十六进制”格式显示两条数据记录(如果您使用它来浏览假脱机输出,请在 SDSF 中设置 HEX ON)。

第一个空白可能是 SDSF 的产物。当您第一次查看假脱机文件时,如果您查看 COLS,您会看到数据从第二列开始。如果您将屏幕向左移动,您将看到第一列,它不是数据。

因此,我们可以猜测您实际上有两条记录。一种是 10 个分区十进制数字(或“字符”),另一种是绝对不一样的。

第一条记录看起来像一个固定长度的记录,有 10 个字节。第二个看起来是一个可变长度的记录。实际上,它是一个可变长度数据

该文件将绝对肯定地为您提供“错误长度记录”。

但是,即便如此,您所展示的内容还是有些不妥。我认为您所做的并不是复制所有尾随空格。

我们知道您的 LRECL 为 121,对于固定长度的记录,这意味着记录的长度为 121 字节,但您显示的是 10 字节。好的,可以从覆盖长度到 10 的内容中写入。

但是,对于可变长度数据,它是这样的

X'007D' = 块长度,125 字节,块描述符字 (BDW) 的前半部分,包括 BDW 的长度(四)。X'0000' = BDW 的后半部分 X'0079' = 记录长度,121 字节,记录描述符字 (RDW) 的前半部分,包括 RDW 的长度(四)。121 字节的数据,显示为 X'40'。所以让我们假设有 121 个字节的空间。

因此,让我们回过头来假设固定长度的记录是 121 个字节,后面有空格。看到在您的“答案”中,第一条“线”没有对齐,我们可以假设您对前导空白以及第二条记录进行了调整。

目前尚不清楚从哪里开始,但您的文件绝对是“混合”。您有一个固定长度的记录,然后是一个可变长度的块(仅包含一条记录) 您需要准确粘贴您在选择假脱机文件后看到的内容,输出为十六进制模式。一直从屏幕的左到右。复制/粘贴,而不是丝网印刷。

你认为哪条线是正确的?空白,还是 0000000121?


好的,仍然没有很多工作要做:-)

您的问题与tmpDS. 看不到内容,但这就是问题所在。

它的名称看起来非常临时,但内容使事情比您预期的要永久得多。

当发生故障的用户在您的系统上并开始运行 COBOL 程序时,该文件(具有该确切名称的数据集)已经存在于系统上。COBOL 将轻松地破坏它,可能使用 FBA 121。如果以前使用的文件不是COBOL 破坏它的文件,您将得到您详细说明的确切情况。

这是如何发生的有多种可能性。在不同的 rexx 程序中使用相同的名称是最简单的。使用 TSO-userid 作为前缀可能会有所帮助,但您需要让系统决定名称或自己生成名称,以免重复。

如果没有看到您的代码,就无法确定这一点。只有 99.3% 肯定,除非你告诉我 :-)

这是一个简短的程序,您可以使用它来读取文件并查看其中的内容:

   ID DIVISION. 
   PROGRAM-ID. STOB26. 
   ENVIRONMENT DIVISION. 
   INPUT-OUTPUT SECTION. 
   FILE-CONTROL. 
       SELECT IN-FILE  ASSIGN TO INFILE 
       FILE STATUS IS W-FILE-STATUS. 
   DATA DIVISION. 
   FILE SECTION. 
   FD  IN-FILE 
       RECORD IS VARYING 
       DEPENDING ON W-REC-LENGTH 
       RECORDING MODE U. 
   01  IN-REC. 
       05  FILLER OCCURS 1 TO 32760 TIMES 
           DEPENDING ON W-REC-LENGTH       PIC X. 
   WORKING-STORAGE SECTION. 
   01  W-FILE-STATUS                       PIC XX. 
       88  FILE-STATUS-GOOD                VALUE "00". 
       88  FILE-STATUS-OK-FOR-INPUT        VALUE "00" "10".
       88  END-OF-FILE                     VALUE "10". 
   01  W-REC-LENGTH                        PIC 9(8) COMP. 
   PROCEDURE DIVISION.
       DISPLAY 'Start of program' 
       OPEN INPUT IN-FILE 
       IF NOT FILE-STATUS-GOOD 
           DISPLAY 
                   'OPEN FAILED' 
                   '>' 
                   W-FILE-STATUS 
                   '<' 
           CALL 'FRED' 
       END-IF 
       PERFORM UNTIL END-OF-FILE 
           READ IN-FILE 
           IF NOT FILE-STATUS-OK-FOR-INPUT 
               DISPLAY 
                       "READ FAILED" 
                       '>' 
                       W-FILE-STATUS 
                       '<' 
               CALL 'FRED' 
           END-IF 
           DISPLAY 
                   'Record length is>'
                   W-REC-LENGTH 
                   '<'
           DISPLAY 
                   'Data is>' 
                   IN-REC 
                   '<'
       END-PERFORM 
       CLOSE IN-FILE 
       IF NOT FILE-STATUS-GOOD 
           DISPLAY 
                   'CLOSE FAILED' 
                   '>' 
                   W-FILE-STATUS 
                   '<' 
           CALL 'FRED' 
       END-IF 
       DISPLAY 'End of program' 
       GOBACK 
       . 

JCL 很简单,可以基于此:

//RUNIT EXEC PGM=VARA,TIME=(,2)
//STEPLIB DD DSN=loadlibrary,DISP=SHR 
//SYSOUT DD SYSOUT=* 
//INFILE DD DSN=yourbusteddsn,LRECL=32760,RECFM=U,DISP=SHR
于 2015-04-02T17:45:36.527 回答
0

我怀疑这与 DFSORT sysout 消息有关。通过指定 DFSPARM 参数将 DFSORT 消息重定向到另一个数据集后,此问题得到解决。我可以通过分配对应于包含的数据集的 DFSPARM ddname 来做到这一点

  MSGDDN=dfsoutdd

此问题也出现在批处理模式中,即它与 TSO alloc 或 rexx 程序无关。总而言之,问题发生在

  1. COBOL 程序具有内部 SORTS,因此会在 SYSOUT 上生成 DFSORT 消息
  2. COBOL 程序本身有一个/或多个文本显示
  3. 当 SYSOUT 被定向到 DISP=NEW 的 DSN 时(SDSF 假脱机上的 SYSOUT 正常)

另一个观察结果是 DFSORT 会导致程序执行后数据集属性发生变化。前

Organization . . . : PS Used tracks . . . . : 1
Record format . . . : VB Used extents . . . : 1
Record length . . . : 121
Block size . . . . : 27998
1st extent tracks . : 1

Organization . . . : PS Used tracks . . . . : 1
Record format . . . : FBA Used extents . . . : 1
Record length . . . : 121
Block size . . . . : 121
1st extent tracks . : 1
Secondary tracks . : 1
于 2015-04-08T08:53:20.093 回答