martes, 16 de diciembre de 2008

Memoria para trabajos batch

En el articulo anterior se explicaba como arrancar los subsistemas QBATCH y QINTER cambiando el subsistema de control a QCTL. Doy por supuesto que tenemos el ajuste de rendimiento del sistema activado.

Por omisión el subsistema QBATCH corre en el pool de memoria *BASE, esta configuración mezcla trabajos de sistema con nuestros trabajos por lotes, que posiblemente tienen unas necesidades de ejecución muy diferentes.

¿Como podemos asignar una memoria especial para nuestros trabajos por lotes en el subsistema QBATCH?, pues es sencillo:
  1. Debemos asignar memoria a un pool de memoria compartido, habitualmente para los trabajos del QBATCH se utiliza el *SHRPOOL1, calcular un tamaño mínimo para el pool (400 p.e. después se ajustara) y un nivel de actividad (numero trabajos activos al mismo tiempo en el pool, 10 p.e.) y ejecutar:
  2. CHGSHRPOOL POOL(*SHRPOOL1) SIZE(400) ACTLVL(10) PAGING(*CALC) TEXT('Batch jobs pool')
  3. Después añadir, al subsistema QBATCH, como segundo pool de memoria el *SHRPOOL1:
  4. CHGSBSD SBSD(QBATCH) POOLS((2 *SHRPOOL1))
  5. Una vez hecho, debemos cambiar el direccionamiento para que los trabajos que se sometan en este subsistema utilicen el segundo pool de memoria:
  6. CHGRTGE SBSD(QSYS/QBATCH) SEQNBR(9999) POOLID(2)
  7. A partir de este instante los trabajos que se sometan en el subsistema QBATCH utilizaran el pool de memoria *SHRPOOL1.
  8. El ajuste automático de rendimiento cambiará el tamaño de ese pool y su nivel de actividad según las necesidades de los trabajos, de la disponibilidad de recursos y de los parámetros que le indiquemos en la gestión de pools (WRKSHRPOOL).
Para más información podemos consultar los artículos:
Memoria para subsistema
Asignar prioridad automáticamente

lunes, 15 de diciembre de 2008

Subsistema de Control

Nuestro sistema iSeries (AS400) viene con dos configuraciones estándar de subsistema de control para la gestión de trabajos.

Esta configuración se controla con el valor de sistema QCTLSBSD, podemos visualizarlo con DSPSYSVAL SYSVAL(QCTLSBSD).

En los nuevos sistemas viene por defecto como QBASE, en este caso solo arranca unos pocos subsistemas (QSYSWRK, QUSRWRK, QSERVER, QSPL) y la gestión de rendimiento es más difícil, ya que casi todos los trabajos corren en el mismo pool de memoria.

La otra configuración estándar (que viene de los tiempos del S/38) es utilizar el subsistema QCTL, para activarlo solo hemos de cambiar el valor del sistema QCTLSBSD con:
CHGSYSVAL SYSVAL(QCTLSBSD) VALUE('QCTL QSYS ')

Para que el cambio se active deberemos realizar IPL del sistema, por lo tanto deberemos planificar este cambio para cuando sea posible hacerlo.

Ahora cuando arranquemos el sistema tendremos el subsistema de control QCTL en lugar del QBASE. Ademas deberemos incluir en nuestro programa de inicio (valor de sistema QSTRUPGM) el arranque de los subsistemas QBATCH (para trabajos por lotes) y QINTER (para trabajos interactivos) si es que lo hemos modificado.

Ya de paso podemos activar el ajuste automático de rendimiento del sistema con:
CHGSYSVAL SYSVAL(QPFRADJ) VALUE('2')
Este cambio indica al sistema que haga el ajuste de rendimiento en IPL y dinámicamente y entra en vigor inmediatamente.

Este ajuste incluye entre otros:
- Tamaño memoria
- Niveles de actividad
- Paginación

Para una información más detallada podemos consultar el documento Experience Report

martes, 2 de diciembre de 2008

Cambiar inicio de sesión

Como cambiar la pantalla de inicio de sesión del AS400.

Primero hemos de tener en cuenta que:
  • El inicio de sesión se asocia a un subsistema, por tanto podemos tener, para algunos subsistemas, diferentes pantallas de inicio de sesión.
  • No es buena idea cambiar la pantalla del subsistema QCTL.
  • También deberíamos crear la nueva pantalla en una biblioteca del sistema, como la QGPL, para evitar problemas en caso de restaurar el sistema.
Una vez tengamos claro los puntos anteriores, podemos continuar con el procedimiento:
  1. Crearemos la nueva pantalla tomando como base la del fuente ubicado en QGPL/QDDSSRC.QDSIGNON, la podemos copiar como MYSIGNON.
  2. CPYSRCF FROMFILE(QGPL/QDDSSRC) TOFILE(QGPL/QDDSSRC) FROMMBR(QDSIGNON) TOMBR(MYSIGNON)
  3. Editar el nuevo archivo de pantalla (tipo DSPF) con el PDM, o el SDA.
  4. Si lo que queremos es añadir un texto tipo ASCII Art, puede que nos sea más fácil añadirla con el SDA.
  5. Hemos de respetar todos los campos, si no queremos mostrarlos, los podemos configurar como ocultos, con la columna Use = H o con las palabras clave DSPATR(PR) y DSPATR(ND).
  6. Lo más habitual es solo dejar los campos de entrada Usuario (USERID) y Contraseña (PASSWRD) y de salida con el nombre del Sistema, Subsistema y dispositivo (SYSNAME, SBSNAME, DEVNAME).
  7. Una vez creada la nueva pantalla de inicio de sesión, podemos probarla creando un subsistema especial, ¿como hacerlo? ver la entrada publicada "Asignar prioridad automáticamente" para crear un subsistema SPECIAL.
  8. CHGSBSD SBSD(QGPL/SPECIAL) SGNDSPF(QGPL/MYSIGNON)
  9. Una vez comprobado el nuevo inicio de sesión funciona correctamente, ya podemos cambiar la configuración del subsistema QINTER:
  10. CHGSBSD SBSD(QINTER) SGNDSPF(QGPL/MYSIGNON)
  11. Una vez hecho esto debemos reiniciar el subsistema QINTER, si tenemos usuarios conectados deberemos buscar el momento adecuado para hacerlo.
  12. Esto deberíamos hacerlo desde la consola del sistema:
  13. ENDSBS SBS(QINTER) OPTION(*IMMED)
  14. y a continuación:
  15. STRSBS SBSD(QINTER)
  16. Y ya tenemos nuestra nueva pantalla de signon.

viernes, 28 de noviembre de 2008

Obtener listas objetos en IFS

Como obtener listas de objetos en el Integrated File System del AS400.

Habitualmente sabemos navegar desde la pantalla verde con el mandato
WRKLNK OBJ('/') DETAIL(*EXTENDED) DSPOPT(*ALL) pero si desde un programa queremos obtener una lista de archivos del directorio '/home/temp' (por ejemplo) no tenemos un mandato para hacerlo directamente y hemos de volcarlo a spool y leer ese spool o utilizar una API del sistema.

Una solución sencilla, si esta instalado el entorno QSHELL (opción 30 del 5722SS1) , es ejecutar mandatos tipo UNIX, pongo algunos ejemplos de los que se puede conseguir:

Obtener contenido del directorio /home/temp (en el archivo MYLIB/LISTDIR):
  • QSH CMD('ls /home/temp/* >/qsys.lib/mylib.lib/listdir.file/listdir.mbr')
Obtener lista de directorios del sistema (atención puede tardar horas):
  • QSH CMD('find / -type d |grep -v "QSYS.LIB" |grep -v "QNTC">/qsys.lib/mylib.lib/listdir.file/listdir.mbr')
o también:
  • QSH CMD('ls -alR / |grep "/" |grep -v "l" |grep -v "QSYS.LIB">/qsys.lib/mylib.lib/listdir.file/listdir.mbr')

martes, 18 de noviembre de 2008

Prompt selectivo de mandato

La función del prompt selectivo en los mandatos es útil en un programa CL interactivo. Con esta función podemos ahorrarnos algún paso de parámetro en el programa.

El prompt selectivo se utiliza insertando caracteres especiales delante de los parámetros de los mandatos, los valores permitidos son:
  • ?? Muestra el prompt del parámetro y permite cambiarlo.
  • ?* Muestra el prompt del parámetro pero no permite cambiarlo
  • ?- Oculta el parámetro.
  • ?< Muestra el prompt del parámetro y permite cambiarlo, pero el valor por omisión es el que le enviamos desde el programa.
  • ?& Solo se muestra el prompt del parámetro si se pulsa F10 y permite cambiarlo.
  • ?% Solo se muestra el prompt del parámetro si se pulsa F10, pero no permite cambiarlo.
Ademas si colocamos un ? delante del mandato nos modifica el comportamiento de los prompt selectivos:
  • blanco Muestra solo los parámetros con prompt selectivo, no permite F9.
  • ? Muestra prompt del mandato y permite cambiar parámetros y pulsar F9.
Un ejemplo para ilustrar esta función, queremos crear un programa que restaure objetos desde un *SAVF, pero queremos dejar al usuario la elección de ciertos parámetros, de otros informarle de su valor y ocultar el resto aunque estén definidos, para ello usaremos el código siguiente:

RSTOBJ ??OBJ(*ALL) SAVLIB(LIBSAV) ?-DEV(*SAVF) OBJTYPE(*ALL) ?*SAVF(LIBSAVF/SAVF) ??RSTLIB(LIBSAV2)

Al ejecutar el programa obtendremos la siguiente pantalla:


De esta forma dejamos al usuario cambiar que objetos quiere restaurar y en que biblioteca, aunque le mostramos una por omisión y si la deja en blanco el prompt vuelve a mostrar el valor que le hemos pasado desde programa; también puede ver que archivo de salvar se utilizará, pero no el resto de parámetros, ni aun pulsando F10 o F9.

Veamos que ocurre si añadimos el carácter ? delante del mandato RSTOBJ, también añadimos ?- en el parámetro DEV :

? RSTOBJ ??OBJ(*ALL) SAVLIB(LIBSAV) ?-DEV(*SAVF) OBJTYPE(*ALL) ?*SAVF(LIBSAVF/SAVF) ??RSTLIB(LIBSAV2)


Ahora vemos el resto de parámetros obligatorios que no se mostraban antes, excepto DEV que tiene la opción de prompt ?-, y además podemos pulsar F10 para ver el resto de parámetros.

Para controlar el prompt de los parámetros opcionales se utiliza ?% y ?&, aunque puede complicarnos el programa ya que hay parámetros que pueden depender de si usamos otros.

Nota: Si usamos el prompt selectivo también debemos de incluir la siguiente instrucción por si nos pulsan F3=Salir o F12=Cancelar:
MONMSG MSGID(CPF6801) /* F3 o F12 */

Más información en iSeries Information Center

domingo, 2 de noviembre de 2008

Asignar prioridad automáticamente

Como asignar una prioridad automáticamente para ciertos trabajos, o aplicaciones.

Supongamos que tenemos unos trabajos que queremos que tengan cierto tipo de prioridad (alta o baja) en la ejecución, habitualmente se utilizan los parámetros RUNPTY y TIMESLICE, para ello habremos de crear una clase especial para nuestros trabajos y es recomendable también crear un subsistema especial para dichos trabajos.

El procedimiento a seguir para crear este entorno especial:
  1. Crear la cola de trabajos asociada al subsistema:
  2. CRTJOBQ JOBQ(QGPL/SPECIAL) TEXT('Job queue for specials jobs Subsystem')
  3. Crear el subsistema:
  4. CRTSBSD SBSD(QGPL/SPECIAL) POOLS((1 *BASE) (2 *SHRPOOL1)) MAXJOBS(*NOMAX) TEXT('Subsystem for specials jobs')
  5. Con esto conseguimos que el trabajo, de tipo subsistema, se ejecute en el pool de memoria base y el resto de trabajos del subsistema se ejecutaran en el pool de memoria *SHRPOOL1.
  6. Añadir la cola de trabajos al subsistema:
  7. ADDJOBQE SBSD(QGPL/SPECIAL) JOBQ(QGPL/SPECIAL) MAXACT(*NOMAX) SEQNBR(10)
  8. Poner *NOMAX, o el numero máximo de trabajos, que queremos que se ejecuten por esa cola, el numero de secuencia es importante por si tenemos más de una cola de trabajos.
  9. Crear la nueva clase:
  10. CRTCLS CLS(QGPL/SPECIAL) RUNPTY(25) TIMESLICE(10000) PURGE(*NO) TEXT('Class for subsystem of special jobs')
  11. Asignar las entradas de direccionamiento para solo los trabajos batch que queramos usen la nueva clase:
  12. ADDRTGE SBSD(QGPL/SPECIAL) SEQNBR(10) CMPVAL('SPECIAL') PGM(QCMD) CLS(QGPL/SPECIAL) POOLID(2)
  13. Añadir entradas de direccionamiento para el resto de trabajos:
  14. ADDRTGE SBSD(QGPL/SPECIAL) SEQNBR(9999) CMPVAL(*ANY) PGM(QCMD) CLS(*LIBL/QBATCH) POOLID(2)
  15. Con estas dos entradas de direccionamiento conseguimos que:
  16. Los trabajos que, en la descripción de trabajo, envían como direccionamiento el valor RTGDTA('SPECIAL') usaran la clase QGPL/SPECIAL que les asignará un RUNPTY de 25 y un TIMESLICE de 10.000.
  17. El resto de trabajos usará la clase QGPL/QBATCH, que les asigna un RUNPTY de 50 y un TIMESLICE de 5.000.
  18. En ambos casos los trabajos se ejecutaran por el POOLID 2, o sea en este caso en el *SHRPOOL1 (ver paso 5).
  19. A continuación creamos una nueva descripción de trabajo, o modificar la que queramos usar, para que los trabajos se sometan por el nuevo subsistema:
  20. CRTJOBD JOBD(QGPL/SPECIAL) JOBQ(QGPL/SPECIAL) TEXT('Job description for special jobs') RTGDTA('SPECIAL')
  21. También podemos someterlos con SBMJOB, pero entonces habrá que acordarse de comprobar y modificar manualmente el parámetro RTGDTA en el mandato SBMJOB, en caso contrario usaran la clase por omisión asignada a *ANY.
  22. Si además queremos usar el mismo subsistema para que se conecte alguna pantalla tendremos de:
  23. Añadir el pool de memoria interactivo al subsistema:
  24. CHGSBSD SBSD(QGPL/SPECIAL) POOLS((1 *BASE) (2 *SHRPOOL1) (3 *INTERACT))
  25. Añadir una entrada de direccionamiento para los trabajos interactivos:
  26. ADDRTGE SBSD(QGPL/SPECIAL) SEQNBR(20) CMPVAL('QCMDI') PGM(QCMD) CLS(*LIBL/QINTER) POOLID(3)
  27. Añadir el nombre de dispositivo de pantalla que tendrá acceso al subsistema:
  28. ADDWSE SBSD(QGPL/SPECIAL) WRKSTN(Device_name)
  29. Con esto conseguimos que los trabajos interactivos se les asigne los valores de la clase QINTER y que son de RUNPTY 20 y un TIMESLICE de 2.000.
  30. Además se ejecutaran en el pool de memoria para trabajos interactivos (*INTERACT), optimizando de esta forma el funcionamiento del ajuste automático de rendimiento del sistema:
  31. Ahora solo nos queda:
  32. Asignar memoria al pool compartido *SHRPOOL1, si no lo estamos usando (podemos comprobarlo con WRKSHRPOOL):
  33. CHGSHRPOOL POOL(*SHRPOOL1) SIZE(256) ACTLVL(1)
  34. Finalmente arrancar el nuevo subsistema:
  35. STRSBS SBSD(QGPL/SPECIAL)
  36. El tamaño del pool y el nivel de actividad se irán ajustando automáticamente si tenemos el ajuste de rendimiento del sistema activado:
  37. DSPSYSVAL SYSVAL(QPFRADJ)


Nota:
Si queremos deshacer la asignación de memoria en *SHRPOOL1 ejecutar el mandato CHGSHRPOOL POOL(*SHRPOOL1) SIZE(*NOSTG)


¿Como podemos controlar la memoria asignada a estos trabajos y de esta forma controlar el ajuste automático del sistema?, entonces habéis de leer la entrada Memoria para subsistema publicada anteriormente.

viernes, 10 de octubre de 2008

Sincronizar la hora del AS400

Para ello utilizaremos el servicio SNTP (Simple Network Time Protocol), este servicio nos sincroniza la hora del equipo con la de un servidor de hora, que puede estar en nuestra red o en Internet.

En nuestro AS400 tenemos disponible este servicio desde la V5R2, y es funcional (o sea que cambia la hora del reloj automáticamente) a partir de la V5R4. Para configurar el servicio SNTP en el AS400 ejecutar el mandato CHGNTPA con los parámetros:
CHGNTPA RMTSYS('direccion_servidor_hora') AUTOSTART(*YES) POLLITV(60) MINADJ(100) MAXADJ(20) ACTLOG(*CHANGE)

Además debemos activar la opción de ajuste automático de la hora:
CHGSYSVAL SYSVAL(QTIMADJ) VALUE(QIBM_OS400_SNTP)

También debemos configurar nuestra zona horaria para ello ejecutar:
WRKSYSVAL SYSVAL(QTIMZON), el valor para Europa es QP0100CET4
Offset . . . . . : +02:00
Full name . . . : Central European Daylight Saving Time
Abbreviated name : CEST

Podemos pulsar F4 para vez las zonas disponibles.

Atención: Cuando realicemos este cambio, inmediatamente después comprobar la hora del sistema, no sea que se le ocurra ajustarse en ese momento al horario de verano/invierno.

Para arrancar el servicio de sincronización de hora la primera vez, después debería ser automático ya que en la configuración del servicio hemos indicado AUTOSTART(*YES) o sea que se arrancara con el sistema :
STRTCPSVR SERVER(*NTP)

Para detener el servicio ejecutar: ENDTCPSVR SERVER(*NTP)

Podemos consultar la actividad de este servicio buscando el mensaje TCP9105 en el log del sistema (DSPLOG MSGID(TCP9105)), el mensaje nos indica donde esta el log del servicio (uno por día), normalmente ubicado en el directorio /QIBM/USERDATA/OS400/TCPIP/NTP/

Nota: Revisar esta carpeta periódicamente, ya que se van acumulando los logs y no se vacían automáticamente.

martes, 7 de octubre de 2008

Modificar menu PetSis

Para modificar el menú de Petición de Sistema (tecla PetSis) hemos de cambiar el mensaje CPX2313 para modificar los mandatos que llama el sistema cuando se pulsa esta tecla.
La opción "1. Visualizar inicio de sesión para trabajo alternativo" no se puede modificar, o sea que la primera opción que se puede modificar es "2. Finalizar petición anterior " que corresponde al mandato ENDQRS del texto del mensaje.
El valor por omisión del mensaje se puede ver con el mandato:
DSPMSGD RANGE(CPX2313) MSGF(QSYS/QCPFMSG)




Por ejemplo, Como modificar la opción "3.Visualizar trabajo actual" para utilizar el comando WRKJOB, en lugar del DSPJOB, y de paso disponer de una línea de mandatos, pero solo según el tipo de usuario, ya que no queremos que ningún usuario normal tenga acceso a la línea de mandatos en mitad de una aplicación.

Para ello seguiremos el siguiente procedimiento:
  1. Crearemos el programa CL DSPJOB2CL
  2. Crearemos el mandato DSPJOB2 que llama al programa DSPJOB2CL
  3. Este programa comprueba el tipo de usuario, si es *SECOFR o *PGMR o *SYSOPR ejecuta el mandato WRKJOB, en caso contrario ejecuta el mandato DSPJOB (como hasta ahora).
  4. Finalmente cambiamos el texto de mensaje CPX2313 para que ejecute DSPJOB2 en lugar de DSPJOB: CHGMSGD MSGID(CPX2313) MSGF(QSYS/QCPFMSG) MSG('ENDRQS DSPJOB2 DSPMSG SNDMSG SIGNOFF DSPMSG DSCJOB DSPWSUSR ENDRDBRQS ')
  5. ¡¡ Respetar espacios en blanco en el cuerpo del mensaje!!

Notas:
  • El código de DSPJOB2 lo podemos bajar de aquí.
  • Si tenemos lenguajes secundarios instalados, deberemos realizar el mismo cambio para todas las bibliotecas QSYSnnnn.
  • Deberemos revisar este mensaje cada vez que actualicemos el sistema operativo, o que alguna ptf modifique el archivo de mensajes QCPFMSG.

Calculadora en ventana

Puesta al día de la utilidad CALCUL que nos muestra, en una ventana en modo texto, una calculadora. La podemos incluir en nuestras aplicaciones de pantalla verde, cuando tenga sentido que la puedan utilizar, o desde la línea de mandatos.



La ayuda la tenemos pulsando la tecla F1.

El código de esta utilidad lo podemos bajar de aquí.

jueves, 2 de octubre de 2008

Memoria para subsistema

Como reservar memoria y asignar una prioridad automáticamente para ciertos trabajos o aplicaciones en uno o más subsistemas utilizando la memoria compartida.

Supongamos que tenemos unos trabajos que queremos que tengan reservada cierta cantidad de memoria solo para ellos y cierto tipo de prioridad (alta o baja) en la ejecución (habitualmente los parámetros RUNPTY y TIMESLICE).

En esta entrada explicare como reservar cierta cantidad de memoria para un subsistema.

  1. Crear un subsistema para ese tipo de trabajo es buena idea, así separamos el consumo de memoria y el ajuste automático del sistema trabaja mejor (QPFRADJ).
  2. Doy por supuesto que tienes el ajuste automático del sistema activado (QPFRADJ 2 o 3)
  3. Puedes asignarle a ese pool una cantidad de memoria, que puede ser variable o fija. Si la quieres siempre fija lo indicaras cuando creas el subsistema (CRTSBSD)
  4. Para crear un pool de memoria haz WRKSHRPOOL y asigna memoria, por ejemplo, al *SHRPOOL2, habitualmente el *SHRPOOL1 se utiliza para trabajos en el subsistema QBATCH, aunque no viene definido por omisión en el sistema.
  5. Después debes cambiar la descripción del nuevo subsistema para que utilice ese nuevo pool de memoria, normalmente yo recomiendo poner 2 pools el *BASE en primer lugar y *SHRPOOL2 en segundo lugar.
  6. Después deberás crear nuevas clases (CRTCLS) para el nuevo subsistema, que utilicen el segundo pool de memoria del subsistema y asignarlas a las entradas de direccionamiento del mismo (CHGRGTE), esto lo explicare en otro howto.
  7. Con esto conseguimos que el trabajo subsistema, corra en el pool *BASE y el resto de trabajos, dentro del subsistema, en el *SHRPOOL2.
  8. Para el ajuste de memoria del *SHRPOOL2, haz WRKSHRPOOL y pulsa F11 (otra vista), en las columnas que ves, puedes definir que porcentaje de memoria mínimo y máximo quieres que se lleven los trabajos de ese pool, si ponemos el mismo porcentaje en min y max lo que conseguimos es dejar fijo el tamaño de la memoria utilizada por ese pool.
  9. Esto creo que es mejor que asignar memoria fija al subsistema (paso 3) ya que en caso de equivocarnos solo hemos de cambiar el porcentaje y el ajuste auto del sistema hará el resto. De la otra forma hay que parar el subsistema.
  10. ¿Como calcular el tamaño de memoria que vas a necesitar?, pues es difícil, seguramente los trabajos están más tiempo esperando o leyendo disco, que utilizando memoria y CPU, pero si tiene que ver con la cantidad de trabajos que tenemos activos y en RUN en el subsistema. Mi recomendación es partir de un valor de tamaño de pool conocido, tirando a alto, y observar la paginación de ese pool de memoria (DSPSYSSTS) , si aparecen trabajos en estado INEL, indica que falta memoria en ese pool, ir añadiendo memoria al pool hasta que veamos que ya no aparecen trabajos en INEL u estado intermedios.
  11. Una recomendacion, para hacer estos ajustes, es mejor que no lo hagas en tu hora punta (mas que nada para que no te lleguen llamadas de usuarios) y tambien es mejor desactivar, mientras haces la prueba, el ajuste automático del sistema (QPFRADJ = 0) ya que en caso contrario te puede distorsionar el resultado.
  12. También debes saber que si tu proceso utiliza SQL el optimizador de SQL puede que decida crear un nuevo plan de acceso si ve que ha cambiado el tamaño del pool, eso no debería suponer un problema, pero en algunas instalaciones se traduce en un peor tiempo de respuesta de la aplicación, ya que reconstruye el plan de acceso demasiado a menudo.

jueves, 25 de septiembre de 2008

Duración de un RCLSTG

Como averiguar la duración del ultimo proceso de Reclaim Storage (RCLSTG) realizado en el sistema, para ello ejecutar el mandato:
DSPDTAARA DTAARA(QUSRSYS/QRCLSTG)

Tal como se ve en la imagen el ultimo RCLSTG se ejecuto desde las 05:45:15h hasta las 09:51:46 del 01/06/2008, por tanto el proceso duro 4h 6min. 31seg.

En el histórico del sistema se graba el mensaje CPC8208 "Proceso de RCLSTG terminado" que nos informa de la cantidad de objetos procesados y suprimidos.

Para imprimir el histórico del sistema con los mensajes de como ha ido:

DSPLOG PERIOD((hora_inicio fecha_inicio) (hora_fin fecha_fin)) OUTPUT(*PRTSECLVL) MSGID(CPC8208 CPF3120 CPC3308 CPF8240 CPF8262 CPF8260 CPFA914 CPI8202 CPI8A10 CPC8A21 CPC8A22)

Para ver el contenido de la biblioteca QRCL , donde van a parar los objetos recuperados por el RCLSTG, ejecuta el mandato:

DSPLIB LIB(QRCL)

Esto es conveniente porque se puede haber recuperado algún objeto de tamaño considerable y que seguramente se debería eliminar.

De paso recordar que se debería pasar un RCLSTG periódicamente o, cuando ha habido una caída del sistema, y es casi obligatorio pasarlo antes de la instalación de una nueva release del sistema operativo.

También tener en cuenta que a partir de la V5R4 (algunos antes) tenemos algunos mandatos para reclamar cosas sin tener el sistema restringido:

  • RCLDBXREF Reclaim DB Cross-Reference
  • RCLDLO Reclaim Document Lib Object
  • RCLLIB Reclaim Library
  • RCLLNK Reclaim Object Links
  • RCLOBJOWN Reclaim Objects by Owner
  • RCLSPLSTG Reclaim Spool Storage
  • RCLSTG Reclaim Storage

miércoles, 10 de septiembre de 2008

Cuenta iSeries gratuita

Como no siempre disponemos de un sistema AS400, cuantas veces nos hemos quedado con las ganas de probar algo en un sistema que no fuera el nuestro, o cuando no estamos en nuestro trabajo, o simplemente por aprender cosas nuevas.

Pues bien existe la web de Innovative Systems que nos da esa posibilidad


Solo hemos de registrarnos y esperar que nos envíen el usuario y la contraseña para acceder a un sistema AS400 remoto a través de Internet.

Espero que os sirva de ayuda :o)

miércoles, 3 de septiembre de 2008

Nefarious Masqueraders

Un articulo que llamo mi atención, hace tiempo, es el titulado "Nefarious Masqueraders" publicado en la web de The AS/400 School.

En él, se nos introduce en las técnicas para introducirse en un AS/400 y que nos puede servir, como administradores de sistemas, para ser conscientes de las vulnerabilidades del sistema y, de esta forma, poder tomar medidas para proteger mejor nuestros sistemas.

martes, 24 de junio de 2008

Lógicos en diferente biblioteca

Una manera rápida de como averiguar qué archivos lógicos no están en la misma biblioteca que sus archivos físicos, es mediante la siguiente instrucción SQL, que accede al fichero QSYS/QADBFDEP :

SELECT DbFLib, DbFFil, DbFLDp, DbFFDp

FROM Qsys/QADbFDep

WHERE DbFLib <> DbFLDp

ORDER BY DbFLib, DbFFil, DbFLDp, DbFFDp


Una de las razones para controlar este tipo de situación es que, en caso de restauración de las bibliotecas, debe hacerse en el orden correcto, ya que sino podemos dejar de restaurar algún archivo lógico, y nos obligaría a realizar una segunda restauración con el parámetro *NEW.
Esto también se aplica a archivos con restricciones, aunque en este caso es recomendable no tener archivos dependientes en diferentes bibliotecas y evitemos, siempre que podamos, estas situaciones.

Por ejemplo, si restauramos desde las copias de seguridad, realizadas con *ALLUSR, las bibliotecas están salvadas en la cinta en orden alfabético, pero el archivo LIB1/INDEX1 no se restaurara, porque no encuentra el archivo físico FILE1, del que depende, ya que esta en la biblioteca LIB2 que aun no se ha restaurado.

Library File Type
LIB1 INDEX1 LF

LIB2 FILE1 PF

jueves, 19 de junio de 2008

Gestionar receptores de diario

Estrategias de como gestionar receptores de diario

El tema es complicado, ya que depende mucho de los requerimientos de la aplicación, de seguridad, de replicación, etc..., para poder aplicar una estrategia de gestión de los receptores de diario. Intentare explicar los casos que se me ocurren en nuestra estrategia, para que sirvan de ejemplo.

Dejo aparte la gestión de los receptores del propio sistema, que habitualmente se autogestionan en tiempo de IPL, si no vamos a realizar IPL en muchos tiempo puede que tengamos también que incluirlos en nuestra estrategia, no sin antes verificar y consultar con IBM, si fuese necesario, que impacto puede tener en el sistema.

  • Caso1: En los sistemas de producción los receptores de diario están gestionados por MIMIX (u otra herramienta de replicación) y se mantienen en linea unos días y después se eliminan automáticamente por el software de replicación y si se han salvado previamente a cinta.
  • Caso2: En los sistemas de producción que no tienen MIMIX, los receptores se van salvando a cinta y eliminando periódicamente (según el sistema).
  • Caso3: En los sistemas de desarrollo (que nunca tienen MIMIX) los receptores los elimina automáticamente el sistema, cuando ya no hay ningún ciclo de compromiso pendiente y aunque no estén salvados a cinta, excepto los de auditoria del sistema (QAUDJRN) que se eliminan una vez salvados a cinta.
  • Caso4: Poner la vuestra...
Formas de detectar si hay ciclos largos de commit abiertos:
  • Caso1: MIMIX detecta en que ciclo de commit estamos "encallados" y que nos retrasa la hora de aplicación de MIMIX, con la utilidad DSPJOBSEC averiguamos rápidamente que trabajo tiene el ciclo de commit abierto y podemos actuar en consecuencia.
  • Caso2: Podemos deducir que con el movimiento normal podemos generar, en una semana (p.e.) 10 receptores de diario, si detectamos que hay más receptores de lo habitual es posible que hayan ciclos de commit abiertos.
  • Caso3: Este es el más fácil, como mucho solo puede haber un receptor conectado al diario, ya que el resto el sistema y los va eliminando automáticamente, por tanto si vemos que hay más, es (casi) seguro que algún trabajo tiene un ciclo de commit abierto.
Causas de los ciclos de commit largos:
  • Programas que no hacen commit (mala programación), o se meten en un bucle.
  • Sentencias SQL. o QMQuery, sin ciclos de compromiso de larga ejecución; deberían evitarse o analizar si es posible lanzarlos con WITH NC (sin commit) aunque eso a veces no es posible si queremos tener consistencia en la base de datos.
  • A veces detectamos algún CPYF que tiene ciclos de commit (no recuerdo bien como fue).
  • Programadores que están debugando, abren un ciclo de commit, les casca el programa y van a por otra cosa, o hacen petición de sistema, o se van a comer, y el ciclo de commit se queda abierto hasta que no hacen signoff.
  • Otras ?? (que cada uno añada las suyas)
Como detectar "automáticamente" si hay ciclos de commit abiertos:
  • Estuve investigando usar el mandato WRKCMTDFN (a partir V5R4) pero de momento no puedo diferenciar los ciclos de commit abiertos con registros pendientes de los que no, aunque si se ve por pantalla con F11, a lo mejor dándole al "coco" mas tiempo....
  • De momento se nos ocurrió: Contar el numero de receptores de diario de cada diario.
    • DSPOBJD OBJ(*ALL/*ALL) OBJTYPE(*JRNRCV) OUTPUT(*OUTFILE) OUTFILE(QTEMP/JRNRCV) OUTMBR(*FIRST *REPLACE)
    • Doy por supuesto que en una biblioteca no hay mas de un diario, que podría ser.
    • Deberemos omitir el diario de auditoria y los de sistema, habitualmente empiezan por Q* y en bibliotecas que también empiezan por Q*.
  • Otra estrategia seria hacer:
    • DSPOBJD OBJ(Mylib/Myjrn1) OBJTYPE(*JRNRCV) OUTPUT(*OUTFILE) OUTFILE(QTEMP/JRNRCV) OUTMBR(*FIRST *REPLACE)
    • DSPOBJD OBJ(Mylib/Myjrn2) OBJTYPE(*JRNRCV) OUTPUT(*OUTFILE) OUTFILE(QTEMP/JRNRCV) OUTMBR(*FIRST *ADD)
    • DSPOBJD OBJ(MylibX/MyjrnX) OBJTYPE(*JRNRCV) OUTPUT(*OUTFILE) OUTFILE(QTEMP/JRNRCV) OUTMBR(*FIRST *ADD)
    • Después contamos los receptores de cada diario, o lo hacemos por cada biblioteca cada vez, en fin múltiples posibilidades según se adapte a nuestra estrategia.
  • Una vez sabemos que diario tiene un numero "anormal" de receptores, dejo para cada uno lo que es anormal, seguimos con:
Como detectar "automáticamente" que trabajo tiene un ciclo de commit abierto:
  • Volcamos el contenido del diario, de las entradas relacionadas con los ciclos de commit, a fichero (esto puede tardar):
    • DSPJRN JRN(Mylib/MyJrn) RCVRNG(*CURCHAIN) JRNCDE((C)) OUTPUT(*OUTFILE) OUTFILE(QTEMP/DSPJRN)
  • Después ejecutamos la sentencia SQL siguiente (esto es la "madre del cordero" ¡¡ gracias Inma!!):
WITH aa AS (SELECT * FROM dspjrn WHERE joentt = 'SC'), bb AS
(SELECT * FROM dspjrn WHERE joentt <> 'SC') SELECT aa.joseqn,
aa.jodate, aa.jotime, aa.jonbr, aa.jouser, aa.jojob, aa.joccid from
aa LEFT EXCEPTION JOIN bb ON aa.joccid = bb.joccid
  • Esta SELECT nos devolverá la lista de trabajos con un ciclo de commit abierto, y la hora de del ciclo de commit, ya solo nos queda ir al trabajo a ver que pasa.
Espero que, al menos, os sirva como base para detectar esos trabajos que nos pueden fastidiar, ya que normalmente los ciclos de commit largos le sientan como una "patada" al OS/400, y ya no digo si hay que hacer un rollback.

Por poner un ejemplo: Un programador un viernes y en un sistema de desarrollo (que estan 24x7) hace un call a un programa que se mete en un bucle, con un ciclo de commit abierto, haciendo updates del mismo registro como un "poseso", se cae su sesión y como no puede volver a entrar, se marcha de fin de semana. El lunes se descubre que hay una sesión en RUN todo el tiempo, se hace un ENDJOB *IMMED, con millones de cambios comprometidos en el mismo ciclo de commit. El trabajo tarda como 2 horas en empezar a hacer el rollback y 2 días en terminarlo. A todo esto la ocupación en disco ha ido subiendo, porque el sistema no elimina los receptores de diario desconectados, y salvados, ya que hay un ciclo de commit con transacciones pendientes. En fin que tenemos maquinas potentes, que si no andamos con cuidado podemos cargarnos el sistema.

domingo, 25 de mayo de 2008

Porcentaje rollback realizado

Procedimiento para ver el porcentaje de Rollback que ya ha realizado un trabajo:
  • Ejecutar mandato DSPJOB JOB(num_job/user_job/name_job)
  • Seleccionar opcion "16. Display commitment control status, if active"
  • Opcion "5=Display"
  • Pulsar "F6=Display resource status"
  • Pulsar AvPag.
  • Seleccionar opcion "1=Select" en el recurso "Journal"
  • Finalmente pulsar "F11=Display rollback status"

lunes, 5 de mayo de 2008

Restaurar archivos QHST

Como restaurar los archivos históricos desde una cinta de SAVSYS, para ello seguir el siguiente procedimiento:
  1. Cargar la cinta donde realizamos el SavSys
  2. DSPTAP DEV(TAP01) DATA(*SAVRST)
  3. Ir pulsando Intro hasta encontrar la secuencia donde están los archivos QHST.
  4. Anotar numero secuencia y ID etiqueta archivo (p.e. Q5722SS1510310090)
  5. Ejecutar RSTOBJ OBJ(QHST*) SAVLIB(QSYS) DEV(TAP01) OBJTYPE(*FILE) VOL(Q5722SS1510310090) SEQNBR(33)

domingo, 6 de abril de 2008

Mejorar teclado emulacion 5250

El IBM Client Access incluye el emulador de pantalla verde 5250 Personal Communications.


La configuración por omisión no incluye ciertas funciones que los usuarios de los sistemas operativos de ventanas encontramos a faltar, como son las teclas Inicio para ir al Inicio del Campo, Fin para ir al Fin del Campo, Ctrl+C para Copiar un texto seleccionado o Ctrl+V para Pegar un texto; Ctrl+X no tiene sentido en una emulación 5250.


Como hacer esta personalización de teclado de la emulación, pues seguir los siguientes pasos:
  1. Bajaros el archivo as400_mejorado.kmp y lo guardais en la carpeta C:\Program Files\ibm\Client Access\Emulator\Private o donde os parezca mejor.
  2. Desde la emulación de pantalla del Personal Communications, pulsais el icono Keyboard button o Edit, Preferences, Keyboard, Customize.
  3. Despues File, Open y seleccionar el archivo de configuración de teclado que os habeis bajado.
  4. A continuación salvar la nueva configuración.
A partir de ese momento ya podreis utilizar el teclado de la emulación de forma mas parecida a la que utilizais con un sistema operativo grafico de ventanas.


Esta configuración de teclado también convierte la tecla grande de Intro, como un Intro y no como Salida de Campo, esta la muevo a la tecla Ctrl de la derecha.

miércoles, 2 de abril de 2008

La clave de las claves

La elección de un buena contraseña, la palabra clave que franquea el acceso a un ordenador, es esencial para salvaguardar la seguridad de los datos que contiene. Los expertos recomiendan las siguientes reglas básicas:
  1. Una contraseña ha de ser sencilla. Desde luego, la clave TMXKQGSW resulta bastante segura frente a hackers que lo intentan al azar, pero es muy difícil de recordar.
  2. Una contraseña no debe tener significado. Las palabras con significado son las más fáciles de reventar. Esto no excluye que sean sencillas de memorizar. Ejemplos: ZAZAMELI, PERPOLAS, RATOGARU.
  3. Una contraseña hay que memorizarla, no apuntarla. Quien no se fíe demasiado de su memoria a largo plazo, puede apuntar su palabra clave, pero nunca de manera que un extraño pueda reconocerla como tal. Así, nunca se la ha de escribir en el listín telefónico bajo CLAVE, SECRETO u ORDENADOR. Es mejor garabatearla en la agenda junto al recordatorio del cumpleaños de la abuela. En ningún caso se debe dejar la nota escrita cerca del ordenador, bajo el teléfono o pinchada en el panel de corcho.
  4. De vez en cuando conviene cambiar la contraseña. Por si acaso alguien no autorizado ya lo conoce pero todavía no se ha decidido a usarlo. Tampoco es preciso cambiarlo muy a menudo, podría causarnos molestas equivocaciones.
  5. Una contraseña se teclea en privado. Al introducir la clave antes de comenzar una sesión de trabajo, hay que asegurarse de que nadie mire por encima del hombro. Las personas de confianza hacen honor a su nombre respetando la intimidad del propietario de la clave.
  6. Ciertas palabras nunca han de servir de contraseña:
  • Nombres propios y apellidos.
  • Apodos. El propio, jamás, pero tampoco el del perro o el gato.
  • Palabras informáticas, como TEST, SYSTEM, CHECK, BYTE...
  • Fechas de cumpleaños.
  • Cadenas con método: ABCDEFGH, A1B2C3, QWERTY...
  • Palabras de moda: CHUNGO, GUAI, SUPER, TOTAL...
  • Nombres de la mitología, la literatura o ciencia-ficción: Zeus, Quijote, Spock, Frodo...
  • La palabra clave por antonomasia: (ábrete) SESAMO.
Articulo extraído de la revista "Muy Interesante", noviembre 1.989

jueves, 27 de marzo de 2008

De mayúsculas a minúsculas

Como convertir un campo de mayúsculas a minúsculas o viceversa en un programa CL.

Para ello añadimos el siguiente código en nuestro programa, para convertir una variable de 5 caracteres de longitud, y utilizaremos la API QLGCNVCS.

DCL VAR(&VAR1) TYPE(*CHAR) LEN(5)
DCL VAR(&VAR2) TYPE(*CHAR) LEN(5)
DCL VAR(&VARLEN) TYPE(*CHAR) LEN(4) VALUE(X'00000005')
DCL VAR(&CASEU) TYPE(*CHAR) LEN(22) + VALUE(X'00000001000000000000000000000000000000000000')
DCL VAR(&CASEL) TYPE(*CHAR) LEN(22) + VALUE(X'00000001000000000000000100000000000000000000')
DCL VAR(&ERR) TYPE(*CHAR) LEN(4) VALUE(X'00000000')


De mayúsculas a minúsculas llamar a la API con el parámetro &CASEL:
CALL PGM(QLGCNVCS) PARM(&CASEL &VAR1 &VAR2 &VARLEN &ERR)

De minúsculas a mayúsculas llamar a la API con el parámetro &CASEU:
CALL PGM(QLGCNVCS) PARM(&CASEU &VAR1 &VAR2 &VARLEN &ERR)

lunes, 10 de marzo de 2008

Plantilla teclado IBM 3197

Plantilla de teclado del terminal 5250 de IBM modelo 3197



A veces no recordamos como eran los terminales "tontos", aunque el IBM-3197 era de los "espabilados". Esta plantilla es la "chuleta" para acordarnos de las funciones que tenia incorporadas la ALU del terminal, como configurar la dirección twinaxial, tipo de terminal (pantalla, pantalla-pantalla, pantalla-impresora), o las macros, entre otras cosas.

lunes, 25 de febrero de 2008

Imprimir fuente en DIN A-4

Como imprimir un miembro de un archivo de fuentes en formato DIN A-4 y doble cara (si nuestra impresora lo soporta):
  1. Entrar al PDM con el mandato STRPDM
  2. Seleccionar opción "9. Work with user-defined options"
  3. Seleccionar archivo opciones, por omision QGPL/QAUOOPT(QAUOOPT) , pulsar Intro.
  4. Pulsar F6=Create
  5. Opción A4 (por ejemplo)
  6. Introducir en la linea de mandatos:
  7. OVRPRTF FILE(QPSUPRTF) PAGESIZE(102) LPI(9) OVRFLW(102) ALIGN(*YES) FONT(220) PRTQLTY(*DRAFT) PAGRTT(0) DUPLEX(*YES)
  8. Pulsar Intro para guardar la nueva opción del PDM.
Como usar nueva opción A4:
Pulsar la opción A4 delante del miembro que queramos imprimir y después la opción 6=Print, si fuera necesario cambiar el listado a una cola de impresora de hojas.
A partir de pulsar la opción A4 todos los listados que pidamos en esa sesión, se imprimirán en ese formato. Con la opción DUPLEX(*YES) conseguimos imprimir por ambas caras si la impresora lo soporta.

Es posible se tenga que ajustar algún valor para que cuadre con la hoja de nuestra impresora.
Pero de todas formas el medio ambiente nos agradecera que ahorremos algunas hojas.

domingo, 24 de febrero de 2008

Cargar imagenes cd a AS400

Como utilizar un cd en un AS400 que no tiene, o al que no podemos acceder, unidad cd cd-rom:

Seguir el siguiente procedimiento (solo funciona en AS400 a partir V5R2).
  1. Colocar cd en un pc
  2. Arrancar pgm para generar imágenes (UltraISO, Nero, etc...) y crear imagen ISO del cd (cd's) que queremos cargar en el AS400.
  3. Copiar archivo iso generado al un directorio del AS400 (p.e. /images)
  4. Crear catalogo de imágenes en el AS400: CRTIMGCLG IMGCLG(MY_SOFTWARE) DIR('/images/MY_SOFTWARE') CRTDIR(*YES) TEXT('My software V.xx for AS400')
  5. Esto creara el directorio /images/MY_SOFTWARE y el objeto QUSRSYS/MY_SOFTWARE de tipo *IMGCLG
  6. Cargar imagen del cd al catalogo de imagenes: ADDIMGCLGE IMGCLG(MY_SOFTWARE) FROMFILE('/images/My_image.iso') TEXT('My software V.xx for AS400')
  7. Esto crea el archivo del ifs /images/MY_SOFTWARE/My_image.iso
  8. Para comprobar si se ha cargado:WRKIMGCLGE IMGCLG(MY_SOFTWARE)
  9. Crear dispositivo óptico virtual (por única vez): CRTDEVOPT DEVD(OPT90) RSRCNAME(*VRT) ONLINE(*NO) TEXT('cd-rom virtual')
  10. Activar el dispositivo óptico virtual:VRYCFG CFGOBJ(OPT90) CFGTYPE(*DEV) STATUS(*ON)
  11. Cargar el catalogo de imagenes (MY_SOFTWARE) al cd virtual (OPT90): LODIMGCLG IMGCLG(MY_SOFTWARE) DEV(OPT90) OPTION(*LOAD)
  12. Operar como un cd cargado en dispositivo optico OPT90 y realizar las operaciones como habitualmente.
  13. Al terminar descargar el catalogo de imagenes (MY_SOFTWARE) al cd virtual (OPT90): LODIMGCLG IMGCLG(MY_SOFTWARE) DEV(OPT90) OPTION(*UNLOAD)

domingo, 17 de febrero de 2008

Copiar archivos spool

La utilidad CPYJOBSPL nos sirve para copiar todos los archivos de spool de un trabajo, del que conocemos su jobid (numero/usuario/nombre_trabajo), si es el trabajo actual podemos usar el símbolo *.
Si utilizamos la opción *SPL nos copiara los archivos de spool a nuestro spool, nos permite indicar un numero máximo de paginas a copiar.
Si usamos la opción *TEXT, nos convierte todos los archivos de spool a ficheros ASCII dentro de una carpeta del IFS que le indiquemos.

jueves, 31 de enero de 2008

Configurar SNA sobre TCP/IP

Para configurar las comunicaciones SNA sobre TCPIP entre dos o más AS400 (iSeries) seguir el siguiente procedimiento en los sistemas a conectar:

Prerequisitos:
• TCPIP configurado correctamente.
• Subsistema QSNADS arrancado.
• Añadir usuarios al directorio (WRKDIRE).

Procedimiento, ejecutar en cada uno de los sistemas a conectar:
1. Activar el atributo de red "Permitir soporte AnyNet" con CHGNETA ALWANYNET(*YES), requiere IPL.
2. Añadir nombre al nombre de sistema principal el de 'nombre_sistema.appn.sna.ibm.com', utilizar el mandato CHGTCPHTE o CFGTCP, opción 10 y opción 2 en el sistema a modificar su entrada, de la tabla de sistema principales (HOSTS).
3. Crear el controlador APPC utilizando el mandato CRTCTLAPPC donde xxxxxxx es el nombre de sistema al que conectamos, en cada sistema origen utilizar el nombre del sistema destino.

CRTCTLAPPC CTLD(xxxxxxxx) LINKTYPE(*ANYNW) ONLINE(*YES) APPN(*YES) RMTNETID(*NETATR) RMTCPNAME(xxxxxxxxx) NODETYPE(*LENNODE) BEXROLE(*NETNODE) HPR(*YES) HPRPTHSWT(*NO) TMSGRPNBR(1) AUTOCRTDEV(*ALL) AUTODLTDEV(1440) USRDFN1(*LIND) USRDFN2(*LIND) USRDFN3(*LIND) TEXT('APPN sobre TCPIP para xxxxxxx') CMNRCYLMT(2 5) MSGQ(*SYSVAL)

4. Para crear el dispositivo APPC, y de paso probar la conexión, ejecutar STRPASTHR nombre_sistema, nos debería aparecer el inicio de sesión del sistema destino.
5. Para configurar el envío/recepción de archivos y spool con SNDNETF y/o SNDNETSPLF:
6. Ejecutar el mandato CFGDSTSRV "Configurar Servicios de Distribución".
7. Seleccionar la opción "1=Colas de distribución" y después pulsar "F6=Añadir cola de distribución"
8. Teclear en los campos Cola y Nombre ubicación remota el nombre del sistema destino:




9. Volver a paso 6 y seleccionar a continuación la opción "2=Tabla de direccionamiento", después pulsar "F6=Añadir entrada tabla de direccionamiento".
10. Teclear en los campos indicados el nombre de sistema de destino:



11. Si además queremos utilizar los mandatos SAVRST* entre sistemas debemos tener instalado el producto "OS/400 - ObjectConnect ", para V5R2 es 5722SS1- opción 22.