• principal_3

    Desde 2015, enseñando sobre el sistema operativo z/OS de IBM en esta web. z/OS se utiliza en máquinas llamadas Mainframe.

  • principal_1

    Para realizar el contenido, utilizo el producto de IBM llamado z/Development and Test Environtment Personal Edition. Este software permite emular un Mainframe y así poder utilizar z/OS para aprender.

  • principal_2

    Es utilizado por grandes empresas (bancos, aseguradoras...). Aquí aprenderás a instalar y configurar productos relacionados con z/OS.

  • principal_4

    ADCD es una distribución de z/OS que contiene productos de IBM como IMS, DB2, CICS, ZOWE, TWS, NetView, System Automation, etc.

Obteniendo estadísticas procesos de spool por REXX

Adjuntos:
Descargar este archivo (SPLPPRIN.TXT)Primer panel[Panel principal del programa]1 kB
Descargar este archivo (SPLPTABL.TXT)Segundo panel[Segundo panel del programa]1 kB
Descargar este archivo (SPLSTATS.TXT)Programa principal[Programa Rexx]7 kB

En esta ocasión vamos a mejorar el programa que escribimos en “Obteniendo datos de ejecución de jobs del spool por REXX”. La mejora consiste en añadir dos paneles de ISPF para poder elegir los datos que queremos obtener. El panel principal permitirá elegir las opciones de filtrado: nombre del job, tipo, estado y el rango de fecha y hora de los datos. El resultado se mostrará en una tabla en el segundo panel. Además, el resultado se guardará en un dataset.

Para que funcione, se puede hacer de dos formas:

La primera consiste crear una librería particionada que se llame XXXXXXXX.PANELES, siendo XXXXXXXX el usuario que estemos usando, y meter ahí los dos paneles. El programa concatena esa librería automáticamente para no tener que modificar el procedimiento de logon.

 

El programa podemos guardarlo en otra librería de usuario y ejecutarlo mediante “exec”.

 

La segunda forma consiste en guardar cada miembro en la librería correspondiente según el procedimiento de logon que estemos usando y ejecutarlo mediante el comando “TSO SPLSTATS)

 

El código del programa y de los dos paneles es el siguiente:

NOTA: Para evitar errores al copiar/pegar, descargar el código de los archivos adjuntos del post.

Programa principal: SPLSTATS 

/* REXX                              */

/* ESCRITO POR: JFG                  */

/* FECHA: 13/10/2017                 */

/* DESCRIPCION:                      */

/*  PANEL PARA FILTRAR LOS PROCESOS  */

/*  DEL SPOOL SEGUN LOS CRITERIOS    */

/*  ELEGIDOS.                        */

/*  EL RESULTADO SE MUESTRA EN UNA   */

/*  TABLA Y SE GUARDA EN UN DATASET  */

/*                                   */

ADDRESS TSO

"PROFILE NOPREFIX"

/* COMPROBAR SI EXISTE LA LIBRERIA DE USUARIO PARA LOS PANELES  */

LIBRERIA=SYSDSN(USERID().PANELES)

/* SI EXISTE, SE CONCATENA A LAS LIBRERIAS ISPPLIB  */

IF LIBRERIA = "OK" THEN

  ISPEXEC "LIBDEF ISPPLIB DATASET ID("USERID()".PANELES)"

DO FOREVER

  /* CREAR TABLA TEMPORAL (NOWRITE) PARA EL RESULTADO */

  ADDRESS ISPEXEC "TBCREATE JOBTABLE KEYS(ZCODIGO)",

    "NAMES(JOBNM,JOBID,FECINI,HORAINI,FECFIN,HORAFIN) NOWRITE"

  /* MOSTRAR PANEL PRINCIPAL */

  ADDRESS ISPEXEC "DISPLAY PANEL(SPLPPRIN) CURSOR(ZCMD)"

  IF RC <> 0 THEN EXIT

  RC=ISFCALLS('ON')

    /* INICIALIZAR VARIABLES */

    JOBNM='*'

    TIPO='*'

    ESTADO='*'

    DESFEC='01/01/1970'

    DESHOR='00:00:00.00'

    /* FECHA DIA SIGUIENTE EN FORMATO MM/DD/YYYY */

    HASFEC=DATE('S',DATE('BASE')+1,'BASE')

    HASFEC=TRANSLATE('45/67/0123',HASFEC,'01234567')

    HASHOR='23:59:59.00'

    /* ASIGNAR LOS VALORES DEL PANEL A LAS VARIABLES */

    IF ZJOBNM<>'' THEN

      JOBNM=ZJOBNM

    IF ZTIPRAD=1 THEN

      TIPO="JOB"

    IF ZTIPRAD=2 THEN

      TIPO="STC"

    IF ZESTRAD=1 THEN

      ESTADO="PRINT"

    IF ZESTRAD=2 THEN

      ESTADO="EXECUTION"

    /* FECHA FORMATO YYYY/MM/DD A MM/DD/YYYY */

    IF ZDESFEC<>'' THEN

      DESFEC=TRANSLATE('56/89/0123',ZDESFEC,'0123456789')

    IF ZDESHOR<>'' THEN

      DESHOR=ZDESHOR

    /* FECHA FORMATO YYYY/MM/DD A MM/DD/YYYY */

    IF ZHASFEC<>'' THEN

      HASFEC=TRANSLATE('56/89/0123',ZHASFEC,'0123456789')

    IF ZHASHOR<>'' THEN

      HASHOR=ZHASHOR

    /* DEFINIR FILTRO DE BUSQUEDA    */

    ISFFILTER = "JNAME EQ "JOBNM" JTYPE EQ "TIPO" QUEUE EQ "ESTADO

    ISFFILTER = ISFFILTER" DATEE GE "DESFEC" TIMEE GE 00:00:00"

    ISFFILTER = ISFFILTER" DATEE LE "HASFEC

    /* DEFINIR RELACION ENTRE LOS FILTROS   */

    ISFFILTERMODE = "AND"

    /* ORDENAR POR FECHA Y HORA DE INICIO DE FORMA ASCENDENTE */

    ISFSORT = "DATEE A TIMEE A"

    /* ACCEDER AL PANEL ST PARA SACAR LOS DATOS  */

    ADDRESS SDSF "ISFEXEC ST (DELAYED ALTERNATE)"

    NUMROWS=ISFROWS

    /* ESCRIBIR CABECERA DEL FICHERO PARA EL RESULTADO */

    CABECERA="JOBNAME "||X2C(05)||"JOBID "||X2C(05)||"F INICIO "||,

    X2C(05)||"H INICIO "||X2C(05)||"F FIN "||X2C(05)||"H FIN"

    QUEUE CABECERA

    /* FECHA FORMATO MM/DD/YYYY A MM/DD/YY   */

    DESFEC=TRANSLATE('01/34/89',DESFEC,'0123456789')

    /* FECHA FORMATO MM/DD/YY A BASE  */

    DESFECB=DATE('BASE',DESFEC,'U')

    /* FECHA FORMATO MM/DD/YYYY A MM/DD/YY   */

    HASFEC=TRANSLATE('01/34/89',HASFEC,'0123456789')

    /* FECHA FORMATO MM/DD/YY A BASE  */

    HASFECB=DATE('BASE',HASFEC,'U')

    /* RECORER RESULTADOS    */

    DO IX=1 TO NUMROWS

      /* FLAG RESULTADO VALIDO  */

      ESCRIBIR=0

      FECHAI=DATEE.IX

      FECHAF=DATEN.IX

      /* SI FECHA INICIO VACIO, PONEMOS 01/01/1970   */

      IF FECHAI='' THEN

         FECHAI='1970.001'

      /* FECHA FORMATO YYYY.DDD A DD/MM/YY */

      FECHAI=FECHAGRE(FECHAI)

      /* SI FECHA FIN VACIO, PONEMOS 01/01/1970   */

      IF FECHAF='' THEN

         FECHAF='1970.001'

      /* FECHA FORMATO YYYY.DDD A DD/MM/YY */

      FECHAF=FECHAGRE(FECHAF)

      /* FECHA INICIO FORMATO DD/MM/YY A BASE */

      FECHAIB=DATE('BASE',FECHAI,'E')

      /* PASAR HORAS A SEGUNDOS               */

      SEGINI=HORASEC(TIMEE.IX)

      SEGDES=HORASEC(DESHOR)

      SEGHAS=HORASEC(HASHOR)

      /* SI FECHAS INICIO, DESDE Y HASTA SON IGUALES  */

      IF (FECHAIB=DESFECB & DESFECB=HASFECB) THEN

        DO

          /* SI LOS SEGUNDOS DE INICIO > SEG. DESDE Y < SEG. HASTA */

          IF (SEGINI >= SEGDES & SEGINI <= SEGHAS) THEN

            /* ESCRIBIR PORQUE ESTA DENTRO DEL EL RANCO   */

            ESCRIBIR=1

        END

      /* SI FECHAS INICIO, DESDE Y HASTA NO SON IGUALES  */

      ELSE

        DO

          /* SI FECHA INICIO = DESDE Y HORA INICIO >= HORA DESDE */

          IF (FECHAIB = DESFECB & SEGINI >= SEGDES) THEN

            /* ESCRIBIR PORQUE ESTA DENTRO DEL EL RANCO   */

             ESCRIBIR=1

          /* SI FECHA INICIO > DESDE Y FECHA INICIO > HASTA */

          IF (FECHAIB>DESFECB & FECHAIB<HASFECB) THEN

            /* ESCRIBIR PORQUE ESTA DENTRO DEL EL RANCO   */

             ESCRIBIR=1

          /* SI FECHA INICIO = HASTA Y HORA INICIO <= HORA DESDE */

          IF (FECHAIB = HASFECB & SEGINI <= SEGHAS) THEN

            /* ESCRIBIR PORQUE ESTA DENTRO DEL EL RANCO   */

             ESCRIBIR=1

        END

      /* SI EL RESULTADO ESTA DENTRO DEL RANGO LO ESCRIBIMOS   */

      IF ESCRIBIR=1 THEN

      DO

        /* DATOS PARA EL FICHERO DEL RESULTADO  */

        DATOS=JNAME.IX||X2C(05)||JOBID.IX||X2C(05)||FECHAI||,

        X2C(05)||TIMEE.IX||X2C(05)||FECHAF||X2C(05)||TIMEN.IX

        /* AÑADIMOS LOS DATOS A LA COLA PARA ESCRIBIR EL FICHERO */

        QUEUE DATOS

        /* GUARDAMOS LOS DATOS EN LAS VARIABLES DE LA TABLA   */

        ZCODIGO=IX

        JOBNM=JNAME.IX

        JOBID=JOBID.IX

        FECINI=FECHAI

        HORAINI=TIMEE.IX

        FECFIN=FECHAF

        HORAFIN=TIMEN.IX

        /* AÑADIMOS EL REGISTRO A LA TABLA     */

        ADDRESS ISPEXEC "TBADD JOBTABLE"

      END

    END

    RC=ISFCALLS('OFF')

    ADDRESS TSO

    "PROFILE NOPREFIX"

    /* COMPROBAR SI EXISTE EL FICHERO PARA EL RESULTADO  */

    LIBRERIA=SYSDSN(USERID().STATS.SPOOL)

    /* SI NO EXISTE, SE CREA    */

    IF LIBRERIA <> "OK" THEN

    DO

    "ALLOCATE F(FICH) DA("USERID()".STATS.SPOOL) NEW CYL

    DSORG(PS) SPACE(2,2) RECFM(F,B) LRECL(80) BLKSIZE(800)"

    "FREE F(FICH)"

    END

    "ALLOCATE F(FICH) DA("USERID()".STATS.SPOOL) OLD"

    /* ESCRIBIMOS LA COLA QUE CONTIENE EL RESULTADO   */

    "EXECIO "QUEUED()" DISKW FICH (FINIS"

    /* LIBERAMOS EL DATASET */

    "FREE F(FICH)"

    /* NOS POSICIONAMOS AL PRINCIPIO DE LA TABLA   */

    ADDRESS ISPEXEC "TBTOP JOBTABLE"

    DO FOREVER

       /* MOSTRAR EL PANEL CON LA TABLA QUE CREAMOS  */

       ADDRESS ISPEXEC "TBDISPL JOBTABLE PANEL(SPLPTABL)"

       IF RC <> 0 THEN

       DO

         /* SI SALIMOS DEL PANEL, CERRAMOS LA TABLA  */

         ADDRESS ISPEXEC "TBCLOSE JOBTABLE"

         LEAVE

       END

    END

END

/*                                                    */

/* FUNCION PARA FORMATEAR LA FECHA JULIANA A DD/MM/YY */

/*                                                    */

FECHAGRE:

PARSE ARG FECHA

/* FORMATEAR DE YYYY.DDD A YYDDD */

FECHA=TRANSLATE('34678',FECHA,'12345678')

/* PASAR FECHA JULIANA A YYYYMMDD */

FECHA=DATE('S',FECHA,'J')

/* FORMATEAR FECHA YYYYMMDD A DD/MM/YY */

FECHA=TRANSLATE('78/56/34',FECHA,'12345678')

RETURN FECHA

/*                                                   */

/* FUNCION PARA PASAR DE HORAS, MIN Y SEG A SEGUNDOS */

/*                                                   */

HORASEC:

PARSE ARG HORA

/* PASAMOS LAS HORAS A SEGUNDOS  */

HORAS=3600*TRANSLATE('01',HORA,'01234567')

/* PASAMOS LOS MINUTOS A SEGUNDOS */

MINUTO=60*TRANSLATE('34',HORA,'01234567')

/* SUMAMOS TODO PARA OBTENER LOS SEGUNDOS */

SEGUNDOS=HORAS+MINUTO+TRANSLATE('67',HORA,'01234567')

RETURN SEGUNDOS

/*                                               */

/* SUBRUTINA GENERICA PARA CONTROLAR LOS ERRORES */

/*                                               */

MSGRTN: PROCEDURE EXPOSE ISFMSG ISFMSG2.

/* THE ISFMSG VARIABLE CONTAINS A SHORT MESSAGE */

IF ISFMSG<>"" THEN

SAY "ISFMSG IS:" ISFMSG

/* THE ISFMSG2 STEM CONTAINS ADDITIONAL DESCRIPTIVE */

/* ERROR MESSAGES */

DO IX=1 TO ISFMSG2.0

SAY "ISFMSG2."IX "IS:" ISFMSG2.IX

END

RETURN

 

Primer panel: SPLPPRIN

)ATTR DEFAULT(%+@)

       % TYPE(TEXT)  INTENS(HIGH)

       ¡ TYPE(TEXT)  INTENS(HIGH) HILITE(REVERSE)

       + TYPE(TEXT)  INTENS(LOW)

       ~ TYPE(OUTPUT) INTENS(LOW) COLOR(YELLOW)

       @ TYPE(OUTPUT) INTENS(LOW) COLOR(GREEN)

       $ TYPE(OUTPUT) INTENS(LOW) COLOR(&COLOREST) HILITE(REVERSE)

       ? TYPE(INPUT) INTENS(LOW) COLOR(GREEN) PAD(_)

)BODY                                                        

+---------------------------%ESTADISTICAS SPOOL+-------------------------------

+

+%OPCION ===>?Z                                                                +

+

+  OBTIENE UNA LISTA CON LOS PROCESOS DEL SPOOL QUE CUMPLEN LO SIGUIENTE

+

+ ¡FILTAR POR :+

+

+     %JOB    : ?Z       +            %NOMBRE PROCESO. EJEMPLO: PE*

+     %TIPO   : ?Z%                    1-JOB        2-STC          3-TODOS

+     %ESTADO : ?Z%                    1-TERMINADOS 2-EN EJECUCION 3-TODOS

+

+ ¡INICIO     :+

+

+     %DESDE  : ?Z         +?Z       % FORMATO YYYY/MM/DD HH:MM:SS

+     %HASTA  : ?Z         +?Z       % FORMATO YYYY/MM/DD HH:MM:SS

+

+

+         PULSA%ENTER+PARA COMENZAR EL PROCESO. PULSA%F3+PARA SALIR

+

)INIT

.ZVARS = '(ZCMD,ZJOBNM,ZTIPRAD,ZESTRAD,ZDESFEC,ZDESHOR,+

           ZHASFEC,ZHASHOR)'

&ZJOBNM='*'

&ZTIPRAD=''

&ZESTRAD=''

&ZDESFEC=''

&ZDESHOR=''

&ZHASFEC=''

&ZHASHOR=''

)REINIT

 REFRESH(*)

)PROC

 VER (&ZJOBNM,NAMEF)

 VER (&ZTIPRAD,NONBLANK,LIST,'1','2','3')

 VER (&ZESTRAD,NONBLANK,LIST,'1','2','3')

 VER (&ZDESFEC,STDDATE)

 VER (&ZDESHOR,STDTIME)

 VER (&ZHASFEC,STDDATE)

 VER (&ZHASHOR,STDTIME)

)END

 

Segundo panel: SPLPTABL

)ATTR DEFAULT(%+@)

       % TYPE(TEXT)  INTENS(HIGH)

       ¡ TYPE(TEXT)  INTENS(HIGH) HILITE(REVERSE)

       + TYPE(TEXT)  INTENS(LOW)

       $ TYPE(TEXT)  INTENS(LOW) HILITE(REVERSE)

       ~ TYPE(OUTPUT) INTENS(LOW) COLOR(YELLOW)

       @ TYPE(OUTPUT) INTENS(HIGH)

       ? TYPE(INPUT) INTENS(LOW) COLOR(GREEN) PAD(_)

)BODY

+---------------------------%ESTADISTICAS SPOOL+-------------------------------

+

+%OPCION ===>?Z                                               %SCROLL ===>?Z   +

+

+    RESULTADO GUARDADO EN@LIBRERIA            +PULSE%F3+PARA VOLVER.

+

+   %Nº TOTAL DE PROCESOS:@ZTDROWS+

+

+   $ JOBNAME  JOBID      -------- INICIO -------  --------- FIN --------- +

    $                      FECHA     HORA           FECHA     HORA         +

)MODEL

+    @JOBNM   @JOBID      @FECINI   @HORAINI       @FECFIN   @HORAFIN

)INIT

.ZVARS = '(ZCMD,ZSCML)'

*REXX(LIBRERIA)

LIBRERIA=USERID()".STATS.SPOOL"

*ENDREXX

VGET (ZSCML) PROFILE

IF (&ZSCML = ' ') &ZSCML = 'PAGE'

/*&ZPROCE=&ZCODIGO */

)REINIT

)PROC

VPUT (ZSCML) PROFILE

)END

 

Una vez lo hemos guardado en los datasets correspondientes, lo ejecutamos. La primera pantalla que aparecerá es la siguiente.

 

Aquí elegiremos que procesos del spool queremos seleccionar.

JOB. Es el nombre de proceso. Si ponemos * o lo dejamos en blanco, seleccionará todos.

TIPO. Permite elegir entre jobs, started task o todo. Si elegimos todo, también aparecerán los usuarios (TSU).

ESTADO. Elegiremos los procesos terminados, en ejecución o todos. Los procesos que se encuentren en ejecución tendrán, en el resultado, su fecha y hora de fin como “01/01/1970 00:00:00”.

INICIO DESDE. Permite seleccionar los procesos que hayan comenzado desde cierto día, hora o día + hora. Si no ponemos nada, usará cogerá todos los días disponibles del spool.

INICIO HASTA. Permite seleccionar los procesos que hayan comenzado hasta cierto día, hora o día + hora. Si no ponemos nada, usará cogerá todos los días disponibles del spool.

 

Para ejecutar el proceso, los únicos campos obligatorios son “TIPO” y “ESTADO”.

 

Una vez hayamos elegido los filtros, pulsaremos enter. Yo he elegido que me muestre todos los procesos (JOB + STC + TSU) que están terminados o en ejecución. El resultado es el siguiente:

 

Vemos que el número total de procesos es de 117. Podemos verlos detallados en la tabla, por la que nos podemos mover con F7 – F8. También podemos elegir el tipo de scroll. Estos mismos datos se guardan en el dataset que indica el panel, en este caso, IBMUSER.STATS.SPOOL.

Este dataset puede ser exportado a Excel, como vimos en la entrada “Obteniendo datos de ejecución de jobs del spool por REXX”

 

Saldremos con F3.

 

El programa es muy sencillo de utilizar, solo hay que ir usando las diferentes opciones.

Espero que os pueda servir de ayuda.

 

Publish modules to the "offcanvs" position.