REXX (Restructured Extended Executor) est un langage de script interprété créé par IBM, bien connu pour les « Roger » qui ont sévit sous OS2.
Il est conçu pour être facile à lire et facile à apprendre, tout en étant très puissant pour l’automatisation.
Sur IBMi, il est utilisé pour :
Automatiser des tâches système
Créer des utilitaires interactifs
Prototyper rapidement
Faire du traitement de texte et de données
Ces points forts sont :
Très rapide à écrire, idéal pour du scripting jetable
Permet d’appeler directement des commandes système sans compiler un programme
Peut servir de « colle » entre RPG, CL, SQL et PASE/QShell
Permet de faire des tests d’appels, des scripts de migration, des reprises de données.
Comment ca marche?
Vous devez créer un fichier source qui contiendra les scripts à exécuter
CRTSRCPF FILE(MALIB/QRXSRC) RCDLEN(112) TEXT(‘Sources REXX’)
Vous devez saisir vos scripts ici REXX01
/* REXX / / Boucle interactive jusqu’à ce que l’utilisateur tape ‘FIN’ */
DO FOREVER
SAY « Entrez une commande CL (ou FIN pour quitter) : »
PULL CMD
IF CMD = « FIN » THEN LEAVE
ADDRESS ‘COMMAND’ CMD
END
Ce scripte exécutera des commandes CLP, jusqu’à ce que saisissiez FIN
Pour exécuter ce script :
STRREXPRC SRCMBR(REXX01) SRCFILE(MALIB/QRXSRC)
Remarque :
Le rexx est de moins en moins utilisé mais, il peut encore être utilisé, en effet, il peut aider a du déploiement et de la mise au point, etc…
Pour en savoir plus :
https://en.wikipedia.org/wiki/Rexx
Merci à Dilhan pour sa contribution
En V7R6 vous avez de nouveaux profils qui apparaissent avec l’extention _NC
QPGMR_NC
QSECOFR_NC
QSYSOPR_NC
QUSER_NC
C’est des profils qui ne sont pas modifiables, et ils n’ont pas de mot de passe
Et certains services ibm démarrent avec ceux ci
Conclusions :
Attention, par exemple, si vous avez customisé QUSER ou QPGMR vous pouvez avoir des surprises après migration
Vous connaissez tous la commande CPYTOARCF qui permet de Zipper un fichier
Mais vous ne pouvez pas un fois généré lui ajouter un fichier !
On va essayer de vous aider
Dans les produits opensys vous avez la commande zip
Vous avez ce répertoire dans votre path (similaire à votre *LIBL)
$
echo $PATH
/QOpenSys/pkgs/bin:/usr/bin:.:/QOpenSys/usr/bin
$Remarque
Vous pouvez le régler par le fichier .profile
Vous pouvez donc zipper sous QSH ou QP2TERM
exemple
$
zip archive.zip analyse.csv
adding: analyse.csv (deflated 84%)
$
et par défaut si vous zippez sur une archive existante il ajoute
zip archive.zip xmlversion.txt
adding: xmlversion.txt (stored 0%)
$
pour voir le résultat
unzip -l archive.zip
Archive: archive.zip
Length Date Time Name
——— ———- —– —-
9934 2019-03-29 23:44 analyse.csv
17 2019-02-13 10:49 xmlversion.txt
——— ——-
9951 2 files
$
Pour vous aider nous proposons une commande ADDTOARCF que vous pouvez retrouver ici
https://github.com/Plberthoin/PLB/tree/master/GTOOLS/
un CLLE + un CMD
Remarque :
Vous pouvez ajouter une un fichier à un zip généré par CPYTOARCF
Par défaut il créera la l’archive
Vous pouvez indiquer des options si elles sont valides dans la commande Zip
Vous avez un fichier stdout.log dans votre répertoire courant
Simple et efficace !
Comment faire afficher un écran à un traitement batch ?
Les traitements 5250 sont faits pour tourner en interactif, mais pour différentes raisons vous pouvez vouloir les faire tourner en batch :
Pas de login
sécurisation pas de attn request
etc …
Voici un exemple, dans une société ou j’ai travaillé, les unités de productions pouvaient demander un mot de passe à l’astreinte, par exemple la nuit.
La solution la plus simple qu’on avait trouvée était de lui afficher un programme de changement sur son unité écran.
On lui demandait donc son profil utilisateur et son unité écran et on lançait le programme sur celle ci, il pouvait changer son mot de passe directement.
C’est cet exemple que j’ai simplifié qui est ci dessous
le DSPF source
A DSPSIZ(24 80 *DS3)
A CA03(03)
A INDARA
A R FMT01
A*%%TS SD 20240527 074541 PLB REL-V7R4M0 5770-WDS
A 4 20'Réinitialiser un mot de passe'
A 7 2'Utilisateur :'
A 8 2'Nouveau mot de passe :'
A 22 1'F3=Exit'
A USER 10A O 7 26
A PWD 32A B 8 26CHECK(LC)
A DEV 10A O 4 54
A TEXTE 30 O 14 3
Le CLP source
pgm (&dev &user)
/*----------------------------------------------------------*/
/* Ce programme permet de faire afficher un écran en batch */
/* vous devez acquérir l'unité écran */
/* pour réinitialiser un mot de passe */
/* sbmjob cmd(call initpwdr (&dev &user) job(QPADEV0001) */
/*----------------------------------------------------------*/
dcl &dev *char 10
dcl &user *char 10
/* Contrôles existence */
CHKOBJ OBJ(&DEV) OBJTYPE(*DEVD)
MONMSG MSGID(CPF9801) EXEC(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('L''unité écran doit exister') +
MSGTYPE(*ESCAPE)
enddo
ALCOBJ OBJ((&DEV *DEVD *EXCLRD)) WAIT(0)
monmsg CPF1002 exec(do)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('Impossible d''allouer l''unité +
écran doit exister') MSGTYPE(*ESCAPE)
enddo
CHKOBJ OBJ(&user) OBJTYPE(*usrprf)
MONMSG MSGID(CPF9801) EXEC(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Le +
profil utilisateur doit exister') +
MSGTYPE(*ESCAPE)
enddo
/* Lancement du programme sur l'écran remote */
SBMJOB CMD(CALL PGM(INITPWDR) PARM((&DEV) (&USER))) +
JOB(&DEV) JOBQ(QSYSNOMAX)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('Travail, ' *bcat &dev *bcat +
'démarré') MSGTYPE(*comp)
endpgm
Le CLP cible
pgm (&dev &user)
/*----------------------------------------------------------*/
/* Ce programme réinitiliase un mot de passe */
/* Peut être envoyé sur un écran remote qui est sur la */
/* Mire */
/*----------------------------------------------------------*/
dcl &dev *char 10
dclf initpwdr
monmsg cpf0000 exec(goto erreur)
/* controles fait dans le programme appelant */
OVRDSPF FILE(INITPWDR) DEV(&DEV) OVRSCOPE(*JOB)
chgvar &pwd 'ici mot de passe'
dountil &in03
SNDRCVF RCDFMT(FMT01)
if cond(*not &in03) then(do)
if (&pwd *ne 'ici mot de passe') then(do)
CHGUSRPRF USRPRF(&USER) PASSWORD(&PWD) PWDEXP(*YES)
Chgvar &texte ('Mot de passe réinitialisé')
enddo
enddo
enddo
/* fin traitement */
DLTOVR FILE(INITPWD) LVL(*JOB)
MONMSG MSGID(CPF0000)
return
erreur:
SNDUSRMSG MSG('Réinitialisation de mot de passe pour' +
*BCAT &USER *BCAT ', actuellement +
impossible') MSGTYPE(*INFO)
MONMSG MSGID(CPF0000)
endpgm
La seule spécificité est de choisir l’unité écran d’affichage, pour qu’elle soit éligible elle doit être à la mire de connexion.
La commande pour habiller
CMD PROMPT('Réinitialisation de PWD')
PARM KWD(UNITE) TYPE(*NAME) LEN(10) MIN(1) +
PROMPT('Unité écran')
PARM KWD(PROFIL) TYPE(*NAME) LEN(10) MIN(1) +
PROMPT('Profil utilisateur')
le lancement job source:
La saisie sur le job cible :
Sur un changement de mot de passe, il peut être important d’avoir un suivi ?
Bien sur, vous pouvez ajouter des contrôles …
Le job cible qui tourne en batch !
Donc pas de possibilité d’ATTN Request , et messages d’erreurs dans QSYSOPR
Remarques :
Vous pouvez choisir l’utilisateur de lancement, mais QSECOFR est interdit dans un SBMJOB
Simple mais efficace, mais difficilement généralisable, on doit avoir un OVRDBF par DSPF
Intéressant pour des demandes ponctuelles
Dans les CLP vous pouvez indiquer directement l’unité sur la commande SNDRCVF
Contrôler le nombre de paramètres passés à un programme CL – %PARMS() / CEETSTA
Il arrive parfois d’avoir moins de paramètres passés à un programme CL que le nombre attendu, par exemple si on ajoute un paramètre à ce dernier mais que pour diverses raisons on ne souhaite pas modifier et recompiler tous les programmes qui y font appel.
Il existe deux solutions relativement simples à implémenter pour contrôler le nombre de paramètres transmis afin d’adapter en conséquence le comportement du programme : La fonction intégrée %PARMS et l’API CEETSTA.
%PARMS() – V7R4 et ultérieures
À partir de la V7R4, rien de plus simple, il suffit d’utiliser la fonction intégrée %PARMS(), qui retourne le nombre de paramètres :
PGM PARM(&PARAM1 &PARAM2)
/* Paramètres */
DCL VAR(&PARAM1) TYPE(*CHAR) LEN(10)
DCL VAR(&PARAM2) TYPE(*CHAR) LEN(10)
/* Corps du programme en fonction du passage du paramètre */
IF COND(%PARMS() *EQ 2) THEN(DO)
SNDPGMMSG MSG('Le paramètre &PARAM2 est renseigné')
ENDDO
ELSE CMD(DO)
SNDPGMMSG MSG('Le paramètre &PARAM2 n''est pas renseigné')
ENDDO
ENDPGM
Malheureusement, si on est confrontés à une contrainte de version, %PARMS ne descend pas en dessous de la V7R4 :

CEETSTA – V7R3 et antérieures
Dans ce cas, la solution la plus propre (je ne parlerai donc pas de monitoring sur un CHGVAR) est l’utilisation de l’API CEETSTA.
Il suffit de lui passer en paramètre :
– Une variable qui contiendra la valeur de retour, 1 si le paramètre est transmis, 0 s’il n’est pas transmis
– Une variable indiquant la position du paramètre à contrôler
presence_flag | Sortie | *INT | Variable de retour : 1 ou 0 |
arg_num | Entrée | *INT | Position de la variable à tester |
PGM PARM(&PARAM1 &PARAM2)
/* Paramètres */
DCL VAR(&PARAM1) TYPE(*CHAR) LEN(10)
DCL VAR(&PARAM2) TYPE(*CHAR) LEN(10)
/* Déclaration des variables nécessaires à l'utilisation de l'API */
DCL VAR(&PRESENCE) TYPE(*INT) /* Variable de retour : 1 ou 0 */
DCL VAR(&ARG_NUM) TYPE(*INT) VALUE(2) /* Position de la variable à tester */
/* Appel de l'API */
CALLPRC PRC('CEETSTA') PARM((&PRESENCE) (&ARG_NUM))
/* Corps du programme en fonction du passage du paramètre */
IF COND(&PRESENCE *EQ 1) THEN(DO)
SNDPGMMSG MSG('Le paramètre &PARAM2 est renseigné')
ENDDO
ELSE CMD(DO)
SNDPGMMSG MSG('Le paramètre &PARAM2 n''est pas renseigné')
ENDDO
ENDPGM
Remarques
Le compte des paramètres pour la arg_num commence à 1
La valeur de retour est un *INT pas un *LGL
Pour plus de détails
Documentation IBM – %PARMS() : https://www.ibm.com/docs/en/i/7.5?topic=procedure-parms-built-in-function
Documentation IBM – CEETSTA : https://www.ibm.com/docs/api/v1/content/ssw_ibm_i_75/apis/CEETSTA.htm
Vous voulez utiliser la souris dans un dspf sur dans un de vos programmes
voici un exemple en CLLE:
DSPF :
A DSPSIZ(24 80 *DS3)
A CA03(03)
A* EVENNEMENT SOURIS
A* UNSHIFT / LEFT / PRESS
A R FMT01
A*%%TS SD 20231025 171347 QSECOFR REL-V7R4M0 5770-WDS
A MOUBTN(*ULP ENTER)
A RTNCSRLOC(*MOUSE &L1 &C1 &L2 &C2)
A* RÉCUPÉRATION DU CURSEUR
A L1 3S 0H
A C1 3S 0H
A L2 3S 0H
A C2 3S 0H
A 3 13'Tester la position de la souris'
A 5 13'En faisant un clic Gauche.'
A* BOUTON BAS DE PAGE
A F1B 2Y 0B 23 2PSHBTNFLD
A PSHBTNCHC(1 'F3=>Exit' CA03)
CLLE
pgm
dclf mouse
DOUNTIL COND(&IN03)
SNDRCVF RCDFMT(FMT01)
if cond(*not &in03) then(do)
SNDUSRMSG MSG('Position du curseur ligne =' *BCAT +
%CHAR(&L1) *BCAT 'et colonne =' *BCAT +
%CHAR(&C1)) MSGTYPE(*INFO)
enddo
ENDDO
endpgm
Remarque:
Vous devez compiler avec l’option ENHDSP(*YES)
C’est la possibilité d’avoir plusieurs messages d’erreur et de pouvoir paginer dessus
Vous pouvez programmer un sous fichier message, mais ca peut être un peu compliqué à réaliser.
Voici une solution simple, il suffit de mettre le mot clé ERRSFL au niveau fichier écran
Ci dessous un exemple avec son programme en CLLE
DSPF
A* Exemple sous fichier d'erreurs
A DSPSIZ(24 80 *DS3)
A ERRSFL
A CA03(03)
A R FMT01
A ZONE1 10A B 11 20
A 41 ERRMSG('Erreur ZONE 1' 41)
A ZONE2 10A B 12 20
A 42 ERRMSG('Erreur ZONE 2' 42)
A ZONE3 10A B 13 20
A 43 ERRMSG('Erreur ZONE 3' 43)
A 6 8'Sous fichier d''erreur'
A DSPATR(HI)
A 11 8'Zone 1 :'
A 12 8'Zone 2 :'
A 13 8'Zone 3 :'
CLLE
/* Exemple sous fichier message d'erreur */
PGM
DCLF ERREUR
dountil &in03
SNDRCVF RCDFMT(FMT01)
IF COND(*NOT &IN03) THEN(DO)
/* activation des indicateurs d'erreur */
CHGVAR &IN41 '1'
CHGVAR &IN42 '1'
CHGVAR &IN43 '1'
enddo
enddo
ENDPGM
Remarque:
La seule limitation, c’est une seule erreur par zone, mais ca suffit dans 90 % des cas