COBOL程序执行后,数据集(Sysout)读取错误

时间:2015-04-01 15:52:09

标签: host cobol mainframe zos rexx

在rexx程序中,调用COBOL程序,它的SYSOUT是 使用临时数据集分配(TSO alloc)捕获,然后使用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上的输出。 我可以通过指定' VB'在我的z / OS系统中重新创建类似的情况。 TSO分配中的属性。在这种情况下,在ISPF中无法查看分配的数据集。当尝试在ISPF中查看时,会显示以下错误消息。

'I/O error occurred reading the edit data'

如果使用SHARED / OLD模式分配了这个损坏的数据,那么 问题解决了。因此,在新分配和COBOL程序执行期间会出现这种问题。

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

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


     if  (existsDSN(tmpDS)) then do  
         ADDRESS TSO,                        /* Here it works */
         "ALLOC DS('"tmpDS"') F(SYSOUT) SHR REUSE"  
     end  
     else do  
         ADDRESS TSO                        /* ds creation error here */   
         "ALLOC DS('"tmpDS"') F(SYSOUT) NEW DSORG(PS)",  
         "BLKSIZE(121) SPACE(5,15) TRACKS RECFM(F B A) DIR(0)"  
     end

请注意,在ISPF浏览模式下,编目的SYSOUT数据集甚至无法读取。


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

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

2 个答案:

答案 0 :(得分:1)

好的,所以这是手册对你的情况所说的:

企业COBOL编程指南

  

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

企业COBOL语言参考

  

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

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

  

// SYSOUT DD

     

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

     

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消息,   代码和诊断指南   注意:只有在OPTION控件上传递MSGDDN时才会处理它   扩展参数列表或DFSPARM中的语句。

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

如果您在测试过程中的任何时刻都已将SYSOUT DD指向SYSOUT =(假脱机)数据集(我猜测接近100%的人会这样做),您已经注意到了该步骤的SYSOUT数据集上的混合输出。我不确定它是怎么看的(从未做过这个,或者知道它已经完成)但是你本来能够至少确定多次使用的来源(相同的COBOL程序,做自己的显示,并且还做多个内部SORTs。)


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

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

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

确保在Rexx程序中为一次执行程序分配的文件随后被解除分配,并且不会重复使用数据集名称,每次都需要注意。确保在任何可以设置RC的情况下始终检查RC。不要在不需要的语句上指定选项。


根据我提供的程序,在您将数据粘贴到您的问题中之前,您的数据如下所示:

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

第二次尝试:

预期的消息文本

44
00

我不确定"预期的消息文本"表示,也不是"第一条记录出现两次",也不是"总共4条消息行"。

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

忽略"预期的消息文本"你正在显示两个数据记录,在"十六进制"格式化(如果您使用它来浏览假脱机输出,则在SDSF中设置HE HEX ON。)

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

所以,我们猜测你实际上有两条记录。一个是10个分区十进制数字(或者#34;字符"),一个非常绝对不一样。

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

此文件绝对肯定会为您提供错误的长度记录"。

然而,即使这样,你所展示的东西也不太对劲。我认为你所做的并不是复制所有尾随空白。

我们知道你有一个121的LRECL,对于固定长度的记录,这意味着记录将是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

答案 1 :(得分:0)

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

的数据集的DFSPARM ddname来完成此操作
  MSGDDN=dfsoutdd

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

  1. COBOL程序具有内部SORTS,因此生成DFSORT消息 在SYSOUT
  2. COBOL程序本身有一个或多个文本显示
  3. 当SYSOUT被定向到带有DISP = NEW的DSN时(SDSF假脱机上的SYSOUT) 没关系)
  4. 另一个观察是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