Les vieux scripts Perl que personne ne veut toucher
Repérez les vieux scripts Perl encore actifs, reconstruisez leurs dépendances CPAN et révélez les règles métier cachées dans les regex.

Un répertoire Perl vieux de quinze ans forme rarement un seul système. C'est plutôt un amas de tâches cron, d'utilitaires copiés, de correctifs d'urgence, de raccords avec des logiciels tiers et d'un ou deux programmes qui déplacent encore de l'argent ou des données clients chaque nuit. Le premier travail n'est pas de le réécrire. Il faut d'abord prouver quels fichiers participent encore au comportement de la production.
J'ai vu des équipes commencer par le plus gros script, nettoyer sa syntaxe, puis découvrir que la production appelait une copie plus petite par l'intermédiaire d'un ordonnanceur sur une autre machine. C'est ainsi qu'un projet de modernisation bien rangé casse un processus laid, mais fonctionnel. Traitez le système en service comme une source de preuves. Construisez l'inventaire en partant de l'exécution, puis décidez ce qui mérite d'être supprimé, confiné, réparé ou remplacé.
Partez de l'exécution, pas de l'arborescence source
Une arborescence source ne peut pas vous dire ce qui tourne encore. Il faut des preuves venant des ordonnanceurs, des relevés de processus, des définitions de services, de l'historique du shell, des lanceurs d'applications, des horodatages de fichiers et des systèmes qui consomment les résultats. Un fichier peut sembler abandonné alors qu'un traitement financier trimestriel l'appelle encore. Un autre peut être modifié chaque jour par un déploiement sans jamais être exécuté.
Inspectez chaque ordonnanceur capable de lancer du travail, pas seulement la crontab de l'utilisateur courant. Vérifiez les répertoires cron du système, les minuteries de services, les ordonnanceurs de lots, les tâches de base de données, les systèmes d'intégration continue, les panneaux d'administration et l'ordonnanceur d'entreprise que l'exploitation a oublié de mentionner. Sur les machines de type Unix, ce premier passage fournit des pistes utiles sans prétendre que la machine en sait plus qu'elle n'en sait réellement :
ps -eo pid,lstart,args | grep '[p]erl'
find /etc/cron.d /etc/cron.daily /etc/cron.hourly -type f -exec grep -nH 'perl\|\.pl' {} \;
grep -R -n 'perl\|\.pl' /etc/systemd/system /usr/lib/systemd/system
find /opt /srv /usr/local -type f \( -name '*.pl' -o -name '*.pm' \) -print
Une sortie de processus typique contient un PID, l'heure de démarrage et la ligne de commande complète. Les arguments comptent, car ils sélectionnent souvent le véritable mode métier :
1842 Mon Aug 10 01:00:02 2026 /usr/bin/perl /opt/billing/bin/post.pl close
Répétez l'échantillonnage des processus sur tout le calendrier de l'entreprise. Un instantané rate les tâches qui ne durent que quelques secondes. Pour chaque exécution observée, conservez le chemin d'origine, le chemin de l'interpréteur, le répertoire de travail, l'utilisateur, les arguments, la source de l'environnement, la condition de démarrage, la fréquence, les entrées, les sorties et le consommateur en aval. Si vous ne pouvez pas nommer le consommateur, l'inventaire n'est pas terminé.
Examinez séparément les traces de déploiement. Un manifeste de paquet peut révéler un script installé hors du chemin du dépôt que vous avez inspecté, et un ancien script de livraison peut renommer ou générer du Perl pendant l'installation. Comparez les empreintes entre machines au lieu de faire confiance aux noms de fichiers identiques. Indiquez qu'un fichier est généré, puis retrouvez le modèle ou la commande qui le produit. Sinon, un futur déploiement peut rétablir discrètement du code que vous pensiez avoir retiré. Interrogez aussi les opérateurs sur les lancements manuels, surtout les réparations de fin de mois et les reprises après un échec partiel. Ces opérations ne laissent souvent aucune entrée permanente dans un ordonnanceur.
Les journaux des machines peuvent renforcer les preuves. La comptabilité des processus, les journaux d'audit, les journaux des ordonnanceurs et la télémétrie des postes peuvent révéler d'anciennes exécutions. Si ces sources n'ont jamais été activées, inscrivez-le dans l'inventaire. Ne transformez pas l'absence de traces en affirmation qu'un script est mort.
Un graphe d'appels a des arêtes hors de Perl
Le graphe d'appels utile comprend le shell, JCL, les entrées d'ordonnanceur, la configuration du serveur web, les tâches de base de données, l'arrivée de fichiers et les personnes qui suivent des procédures. L'analyse statique de Perl ne couvre qu'une partie de ce graphe. Un require dynamique, des noms de modules construits, eval, des fonctions de rappel et des gestionnaires choisis par la configuration peuvent masquer des arêtes même à l'intérieur du langage.
Commencez par les références littérales et les shebangs, puis suivez chaque point d'entrée confirmé vers l'extérieur :
grep -R -n 'use \|require \|do ' /opt/legacy-perl
grep -R -n '/opt/legacy-perl\|perl ' /opt /srv /usr/local/etc
find /opt/legacy-perl -type f -perm -u+x -exec head -n 1 {} \;
Créez un registre comportant une ligne par fichier exécutable. Attribuez à chaque ligne un état de preuve : observé, configuré, référencé ou sans référence. Gardez ces états distincts. Une entrée d'ordonnanceur prouve une configuration, pas une exécution réussie. Un nom de fichier dans une procédure prouve une intention humaine, pas un usage actuel. Un processus actif constitue une preuve forte, mais il peut s'agir d'une tâche bloquée plutôt que saine.
Consignez ensuite les arêtes entrantes et sortantes. Les arêtes entrantes expliquent le début de l'exécution. Les arêtes sortantes comprennent les modules, les exécutables, les bases de données, les files de messages, les relais de courrier, les machines distantes et les fichiers. Notez aussi les formats de données. Un fichier séparé par des tabulations dont l'ordre des colonnes n'est pas documenté est une interface, même si personne ne l'a jamais appelée ainsi.
Une suppression demande deux types de preuves : aucune arête entrante observée ou configurée pendant une période de fonctionnement représentative, et aucune sortie unique attendue par un autre processus. Placez le candidat en quarantaine avant de le supprimer. Retirez son droit d'exécution ou déplacez son entrée d'ordonnanceur dans un fichier désactivé et versionné, puis surveillez les attentes non satisfaites. Gardez un moyen de restauration rapide. L'ancienneté ne donne pas au code une immunité sentimentale, mais l'incertitude n'est pas une preuve.
Reproduisez l'interpréteur avant de corriger le code
Le comportement de Perl dépend de plus que le fichier .pl. Relevez l'interpréteur exact et ses options de compilation avant tout essai. /usr/bin/perl peut différer d'un Perl installé sous /opt, et un wrapper peut modifier PERL5LIB, la langue, le fuseau horaire ou le répertoire courant. Ces différences peuvent changer la résolution des modules, l'analyse des dates, le tri et le traitement du texte.
Exécutez les commandes suivantes avec l'identité de production, dans son répertoire de travail, et retirez les secrets de la sortie enregistrée :
command -v perl
perl -v
perl -V
perl -e 'print join("\n", @INC), "\n"'
env | grep '^PERL\|^LANG\|^LC_\|^TZ'
perl -V indique comment l'interpréteur a été construit et affiche des valeurs de configuration qui expliquent les problèmes de portabilité. La sortie de @INC montre dans quel ordre Perl cherche réellement les modules. Conservez les deux avec l'inventaire. Une dépendance dans un répertoire privé de l'application passe facilement inaperçue si vous ne consultez que la liste des paquets du système d'exploitation.
Les contrôles de compilation sont utiles, à condition d'en comprendre la portée :
perl -c /opt/legacy-perl/bin/post.pl
Un résultat comme syntax OK prouve que la compilation a abouti dans cet environnement. Il ne prouve pas qu'un module chargé dynamiquement existe sur une branche rare, qu'une connexion à la base de données fonctionne ou que le script produit le bon résultat. Compilez chaque point d'entrée confirmé avec le même utilisateur, le même environnement, les mêmes arguments et le même répertoire de travail qu'en production. Ne commencez jamais par ajouter use strict ou modifier les avertissements dans toute l'arborescence. Ce sont de bonnes pratiques pour du code entretenu, mais elles modifient la surface de diagnostic avant que le comportement de référence soit enregistré.
Mettre l'ancien environnement dans un conteneur peut faciliter sa reproduction, mais un conteneur n'est pas une machine à vérité archéologique. Les bibliothèques natives, les commandes système, les certificats, le DNS, les droits du système de fichiers, les données de langue et le comportement de l'ordonnanceur restent hors de la liste des dépendances Perl. Consignez ces arêtes au lieu de supposer que l'image les a capturées.
Observez sans risque avant d'instrumenter
L'observation de l'exécution doit commencer hors du processus, car modifier un ancien script peut changer sa temporisation, son environnement et son traitement des erreurs. Relevez d'abord les horodatages de l'ordonnanceur, la durée du processus, les fichiers ouverts, les processus enfants, les destinations réseau, le code de retour et les changements du système de fichiers. Rassemblez si possible ces faits dans une copie de l'environnement. En production, utilisez des moyens en lecture seule déjà autorisés par l'exploitation et fixez une courte période d'observation.
La trace des appels système aide lorsque le code cache des chemins derrière des variables ou la configuration. Elle peut montrer quel fichier de module a été ouvert, quel exécutable le script a lancé et quel fichier de configuration il a essayé avant de se rabattre sur une valeur par défaut. Elle enregistre aussi beaucoup de données sensibles et peut ralentir un processus chargé. Filtrez les opérations sur les fichiers et les processus, stockez la trace dans un espace protégé et faites approuver la commande par un opérateur. Ne vous attachez pas sans précaution à un traitement de paiement ou de règlement sous prétexte que la trace semble passive. Observer a un coût d'exploitation.
Comparez le processus avant et pendant la sonde. Relevez les heures de début et de fin, l'utilisation du processeur et de la mémoire, le code de sortie, le nombre de lignes ou de fichiers et le signal d'échec habituel. Si l'exécution instrumentée dure nettement plus longtemps ou change l'ordre des opérations, écartez-la comme référence de comportement et cherchez la cause. Une sonde qui perturbe le système peut encore révéler des dépendances, mais elle ne doit pas définir la parité.
La journalisation dans l'application vient plus tard. Placez-la derrière une variable d'environnement désactivée par défaut et émettez des événements aux frontières métier plutôt qu'à chaque appel de sous-programme. Un événement utile nomme le mode choisi, l'identifiant d'entrée, le résultat de la règle, le chemin de dépendance, l'action externe et l'état final. Ne journalisez pas les dossiers bruts simplement parce que l'ancien code ne classe pas les données. Expurgez avant la sérialisation afin qu'une valeur sensible n'arrive jamais dans le collecteur de journaux.
Un wrapper est souvent plus sûr que des modifications du script. Il peut enregistrer le répertoire de travail, l'environnement expurgé, les arguments, les heures de début et de fin, le code de sortie et les empreintes des résultats désignés. Conservez l'ordre des arguments et utilisez exec lorsque le wrapper doit préserver le comportement des processus et des signaux. Testez la propagation des signaux, car les ordonnanceurs peuvent utiliser un signal de fin pour imposer une fenêtre d'exécution. Un wrapper qui absorbe ce signal modifie le contrat de production.
Ne laissez pas une trace temporaire sans responsable ni date de retrait. Les points de diagnostic deviennent facilement permanents, surtout lorsqu'ils produisent le seul relevé d'erreur exploitable. Si l'un d'eux doit rester, traitez-le comme un dispositif maintenu: documentez son schéma, sa rotation, ses contrôles d'accès, son expurgation et son comportement en panne. Décidez ce qui se passe si la destination des journaux est pleine ou disparaît. Un ancien lot ne doit pas cesser de comptabiliser des factures parce qu'un nouveau disque de diagnostic est plein.
Le résultat de l'observation doit modifier des lignes précises du registre. Remplacez un chemin de module supposé par le chemin observé, ajoutez un processus enfant nouvellement vu ou faites passer un point d'entrée de configuré à observé. Conservez la trace brute séparément avec des droits plus stricts et notez son mode de collecte. Cette séparation garde l'inventaire de travail utile sans en faire un entrepôt de données clients ou de secrets.
Reconstruire CPAN demande des preuves
Un module nommé dans use n'est pas forcément une dépendance CPAN. Il peut être fourni avec cette version de Perl, venir d'un paquet du système, se trouver dans le dépôt ou être une copie corrigée localement qui porte le nom d'un module public. À l'inverse, un script peut charger dynamiquement un module sans instruction use visible. Construisez l'ensemble des dépendances en partant de l'exécution.
Pour chaque point d'entrée confirmé, relevez les chemins des modules chargés dans un environnement de test sûr :
perl -MData::Dumper -e 'END { print Dumper(\%INC) } do shift' /opt/legacy-perl/bin/post.pl
Cette sonde simple n'est pas sûre pour un script qui agit dès son chargement. Utilisez-la uniquement dans une copie de l'environnement où les écritures externes sont bloquées, ou ajoutez temporairement un point de diagnostic dans une branche de test. %INC associe les noms des modules chargés aux fichiers choisis par Perl, ce qui révèle les copies privées et les surprises dues à l'ordre des chemins. Exercez d'autres parcours que le cas nominal, car les chargements conditionnels n'apparaissent que lorsque leur branche s'exécute.
Comparez quatre sources : les imports trouvés dans le code, %INC lors d'exécutions représentatives, les fichiers des répertoires de bibliothèques locales et les distributions installées signalées par la machine d'origine. perldoc perllocal peut garder la trace des modules installés par les outils CPAN, mais les paquets système et les copies manuelles peuvent la rendre incomplète. La base des paquets du système d'exploitation apporte une autre pièce. Aucune de ces sources ne suffit seule.
Inscrivez les dépendances directes reconstruites et leurs contraintes de version dans cpanfile. Fixez ce dont l'application prouve qu'elle a besoin, pas tous les modules transitifs présents sur un ancien serveur. Utilisez ensuite Carton ou un autre installateur contrôlé pour résoudre et installer dans un répertoire isolé. Gardez la sortie du résolveur et les journaux des compilations échouées comme preuves du projet.
requires 'DBI', '1.643';
requires 'DateTime', '1.54';
requires 'Text::CSV_XS', '1.49';
Ces versions illustrent la forme du fichier, elles ne sont pas des recommandations. Vos contraintes doivent venir de la machine qui fonctionne, des exigences du code source et des tests de comportement. Si aucune version n'était déclarée, commencez par consigner la version installée qui a produit le comportement de référence. Ne l'assouplissez qu'après avoir démontré par des tests qu'une autre version conserve ce comportement.
Lorsqu'une ancienne version ne s'installe plus, trouvez la cause exacte. Un compilateur absent, une bibliothèque C indisponible, une distribution retirée, un test en échec et du code incompatible avec un nouveau Perl demandent des corrections différentes. Ne résolvez pas les cinq en copiant l'ancien répertoire site_perl. Cette copie peut conserver un module binaire compilé pour la mauvaise ABI et reporter la panne jusqu'à la mise en charge. Archivez les distributions et correctifs d'origine lorsque les licences le permettent, mais rendez la nouvelle construction reproductible à partir d'entrées déclarées.
Les expressions régulières sont des règles exécutables
L'expression régulière dangereuse est rarement la plus longue. C'est celle dont le résultat décide d'un prix, d'une catégorie de compte, d'une destination, d'un motif de refus ou d'un indicateur de conformité. Traitez ces expressions comme des règles métier même si elles se cachent dans une substitution ou un grep d'une ligne. Une regex de mise en forme et une regex de décision ne se révisent pas de la même manière.
Repérez les candidates par une recherche dans le code, puis classez-les selon leurs conséquences. La syntaxe de Perl rend irréaliste une extraction statique parfaite. Examinez donc les branches et les sorties voisines au lieu de compter les métacaractères. Surveillez surtout les substitutions, les variables de capture comme $1, les alternatives qui contiennent du vocabulaire métier et les motifs construits depuis la configuration.
Le manuel perlre explique que Perl choisit d'abord la correspondance la plus à gauche et que les quantificateurs sont gourmands par défaut. Ces faits semblent élémentaires, mais ils deviennent un comportement métier lorsque des alternatives se chevauchent ou que des captures alimentent des calculs. Un nettoyage ultérieur qui réordonne les alternatives ou ajoute une ancre peut changer les dossiers clients retenus. Un changement d'Unicode ou de langue peut aussi modifier les classes de caractères et la conversion de casse.
Avant toute restructuration, transformez chaque expression lourde de conséquences en table nommée d'exemples :
my @cases = (
['ACCT-001-EU', 'eu', 1],
['ACCT-001-US', 'domestic', 1],
['acct-001-eu', undef, 0],
['ACCT-001-EU ', undef, 0],
);
for my $case (@cases) {
my ($input, $class, $accepted) = @$case;
my ($got) = $input =~ /\AACCT-\d{3}-(EU|US)\z/;
my $ok = defined $got ? 1 : 0;
die "acceptance changed for <$input>" if $ok != $accepted;
}
Les valeurs de cet exemple sont inventées pour montrer la forme d'un test de caractérisation. Les vrais cas doivent venir d'entrées de production expurgées, de dossiers rejetés, d'exemples donnés par les opérateurs et de valeurs limites. Conservez les espaces initiaux, l'encodage, les fins de ligne, les champs vides et les entrées mal formées. Normaliser les jeux de données trop tôt efface le comportement à découvrir.
Ne traduisez pas directement une regex dense en expression tout aussi dense dans le langage cible. Nommez d'abord la règle dans le vocabulaire du métier, gardez le motif original comme oracle pour les cas de test et écrivez des tests autour des valeurs acceptées, rejetées et extraites. Certaines expressions devraient devenir du code d'analyse ordinaire ou une table, car la règle doit être relue par des personnes qui ne parlent pas regex.
Enregistrez le comportement aux frontières du système
Des tests unitaires ajoutés aux anciens composants internes entérinent souvent des accidents d'implémentation tout en ratant le contrat dont dépendent les autres systèmes. Capturez d'abord le comportement aux frontières : fichiers d'entrée, arguments de commande, lectures en base, lignes émises, codes de sortie, sortie standard, erreur standard, messages et changements d'état. Vous pourrez ensuite modifier l'architecture interne.
Choisissez un corpus représentatif dans le trafic de production enregistré ou dans des entrées copiées de façon sûre. Retirez ou remplacez par des jetons les valeurs sensibles, tout en préservant les longueurs, classes de caractères, séparateurs et relations qui influencent l'analyse. Pour chaque exécution, gardez l'empreinte de l'interpréteur, le verrou des dépendances, l'environnement, l'empreinte de l'entrée, la sortie, le code de retour et les écritures visibles de l'extérieur. Figez le temps et les sources aléatoires lorsque le programme le permet. Sinon, comparez les champs stables et décrivez explicitement chaque champ ignoré.
Un petit banc d'essai shell peut révéler davantage qu'une semaine de lecture spéculative :
case_dir=/tmp/perl-parity-case-01
mkdir -p "$case_dir"
cp fixtures/invoice.dat "$case_dir/input.dat"
cd "$case_dir" || exit 1
TZ=UTC LC_ALL=C /opt/oldperl/bin/perl /opt/app/run.pl input.dat >stdout.txt 2>stderr.txt
printf '%s\n' "$?" >exit-status.txt
find . -type f -print | sort >files.txt
Exécutez ce banc dans un environnement isolé, car le script peut envoyer du courrier, modifier une base de données ou appeler un autre exécutable. Rediriger la sortie standard ne contient pas les effets de bord. Remplacez si possible les services externes par des enregistreurs, ou restaurez un instantané de la base entre les cas.
Comparez les données structurées comme telles. Ne triez que lorsque le contrat dit que l'ordre ne compte pas. Ne normalisez les horodatages que si les consommateurs les ignorent. Un nettoyage général des espaces peut masquer la corruption d'un enregistrement à largeur fixe. Un tri général du JSON peut masquer un changement d'ordre dans un tableau. Chaque normalisation affirme quelque chose sur le contrat et doit être relue comme du code.
Un responsable maintient l'inventaire en vie
Un inventaire sans responsable devient un autre document abandonné. Affectez un responsable technique et un responsable métier à chaque point d'entrée actif. Le premier peut expliquer comment il tourne et comment le restaurer. Le second peut dire quel résultat il produit et approuver les changements de ce résultat. Si personne n'accepte la responsabilité métier, faites remonter ce fait avant la mise hors service.
Placez le registre dans le contrôle de versions avec le travail de modernisation. Une ligne utile contient l'état des preuves, la dernière exécution confirmée, la planification, l'identité d'exécution, les entrées, les sorties, les consommateurs, le manifeste des dépendances, la sensibilité des données, le signal d'échec, la procédure de reprise et la décision. Évitez les liens vers des tableaux de bord éphémères. Stockez des identifiants durables qu'un opérateur pourra rechercher.
Définissez quatre décisions et ne les présentez pas comme les étapes d'un même parcours :
- Retirez le code dont l'inutilisation est bien établie, après une quarantaine réversible.
- Confinez le code actif dont le comportement compte, mais dont le risque de modification dépasse actuellement le coût de maintenance.
- Réparez le code qui peut rester en Perl avec un environnement reproductible, des tests et un responsable.
- Réécrivez le code dont la fonction métier reste nécessaire et dont les risques d'environnement, d'architecture ou de personnel justifient le remplacement.
Un script minuscule peut mériter une réécriture parce qu'il contrôle un règlement. Un gros programme de reporting peut mériter le confinement parce qu'il est stable, isolé et facile à exploiter. Le nombre de lignes mesure mal le risque métier. Utilisez les conséquences, la fréquence des changements, la capacité de reprise, l'état des dépendances et la qualité des observations.
Rendez les inconnues visibles
Ajoutez une colonne explicite pour les inconnues au lieu de forcer chaque ligne dans un état faussement assuré. On y trouvera par exemple un alias de base de données non vérifié, un répertoire de sortie sans consommateur nommé, un mot de passe fourni par un wrapper inconnu ou un module présent sur une seule machine. Donnez un responsable et une prochaine observation à chaque inconnue. Sans observation prévue, elle devient silencieusement un risque accepté.
Le registre doit aussi distinguer l'instance d'un script de son fichier source. Le même fichier peut tourner sous deux comptes avec des configurations, des arguments et des droits différents. Il s'agit de deux comportements de production qui peuvent demander deux décisions. Calculez l'empreinte du fichier déployé afin de voir si des chemins apparemment identiques contiennent des copies différentes. Relevez la cible des liens symboliques, car un changement de version peut faire pointer le même chemin vers un autre code d'un jour à l'autre.
Les pannes révèlent des dépendances que les exécutions réussies cachent. Consultez les courriels de l'ordonnanceur, les répertoires de messages en échec, les sorties partielles, les scripts de reprise et les tickets d'exploitation. Une commande de récupération copiée dans une procédure peut être la seule arête entrante d'un script de réparation. Si l'équipe supprime ce script parce que la production normale ne l'appelle jamais, le prochain lot en échec servira de moyen de découverte. Marquez comme actifs les points d'entrée réservés à la reprise et testez-les sur une panne réversible.
La mise hors service demande aussi un contrat de sortie. Pour un rapport, déterminez qui le reçoit et ce qui se passe s'il manque. Pour un transfert, trouvez l'accusé de réception ou l'enregistrement de rapprochement. Pour un nettoyage, trouvez le symptôme de stockage, de délai ou de justesse qui réapparaît à l'arrêt. Un script sans appelant visible peut encore empêcher un résultat négatif, comme des lignes en double ou des données temporaires non expirées. Cherchez la situation qu'il empêche.
Utilisez le registre pendant les incidents. Lorsqu'un opérateur découvre une nouvelle exécution, un changement d'interpréteur ou un consommateur, modifiez la ligne dans le même commit que le correctif d'exploitation. Après plusieurs incidents, l'inventaire gagne en précision parce qu'il absorbe des preuves recueillies sous contrainte réelle. Une feuille de calcul envoyée une fois à la direction se dégrade, car ceux qui apprennent de nouveaux faits ne peuvent pas la corriger là où ils travaillent.
Choisissez une frontière métier, pas un fichier
Une réécriture fichier par fichier conserve les accidents de l'ancienne structure. Choisissez une frontière autour d'une capacité observable : ingérer un flux, classer des enregistrements, calculer des frais, produire un rapport ou comptabiliser un lot. Définissez la frontière par ses entrées, ses sorties, son comportement en erreur et ses changements d'état, puis soumettez l'ancienne et la nouvelle implémentation aux mêmes cas.
Les déploiements par étranglement sont populaires parce qu'ils réduisent la taille du basculement, mais ils conviennent mal lorsque la frontière proposée partage des transactions ou un état modifiable impossible à séparer sans risque. Faire écrire deux systèmes dans un schéma mal compris crée plus d'ambiguïté que remplacer un lot cohérent. Dans ce cas, construisez un lecteur fantôme, comparez les sorties et basculez toute la frontière d'écriture lorsque la parité est solide. La frontière doit suivre la responsabilité des effets, pas les noms de fonctions en Perl.
Ne transposez pas les habitudes de Perl mot à mot dans un nouveau langage. Les variables globales implicites, les valeurs de retour sensibles au contexte, l'autovivification, les valeurs vraies ou fausses et les effets de bord des regex ont pu façonner l'ancien programme. La nouvelle architecture doit rendre l'état et les erreurs explicites. Conservez le comportement externe dont dépendent les consommateurs. Remplacez le comportement interne qui existe seulement parce que Perl le rendait commode.
CodeHero lit toute l'arborescence multilingue, réécrit Perl en Go, Rust ou TypeScript, puis vérifie le comportement avec un banc de parité alimenté par le trafic de production enregistré. Cette approche ne convient qu'après avoir réuni les preuves d'exécution et les cas aux frontières. Une réécriture automatisée ne peut pas retrouver une entrée trimestrielle que personne n'a capturée, ni une décision d'opérateur qui vivait hors du code.
Les dix premiers jours doivent réduire l'incertitude
Les premiers jours de travail doivent produire des preuves, pas un module réécrit. Le premier jour, arrêtez les nettoyages improvisés et identifiez les machines, les dépôts, les ordonnanceurs et les personnes qui reçoivent les sorties. Au troisième jour, vous devez avoir des points d'entrée confirmés, les empreintes des environnements et une liste des consommateurs inconnus. Au sixième jour, des exécutions représentatives doivent montrer les dépendances chargées et les effets aux frontières. Au dixième jour, l'équipe doit pouvoir défendre chaque décision avec des relevés plutôt qu'avec son assurance.
Protégez la production pendant la collecte. Lisez la configuration avant de la modifier. Consignez les commandes et leurs sorties dans un journal contrôlé. Retirez les secrets. N'exécutez les scripts copiés qu'après avoir bloqué le courrier, les écritures en base, les appels distants et les chemins de fichiers destructifs. Faites relire par un opérateur toute sonde qui touche un ordonnanceur actif ou un compte de production.
Vous découvrirez peut-être que personne ne sait reconstruire l'interpréteur, que plusieurs versions CPAN ont disparu des voies d'installation habituelles et que la seule spécification tient dans une regex et les fichiers de l'an dernier. C'est tout de même un progrès. Vous savez désormais où se trouve le risque. Conservez l'environnement fonctionnel, rassemblez des entrées représentatives, nommez le responsable métier et rendez le comportement exécutable dans des tests.
Ne récompensez pas le premier ingénieur qui donne au vieux code un air moderne. Récompensez celui qui prouve ce que l'entreprise lui demande encore de faire. Une fois cette preuve acquise, supprimer et réécrire deviennent des décisions d'ingénierie plutôt que du folklore.
FAQ
Comment savoir si un ancien script Perl tourne encore ?
Rassemblez des preuves dans les processus, tous les ordonnanceurs, les définitions de services, les journaux d'audit et les sorties en aval. L'absence de modification récente ne prouve rien, et une entrée d'ordonnanceur prouve une configuration plutôt qu'une exécution réussie.
Combien de temps faut-il surveiller avant de déclarer un script Perl inutilisé ?
Surveillez pendant le plus long cycle métier pertinent, y compris les fins de trimestre, fins d'année et traitements d'exception applicables. Si vous ne pouvez pas observer tout ce cycle, mettez le script en quarantaine de manière réversible et recherchez les sorties manquantes ou les attentes non satisfaites.
Faut-il ajouter strict et warnings avant d'auditer un vieux code Perl ?
Pas dans toute l'arborescence. Capturez d'abord l'interpréteur, l'environnement et le comportement de référence, puis introduisez les diagnostics dans une branche contrôlée où vous pourrez distinguer les nouveaux avertissements des changements de comportement.
Comment trouver les modules CPAN utilisés par une application Perl ?
Combinez les imports statiques, %INC pendant des exécutions représentatives, les répertoires de bibliothèques privées, les paquets de la machine et l'historique d'installation. Aucune source ne voit seule de façon fiable les chargements dynamiques, les copies locales et les paquets système.
Que faire lorsqu'un ancien module CPAN ne s'installe plus ?
Déterminez si l'échec vient du compilateur, d'une bibliothèque native, d'une version manquante, d'un test ou d'une incompatibilité avec Perl. Conservez l'artefact fonctionnel, puis ne changez qu'un élément diagnostiqué à la fois derrière des tests aux frontières.
Puis-je copier site_perl depuis l'ancien serveur ?
Utilisez cette copie comme preuve technique, pas comme nouvelle méthode de construction. Les modules binaires peuvent cibler l'ancienne ABI de l'interpréteur, et les arborescences copiées masquent les entrées nécessaires à une installation répétable.
Comment tester les règles métier cachées dans des regex Perl ?
Construisez une table nommée d'entrées acceptées, rejetées et limites à partir de vrais enregistrements expurgés. Vérifiez la décision de correspondance et les champs capturés, car le code en aval traite souvent ces captures comme des données métier.
Placer l'ancien environnement Perl dans un conteneur suffit-il ?
Cela peut préserver une partie de l'environnement, mais pas automatiquement les bibliothèques natives, les commandes, les certificats, les droits, les données de langue ou les services externes. Inventoriez et testez explicitement ces frontières.
Faut-il réécrire l'ancien Perl fichier par fichier ?
En général, non. Choisissez une frontière fonctionnelle avec des entrées, sorties, erreurs et changements d'état observables, puis comparez l'ancienne et la nouvelle implémentation à cette frontière.
Quand est-il plus sûr de garder un script Perl ?
Confinez-le lorsqu'il est stable, isolé, reproductible, attribué à un responsable et moins coûteux à exploiter qu'à remplacer. L'âge seul ne justifie pas une réécriture. Des conséquences sans limite et un savoir d'exploitation irrécupérable sont de meilleurs motifs.