Guardar SYSLOG con XWTR
Estos primeros pasos son opcionales. Los hago para poder tener los SYSLOG archivados en un disco dedicado para ellos.
- Crear un disco nuevo
- Crear un catálogo en ese disco
- Crear un ALIAS que apunte a ese catálogo
Crear disco para archivar SYSLOG - Opcional
Crear un disco nuevo
Antes de empezar a archivar el SYSLOG, voy a crear e inicializar un disco para tenerlo almacenado en un mismo sitio.
En ZD&T, el fichero de disco se crea con el comando “alcckd”. En mi caso, modelo 3. Por ejemplo:
alcckd /mnt/1TB2/ADCD/3.1_B_acc/SLOG00 -d3390-3
De forma opcional, lo podemos montar dinámicamente. O añadirlo al fichero de configuración y volver a arrancar el sistema.
awsmount 0AA8 -m /mnt/1TB2/ADCD/3.1_B_acc/SLOG00Para montarlo dinámicamente, lo haría en la unidad 0AA8 porque es una de las unidades que tengo disponibles para montajes dinámicos.

En el sistema z/OS, ponemos el device offline:
V 0AAD,OFFLINE
Con un job similar a este, inicializamos el disco como NO-SMS:
//IBMUSERC JOB (20,FB3),'INIT NO SMS DASD',COND=(0,NE),
// CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID
//ICKDSF EXEC PGM=ICKDSF,REGION=4096K
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
INIT UNITADDRESS(0AAD) NOVERIFY VOLID(SLOG00) PURGE -
VTOC(0,1,149) INDEX(15,0,100)
/*
Respondemos al reply que genera este job:
nn,U
Termina correctamente.

Ponemos online el disco:
V 0AAD,ONLINEEn 3.4 comprobamos que es accesible y está bien definido.

Crear catálogo en el disco
Se puede usar el siguiente job. Solo hay que indicar el disco en el parámetro SET P1='SLOG00':
//IBMUSERC JOB (20,FB3),'JOB',COND=(0,NE),
// CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID
//E1 EXPORT SYMLIST=(P1)
// SET P1='SLOG00'
//DEFMCAT EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//CATVOL1 DD UNIT=3390,VOL=SER=&P1.,DISP=SHR
//SYSIN DD *,SYMBOLS=JCLONLY
DEFINE USERCATALOG ( -
NAME(USERCAT.V&P1. ) -
VOLUME(&P1.) -
ICFCATALOG -
CYL (1 1) -
SHAREOPTIONS(3 4) -
STORCLAS(SCNOSMS) -
NWCK NOIMBED NOREPLICATE)
Terminará correctamente.

Crear ALIAS que apunte a ese catálogo
Usamos un job como este para definir un ALIAS para SYSLOG:
//IBMUSERC JOB (20,FB3),'JOB',COND=(0,NE),
// CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID
//* DEFINE ALIAS
//PASO001 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEFINE ALIAS (NAME(SYSLOG) -
RELATE(USERCAT.VSLOG00)) -
CATALOG(CATALOG.Z31B.MASTER)
/*

Tendremos el ALIAS “SYSLOG” definido y el catálogo creado.


Configurar la tarea XWTR
Para poder guardar el SYSLOG del sistema en un dataset podemos usar la tarea XWTR.
En mi caso, se encuentra en SYS1.PROCLIB.

Por defecto, está definida de esta forma:

Para modificarla, la copio a USER.Z31B.PROCLIB que está antes en la concatenación de PROCLIB en mi sistema.

Con el comando WRITELOG (o W) sin más parámetros hacemos que el SYSLOG se guarde (PRINT) en la clase que tenga definida, en mi caso, clase L.
De esta forma, después la tarea XWTR puede capturarlo.
https://www.ibm.com/docs/en/zos/3.1.0?topic=wc-syntax
Hay que tener en cuenta que cada vez que hacemos WRITELOG podremos capturar lo que haya ocurrido en el log desde el WRITELOG anterior. Si, por ejemplo, hacemos varios WRITELOG durante el día, debemos tener en cuenta cómo los capturará la tarea XWTR para no perder información y tener un log completo del día y no tener un mismo día en ficheros distintos.
Una forma puede ser configurando en la tarea XWTR un dataset que exista previamente y volcar los datos del log (usando DISP=MOD) para ir añadiéndolos.
Luego otro job diferente, una vez al día, copia a un GDG lo que haya en ese fichero (que ha ido acumulando datos durante el día) y borra su contenido para no tener log duplicado.
Crear el fichero para archivar
Podemos empezar creando el fichero que contendrá el log con este job:
//CREASYSL JOB (CUENTA),'CREAR FICHERO',CLASS=A,MSGCLASS=X,
// MSGLEVEL=(1,1),NOTIFY=&SYSUID
//*-----------------------------------------------------------------
//* EJEMPLO PARA CREAR UN DATASET FB 133
//*-----------------------------------------------------------------
//STEP01 EXEC PGM=IEFBR14
//SYSOUT DD SYSOUT=*
//FICHERO DD DSN=USER.SYSLOG.ARCHIVE,
// DISP=(,CATLG),
// UNIT=3390,
// SPACE=(TRK,(500,300)),
// DCB=(DSORG=PS,RECFM=FB,LRECL=133,BLKSIZE=133)

El parámetro “PARM=PL” quiere decir que haga “PRINT” de la clase L.
Luego, con el comando WRITELOG (o W), redirigimos el SYSLOG a la clase L para que lo capture.
//XWTRPROC PROC
//IEFPROC EXEC PGM=IASXWR00,PARM='PL',REGION=4M
//IEFRDER DD DISP=MOD,DSNAME=USER.SYSLOG.ARCHIVE
Enviar el SYSLOG a la clase L con WRITELOG
Si entramos con el signo de interrogación a la tarea SYSLOG, veremos que por defecto va a la clase L.


Si usamos “WRITELOG L”, forzamos a que la salida vaya a la clase L (o la que deseemos). Lo importante es que el SYSLOG se guarde en la misma clase que luego la tarea XWTR vaya a capturar.
WRITELOG L
IEF196I IEF237I JES2 ALLOCATED TO SYSLOG01
IEE042I SYSTEM LOG DATA SET INITIALIZED
IEF196I IEF285I +MASTER+.SYSLOG.STC00203.D0000101.? SYSOUT
IEE043I A SYSTEM LOG DATA SET HAS BEEN QUEUED TO SYSOUT CLASS L 
Ahora la DDNAME SYSLOG00 tendrá Dest LOCAL y se generará una nueva para seguir guardando el LOG.

Arrancar XWTR
Ahora arrancamos la tarea XWTR. La forma de arrancarla es así:
S XWTR.XWTRError de seguridad en JESSPOOL
En mi caso, aparecieron unos errores de seguridad al intentar capturar los SYSLOG.
$HASP186 SYSLOG OUTGRP=1.1.1 NOT SELECTED BY STC07595/XWTR.XWTR DUE 518
TO SECURITY POLICY
$HASP186 SYSLOG OUTGRP=1.1.1 NOT SELECTED BY STC07595/XWTR.XWTR DUE 519
TO SECURITY POLICY 
Estos errores están relacionados con la clase JESSPOOL de RACF, pero no nos dan mucho detalle.
Ver el detalle con $T DEBUG
Para poder saber exactamente qué permiso nos falta, vamos a usar el siguiente comando:
$T DEBUG,SECURITY=YESMás información sobre este comando:
https://www.ibm.com/docs/en/zos/3.1.0?topic=option-parameter-description-debug


Ahora volvemos a dar el comando WRITELOG (o W) y veremos el detalle del error:
W
IEF196I IEF237I JES2 ALLOCATED TO SYSLOG04
IEE042I SYSTEM LOG DATA SET INITIALIZED
IEF196I IEF285I +MASTER+.SYSLOG.STC07414.D0000104.? SYSOUT
IEE043I A SYSTEM LOG DATA SET HAS BEEN QUEUED TO SYSOUT CLASS L
ICH408I USER(START1 ) GROUP(SYS1 ) NAME(ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ) 675
S0W1.+MASTER+.SYSLOG.STC07414.D0000104.? CL(JESSPOOL)
INSUFFICIENT ACCESS AUTHORITY
FROM S0W1.+MASTER+.SYSLOG.*.* (G)
ACCESS INTENT(ALTER ) ACCESS ALLOWED(READ )
$HASP186 SYSLOG OUTGRP=4.1.1 NOT SELECTED BY STC07595/XWTR.XWTR DUE 676
TO SECURITY POLICY Necesito el acceso ALTER y tengo READ.

Dar permiso ALTER al usuario de la STC
Con este comando le damos permiso ALTER al usuario de la STC (START1).
También podemos dar permiso al grupo con ID(SYS1).
PERMIT S0W1.+MASTER+.SYSLOG.*.* CLASS(JESSPOOL) ID(START1) ACCESS(ALTER)
SETROPTS GENERIC(JESSPOOL) REFRESH

Ahora volvemos a dar el comando WRITELOG (o W) y ya no aparecerán errores de permisos.

Desactivamos el DEBUG ya que hemos corregido el error.
$T DEBUG,SECURITY=NO
Si el fichero se llena (B37)
Puede ocurrir que si tenemos demasiado LOG “acumulado” el fichero se llene.


En este caso, hay que tener cuidado porque si borramos el fichero USER.SYSLOG.ARCHIVE, podemos perder parte del log acumulado.
Mejor renombrar el antiguo a OLD y crear uno nuevo (podemos hacerlo más grande si lo creemos necesario).

Por ejemplo, el fichero USER.SYSLOG.ARCHIVE.OLD empieza el día 39 (8 feb) a las 11:54.

Y termina el día 39 (8 feb) a las 15:31:

Pero el nuevo que hemos creado (después de volver a ejecutar: S XWTR.XWTR), empieza el día 39 a las 12:23. Es decir, si hubiéramos borrado el fichero anterior, habríamos perdido una parte del log (desde las 11:54 a las 12:23).

El nuevo fichero de log USER.SYSLOG.ARCHIVE termina el día 98 (8 abr) a las 22:46.

Esto ocurre cuando tenemos varios SYSLOGs de días anteriores que no fueron archivados (como me ocurre a mí en mi HOMELAB).

Si estamos archivando el log del SYSLOG activo, la DDNAME (en este caso, SYSLOG00) no se borrará hasta que se vuelque completamente, es decir, si falla por espacio (B37), podríamos borrar el fichero USER.SYSLOG.ARCHIVE y generar uno nuevo más grande.
Si preferimos asegurarnos, en vez de borrarlo, se puede renombrar. Cuando tengamos el nuevo fichero completo, se comparan ambos y se borra lo que no se necesite.


Parar XWTR
Cuando haya terminado de capturar el log sin errores, se quedará esperando hasta que hagamos el siguiente comando “WRITELOG L” para capturar el log.
Si no queremos que se quede en ejecución, paramos la STC XWTR. Además, si queremos guardar el log en el fichero GDG, debemos parar esta tarea previamente.
La podremos arrancar de nuevo después de usar el comando “WRITELOG L”.
P XWTR

Guardar el log diario en un GDG
Con la tarea XWTR, el fichero USER.SYSLOG.ARCHIVE va acumulando el log. Para no tener un mismo día repartido en ficheros distintos, una vez al día (cuando tengamos el día completo) vamos a volcar su contenido a una nueva generación de un GDG, y después borraremos el ARCHIVE y lo crearemos de nuevo vacío.
Crear el GDG
Este job solo se ejecuta una vez. Como el nombre empieza por SYSLOG, se cataloga en el catálogo USERCAT.VSLOG00 gracias al ALIAS que creamos antes.
//IBMUSERG JOB (20,FB3),'DEFINE GDG',COND=(0,NE),
// CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID
//DEFGDG EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEFINE GDG (NAME(SYSLOG.DAILY) -
LIMIT(30) -
NOEMPTY -
SCRATCH)
/*Con LIMIT(30) guardamos 30 generaciones, es decir, 30 días de log. Cuando se cree la generación 31, se borrará automáticamente la más antigua (NOEMPTY y SCRATCH). Podemos aumentar el número de días si fuese necesario.


Volcar el ARCHIVE al GDG
Este job hace tres pasos:
- Copia USER.SYSLOG.ARCHIVE a una nueva generación de SYSLOG.DAILY en el disco SLOG00.
- Borra USER.SYSLOG.ARCHIVE.
- Lo crea de nuevo vacío para que XWTR siga guardando el log.
//IBMUSERD JOB (20,FB3),'SYSLOG DAILY',COND=(0,NE),
// CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID
//*-----------------------------------------------------------------
//* 1) COPY TODAY'S ARCHIVE TO A NEW GDG GENERATION
//*-----------------------------------------------------------------
//COPY EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT1 DD DSN=USER.SYSLOG.ARCHIVE,DISP=OLD
//SYSUT2 DD DSN=SYSLOG.DAILY(+1),STORCLAS=SCNOSMS,
// DISP=(NEW,CATLG,DELETE),
// UNIT=3390,VOL=SER=SLOG00,
// SPACE=(CYL,(100,50),RLSE),
// DCB=(DSORG=PS,RECFM=FB,LRECL=133,BLKSIZE=0)
//*-----------------------------------------------------------------
//* 2) DELETE THE ARCHIVE (ONLY IF THE COPY ENDED RC=0)
//*-----------------------------------------------------------------
//DELETE EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DELETE USER.SYSLOG.ARCHIVE NONVSAM
/*
//*-----------------------------------------------------------------
//* 3) CREATE AN EMPTY ARCHIVE AGAIN
//*-----------------------------------------------------------------
//CREATE EXEC PGM=IEFBR14
//ARCHIVE DD DSN=USER.SYSLOG.ARCHIVE,
// DISP=(NEW,CATLG),
// UNIT=3390,
// SPACE=(TRK,(500,300)),
// DCB=(DSORG=PS,RECFM=FB,LRECL=133,BLKSIZE=133)El parámetro COND=(0,NE) en la ficha JOB hace que, si la copia falla (por ejemplo, por falta de espacio en SLOG00), no se ejecuten los pasos de borrado y creación. Así no perdemos el log de ese día.
Uso STORCLAS=SCNOSMS porque, sin él, SMS ignora el VOL=SER y el fichero se crea en un disco USERxx.

Al terminar, tendremos una nueva generación (por ejemplo, SYSLOG.DAILY.G0001V00) con el log completo del día y el fichero USER.SYSLOG.ARCHIVE vacío.

Estos pasos se pueden automatizar con los comandos automáticos de JES2 ($TA), que permiten lanzar comandos a una hora determinada. Por ejemplo:
$TA,T=00.05,'$VS,''W L'''