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.