Les paramètres régionaux dans les tests d’agents
Les paramètres régionaux distants modifient dates, tri, décimales et décodage. Fixez l’environnement, consignez-le et testez ses variantes.

Un agent peut exécuter la même commande, avec les mêmes arguments et sur les mêmes fichiers, puis obtenir un autre résultat sur un hôte distant. L’entrée manquante est souvent la configuration régionale du processus. Elle modifie la façon dont les outils courants classent le texte, trient les noms, présentent les nombres, affichent les dates, choisissent un encodage et rédigent leurs erreurs.
Traitez la configuration régionale comme une donnée de test, pas comme un réglage décoratif de la machine. Fixez-la lorsqu’un test attend un protocole stable, faites-la varier lorsque le code promet de gérer les usages humains et consignez-la chaque fois qu’un agent franchit une frontière de processus ou SSH. Sinon, un test local au vert peut cacher une erreur d’analyse distante jusqu’au moment où l’agent agit sur la mauvaise ligne, la mauvaise somme ou la mauvaise date.
Il ne s’agit pas d’imposer l’anglais partout. Une interface machine et une interface humaine ont des fonctions différentes. Une sortie machine stable exige un format et un environnement explicites. Une sortie destinée aux utilisateurs mérite une localisation délibérée. Les mélanger conduit à analyser un diagnostic traduit comme un état, ou à transformer silencieusement une virgule décimale en valeur erronée.
Le processus distant détermine le résultat
La configuration régionale effective appartient au processus qui exécute la commande. Celle de votre ordinateur portable ne contrôle pas un programme lancé par SSH, sauf si un mécanisme transmet ou définit volontairement ces variables. Un shell distant interactif peut aussi différer d’une session de commande non interactive.
POSIX.1-2024 définit précisément l’ordre de priorité. Une variable LC_ALL non vide remplace toutes les catégories. En son absence, une variable de catégorie comme LC_TIME ou LC_COLLATE l’emporte pour cette catégorie. LANG fournit la valeur par défaut aux catégories encore indéfinies. Ainsi, LANG=C ne produit aucun effet si un LC_ALL=de_DE.UTF-8 hérité reste présent.
OpenSSH ajoute une autre frontière. Son manuel client indique que SendEnv sélectionne les variables locales à transmettre, mais que le serveur doit les accepter. Par défaut, le client n’en envoie aucune. SetEnv peut demander des valeurs explicites, avec la même obligation d’acceptation côté serveur. Un développeur peut avoir SendEnv LANG LC_* dans sa configuration SSH personnelle, alors que l’assistant SSH sans état de l’agent ne l’utilise pas, ou l’inverse. Aucun des deux comportements ne doit être supposé.
Les fichiers de démarrage compliquent encore la situation. Une distribution peut définir LANG par PAM ou par sa configuration système. Le profil d’un utilisateur peut le modifier pour une connexion interactive. Une commande distante suit souvent un autre chemin de démarrage. Un conteneur lancé par cette commande peut apporter sa propre configuration, et une image minimale peut ne pas contenir le locale demandé.
La solution consiste à définir l’environnement voulu au dernier point d’exécution. Ne comptez pas sur la transmission lorsqu’une commande exige une configuration stable. Placez l’affectation à côté de l’outil :
ssh buildbox 'env LC_ALL=C.UTF-8 TZ=UTC command-to-test --format=plain'
Le contrat du test devient visible. Si C.UTF-8 est indisponible, l’échec se produit aussi à un endroit instructif au lieu d’hériter sans bruit du choix de l’hôte. Lorsque ce nom n’est pas garanti, détectez les locales disponibles pendant le provisionnement et utilisez une solution de repli documentée.
Consignez l’environnement avant d’interpréter la sortie
Un rapport d’échec distant doit contenir les catégories effectives, l’encodage, le fuseau horaire, l’identité de l’outil et les octets bruts. Enregistrer seulement LANG ne suffit pas, car LC_ALL ou une variable de catégorie peut le remplacer. Ne garder que le texte décodé peut effacer les preuves d’un défaut d’encodage.
Exécutez cette petite sonde avant la commande étudiée :
env | LC_ALL=C sort | sed -n '/^LANG=/p;/^LC_/p;/^TZ=/p'
printf 'charmap='; locale charmap
printf 'decimal='; locale -k decimal_point 2>/dev/null || true
printf 'date='; date +'%Y-%m-%dT%H:%M:%S%z'
printf 'tool='; command -v sort
sort --version 2>/dev/null | sed -n '1p'
Un résultat Linux courant peut avoir cette forme :
LANG=de_DE.UTF-8
LC_NUMERIC=de_DE.UTF-8
TZ=Europe/Berlin
charmap=UTF-8
decimal=decimal_point=","
date=2026-07-24T143105+0200
tool=/usr/bin/sort
sort (GNU coreutils) 9.5
Ne transformez pas cet exemple en valeur attendue. C’est l’ensemble des champs qui compte. Certaines implémentations de locale présentent différemment les mots-clés, et d’autres outils peuvent ignorer --version. Capturez le statut de sortie et l’erreur standard de chaque sonde afin qu’une fonction absente ne ressemble pas à une valeur vide.
Pour les erreurs d’encodage, conservez les octets avant le décodage. Un banc de test peut écrire la sortie standard et l’erreur dans des fichiers séparés, calculer leurs empreintes, puis décoder une copie selon l’encodage déclaré. Un extrait hexadécimal autour du premier octet invalide est bien plus utile qu’un caractère de remplacement ajouté par la couche de journalisation.
Consignez aussi le transport exact de la commande. ssh host command, ssh host sh -lc command, un terminal interactif et un processus lancé par un outil d’agent sont des chemins d’exécution distincts. Ils peuvent choisir des shells, des fichiers de démarrage, des pseudo-terminaux et des filtres d’environnement différents. Si le chemin en échec passe par une action d’agent, reproduisez ce chemin au lieu de prouver qu’une connexion saisie à la main fonctionne.
Ce dossier de diagnostic doit accompagner l’artefact de test dès que les résultats divergent. Il transforme « le tri distant est instable » en comparaison d’entrées concrètes.
Fixez un locale pour les protocoles, pas pour les gens
Utilisez une configuration fixe lorsque la sortie alimente un analyseur, un instantané, une comparaison, une clé de cache, une décision de déploiement ou un autre programme. Utilisez le locale humain demandé quand la sortie s’adresse à une personne. Ces interfaces restent distinctes même si une seule commande produit aujourd’hui les deux.
Le conseil habituel qui consiste à définir LC_ALL=C partout est populaire, car il rend de nombreux outils Unix prévisibles et existe sur les systèmes POSIX. Comme règle générale, il est erroné. Selon le système et le moteur d’exécution, le locale C peut impliquer un modèle de caractères orienté ASCII. Un programme qui lit des noms comme Málaga risque alors de refuser ou de mal traiter leurs octets, même si le tri est devenu stable.
C.UTF-8 associe un classement simple à UTF-8 sur de nombreux systèmes Unix actuels, ce qui en fait un locale pratique pour les tests. POSIX n’impose toutefois pas ce nom précis. macOS, les distributions Linux, les conteneurs et les moteurs de langage n’exposent pas le même catalogue. locale -a affiche ce que l’hôte propose, et les images de test provisionnées doivent déclarer le nom qu’elles garantissent.
Une autre distinction mérite d’être nette : la stabilité du locale n’est pas celle du format de sortie. Fixer LC_ALL ne garantit pas que deux versions d’un outil imprimeront les mêmes colonnes, espaces, avertissements ou champs JSON. Si l’outil propose JSON, des séparateurs NUL, des secondes depuis l’époque ou une chaîne de format explicite, choisissez aussi cette interface. Le contrôle du locale élimine une variable, il ne fige pas le programme.
Un bon wrapper efface les remplacements possibles et n’ajoute que le nécessaire :
run_stable() {
env -u LANGUAGE -u LC_COLLATE -u LC_CTYPE -u LC_MESSAGES \
-u LC_MONETARY -u LC_NUMERIC -u LC_TIME \
LC_ALL=C.UTF-8 TZ=UTC "$@"
}
run_stable sort input.txt
Si votre cible comprend des systèmes dont env ne reconnaît pas -u, construisez plutôt un environnement minimal. Définissez PATH explicitement et ne conservez que les variables nécessaires à l’application. Ne copiez pas tout l’environnement parent pour ne corriger que LANG, car les remplacements de catégories resteraient actifs.
Les tests d’un comportement destiné aux utilisateurs doivent suivre l’approche inverse. Ils sélectionnent volontairement un locale pris en charge et vérifient la convention pertinente. Un test de rapport allemand peut attendre une virgule décimale et des noms de mois allemands. L’analyseur derrière ce rapport doit toujours échanger des nombres et des dates normalisés en interne.
Une date exige un format et un fuseau
Le locale et le fuseau horaire provoquent des erreurs de date différentes. LC_TIME contrôle les noms et les représentations conventionnelles. TZ détermine l’heure civile correspondant à un instant. Fixer l’un ne fixe pas l’autre.
GNU Coreutils avertit que la sortie de date ne peut pas toujours être analysée ultérieurement. Son manuel recommande un format indépendant de la langue, une représentation grégorienne et une zone sans ambiguïté comme UTC ou Z pour les données générées. Ce conseil vaut davantage qu’un instantané qui réussit par hasard sous des paramètres anglais.
Choisissez une représentation explicite pour un protocole de test :
env LC_ALL=C.UTF-8 TZ=UTC date +'%Y-%m-%dT%H:%M:%SZ'
La sortie a la forme 2026-07-24T12:31:05Z. Si le test a besoin d’un instant fixe plutôt que de l’horloge courante, fournissez-le par une option de l’outil ou injectez une horloge dans l’application. Contrôler le locale ne peut pas arrêter le temps.
Évitez %c, %x, %X, %a et %b dans les données qu’un autre programme doit analyser. Ces directives demandent intentionnellement des conventions régionales ou des noms traduits. Des directives numériques peuvent encore comporter des particularités de calendrier. Le manuel GNU documente des locales qui emploient d’autres calendriers pour certaines directives. Une année apparemment numérique ne constitue donc pas une promesse universelle sans définition par le format et le locale choisi.
Les numéros de semaine sont un autre piège. L’année civile, l’année ISO fondée sur les semaines et les usages locaux répondent à des questions différentes près du jour de l’An. Indiquez celui qu’utilise la règle métier et testez les dates limites. Fixer le locale ne corrigera pas une mauvaise combinaison %Y-%V.
Les rapports humains doivent formater les dates à la frontière du système. Conservez l’instant stocké ou transmis sous une forme stable, puis appliquez le locale et le fuseau du lecteur à l’affichage. Si un agent doit comparer des horodatages de plusieurs hôtes, demandez des valeurs d’époque ou des chaînes de type RFC 3339 avec décalage. Ne lui demandez pas de deviner si 03/04/26 désigne le 3 avril ou le 4 mars.
Une matrice de dates utile comprend un locale avec des mois anglais, un autre avec des noms différents, UTC, un fuseau qui pratique le changement d’heure et des dates proches d’un changement d’heure et d’année. Le but n’est pas de recenser la planète, mais de révéler le code qui a supposé les habitudes du développeur.
Le tri doit correspondre au consommateur
Le texte ne possède pas un ordre naturel unique. L’ordre des octets, celui des points de code Unicode et le classement linguistique produisent des suites différentes. Les tests échouent quand ils attendent l’un et invoquent l’autre.
Le manuel de GNU sort indique que les comparaisons utilisent normalement la séquence choisie par LC_COLLATE. Il recommande précisément LC_ALL=C lorsqu’un script exige l’ordre traditionnel. Le même manuel prévient que définir uniquement LC_COLLATE est risqué si LC_ALL le remplace ou si les catégories de caractères emploient des encodages incompatibles.
Prenez ce fixture :
Zebra
apple
zebra
Ångström
ábaco
Un locale de type C trie généralement selon les octets encodés, avec les majuscules ASCII avant les minuscules et les séquences UTF-8 hors ASCII ensuite. Un locale linguistique peut comparer la casse ou les accents à différents niveaux. Ne copiez pas un ordre supposé dans un article ou un test multiplateforme. Exécutez le locale réellement pris en charge et vérifiez la propriété sémantique dont vous avez besoin.
Pour un manifeste reproductible ou un fichier de référence, l’ordre par octets convient souvent. Définissez LC_ALL=C si tous les chemins se limitent au jeu de caractères portable, ou utilisez un locale UTF-8 vérifié et définissez la fonction d’ordre dans le programme. Pour une liste affichée à des lecteurs espagnols, suédois ou allemands, un ordre binaire est médiocre. Utilisez une bibliothèque de classement régional dont la version des données est fixée, car les données du système peuvent changer sans modification de votre code.
Le tri et la jointure doivent partager les mêmes règles. GNU Coreutils demande d’exécuter sort et join avec des locales et options cohérents. Un fichier trié sous un classement peut sembler non trié à join sous un autre, entraînant des correspondances manquées ou des diagnostics. Il en va de même pour comm, la suppression de doublons, les fusions et tout pipeline qui suppose que les valeurs égales sont voisines.
Préférez des assertions qui expriment l’intention. Si l’ordre ne compte pas, comparez des ensembles ou des tables plutôt qu’un instantané accidentel. Si l’ordre des octets fait partie du protocole, calculez-le dans le test et nommez-le. Si le classement localisé est la fonction testée, ajoutez des fixtures avec accents, variantes de casse et ponctuation qui le distinguent du tri binaire.
Un agent peut aggraver le problème en lançant un sort exploratoire, puis en traitant la première ligne comme l’élément « le plus petit » ou « suivant ». Inscrivez la règle de tri dans son contrat d’action. « Sélectionner la première version selon l’ordre sémantique » diffère de « sélectionner le premier nom de fichier selon le locale distant ».
La virgule décimale casse les pipelines en silence
LC_NUMERIC définit le signe décimal et les conventions de groupement des fonctions sensibles au locale et de certaines options de commande. Une valeur affichée comme 1,25 peut être correcte pour une personne et invalide pour un analyseur qui attend 1.25. Pire, un analyseur permissif peut accepter seulement le préfixe et renvoyer 1 sans erreur manifeste.
GNU sort -n utilise le séparateur des milliers et le signe décimal du locale lorsqu’il reconnaît un préfixe numérique. locale.format_string, locale.atof et les fonctions associées de Python suivent aussi LC_NUMERIC. Le float() ordinaire de Python et de nombreux formats de données ne le font pas. Faire circuler du texte entre ces deux familles sans frontière définie produit une erreur visible uniquement sous certains paramètres.
Gardez les nombres de protocole normalisés. Les nombres JSON utilisent un point, les options de commande documentent généralement une grammaire fixe et les formats de base de données ont leur propre représentation. N’ajoutez une virgule ou des groupes que pour l’affichage, après le calcul et la sérialisation.
Testez les analyseurs avec des valeurs qui rendent une troncature silencieuse évidente :
0.5
1.25
1234.75
-0.125
Exécutez ensuite la même opération avec un locale à virgule. Si l’outil accepte volontairement une entrée localisée, fournissez les fixtures équivalents avec virgule et refusez les groupements ambigus. S’il promet une grammaire fixe, définissez le locale de la commande et vérifiez qu’une virgule échoue clairement.
Ne « corrigez » pas une sortie quelconque en remplaçant toutes les virgules par des points. Une virgule peut séparer des champs, grouper des milliers ou figurer dans du texte. Utilisez une sortie structurée ou un analyseur qui connaît le locale déclaré. Si le producteur ne publie aucune grammaire, considérez sa sortie humaine comme impropre à l’automatisation.
L’arithmétique du shell donne aussi une fausse confiance. Le shell peut utiliser une syntaxe fixe alors que awk, printf, un convertisseur de tableur ou un moteur de langage applique le locale dans certaines opérations. Testez tout le pipeline sous un seul environnement plutôt que chaque commande dans votre shell de connexion.
L’argent exige une discipline plus stricte. Stockez des unités mineures ou un type décimal avec une devise explicite, puis localisez seulement la valeur affichée. Un agent chargé de décider si un montant dépasse une limite doit recevoir la valeur numérique normalisée, pas extraire un nombre d’un rapport humain.
Les erreurs d’encodage commencent avant le décodage
Le locale peut indiquer à un processus comment interpréter des suites d’octets comme des caractères. LC_CTYPE affecte la classification et est souvent associé à un jeu de caractères. Cela concerne les outils qui découpent du texte, reconnaissent des classes, changent la casse, calculent la largeur ou convertissent octets et chaînes.
La présence d’UTF-8 sur les deux machines ne prouve pas que chaque processus l’utilise. Un service distant peut démarrer dans le locale C, un conteneur minimal peut manquer de données générées ou un moteur de langage activer son propre mode UTF-8. La documentation Python est franche : l’encodage préféré peut n’être qu’une estimation sur certains systèmes, et Python UTF-8 Mode peut ignorer l’encodage régional pour cette requête.
Décodez explicitement aux frontières. Quand le contrat d’une commande indique UTF-8, lisez des octets et décodez-les en UTF-8 avec une politique d’erreur stricte. N’appelez pas le décodeur par défaut de la plateforme en espérant le bon résultat. Si Unix autorise des noms de fichiers arbitraires, rappelez-vous qu’ils sont des suites d’octets à la frontière du système. Les forcer dans du texte ordinaire peut perdre des informations. Employez l’encodage de système de fichiers et la stratégie d’erreur réversible du moteur lorsqu’ils existent.
Le remplacement des erreurs aide à l’affichage mais devient dangereux pour une décision. Deux suites invalides distinctes peuvent produire le même caractère visible. Un test doit échouer avec la position de l’octet, conserver la sortie originale et montrer une courte fenêtre hexadécimale. Ces éléments indiquent si le producteur a émis un ancien encodage, tronqué une séquence ou renvoyé du binaire dans un canal texte.
Les classes de caractères méritent des fixtures directs. Selon le locale, [[:alpha:]], les conversions de casse et la reconnaissance des espaces peuvent inclure d’autres caractères. POSIX explique que LC_CTYPE détermine comment les suites d’octets deviennent des caractères et lesquels appartiennent aux classes. Un script qui nettoie des noms avec une plage sensible au locale peut accepter ou supprimer un autre texte à distance.
Utilisez du code conscient d’Unicode pour le texte humain et des règles ASCII explicites pour les identifiants de protocole. Ne laissez pas le locale ambiant décider ce qui constitue un nom de variable, un jeton ou un champ. Inversement, n’appliquez pas un filtre limité à ASCII au nom d’une personne pour appeler le résultat une validation.
Un petit jeu de tests d’encodage doit contenir de l’ASCII simple, du texte accentué précomposé, le même rendu avec des marques combinées, un autre système d’écriture et une séquence d’octets volontairement invalide lorsque l’interface accepte les octets. Vérifiez les octets aux frontières et les caractères après décodage. Cette séparation rend les échecs lisibles.
Une petite matrice révèle les suppositions
Exécutez la majorité des tests déterministes sous un locale fixé, puis une suite plus petite de variantes choisies pour casser les suppositions. Tester tous les locales installés prend du temps tout en offrant une couverture faible, car beaucoup partagent les mêmes conventions pertinentes.
Choisissez les variantes selon leur comportement :
- Utilisez
Cpour le comportement portable des octets et les diagnostics traduits qui ne doivent pas être analysés. - Utilisez un locale UTF-8 disponible avec un point décimal et un classement non trivial.
- Utilisez-en un avec une virgule et des noms de date différents.
- Ajoutez un locale ou un mode d’exécution qui expose les suppositions d’encodage si le produit le permet.
- Associez les cas de date à UTC et à un fuseau avec changement d’heure.
Provisionnez ces locales dans l’image de test. Un test ignoré parce que le runner ne possède pas les données n’est pas un succès. Affichez locale -a si la préparation échoue et inscrivez le catalogue requis dans la définition de l’image.
Gardez la matrice près du lancement du processus. En Python, transmettez une copie de l’environnement à subprocess.run plutôt que de modifier le locale global dans un runner multithread :
import os
import subprocess
def run_case(locale_name):
child_env = os.environ.copy()
child_env.update({"LC_ALL": locale_name, "TZ": "UTC"})
return subprocess.run(
["./agent-command", "inspect", "fixtures/names.txt"],
env=child_env,
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
Le manuel Python indique que setlocale() n’est pas sûr entre threads sur la plupart des systèmes et modifie une propriété globale du programme. Le changer entre les tests peut faire interagir des cas parallèles. L’environnement enfant isole la commande et reflète la façon dont l’exécution distante fonctionne.
Les assertions doivent séparer statut de sortie, octets de la sortie standard, octets de l’erreur et sens analysé. LC_MESSAGES peut changer la langue du diagnostic sans changer l’erreur. Un test qui recherche la phrase anglaise « No such file » teste un catalogue de traduction, pas la condition d’erreur. Préférez les statuts, les champs structurés ou les identifiants stables.
Lorsqu’une variante échoue, réduisez par catégorie. Commencez avec LC_ALL effacé, puis définissez LANG et chaque catégorie pour savoir si le temps, le classement, les nombres, les messages ou les caractères sont responsables. Les variables de catégorie restent d’excellents outils de diagnostic même si la production utilise une seule valeur LC_ALL.
Exécutez cette petite matrice sur les changements qui touchent l’analyse, le lancement des processus, SSH, les rapports ou les fixtures. Une exécution planifiée peut couvrir davantage de systèmes et de versions. Sauvegardez la sonde d’environnement avec chaque échec afin qu’une nouvelle exécution ne dépende pas des souvenirs.
Une action d’agent exige un contrat d’exécution
Un agent autonome amplifie l’ambiguïté régionale parce qu’il peut enchaîner une sortie plausible avec une action lourde de conséquences. Si une liste change d’ordre, il peut sélectionner un autre fichier. Si un analyseur tronque une décimale, il peut comparer la mauvaise limite. Si une date traverse un fuseau, il peut agir sur l’enregistrement du mauvais jour.
Donnez aux outils distants un contrat explicite en quatre parties : l’environnement défini, les octets ou données structurées renvoyés, les informations de sortie conservées et la sémantique du shell. Incluez les versions ou des sondes de capacité lorsque la sortie varie selon l’implémentation. Un prompt ne peut pas réparer une frontière de processus non spécifiée.
Définissez la réussite avant que l’agent voie la sortie. Un statut nul peut indiquer que la commande s’est terminée, pas qu’elle a trouvé un enregistrement. Certains outils signalent des résultats partiels par un avertissement, d’autres écrivent leur progression sur l’erreur standard même en cas de succès. Conservez les trois canaux, puis laissez un analyseur à grammaire déclarée décider si le résultat est exploitable. Ne demandez pas à un modèle de déduire la réussite du ton d’un message localisé.
Faites d’un locale indisponible une erreur de préparation plutôt qu’une surprise d’exécution. Si une commande démarre avec LC_ALL=fr_FR.UTF-8 sur un hôte qui ne le possède pas, le shell ou le moteur peut avertir puis revenir à une autre valeur, ou le programme peut échouer. Le banc doit d’abord confirmer le locale par locale -a ou un contrôle de capacité, enregistrer son nom et s’arrêter si le comportement requis ne peut être testé. Un repli choisi au provisionnement est contrôlé, celui choisi au milieu d’une action est un état caché.
Examinez séparément les couches d’interprétation. Le processus local construit un argument SSH, le service distant lance le shell de l’utilisateur et ce shell analyse la chaîne avant que le programme cible lise ses arguments. Les affectations et les guillemets peuvent changer à chaque couche. Préférez une API distante fondée sur des arguments lorsqu’elle existe. Si seule une chaîne shell est disponible, testez sa sérialisation exacte avec des espaces, une apostrophe, un saut de ligne et du texte hors ASCII. Fixer le locale ne répare pas les guillemets, mais une erreur de guillemets peut appliquer l’affectation à la mauvaise commande.
Traitez les sorties souvent analysées comme de petits protocoles versionnés. Conservez un fixture des octets, documentez le locale et la famille d’outil attendus et refusez les formes inconnues. Quand une mise à jour change la forme, mettez à jour ensemble l’analyseur et le fixture. C’est moins spectaculaire que demander à l’agent de « comprendre » une autre présentation, et nettement plus sûr pour les commandes qui précèdent une écriture.
Pour SSH, préférez une commande qui définit l’environnement à distance plutôt que l’espoir que la transmission du client corresponde. Placez les guillemets à la bonne couche et testez les espaces, les apostrophes et le texte hors ASCII. N’ajoutez pas un shell de connexion uniquement pour hériter du locale, car il importerait aussi des alias, des scripts et d’autres états.
Gardez les résultats bruts disponibles pour examen. Sallyport peut exécuter des actions SSH grâce à son assistant sp-ssh tout en gardant les clés SSH dans son coffre chiffré, et le journal Activity enregistre chaque appel. Cela ne rend pas la sortie indépendante du locale, mais conserve une frontière utile : l’agent reçoit les résultats sans recevoir la clé qui a permis de les obtenir.
Quand une action peut modifier un état externe, validez la valeur analysée avant l’écriture. Exigez un format explicite de la commande de lecture, refusez les octets indécodables et joignez le locale enregistré à l’action proposée. L’approbation humaine n’a de sens que si la carte montre la valeur réellement analysée par le système.
La première correction d’une suite existante est concrète. Trouvez chaque commande distante dont la sortie est analysée ou enregistrée. Ajoutez la sonde aux échecs, fixez locale et fuseau dans le processus distant, puis introduisez un locale à virgule et un autre classement comme cas adverses. Les échecs surprenants sont les suppositions que votre shell local cachait depuis longtemps.
FAQ
SSH peut-il copier automatiquement mon locale vers l’hôte distant ?
Seulement si le client envoie les variables choisies et si le serveur les accepte. OpenSSH n’envoie aucune variable d’environnement par défaut, définissez donc le locale dans la commande distante plutôt que de supposer sa transmission.
Les tests doivent-ils utiliser LC_ALL=C ou C.UTF-8 ?
Utilisez C lorsque l’entrée se limite à l’ASCII portable et que le protocole impose l’ordre des octets. Préférez un locale de type C.UTF-8 disponible pour traiter UTF-8, mais vérifiez son nom au provisionnement car POSIX ne l’impose pas.
Pourquoi LANG=C ne stabilise-t-il pas la sortie ?
Un LC_ALL non vide remplace LANG, et les variables de catégorie peuvent remplacer leur comportement. Effacez les variables en conflit ou définissez LC_ALL sur le processus réellement lancé.
Quelles variables modifient le tri et les nombres ?
LC_COLLATE contrôle le classement et LC_NUMERIC les conventions décimales et de groupement des opérations régionales. LC_CTYPE compte aussi, car l’outil doit interpréter les caractères avant de les comparer.
Fixer le locale corrige-t-il aussi le fuseau horaire ?
Non. Définissez TZ séparément et choisissez un format de date explicite. Un test stable exige généralement un locale comme C.UTF-8 et un fuseau comme UTC.
Comment tester si l’image CI ne contient pas les locales ?
Provisionnez le catalogue exact dans l’image et faites échouer la préparation s’il manque. Afficher locale -a aide au diagnostic, mais ignorer silencieusement le cas ne fait que masquer le risque.
La sortie JSON est-elle toujours indépendante du locale ?
La grammaire JSON emploie une ponctuation fixe, mais un producteur peut placer des dates ou nombres localisés dans des chaînes. Testez le contrat des champs et l’analyseur, pas seulement les accolades.
Pourquoi conserver les octets bruts des commandes ?
Un décodeur peut remplacer ou supprimer des séquences invalides avant la journalisation. La sortie et l’erreur brutes gardent les preuves nécessaires pour trouver le premier octet incorrect et identifier l’encodage.
Puis-je changer le locale dans des tests parallèles ?
Évitez-le. De nombreux moteurs en font un état global, et Python indique que setlocale() n’est pas sûr entre threads sur la plupart des systèmes. Donnez son propre environnement à chaque processus enfant.
Combien de variantes régionales une suite doit-elle exécuter ?
Exécutez la suite principale sous un locale fixé et choisissez une petite matrice par comportement : ordre des octets, virgule, autres noms de dates et UTF-8. Davantage de noms n’aident pas s’ils testent la même supposition.