Les dépendances JCL dépassent le JCL
Cartographiez les dépendances JCL avec les procédures, règles d'ordonnanceur et traces de production, puis prouvez chaque producteur.

Une carte de dépendances du batch nocturne se trompe souvent de façon très précise : elle consigne l'ordre prévu et manque les relations de données réellement utilisées. Le job qui lit un enregistrement à 02:00 peut n'avoir aucun prédécesseur explicite vers celui qui l'a écrit. Le lien peut se cacher dans une procédure cataloguée, un paramètre symbolique, une ressource d'ordonnanceur, un GDG, un commit de base de données ou un fichier renommé par un autre job.
J'ai vu des équipes lire du JCL pendant des jours et désigner malgré tout le mauvais producteur. Le JCL indique ce qu'un job soumis peut ouvrir. L'ordonnanceur explique pourquoi il pouvait s'exécuter cette nuit-là. Les preuves de production montrent ce qu'il a fait, avec quels noms résolus et à quelle heure. Il faut réunir ces trois vues par des identités et des temps stables. Personne ne connaît tout le graphe, car aucune personne ni couche de contrôle n'a jamais dû le représenter en entier.
Une dépendance est un fait de données, pas une flèche
La définition utile est stricte : B dépend de A quand B consomme un état produit par A, ou quand A modifie une condition qui commande l'exécution correcte de B. Une flèche de prédécesseur peut imposer ce lien, mais elle reste une règle d'ordre. Les ordonnanceurs contiennent aussi des ordres opérationnels sans rapport avec les données, comme attendre la fin d'une sauvegarde avant un rapport bruyant. À l'inverse, deux jobs peuvent échanger des données sans lien direct.
Séparez quatre types d'arêtes. Une arête de données relie auteur et lecteur par un dataset, une génération GDG, une table, un message ou un enregistrement de contrôle. Une arête de contrôle relie un job à un code retour, un événement, une ressource ou un déclencheur. Une arête d'ordre consigne un prédécesseur. Une arête inférée reste à prouver. En les réduisant à une seule flèche, chaque enquête devient un débat sur son sens.
Inscrivez l'objet sur chaque arête de données. PAYM020 ne dépend pas simplement de PAYM010 : il lit PROD.PAYMENTS.CLEARED.G0123V00, fermé par PAYM010 à 01:47:12. Cette phrase se vérifie. Une flèche entre jobs ne dit pas s'il s'agit de la génération courante, de celle d'hier, d'une table partagée ou d'un forçage manuel.
La distinction compte lors d'une panne. Si A finit avec le code 0 mais écrit un fichier vide, l'ordre est satisfait et le contrat de données est rompu. Si un opérateur relance A après B, l'historique peut afficher une séquence valide alors que B a lu l'ancienne génération. Succès de l'ordonnancement et justesse des données sont deux questions.
Utilisez un enregistrement d'arête vérifiable :
consumer_job: PAYM020
producer_job: PAYM010
object: PROD.PAYMENTS.CLEARED.G0123V00
consumer_access: read
producer_access: create-and-close
producer_close_utc: 01:47:12
consumer_open_utc: 02:00:08
schedule_edge: none
evidence: expanded-jcl, catalog, smf
confidence: observed
Le format de stockage importe peu. La séparation entre objet, temps, type d'arête, preuve et confiance est indispensable.
Partez du lecteur de 02:00 et résolvez son exécution
Commencez par l'instance consommatrice, pas par un nom copié d'un schéma. Relevez le nom du job, l'ID JES, l'occurrence ou le numéro d'exécution, l'heure réelle, le système et la date métier traitée. Autour de minuit, des jours fériés et des relances, la date batch diffère souvent de la date civile. Sans identité d'occurrence, deux exécutions du même job se mélangent.
Récupérez le JCL soumis ou développé de cette occurrence si les sorties conservées le permettent. Le JCL source d'une bibliothèque est une preuve plus faible, car une procédure ou variable a pu changer. Développez les procédures cataloguées et en ligne, appliquez les SET, résolvez les symboles et relevez les surcharges EXEC et DD. Ajoutez les datasets alloués dynamiquement signalés par le programme ou les traces, absents des DD source.
Ce petit exemple montre la limite du seul membre :
//PAYM020 JOB ...
// SET BDATE=20260813
//READ EXEC PROC=PAYREAD,ENV=P,DAY=&BDATE
//INFILE DD DSN=PROD.PAYMENTS.CLEARED(+0),DISP=SHR
//CTL DD DSN=PROD.CTL.PAY.&BDATE,DISP=SHR
Le catalogue résout (+0) à l'allocation, pas lorsqu'une personne rouvre le membre. Après la création d'une génération, le (+0) actuel peut désigner un autre objet que celui lu à 02:00. Conservez l'expression relative et le nom absolu GnnnnVnn observé pour l'occurrence. Même règle pour les symboles de date : &BDATE ne donne un lignage qu'avec sa valeur résolue.
Classez chaque entrée. Datasets séquentiels permanents, GDG, clusters VSAM, temporaires transmis dans un job, fichiers UNIX, tables et fichiers de contrôle demandent des traces différentes. DISP=SHR suggère une entrée mais ne prouve pas la lecture, et un programme peut lire un DD nommé comme sortie. La preuve d'accès prime sur la convention.
Pour l'enregistrement lu à 02:00, remontez depuis le fichier ou l'objet de base qui le contient. Ne cherchez pas d'abord sa valeur dans tout le parc : les valeurs se répètent, les formats évoluent et les données personnelles compliquent le traitement. Établissez l'objet, le membre, la partition ou la table et l'heure d'accès, puis cherchez les auteurs vers l'amont.
Le JCL développé donne des candidats, pas des auteurs
L'analyse statique doit produire vite un graphe candidat sans attribuer la paternité finale. Décomposez chaque job en étapes et DD. Ne normalisez les noms qu'après avoir gardé l'expression d'origine. Relevez programme, origine de procédure, disposition, référence de génération, position dans une concaténation et valeurs symboliques. Une concaténation rend le lignage conditionnel : un membre peut venir de la première bibliothèque ce soir et de la troisième après un déploiement.
La disposition fournit des indices. DISP=NEW avec catalogage à la fin normale suggère une création. DISP=MOD peut ajouter ou créer. DISP=OLD donne l'exclusivité sans dire si le programme lit, remplace ou met à jour. DISP=SHR autorise le partage chez lecteurs comme auteurs. Ce sont des étiquettes candidates, jamais une preuve du mode d'ouverture.
Les datasets temporaires créent des arêtes entre étapes. Un &&WORK transmis peut expliquer l'enregistrement avant toute sortie permanente. Donnez-lui une identité limitée à l'occurrence, comme ID de job plus identifiant d'allocation DD. Ne fusionnez pas tous les &&TEMP du parc.
Inspectez aussi utilitaires et programmes appelés. SORT peut créer le fichier sous une étape COPY. IDCAMS peut modifier un cluster VSAM cité dans ses commandes. Un programme COBOL peut construire un nom et demander l'allocation dynamique. Une mise à jour peut se cacher derrière un plan générique ou une procédure stockée. Marquez ces effets comme non résolus et dirigez-les vers la bonne source. Deviner à partir du nom d'étape fabrique un faux lignage.
Un analyseur utile émet des candidats :
PAYM010/SORTCLR -> may_write -> PROD.PAYMENTS.CLEARED(+1)
PAYM020/READ -> may_read -> PROD.PAYMENTS.CLEARED(+0)
PAYM025/ARCHIVE -> may_read -> PROD.PAYMENTS.CLEARED(-1)
Résolvez ensuite les générations par occurrence. Si PAYM010 crée et catalogue G0123V00 avant l'allocation de (+0) par PAYM020, les expressions convergent. Si l'allocation précède la mise à jour du catalogue, elles divergent. L'ordre des jobs ne suffit pas, car les heures d'allocation et d'ouverture comptent.
L'ordonnanceur explique l'éligibilité et les barrières cachées
Exportez définitions et historique pour la même date métier. Les définitions montrent prédécesseurs, calendriers, cycles, ressources, événements, arrivées de fichiers, tests de code retour et tables de variables. L'historique montre ce qui s'est appliqué et les jobs supprimés, ajoutés, retenus, forcés, relancés ou libérés à la main. Les deux sont nécessaires. Une définition propre peut décrire une nuit qui n'a jamais eu lieu.
Les ressources cachent souvent le lien manquant. Un producteur pose FILE.CLEARED.READY, tandis que le consommateur attend cette ressource sans nommer le producteur. Un job de reprise peut aussi la poser. Faites de la ressource un nœud : le producteur la pose, elle libère le consommateur. Une arête directe masque l'auteur alternatif et l'action opérateur.
Les calendriers créent des graphes conditionnels. Le producteur de clôture peut tourner seulement le dernier jour bancaire, alors que le lecteur tourne chaque jour et réutilise sinon le fichier précédent. Aucun schéma universel ne le représente honnêtement. Attachez calendrier métier, date applicative et type d'exécution à l'arête. Générez un graphe pour une occurrence ou un scénario nommé.
La logique des codes retour mérite la même précision. Un lecteur peut continuer après un avertissement mais prendre un dataset de secours. Une étape peut dépendre d'un code particulier. Gardez les conditions au niveau job et étape. après PAYM010 est moins utile que éligible si PAYM010 finit avec RC <= 4 et FILE.CLEARED.READY existe.
Les actions manuelles appartiennent au graphe car elles changent la causalité. Si la politique le permet, relevez l'opérateur, l'heure, l'ancien et le nouvel état, et la justification. Un prédécesseur forcé à terminé n'a pas produit de données. Il a seulement fait réagir l'ordonnanceur comme si le prérequis était satisfait. Cette nuance explique vite une lecture de données périmées.
L'ordonnanceur n'est pas un catalogue de données. Il explique pourquoi le travail a démarré, pas forcément quels octets il a lus. Sa meilleure contribution est un historique daté des permissions, exceptions et interventions humaines.
Les traces de production désignent l'auteur réel
Les preuves de production transforment les possibilités en observations. Sur z/OS, joignez temps de job et d'étape, activité dataset, sorties JES, catalogue, messages utilitaires, journaux applicatifs et données d'audit ou logs de base disponibles. La documentation SMF d'IBM sépare comptabilité des jobs et activité des datasets, car aucun type ne forme seul un lignage complet. Le type 30 ancre les exécutions, et les types 14 et 15 peuvent fournir la fermeture de datasets non VSAM si l'enregistrement est actif. VSAM et les bases exigent leurs propres données.
Cette réserve compte. L'absence d'un enregistrement SMF ne prouve pas l'absence d'accès. Options, méthode d'accès, tampons, sous-système et rétention peuvent retirer la preuve attendue. Notez non observé plutôt que n'a pas eu lieu, sauf si vos contrôles autorisent cette dernière conclusion.
Pour un dataset séquentiel, partez à rebours de la fenêtre du consommateur :
- Résolvez l'occurrence et le nom absolu.
- Trouvez les lectures observées de son job et de son étape.
- Cherchez les écritures antérieures du même nom.
- Joignez les auteurs candidats au type 30 et aux sorties JES.
- Vérifiez catalogue et ordonnanceur autour des reprises et libérations manuelles.
Supposons que PAYM020 lise G0123V00 à 02:00. L'ordonnanceur place la fin de PAYM010 à 01:48 et SMF sa fermeture à 01:47. Un job de reprise ouvre aussi l'objet en sortie à 01:55 et le ferme à 01:58. Le prédécesseur n'est pas le dernier auteur. Le graphe doit garder les deux écritures, et l'arête du lecteur viser l'état suivant la reprise. Pour un objet modifié en place, l'identité seule ne suffit pas : le temps sépare les états.
Les lignes de base exigent une autre jointure. Trouvez la table et la clé métier, puis utilisez logs, audit, heures de commit, identifiants de corrélation, plans ou packages et contexte du job. L'auteur est la transaction qui a validé la version visible, pas le batch parti en premier. Le niveau d'isolation détermine aussi la version lisible. Si la télémétrie ne relie pas transaction et occurrence, dites-le et gardez un ensemble borné de candidats.
Le temps et l'identité empêchent les fausses jointures
La plupart des mauvais graphes joignent des noms sans intervalles. Les noms de jobs reviennent, les datasets se réutilisent, une référence GDG relative change de sens, une occurrence peut être reconstruite et une ligne possède plusieurs versions. Modélisez d'abord les événements, puis dérivez des arêtes entre états observés à des instants précis.
Employez une chronologie commune, de préférence UTC avec heure locale et zone d'origine. Les horloges du mainframe, de l'ordonnanceur, de la base et des logs distribués peuvent diverger. Mesurez les décalages ou conservez une fenêtre d'incertitude. N'imposez pas d'ordre exact à deux événements dans cette fenêtre. Une fermeture à 01:59:59,8 et une ouverture à 02:00:00,1 semblent ordonnées jusqu'à la découverte de deux secondes de décalage.
L'identité doit inclure système et occurrence. Une clé pratique réunit application et occurrence de l'ordonnanceur, nom, ID JES, système et heure de début. Pour une étape, ajoutez nom et séquence, car l'expansion peut répéter les noms. Pour l'état d'un dataset, gardez le nom absolu qualifié, le contexte volume ou catalogue si nécessaire et l'intervalle d'écriture.
Attribuez la confiance d'après les preuves. Observé signifie que la télémétrie consigne l'accès. Corroboré signifie que des sources indépendantes concordent. Déclaré repose seulement sur une règle. Inféré vient d'une convention ou d'une proximité. Contradictoire signale un désaccord. Ces étiquettes évitent de faire passer toutes les arêtes pour également certaines.
Précisez aussi les résultats négatifs. Aucun auteur trouvé dans le SMF conservé entre 00:00 et 02:00 ; enregistrement actif sur les systèmes concernés ; état antérieur non examiné est utile. Producteur inconnu perd le périmètre de recherche. Toute preuve a une portée que le graphe doit conserver.
Les relances révèlent le graphe jamais documenté
Les relances font échouer les cartes nominales. L'ordonnanceur peut créer une occurrence, reprendre à une étape ou réutiliser le nom avec un nouvel ID JES. Le job peut réutiliser un GDG, créer une génération, ajouter à un dataset fixe ou corriger seulement certaines lignes. Modélisez chaque exécution et écriture comme un événement. N'écrasez jamais le premier passage par la reprise.
Cas courant : le producteur crée G0123V00 puis finit avec RC 8 après l'écriture mais avant la ressource. Un opérateur vérifie le fichier, force la fin et libère le lecteur. Une reprise corrige ensuite quelques enregistrements sur place. Le lecteur démarre entre les deux. Le graphe de définition dit échec puis reprise ; le graphe de données dit lecture du fichier initial avant correction. Les deux sont vrais.
Tester l'existence du fichier est une barrière faible. Un fichier fixe périmé la satisfait. (+0) peut résoudre la dernière génération cataloguée même si le producteur du jour n'a pas tourné. Un code 0 peut accompagner un extrait vide. Liez la disponibilité à la date métier et à la version, puis vérifiez le contrat de contenu. Un petit contrôle contenant date, occurrence, nombre de lignes et état final rend ce lien explicite s'il est écrit seulement après commit ou fermeture réussis.
N'ajoutez pas une flèche pour chaque arête observée. Certaines données sont partagées volontairement, et un prédécesseur direct peut sérialiser des travaux indépendants ou créer des cycles. Ajoutez un ordre lorsque la justesse l'exige. Ailleurs, fraîcheur et contrôle de version expriment mieux le contrat. Le conseil populaire d'ajouter des prédécesseurs pour faire correspondre dessin et production confond documentation et politique d'exécution.
Les tests de reprise doivent couvrir sortie partielle, redémarrage après l'étape d'écriture, double génération, fin forcée, auteur de reprise tardif et lecteur lancé pendant la correction. Un graphe incapable de décrire ces états ne représente que les bonnes nuits.
Tenez un registre de preuves avant de dessiner
Le graphe est une vue, pas le registre principal. Stockez observations et déclarations dans un journal en ajout seulement, puis dérivez la vue d'une date métier ou d'un incident. On peut alors corriger une conclusion sans effacer celle d'un outil antérieur, et remonter de chaque arête à sa source.
Chaque entrée demande source, heure de collecte, heure d'événement, système, identités de l'occurrence et de l'objet, action, attributs résolus et pointeur de rétention. Laissez les preuves brutes sous leurs contrôles existants ; le registre peut garder une référence et quelques champs non sensibles. Les noms de datasets et métadonnées de jobs peuvent révéler des fonctions métier : la carte n'est pas anodine.
Une requête de rapprochement doit signaler les divergences plutôt que choisir en silence : prédécesseur déclaré sans objet partagé observé, couple auteur-lecteur sans contrôle, GDG relatif non résolu ou ouverture du lecteur précédant la fermeture choisie dans la fenêtre d'incertitude. Ce sont des files de travail pour un ingénieur, pas des défauts automatiquement prouvés.
L'attribution devient gérable par domaine de preuve. Les administrateurs de l'ordonnanceur extraient les définitions, les équipes stockage ou plateforme collectent catalogue et SMF, les applications expliquent allocation dynamique et sémantique, les bases suivent les versions validées. Personne ne doit connaître tout le graphe ; le journal a besoin d'interfaces stables entre ces preuves.
Fixez la rétention selon l'horizon d'enquête. Si l'historique de l'ordonnanceur survit aux activités dataset, un ancien incident semblera n'avoir que des arêtes d'ordre. Si le JCL développé disparaît avant la prochaine clôture, résoudre les symboles devient une devinette. Consignez le premier instant disponible de chaque source pour rendre visible la baisse de confiance.
CodeHero lit en parallèle tout l'arbre patrimonial, dont COBOL et JCL, et peut utiliser le trafic de production enregistré dans un banc de parité pendant la réécriture. Le graphe statique et le comportement observé restent ainsi deux preuves distinctes jusqu'à leur accord.
Une carte fiable change la manière de remplacer le batch
Quand le registre sait qui a écrit l'état lu à 02:00, utilisez-le pour fixer les frontières de migration. Groupez les jobs par contrats transactionnels et de données, pas par dossier ou préfixe. Producteur et lecteur peuvent appartenir au même lot malgré des propriétaires différents. Deux voisins dans l'ordonnanceur peuvent rester séparés si seul un créneau opérationnel les relie.
Transformez chaque arête observée en assertion de parité. Avec le même état d'entrée enregistré, le remplacement doit produire les mêmes enregistrements externes, modifications de base, conditions de retour et signaux de disponibilité. Normalisez les champs volontairement variables comme les ID ou heures, en documentant chaque règle. Un banc qui ignore l'ordre, les sorties vides et la reprise approuvera la nuit facile et échouera pendant l'incident.
Gardez l'observation de l'ancien système pendant les répétitions de bascule. Un nouveau service peut publier une transaction Postgres là où le batch cataloguait un dataset et posait une ressource. L'implémentation change, mais le contrat garde un état producteur, un instant de visibilité, un lecteur et une date métier. Reliez explicitement les anciennes preuves au nouveau contrat au lieu de copier les flèches dans un schéma de services.
Le premier livrable doit rester étroit : une occurrence consommatrice, toutes les entrées réellement ouvertes et le dernier auteur de chaque état visible. Incluez candidats non résolus et lacunes. Examinez-le avec l'exploitation pendant une nuit comprenant une relance, pas seulement devant un calendrier propre. Étendez ensuite par les objets observés.
Le processus de revue a besoin de critères explicites. Pour chaque arête observée, un réviseur doit pouvoir ouvrir les preuves, identifier les deux occurrences, résoudre le nom de l'objet et reproduire l'ordre temporel sans convention orale. Pour chaque arête déclarée sans observation, le registre doit préciser si la télémétrie manquait, si le chemin était inactif à cette date ou si la déclaration semble périmée. Le graphe peut contenir de l'incertitude, mais pas en cacher la cause.
Recalculez la vue lorsque changent une définition, une procédure, la logique d'allocation ou la collecte. Ne reconstruisez pas toutes les arêtes à intervalles fixes. Invalidez les relations candidates touchées, puis attendez une occurrence de production adaptée pour les confirmer. Une seule procédure modifiée ne fera pas paraître tout le graphe nouvellement découvert, et l'historique expliquera encore la différence entre hier et aujourd'hui.
Ajoutez des contrôles aux frontières de la collecte. Refusez un accès sans source d'horloge système. Isolez un nom GDG absolu contraire à l'instantané du catalogue. Alertez si deux occurrences revendiquent le même ID JES sur le même système pendant des périodes qui se chevauchent. Signalez un objet déclaré nouveau sans fermeture ni commit avant le départ du lecteur. Ces contrôles ne jugent pas la justesse métier, mais empêchent une preuve mal formée de devenir une dépendance certaine.
Mesurez la carte par les questions auxquelles elle répond, pas par son nombre de nœuds. Reprenez des incidents et demandez quel état chaque lecteur a vu, pourquoi il a été libéré, quelle action manuelle a changé le chemin et quelle source prouve chaque réponse. Incluez une nuit normale, une entrée tardive, un redémarrage à une étape ultérieure et une écriture de reprise après le producteur nominal. Si un ingénieur doit encore fouiller le spool, le registre possède une lacune nommée. Un grand graphe vague aide moins qu'un petit graphe reproductible.
Le graphe utile ne sera jamais une affiche intemporelle. C'est une requête sur des preuves versionnées : plan déclaré, faits d'une nuit choisie et écarts entre les deux. À la question de l'auteur de l'enregistrement lu à 02:00, la réponse doit nommer occurrence, version d'objet, heure de visibilité et sources probantes. Sinon, elle reste une supposition.
FAQ
Le JCL suffit-il à révéler toutes les dépendances nocturnes ?
Non. Il montre des accès déclarés ou possibles, mais procédures, allocations dynamiques, bases et résolutions à l'exécution laissent des trous. Trouvez les candidats avec le JCL développé, puis confirmez-les par l'historique et les traces.
Comment trouver le job qui a créé une génération GDG ?
Résolvez la référence relative du lecteur en nom absolu GnnnnVnn pour cette occurrence. Cherchez ensuite création et fermeture dans le catalogue et les traces, puis joignez-les à l'ID JES et aux temps d'étape.
Un prédécesseur d'ordonnanceur prouve-t-il une dépendance de données ?
Non. Il prouve une règle d'ordre déclarée ou appliquée. Identifiez l'objet partagé et montrez que le lecteur a vu l'état créé par cette occurrence.
Que faire si SMF ne montre aucun accès au dataset ?
Vérifiez types d'enregistrements, systèmes, méthodes d'accès et fenêtre de rétention. Notez non observé dans ce périmètre ; une télémétrie absente ne prouve pas l'absence d'accès.
Comment représenter les jobs relancés dans le graphe ?
Donnez à chaque relance sa propre occurrence et son ID JES, et gardez chaque écriture comme événement. Reliez le lecteur à l'état visible lors de son ouverture, même issu d'une reprise.
Un code retour nul prouve-t-il que l'entrée était prête ?
Non. Un job peut finir normalement avec un résultat vide, périmé ou incomplet. Liez la disponibilité à la date métier et à la version, puis contrôlez le contenu selon le risque.
Comment relier une ligne de base à un job batch ?
Partez de la clé métier et de la version validée visible, puis corrélez logs ou audit avec plan, package, transaction et contexte du job. Si la jointure reste impossible, gardez les auteurs candidats au lieu de choisir par l'heure.
Pourquoi les cartes échouent-elles autour de minuit ?
Date civile, date métier et occurrence peuvent diverger, et les horloges dérivent. Stockez la date métier et comparez les événements sur une chronologie commune avec une fenêtre d'incertitude.
Chaque dépendance observée doit-elle devenir un lien d'ordonnancement ?
Non. N'ajoutez l'ordre que lorsque la justesse l'exige. Les données de référence partagées demandent parfois un contrôle de fraîcheur plutôt qu'un prédécesseur qui bloque du travail indépendant.
Quel est le plus petit livrable utile de lignage batch ?
Documentez une occurrence, les entrées réellement ouvertes et le dernier auteur de chaque état visible. Ajoutez sources, heures, confiance et candidats non résolus pour que le résultat soit reproductible.