, , Changer le groupe d’activation d’un programme

Vous voulez changer le groupe d’activation d’un programme. Contrairement à une idée reçue, on peut dans certains cas renommer le groupe d’activation d’un programme ILE

Si vous créez un programme

CRTPGM

Ou 

CRTBNDRPG

Vous allez indiquer le groupe d’activation d’exécution de votre programme

Vous ne pouvez pas changer le groupe d’activation par CHGPGM !

Mais vous pouvez le faire par la commande UPDPGM 

avant ==> DSPPGM AATSTRET

Attribut du groupe d’activation  . . . . . . . :   PLB1

UPDPGM PGM(AATSTRET) MODULE(*NONE) ACTGRP(PLB45)              
Valeurs des paramètres AUT et USRPRF ignorées.                
L’objet remplacé AATSTRET type *PGM a été déplacé dans QRPLOBJ.
Programme AATSTRET créé dans la bibliothèque GDATA.            
Programme AATSTRET mis à jour dans GDATA.   

après  ==>DSPPGM AATSTRET

Attribut du groupe d’activation  . . . . . . . :   PLB45                   

la seule limitation est que le groupe doit être nommé

Pour interdir ce changement à l’assemblage vous devez indiquer

CRTPGM …  ALWUPD(*NO) 

PS :    

Cette option n’existe pas sur le CRTBNDRPG donc modifiable par défaut 

Vous devez avoir le droit *change sur programme.

Rappel:

En batch on essaye d’avoir le premier programme qui crée le groupe d’activation et les programmes appelés s’exécuteront en *caller

Dans les autres cas, webservice, interactif, etc il peut être préférable d’avoir un groupe d’activation par programme

Pour analyser les groupes actifs, vous pouvez utiliser le service : QSYS2.ACTIVATION_GROUP_INFO

— Liste des groupes par Travail
SELECT A.JOB_NAME,
       count(*)
    FROM TABLE (
             QSYS2.ACTIVE_JOB_INFO()
         ) AS A
         LEFT JOIN TABLE (
                 QSYS2.ACTIVATION_GROUP_INFO(JOB_NAME => A.JOB_NAME)
             ) AS G
             ON 1 = 1
    group by A.JOB_NAME         
        ORDER BY count(*) desc
            ;

Parlez REXX sur IBMi

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

https://www.rexxla.org

Merci à Dilhan pour sa contribution

, Retour d’expérience installation IBM i 7.6

En bons élèves, nous profitons de l’été pour faire nos devoirs de vacances. Entre autre, installation de la version 7.6 sur plusieurs de nos partitions.

D’abord une partition de test, bac à sable, puis nos partitions de production i(vous avez peut être vu une interruption de service sur nos sites web).

J’en profite pour faire un petit retour d’expérience sur ces installations.

Et pour finir ce préambule, je remercie l’équipe du support !

Une mise à jour comme les autres ?

Oui, je ne détaille pas ici le processus de mise à jour, c’est classique : téléchargement des images et clés sur ESS, PRUV pour les contrôle etc …

Quelques points d’attention

  • DST/SST
    • Le mot de passe de QSECOFR ne doit pas être celui par défaut (sinon il sera inutilisable)
    • Les profils 11111111 et 22222222 sont supprimés pendant l’installation
    • Bonne pratique : créer au moins un autre profil avec tous les droits pour DST, changer le mot de passe de QSECOFR. Les profils 11111111 et 22222222 ne devraient déjà plus être utilisés depuis longtemps
  • Java 11 64 bit non supporté

Ce qui nous a échappé

Deux sujets qui m’ont mobilisés !

Impossible de saisir le mot de passe de QSECOFR au démarrage

Après l’installation de la 7.6 sur la partition, et fort satisfait, je tentes de me loguer avec QSECOFR : informations d’authentification incorrectes !

Après vérification dans mon gestionnaire de mots de passe, nouvelle tentative : idem.

A la 3ème, profil désactivé …

Heureusement, j’ai toujours un profil clone de QSECOFR pour remédier à ces situations : je change le mot de passe de QSECOFR, et là cela fonctionne !

Le problème est connu et nécessite d’appliquer la PTF SJ05805 (cf https://www.ibm.com/mysupport/s/defect/aCIgJ0000000lGfWAI/dt438834?language=fr). Les mots de passe sont testés en CCSID 37 par le système au lieu du CCSID du travail (émulateur). C’est principalement le caractère « ! » qui pose problème.

Bonne pratique : changer le mot de passe de QSECOFR avant la migration pour un mot de passe simple (quitte à déroger aux règles le temps de l’installation).

Problème de connexion sur tous les serveurs hôtes en TLS

Après installation de la 7.6, impossible de se connecter en telnet sécurisé, ni aux autres services

Et effectivement, le mémo to user (cf https://www.ibm.com/docs/en/ssw_ibm_i_76/pdf/rzaq9.pdf) indique bien :

Dans DCM, allez dans le magasin *SYSTEM, puis gérer « Manage Applications Definitions », sélectionner l’application QIBM_QZBS_SVR_HOSTCNN et associez un certificat (en général le même pour l’ensemble des serveurs hôtes) :

Dès validation la connexion TLS fonctionne, pas besoin d’arrêter/redémarrer des services.

Ce fonctionnement est nécessaire pour la mise en œuvre du MFA, mais impact les services existants.

Tous les systèmes étant sécurisés depuis de nombreuses années, vous devriez être impacté …

En synthèse

A noter que l’ensemble des éléments est bien documenté, y compris les « détails » qui nous ont posés quelques soucis (exception du mot de passe non reconnu).

Une bonne préparation permet de réaliser une migration maitrisée, l’installation elle-même se déroule très bien et rapidement.

, V7R6, la liste des commandes supprimées

APYJRNCHGX Appliquer modifs journal étend
CFGPMAGT Configure PM Agent
CFGPM400 Configure PM Agent
CHGDHCPSVR Change DHCP Server
CHGRTDA Change RouteD Attributes
CPYIGCSRT Copy DBCS Master Sort Table
MRGFORMD Fusionner description imprimé
STRAPF Démarrer APF
STRCGU Start CGU
STRRLU Démarrer Utilit maquette état
STRSDA Démarrer SDA
WRKPMRMTS Work With Remote Systems
WRKPMRPTO Work With Omissions
WRKPMSCH Work With Scheduled Jobs
WRKRTDCFG Work with RouteD Configuration

Remarque :

Sans surprise on retrouve bien SDA et RLU

, , Les profils _NC en V7R6

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

Routage des travaux interactifs

Je vais essayer de vous expliquer le routage des travaux interactifs.

Un travail interactif est routé vers un sous système par rapport au nom de son unité.

Vous l’indiquez dans la commande ADDWSE
Vous avez 2 paramètres
WRKSTN() nom écran ou nom générique
WRKSTNTYPE type d’écran

l’ordre c’est
nom
nom générique
type

Par contre ce n’est pas dynamique un écran affecté ne sera pas réaffecté dynamiquement, si par exemple votre sous système spécifique est démarré après QINTER.

Il peut être important pour des questions d’administration d’avoir les travaux dans le bon système.

On peut donc ajouter un programme SDA (sélection dynamique à l’arrivée), parce que le critère de nom n’est pas forcément suffisant , ou que suite à un redémarrage, on veut replacer le travail dans le bon sous système, ou tout autre raison.

C’est dans les données de routage qu’il va falloir agir, par défaut PGM(QCMD), mais vous pouvez indiquer un programme à vous.
Ce programme ne reçoit pas de paramètre extérieur et il va par rapport à un algorithme que vous aurez déterminé transférer le travail vers une JOBQ, c’est la commande TFRJOB qui permet de transférer
Le plus souvent on utilise comme critère l’utilisateur ou le nom de l’unité, mais on peut ajouter beaucoup d’autres critéres

Voici un exemple très simple et relativement classique, à mettre sur QINTER qui est souvent le sous système par défaut puisqu’il a une entrée par type

/*------------------------------------------------------------------*/
/*     Ce programme est utilisé dans un sous système interactif     */
/* dans les données de routage il va rerouter une jobq              */
/*  ADDRTGE  ... PGM(MALIB/REROOT)                                  */
/* Ce programme doit être en adoption de droit par rapport QSECOFR  */
/*------------------------------------------------------------------*/
PGM
dcl &user *char 10  /* Utilisateur en cours */
dcl &grp  *char 10  /* Groupe de l'utilisateur */
dcl &unit *char 10  /* nom de l'unité          */
dcl &status *char 2
/* information pour adresse ip */
dcl var(&IPV4ADDR) type(*char) len(15)
DCL    VAR(&JOBI) TYPE(*CHAR) LEN(700) VALUE(' ')
DCL    VAR(&JOBILEN) TYPE(*DEC) LEN(4 0) VALUE(700)
DCL    VAR(&FMTNAME) TYPE(*CHAR) LEN(8) VALUE(JOBI0600)
DCL    VAR(&QUALJN) TYPE(*CHAR) LEN(26) VALUE('*')
DCL    VAR(&INJOB) TYPE(*CHAR) LEN(16) VALUE('                ')
/*-------------------------------------------------*/
/* Extraction des informations de routage          */
/* ici Utilisateur, groupe et nom unité            */
/*-------------------------------------------------*/
             RTVJOBA    USER(&USER) job(&unit)
             RTVUSRPRF  GRPPRF(&GRP)
/* Call QUSRJOBI to retrieve job information */
             CALL       PGM(QSYS/QUSRJOBI) PARM(&JOBI &JOBILEN &FMTNAME +
                        &QUALJN &INJOB)
/* Extract data from the output of QUSRJOBI */
             CHGVAR     VAR(&IPV4ADDR) VALUE(%SST(&JOBI 308 15))
/*-------------------------------------------------*/
/* Règles de routage  sur utilisateur  et groupe   */
/*-------------------------------------------------*/
if cond(&GRP  = 'COMPTA') then(do)
             TFRJOB     JOBQ(COMPTA)
enddo
/*-------------------------------------------------*/
/* Règles de routage  sur unité                    */
/* reroutage de l'unité de secours dans QCTL       */
/* Pour faire des operations en mode restreint     */
/*-------------------------------------------------*/
if cond(&UNIT = 'SECOURS') then(do)
             TFRJOB     JOBQ(QCTL)
enddo
/*-------------------------------------------------*/
/* Règles de routage  sur nom d'ecran              */
/* AAAAAAxxxxx vers JOBQ AAAAAAJOBQ                */
/* AAAAAA racine de l'ecran                        */
/* xxxx   numéro                                   */
/*-------------------------------------------------*/
             chgvar &status 'OK'
             CHKOBJ     OBJ((%SST(&UNIT 1 6) *TCAT 'JOBQ')) +
                          OBJTYPE(*JOBQ)
             monmsg cpf9800 exec(do)
             chgvar &status 'KO'
             enddo
/* si JOBQ existe */
if cond(&status = 'OK') then(do)
             TFRJOB     JOBQ((%SST(&UNIT 1 6) *TCAT 'JOBQ'))
enddo
/*-------------------------------------------------*/
/* Règles de routage  sur adresse ip               */
/* Ici controle adresse ip  avec refus si pas reseau*/
/*  172                                            */
/*-------------------------------------------------*/
if cond(%sst(&IPV4ADDR 1 3) *ne '172') +
then(do)
             SNDMSG     MSG('Tentative de connexion refusée,' *BCAT +
                       &IPV4ADDR *BCAT ', sur adresse IP' *BCAT +
                         &UNIT) TOMSGQ(*HSTLOG)
             ENDJOB     JOB(*)
enddo
/*-------------------------------------------------*/
/* Les autres ne sont pas reroutés                  */
/*-------------------------------------------------*/
endpgm

Dans notre exemple, on a ajouté un contrôle sur l’adresse IP avec un blocage si pas le réseau attendu

Remarques :

La limite c’est votre imagination, vous devez bien réfléchir et cibler votre besoin , vous pouvez par exemple ajouter du paramétrage


Vous pouvez également utiliser le programme d’exit (QIBM_QTG_DEVINIT) , mais plus compliqué à mettre en œuvre

Vous devez vous assurer que le programme utilisé pour SDA ne plante pas

Les unités peuvent être créer automatiquement c’est la valeur système QAUTOVRT

Si vous choisissez de l’utiliser, préférez un nombre (exemple : 500 ) plutôt que *NOMAX et tous les 6 mois faites un coup de ménage sur les unités inutilisées

===> DSPOBJD OBJ(ALL) OBJTYPE(DEVD)

Vous pouvez les identifier facilement :

Par défaut les unités s’appellent QPADEVxxxx , ne pas hésiter à les supprimer 2 fois par an

, , Utiliser l’instruction merge en SQL

Vous avez une instruction SQL , MERGE qui est assez PUISSANTE pour fusionner des fichiers
Voici un exemple complet :


Il intègre les éléments suivants
-La création
-La mise à jour
-La suppression


On a 2 tables Products et Mouvements

Les règles choisies sont les suivantes :

-Si le produit existe on ajoute la quantité
-S’ il est nouveau, on le créé
-Si nom du produit est SUPPRESSION, on supprime

J’ai utilisé la convention de nommage *SYS

et dans tous les cas on met à jour la date de modification

-- voici les scripts pour tester 
-- Création de la table des produits
-- Option *SYS et *NONE 
CREATE TABLE GDATA/PRODUCTS (
    PRODUCT_NUMBER  DECIMAL(10, 0)      NOT NULL ,
    PRODUCT_NAME    VARCHAR(100)        NOT NULL,
    QUANTITY        DECIMAL(10, 0)      NOT NULL DEFAULT 0,
    LAST_UPDATE_TS  TIMESTAMP           NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (PRODUCT_NUMBER)
    );
-- alimentation du fichier
INSERT INTO GDATA/PRODUCTS VALUES(1, 'CLOU', 50, current timestamp) ;
INSERT INTO GDATA/PRODUCTS VALUES(2, 'VIS', 20, current timestamp) ;
INSERT INTO GDATA/PRODUCTS VALUES(3, 'ECROU', 25, current timestamp) ;
INSERT INTO GDATA/PRODUCTS VALUES(4, 'RONDELLE', 120, current timestamp) ;
-- Création de la table des mouvements
CREATE TABLE GDATA/MOUVEMENTS (
    PRODUCT_NUMBER  DECIMAL(10, 0)      NOT NULL ,
    PRODUCT_NAME    VARCHAR(100)        NOT NULL,
    QUANTITY        DECIMAL(10, 0)      NOT NULL DEFAULT 0,
    LAST_UPDATE_TS  TIMESTAMP           NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (PRODUCT_NUMBER)
    );
-- alimentation de la tables des mouvements
INSERT INTO GDATA/MOUVEMENTS VALUES(1, 'CLOU', 30, current timestamp) ; -- changement de quantité
INSERT INTO GDATA/MOUVEMENTS VALUES(3, 'SUPPRESSION', 0, current timestamp) ; -- suppression
INSERT INTO GDATA/MOUVEMENTS VALUES(5, 'RESSORT', 100, current timestamp); -- Nouveau
-- Fusion des 2 tables 
MERGE INTO GDATA/PRODUCTS AS T  -- T est l'alias de la table CIBLE (PRODUCTS)
USING GDATA/MOUVEMENTS AS S      -- S est l'alias de la table SOURCE (MOUVEMENT)
ON (T.PRODUCT_NAME = S.PRODUCT_NAME) -- La jointure se fait sur le nom du produit
-- 1. Gérer la suppression si le produit correspond ET que la source indique 'SUPPRESSION'
WHEN MATCHED AND S.PRODUCT_NAME = 'SUPPRESSION' THEN
    DELETE
-- 2. Gérer la mise à jour si le produit correspond ET que la source N'indique PAS 'SUPPRESSION'
WHEN MATCHED AND S.PRODUCT_NAME <> 'SUPPRESSION' THEN
    UPDATE SET T.QUANTITY = T.QUANTITY + S.QUANTITY,
               T.LAST_UPDATE_TS = CURRENT_TIMESTAMP
-- 3. Gérer l'insertion si le produit NE correspond PAS ET que la source N'indique PAS 'SUPPRESSION'
WHEN NOT MATCHED AND S.PRODUCT_NAME <> 'SUPPRESSION' THEN
    INSERT (PRODUCT_NUMBER, PRODUCT_NAME, QUANTITY, LAST_UPDATE_TS)
    VALUES (S.PRODUCT_NUMBER, S.PRODUCT_NAME, S.QUANTITY, CURRENT_TIMESTAMP);

Remarque :

Vous pouvez également utiliser la commande CPYF avec le paramètre MBROPT(*UPDADD) mais plus compliqué de gérer les suppressions.

Bien sur , bien tester tous les cas

, Visual Explain : affichage des index considérés

Access Client Solutions 1.1.9.8, disponible depuis avril 2025, amène son lot d’évolutions. Une m’a particulièrement intéressée : l’affichage des index considérés.

Visual Explain, les index ?

Visual Explain permet d’afficher le plan d’exécution de la requête SQL : l’ensemble des étapes nécessaires à l’obtention du résultat, de la façon la plus optimisée possible.

Pour déterminer la façon la plus optimisée, le moteur SQL va réécrire la requête, considérer les index/LF existants, exploiter les statistiques de chaque table, index ou clé sous-jacents aux tables utilisées dans la requête.

Dans le plan affiché, pour une première analyse macroscopique, on cherche en général les éléments suivants :

  • Scan de table : on préfère utiliser des accès par index plutôt que parcourir l’ensemble de la table. Il s’agit d’analyser pourquoi aucun index ne satisfait les conditions de la requête
  • Les index utilisés : même si l’on se félicite de l’utilisation d’index, il est souvent possible de faire mieux
  • Les index recommandés : justement pour faire mieux !

Une information est disponible mais difficilement exploitable : l’optimiseur explique pour chaque index trouvé pourquoi il a été utilisé, ou pourquoi il ne l’a pas été.

Un exemple

Nous avons une table dans laquelle nous consolidons certains événements logués par nos serveurs web (access_log générés par Apache). Aujourd’hui cette table HTTPLOG contient environ 240 millions d’entrées, et dispose bien évidemment d’un certains nombres d’index existants :

Prenons une requête basique :

L’affichage de Visual Explain nous montre :

En sélectionnant l’étape « Test de table », le volet de droite indique :

Ce sont la liste des index que l’optimiseur a regardé et le chiffre correspond au code qui indique pourquoi il n’a pas été utilisé. Il est possible d’aller chercher le détail des codes dans les messages (il faut activer les messages de débogage).

Cette information est accessible pour chaque étape du plan, dans le cas de jointure ou de sous-requête.

Index considérés

Prenons une autre requête SQL permettant d’analyser toutes les requêtes HTTP authentifiées et dont le retour provoque un warning ou une erreur (autre que code HTTP 200 OK).

Visual Explain nous donne :

Nous retrouvons bien entendu nos informations sur les index :

Mais il est maintenant possible de demander ces informations pour l’ensemble de la requête :

Et d’obtenir des libellés plus parlants :

Cela vous donne plus d’informations quant à l’usage des index. Pour compléter, l’index advisor nous donne :

A noter que l’optimiseur ne propose pas d’index dérivé par exemple, ou difficilement les index EVI … Gardez donc un œil critique sur ces informations, mais leur compréhension est nécessaire.

, , Gestion du SQLCODE dans un SQL embarqué

En SQL embarquée la gestion des erreurs est différente par rapport à un RPGLE classique.


Essentiellement sur 2 points


1) Ca ne plante pas
Vous pouvez donc avoir des erreurs silencieuses
Il est très important de traiter les SQLCODE
Même si vous pensez ne pas en avoir besoin
Les 3 lignes suivantes peuvent être ajoutées sans risque !

EXEC SQL ... ;
IF SQLCODE <> 0;
DSPLY ('nompgm' + ' : ' + %CHAR(SQLCODE) ;
ENDIF;


Permettra d’avoir un message dans la log qui peut vous aider en cas de probléme.

2) On n’a le résultat de la dernière instruction dans le SQLCODE.

Le risque est donc sur une boucle, il est possible que le SQLCODE soit parasité par une autre requête SQL dans une autre fonction par exemple

dou sqlcode <> 0                    ;
  exec sql ... ;                                         
  if sqlcode <> 0                   ;
    leave                           ;
  endif                             ;
enddo                               ;

Pour éliminer ce probléme vous devez sauvegarder votre SQLCODE dans une variable de travail

Votre boucle deviendra

// Déclaration de la variable de travail ! 
DCL-S  W_SQLCODE like SQLCODE; 
//
dou w_sqlcode <> 0                    ;
  exec sql ... ;                                         
  if sqlcode <> 0                   ;
    leave                           ;
  endif                             ;
  W_SQLCODE = SQLCODE                 ;
enddo  

Ainsi vous êtes sur de tester le bon SQLCODE

Remarque :
Pour ceux qui utilisent le sqlstate, la remarque est la même.
Vous pouvez être plus précis que <> 0 ;

Rappel :
en dessus de 0 c’est des avertissements
en dessous c’est des erreurs
par exemple if sqlcode < 0 ; traitera les erreurs uniquement

, Gestion des spools par ACS

Vous connaissez l’option ACS qui vous permet de gérer vos SPOOLs , c’est une alternative intéressante à la commande WRKSPLF et si vos utilisateurs ont beaucoup de spools à gérer, ca peut leurs simplifier la tache, n’hésitez pas à leurs donner l’option, c’est relativement intuitif .

Vous pouvez par exemple faire simplement un fichier PDF et le joindre à un mail .

Vous voulez simplifiez la vie de vos utilisateurs en leurs présentant cette option à la place d’un WRKSPLF dans vos applications existantes

Voici une ébauche de solution

Un programme de lancement

Vous devrez d’abord écrire un programme qui lance l’option ACS à partir de votre programme IBMi à base des commandes STRPCO et STRPCCMD

Voici un exemple RPGLE

**free                                                                         
// Ce programme permet de remplacer les commandes WRKSPLF par                  
// L'explorateur de spool ACS                                                  
// ici le javabundle est dans \Users\Public\IBM\ClientSolutions\               
//                                                                             
dcl-s cmd  CHAR(1024) ;                                                        
// démarrage de PCO                                                            
cmd ='STRPCO' ;                                                                
 exec sql call qsys2.qcmdexc(:cmd) ;                                           
// Démarrage de l'explorer de spools                                           
cmd =' +                                                                       
STRPCCMD PCCMD(''java -jar C:\Users\Public\IBM\ClientSolutions\acsbundle.jar + 
/PLUGIN=splf /system=neptune +                                                 
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true'') PAUSE(*NO)' ;      
 exec sql                                                                      
 call qsys2.qcmdexc(:cmd) ;                                                    
 *inlr= *on ;                                                                  

On a fixé le répertoire du programme ici \Users\Public\IBM\ClientSolutions\

Si vous lancez ce programme, vous ouvrez alors l’écran ACS de gestion des spools, il est possible que cela vous redemande le mot de passe en fonction de votre paramétrage.

Un programme pour Associer à la commande WRKSPLF

Si vous voulez automatiser, vous pouvez utiliser un programme d’exit sur l’exit point QIBM_QCA_CHG_COMMAND

PGM PARM(&COMMAND)                                                               
/* ADDEXITPGM EXITPNT(QIBM_QCA_CHG_COMMAND) FORMAT(CHGC0100) PGMNBR(1) PGM(GDATA/WRKSPLFAC1) */ 
/*  PGMDTA(*JOB 20 'WRKSPLF   QSYSGAIA ')   */                    
DCL VAR(&COMMAND) TYPE(*CHAR) LEN(256)                                           
DCL VAR(&Cmdibm ) TYPE(*CHAR) LEN(20)                                            
chgvar &cmdibm %sst(&COMMAND 29 20)                                              
             IF         COND(&CMDIBM *EQ 'WRKSPLF   QSYSGAIA') THEN(DO)          
             CALL       PGM(WRKSPLFACS)                                          
             ENDDO                                                               
RETURN                                                                           
ENDPGM                                                                           

Vous avez la commande ADDEXITPGM pour ajouter un programme d’exit , vous pouvez également passer par la commande ==>WRKREGINF et faire l’option 8

Remarque :

Vous pouvez comme ici mettre une commande WRKSPLF dans une bibliothèque avant QSYS, qui vous permettra de bien gérer que les interactifs et de bypasser si besoin en faisant ==>QSYS/WRKSPLF .

Vous aurez intérêt a identifier les utilisateurs qui doivent bénéficier de la fonctionnalité, une solution très simple c’est l’utilisation d’une liste d’autorisation