Vous lancez le script. Le fichier est juste là. Vous pouvez ls le voir, l’autocompléter avec la touche Tab, le fixer du regard comme s’il vous devait de l’argent.
Et WSL répond : Aucun fichier ou dossier.
Cette erreur est le tour de magie préféré de WSL : elle fait « disparaître » un fichier réel en attaquant le chemin à un autre niveau que celui où vous regardez.
La correction n’est que rarement « créez le fichier ». La correction consiste à comprendre sur quel système de fichiers vous êtes, quelle syntaxe de chemin s’applique, et quel traducteur réécrit silencieusement vos hypothèses.
Le véritable problème : votre chemin est valide… dans le mauvais univers
WSL n’est pas tant « Linux sur Windows » que « Linux à côté de Windows avec un traité ». Ce traité inclut la traduction des chemins, des couches de montage,
la sémantique des noms de fichiers, et un pont d’interop qui essaie d’être utile… jusqu’à ce qu’il ne le soit plus.
Quand WSL indique « Aucun fichier ou dossier », cela peut vouloir dire :
- Le fichier existe, mais l’interpréteur nommé dans le shebang n’existe pas (ou ne peut pas être trouvé).
- Le fichier existe, mais vous êtes sur
/mnt/cet le mappage des permissions/métadonnées le rend effectivement non exécutable. - Le fichier existe, mais le chemin contient des problèmes d’échappement Windows (espaces, parenthèses, antislash) et votre shell vous trompe.
- Le fichier existe, mais il est en CRLF, donc le chemin de l’interpréteur est en réalité
/bin/bash\r, qui n’existe pas. - Le fichier existe, mais vous mélangez UNC, liens symboliques ou comportement de casse et vous atterrissez ailleurs.
- Le fichier existe, mais vous l’appelez depuis un processus Windows qui « réécrit » utilement les arguments.
Votre travail est d’identifier quelle couche génère la condition de « manquant ». Ne devinez pas. Diagnostiquez.
Mode opératoire de diagnostic rapide
Voici l’ordre dans lequel je vérifie les choses quand une page d’astreinte signale « pipeline en échec dans WSL, aucun fichier, fichier présent ».
C’est optimisé pour atteindre la cause racine rapidement, pas pour vous apprendre les fondamentaux Linux.
Premier : est-ce un problème de chemin ou d’interpréteur ?
- Si c’est un script : vérifiez le shebang et les fins de ligne (
head -n1,file). - Si c’est un binaire : vérifiez l’architecture et le loader (
file,ldd).
Deuxième : où se trouve le fichier ?
/home(ext4 à l’intérieur du VHDX WSL2) se comporte comme Linux./mnt/c(DrvFs) se comporte comme « Linux parlant à NTFS via une couche de compatibilité ».- Les partages réseau ajoutent une couche de compatibilité supplémentaire. C’est là que la joie prend sa retraite.
Troisième : qui appelle qui ?
- Linux appelant Linux est généralement sain.
- Linux appelant des EXE Windows via l’interop a des cas limites de quoting/chemins.
- Windows appelant dans WSL (
wsl.exe) peut réécrire le répertoire de travail et les arguments.
Quatrième : validez les octets exacts du chemin
- Recherchez les caractères cachés : CR, espaces insécables, guillemets typographiques, normalisation Unicode.
- Confirmez que l’entrée de répertoire existe et est atteignable (
stat), pas seulement listée.
Cinquième : identifiez les options de montage et le comportement des métadonnées
- Les options de montage DrvFs décident si
chmod +xsignifie quelque chose. - La sensibilité à la casse peut être par-répertoire sur NTFS ; elle peut changer d’un poste à l’autre.
Exécutez les tâches de la section suivante dans l’ordre jusqu’à ce que quelque chose paraisse anormal. Ça arrivera. C’est le but.
Modèle de chemins WSL, expliqué comme en production
WSL2 vous donne un vrai noyau Linux—puis vous fournit une série de traducteurs
Dans WSL2, votre distribution Linux vit sur un système de fichiers ext4 à l’intérieur d’un disque virtuel (VHDX). C’est la partie « vrai Linux ».
Vos lecteurs Windows sont rendus visibles dans Linux via des montages DrvFs, typiquement sous /mnt/c, /mnt/d, etc.
Ces deux mondes diffèrent de façons importantes pour le « fichier introuvable » :
- Syntaxe des chemins : Linux utilise
/, Windows utilise\et les lettres de lecteur. - Comportement de casse : Linux est sensible à la casse ; Windows historiquement ne l’est pas (mais peut être configuré par répertoire).
- Sémantique des exécutables : Linux utilise les bits de mode et les interpréteurs ; Windows utilise les extensions de fichier et les en-têtes PE.
- Liens symboliques : les symlinks Linux sont natifs ; les symlinks Windows sont… un débat de politique.
Quand WSL dit qu’il ne trouve pas un fichier, cela peut vouloir dire qu’il ne trouve pas une entrée de répertoire—ou qu’il ne peut pas l’exécuter
Linux a une taxonomie d’erreurs délicieusement franche. Plusieurs problèmes distincts se retrouvent sous des messages similaires :
ENOENT: aucun fichier ou dossier (également levé quand l’interpréteur ou le chargeur dynamique est manquant).EACCES: permission refusée (souvent ce que vous vouliez voir, mais que vous ne voyez pas).ENOTDIR: un composant du chemin n’était pas un répertoire (peut arriver avec des cibles de symlink bizarres).
WSL ajoute une torsion : les couches de traduction peuvent renvoyer ENOENT lorsque le côté Linux demande quelque chose que le côté Windows ne peut pas représenter.
Le résultat est une erreur techniquement correcte et opérationnellement pénible.
L’interop est puissante, mais c’est un champ de mines de quoting et de répertoires de travail
WSL vous permet d’exécuter des exécutables Windows depuis Linux et des commandes Linux depuis Windows. C’est génial jusqu’à ce que vous passiez :
- Des chemins avec des espaces ou des parenthèses
- Des chemins qui ressemblent à des options (commençant par
-) - Des chemins UNC (
\\server\share) - Des arguments contenant des antislashs que votre shell interprète « gentiment »
En termes d’incident : l’interop augmente votre rayon d’impact. C’est pratique en développement ; c’est fragile en automatisation à moins d’être discipliné.
Faits et historique intéressants (parce que le passé casse toujours votre build)
- Fait 1 : WSL1 traduisait les appels système Linux en appels système Windows. WSL2 est passé à un vrai noyau Linux dans une VM légère, changeant drastiquement les compromis de performances du système de fichiers.
- Fait 2 : Les montages par défaut des lecteurs Windows vivent sous
/mntparce que les premières versions de WSL cherchaient à ressembler à un agencement Linux classique sans entrer en collision avec les répertoires de la distro. - Fait 3 : NTFS se comportait historiquement en insensible à la casse mais en conservant la casse ; Windows moderne peut activer la sensibilité à la casse par répertoire, ce qui rend le comportement entre outils… épicé.
- Fait 4 : Le classique problème CRLF précède WSL de décennies ; c’est un artefact des conventions DOS/Windows rencontrant les conventions Unix de fin de ligne.
- Fait 5 : Linux rapporte ENOENT non seulement quand un fichier cible manque, mais aussi quand l’interpréteur ELF ou le chargeur dynamique référencé par un binaire est introuvable.
- Fait 6 : Les chemins Windows peuvent légalement contenir des caractères syntaxiquement significatifs pour les shells (espaces, parenthèses, esperluette). Dans une pipeline shell, ce n’est pas « juste un chemin », c’est un incident.
- Fait 7 : Le mappage des permissions DrvFs a longtemps été source de confusion ; des options de montage comme
metadataexistent spécifiquement pour préserver les bits de mode Linux sur les systèmes de fichiers Windows. - Fait 8 : Les réglages de fin de ligne de Git (autocrlf) sont une des raisons les plus courantes pour qu’un script devienne « inexécutable » sous Linux tout en semblant correct dans les éditeurs Windows.
- Fait 9 :
wsl.exea changé de comportement selon les versions de Windows concernant le répertoire de travail par défaut et les flags de traduction de chemin ; des scripts qui supposent le comportement d’une version peuvent échouer sur une autre.
Tâches pratiques : commandes, sorties et ce qu’elles signifient
Voici de vrais diagnostics que j’utilise. Chaque tâche inclut (1) la commande, (2) ce que vous pourriez voir, et (3) la décision à prendre.
Ne les exécutez pas tous aveuglément dans un pipeline de production—exécutez-les dans l’environnement qui échoue avec les mêmes entrées.
Task 1: Confirm you’re in WSL1 or WSL2 (it changes filesystem behavior)
cr0x@server:~$ uname -a
Linux server 5.15.146.1-microsoft-standard-WSL2 #1 SMP Fri Jan 12 18:22:05 UTC 2024 x86_64 GNU/Linux
Signification : microsoft-standard-WSL2 indique WSL2. Si vous voyez WSL1, la traduction des chemins et la sémantique du système de fichiers diffèrent.
Décision : Si c’est WSL1, attendez-vous à plus d’anomalies de traduction d’appels système ; si c’est WSL2, concentrez-vous fortement sur les montages DrvFs et les performances/métadonnées inter-systèmes de fichiers.
Task 2: Identify where the file actually lives (Linux ext4 vs Windows drive)
cr0x@server:~$ df -T /home /mnt/c | sed -n '1,3p'
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/sdc ext4 263174212 93481244 156278972 38% /
C:\ 9p 976762876 512331244 464431632 53% /mnt/c
Signification : ext4 est le système de fichiers VHDX de WSL2 ; 9p ici représente le canal de montage du lecteur Windows.
Décision : Si le fichier en échec est sous /mnt/c, traitez-le comme « étranger ». Déplacez les artefacts de build/exécution dans $HOME si vous voulez moins de surprises.
Task 3: Verify the path is not lying (stat doesn’t lie like your terminal does)
cr0x@server:~$ stat "/mnt/c/Users/alex/Projects/demo/run.sh"
File: /mnt/c/Users/alex/Projects/demo/run.sh
Size: 231 Blocks: 0 IO Block: 4096 regular file
Device: 33h/51d Inode: 0 Links: 1
Access: (0777/-rwxrwxrwx) Uid: ( 1000/ cr0x) Gid: ( 1000/ cr0x)
Access: 2026-02-05 11:34:40.000000000 +0000
Modify: 2026-02-05 11:34:39.000000000 +0000
Change: 2026-02-05 11:34:39.000000000 +0000
Signification : Si stat échoue avec ENOENT, vous n’avez véritablement pas de chemin atteignable depuis Linux. S’il réussit, le fichier existe ; l’exécution peut encore échouer pour d’autres raisons.
Décision : Si stat fonctionne mais que l’exécution échoue avec « Aucun fichier ou dossier », passez immédiatement au shebang et aux fins de ligne.
Task 4: If executing a script fails, check the first line (shebang)
cr0x@server:~$ head -n1 /mnt/c/Users/alex/Projects/demo/run.sh | cat -A
#!/bin/bash^M$
Signification : Ce ^M est un retour chariot. Le chemin d’interpréteur de votre script est effectivement /bin/bash\r, qui n’existe pas.
Décision : Convertissez les fins de ligne en LF (dos2unix) ou configurez Git/éditeur pour arrêter de réintroduire des CRLF.
Task 5: Confirm line endings and file type with file
cr0x@server:~$ file /mnt/c/Users/alex/Projects/demo/run.sh
/mnt/c/Users/alex/Projects/demo/run.sh: Bourne-Again shell script, ASCII text, with CRLF line terminators
Signification : C’est le mode d’échec classique « il existe mais ne peut pas s’exécuter ».
Décision : Corrigez les fins de ligne et validez le correctif, sinon vous le referez tous les lundis.
Task 6: Convert CRLF to LF safely (and verify)
cr0x@server:~$ dos2unix /mnt/c/Users/alex/Projects/demo/run.sh
dos2unix: converting file /mnt/c/Users/alex/Projects/demo/run.sh to Unix format...
cr0x@server:~$ file /mnt/c/Users/alex/Projects/demo/run.sh
/mnt/c/Users/alex/Projects/demo/run.sh: Bourne-Again shell script, ASCII text
Signification : Le chemin de l’interpréteur est maintenant propre.
Décision : Si le script échoue encore, vérifiez le bit d’exécution et les options de montage ensuite.
Task 7: Check execute permissions and mount metadata behavior
cr0x@server:~$ ls -l /mnt/c/Users/alex/Projects/demo/run.sh
-rwxrwxrwx 1 cr0x cr0x 231 Feb 5 11:34 /mnt/c/Users/alex/Projects/demo/run.sh
Signification : Sur DrvFs sans metadata, les permissions peuvent être synthétiques ; tout peut sembler exécutable même si la politique en décide autrement. Ou l’inverse : vous faites chmod +x et ça ne tient pas.
Décision : Si les changements de bit d’exécution ne persistent pas ou que le comportement diffère entre machines, inspectez /etc/wsl.conf et les options de montage actuelles.
Task 8: Inspect DrvFs mount options (the root of many “it worked yesterday” cases)
cr0x@server:~$ mount | grep -E ' /mnt/c '
C:\ on /mnt/c type 9p (rw,relatime,dirsync,aname=drvfs;path=C:\;uid=1000;gid=1000;metadata;umask=22;fmask=11;case=off)
Signification : metadata est présent, donc les bits de mode Linux peuvent être stockés dans des attributs étendus NTFS. case=off suggère un comportement insensible à la casse.
Décision : Si metadata manque et que vous dépendez des bits exécutables ou des symlinks, activez-le dans /etc/wsl.conf et redémarrez WSL.
Task 9: Validate shebang interpreter existence (it’s not always /bin/bash)
cr0x@server:~$ head -n1 ./run.sh
#!/usr/bin/env bash
cr0x@server:~$ command -v env
/usr/bin/env
Signification : Utiliser /usr/bin/env est portable, mais seulement si env existe (ce qui est généralement le cas) et que l’interpréteur cible existe dans PATH.
Décision : Si command -v bash échoue, installez-le ou corrigez PATH. Si env est contaminé par des CRLF, vous revenez à la Task 4.
Task 10: If a binary fails with ENOENT, check dynamic loader/architecture
cr0x@server:~$ file ./tool
./tool: ELF 64-bit LSB pie executable, x86-64, dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped
cr0x@server:~$ ldd ./tool | sed -n '1,6p'
linux-vdso.so.1 (0x00007ffc6c5f8000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fda1b0d0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fda1aeb0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fda1b2f0000)
Signification : Si le chemin de l’interpréteur indiqué par file pointe vers quelque chose d’inexistant, exécuter le binaire peut donner « Aucun fichier ou dossier ».
Décision : Si ldd indique « not found » pour une librairie, installez les dépendances. Si le chemin de l’interpréteur est manquant, vous exécutez probablement un binaire compilé pour une autre distro/architecture.
Task 11: Confirm current working directory and symlink resolution
cr0x@server:~$ pwd -P
/mnt/c/Users/alex/Projects/demo
cr0x@server:~$ readlink -f .
/mnt/c/Users/alex/Projects/demo
Signification : Si vos outils reposent sur des symlinks ou des chemins relatifs, un pwd différent de ce que vous attendiez peut casser des jonctions de chemins.
Décision : En automatisation, résolvez les chemins en absolus tôt et consignez-les. Si vous êtes sur /mnt/c, envisagez de déplacer l’exécution vers le système de fichiers Linux.
Task 12: Check for Windows “smart quotes” or Unicode oddities in filenames
cr0x@server:~$ ls | cat -A
run.sh$
deploy–prod.sh$
Signification : Ce nom de fichier contient un tiret long (–) et non un trait d’union (-). Votre commande copiée-collée utilise -, donc le fichier est « introuvable ».
Décision : Renommez le fichier en un nom ASCII sûr, ou au moins arrêtez de coller depuis du texte enrichi. L’automatisation déteste la typographie.
Task 13: Test Windows-to-WSL invocation and path translation explicitly
cr0x@server:~$ wsl.exe -e bash -lc 'pwd; ls -l ./run.sh'
/mnt/c/Users/alex/Projects/demo
-rwxrwxrwx 1 cr0x cr0x 231 Feb 5 11:34 ./run.sh
Signification : Quand Windows lance WSL, le répertoire de travail peut ne pas être ce que votre script attend à moins que vous ne le définissiez.
Décision : Dans CI ou le Planificateur de tâches, définissez toujours explicitement le répertoire de travail, ou passez des chemins absolus.
Task 14: Convert Windows paths to WSL paths (and validate)
cr0x@server:~$ wslpath "C:\Users\alex\Projects\demo\run.sh"
/mnt/c/Users/alex/Projects/demo/run.sh
cr0x@server:~$ test -e "$(wslpath 'C:\Users\alex\Projects\demo\run.sh')" && echo OK || echo MISSING
OK
Signification : wslpath est la façon la moins pire de traduire les chemins, surtout lorsqu’il est appelé depuis des contextes Windows.
Décision : Standardisez l’usage d’aides à la traduction de chemins dans les scripts plutôt que de réinventer des remplacements de chaînes.
Task 15: Diagnose quoting issues with spaces and parentheses (classic interop trap)
cr0x@server:~$ p="/mnt/c/Program Files (x86)/Vendor Tool/bin/tool.exe"; test -e "$p" && echo EXISTS || echo MISSING
EXISTS
cr0x@server:~$ "$p" --version
VendorTool 4.2.1
Signification : Si vous ne le quotez pas, le shell découpe sur les espaces et les parenthèses deviennent syntaxe. Alors « Aucun fichier » est la partie la moins confuse.
Décision : Quotez chaque chemin. En revue de code, traitez les chemins non quotés comme des SQL non échappées : pas toujours exploitables, mais toujours risqués.
Task 16: Inspect /etc/wsl.conf for mount configuration (the silent policy file)
cr0x@server:~$ sed -n '1,120p' /etc/wsl.conf
[automount]
enabled = true
options = "metadata,umask=22,fmask=11"
mountFsTab = false
Signification : Cela contrôle comment les lecteurs Windows sont montés. metadata est le grand point pour les permissions ; umask/fmask affectent les modes par défaut.
Décision : Si ceci manque ou est incohérent entre machines, standardisez-le. La dérive ici cause des « ça marche sur mon laptop » comme service.
Erreurs courantes : symptôme → cause → correction
1) Symptom: “No such file or directory” when running a script that clearly exists
Cause racine : fins de ligne CRLF dans la ligne de shebang, résultant en /bin/bash^M.
Correction : Convertir en LF (dos2unix file), imposer LF dans les attributs Git, et configurer votre éditeur pour qu’il arrête d’« aider ».
2) Symptom: “No such file or directory” only when executed from Windows (Task Scheduler, VS Code task, CI runner)
Cause racine : mauvais répertoire de travail, ou le quoting des arguments change quand la commande traverse la frontière Windows↔WSL.
Correction : Utilisez wsl.exe -e bash -lc avec un cd explicite, passez des chemins absolus, et translatez les chemins Windows via wslpath.
3) Symptom: chmod +x “works” but execution still behaves inconsistently on /mnt/c
Cause racine : options de montage DrvFs sans metadata (ou politique de montage incohérente entre machines).
Correction : Configurez /etc/wsl.conf pour activer metadata ; redémarrez WSL. Préférez exécuter les outils de build sur le système de fichiers Linux ($HOME) quand c’est possible.
4) Symptom: File exists, but ./tool returns “No such file or directory”
Cause racine : chargeur dynamique ou dépendance partagée manquante ; ENOENT peut être lancé pour un interpréteur ELF manquant.
Correction : file tool et ldd tool. Installez les libs requises, ou recompilez pour la distro/ l’environnement WSL cible.
5) Symptom: A path works in one repo but not another; same filename, different behavior
Cause racine : mismatch de sensibilité à la casse. Un répertoire peut être sensible à la casse sur NTFS ; un autre ne l’est pas. Ou les outils utilisent des casses incohérentes dans les imports/chemins.
Correction : Normalisez la casse dans le code et les scripts de build. Évitez de compter sur un comportement insensible à la casse. Traitez les dépôts hébergés sur Windows comme du chaos de casse sauf preuve du contraire.
6) Symptom: “No such file or directory” with paths containing Unicode dashes or smart quotes
Cause racine : les octets du nom de fichier ne correspondent pas à ce que vous avez tapé. La ponctuation fancy ressemble à s’y méprendre jusqu’au moment où elle vous ruine la soirée.
Correction : Renommez les fichiers en noms ASCII sûrs, ou copiez-collez le nom exact depuis ls. Préférez des chemins générés par machine pour l’automatisation.
7) Symptom: Scripts fail only on network shares mapped into Windows drives
Cause racine : couche de traduction additionnelle (SMB/CIFS, redirecteur Windows, puis DrvFs). Les permissions et la sémantique des changements de fichier peuvent différer.
Correction : Copiez ou synchronisez sur le système de fichiers Linux avant d’exécuter ; évitez d’exécuter des scripts directement depuis des partages réseau.
8) Symptom: “No such file or directory” when using relative paths in makefiles or npm scripts
Cause racine : L’outil change son répertoire de travail en interne, ou vous avez supposé que $PWD est stable à travers les lancements interop.
Correction : Résolvez les chemins en utilisant la détection de la racine du repo, des chemins absolus, et consignez-les. Dans les scripts shell, utilisez script_dir="$(cd "$(dirname "$0")" && pwd -P)".
Trois mini-récits d’entreprise issus des tranchées des chemins
Mini-récit 1 : L’incident causé par une mauvaise hypothèse
Une entreprise de taille moyenne utilisait un runner CI basé sur Windows qui exécutait des étapes de build Linux via WSL.
Il avait été stable pendant des mois, principalement parce que l’équipe touchait rarement les images du runner.
Puis un nouveau dépôt est arrivé avec un script bootstrap « simple » commis par quelqu’un qui vivait dans des éditeurs Windows.
Le script de bootstrap était présent. Les logs du pipeline montraient qu’il était listé dans le répertoire. Mais chaque tentative de l’exécuter se terminait par :
« Aucun fichier ou dossier. » Le premier intervenant a fait ce que font les premiers intervenants : relancer le job. Même résultat.
Puis ils ont essayé des chemins absolus. Même résultat. Ils ont ensuite copié le fichier partout, comme si déplacer une plante d’appartement allait arrêter la décadence.
La mauvaise hypothèse était subtile : tout le monde supposait qu’ENOENT signifiait « fichier manquant ». Le fichier n’était pas manquant.
Le chemin d’interpréteur l’était. Des CRLF dans le shebang transformaient /usr/bin/env en /usr/bin/env\r.
Le noyau ne trouvait pas cet interpréteur, donc il rapportait ENOENT à l’exécution du script.
Ils ont corrigé ça par une enforcement des fins de ligne au niveau du dépôt, pas en disant aux développeurs de « faire attention ».
Un hook pre-commit a aidé, mais la vraie victoire a été une étape CI qui échouait vite quand un shebang contenait un CR.
Ça a transformé une erreur fantôme en une erreur lisible.
Leçon du post-mortem : ne supposez rien sur « fichier introuvable » tant que vous n’avez pas vérifié la ligne d’interpréteur.
Les ordinateurs sont littéraux. Les gens sont optimistes. L’optimisme ne fait pas passer les builds.
Mini-récit 2 : L’optimisation qui s’est retournée contre eux
Une autre équipe a essayé d’accélérer son environnement de dev WSL. Ils gardaient leur repo sur /mnt/c
pour que les outils Windows (indexeurs d’IDE, exclusions antivirus, watchers de fichiers) puissent y accéder facilement.
Mais les builds étaient lents, alors ils ont fait une chose « intelligente » : lancer la compilation dans WSL mais garder les artefacts sur /mnt/c
pour que Windows puisse les récupérer sans copie.
La première semaine était excellente. Certains workloads étaient plus rapides, principalement parce que les caches étaient chauds et que personne n’avait touché les cas limites.
Puis un candidat de release a échoué lors du packaging. Le bundler s’est plaint qu’un script généré manquait.
Le script existait, mais « ne pouvait parfois pas être trouvé » durant des étapes parallèles.
Le retour de bâton n’était pas mystique. Ils avaient mis une charge concurrente lourde sur un pont de système de fichiers qui ne se comportait pas comme un ext4 natif.
Les mises à jour de métadonnées, les notifications de fichier, et la sémantique des renommages sous forte parallélisation ont exposé des fenêtres de timing.
La logique de retry du pipeline a empiré le problème en masquant les signes précoces.
Ils ont réglé cela en faisant la chose ennuyeuse : déplacer le repo et les sorties de build dans le système de fichiers Linux ($HOME)
et ne copier les artefacts finaux vers Windows que si nécessaire. Les performances sont devenues cohérentes. Les échecs ont cessé d’être « intermittents ».
Leçon : « moins de copies » n’est pas toujours « plus rapide ». Parfois c’est juste « plus proche de la partie bizarre du système ».
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une entreprise régulée avait une flotte mixte : certains développeurs utilisaient WSL, d’autres des laptops Linux, et la CI tournait sur Linux.
Leur modèle de menace et les exigences d’audit les rendaient allergiques aux « magies spécifiques aux développeurs ». C’était pénible, mais ça a imposé de la discipline.
Ils ont standardisé un petit ensemble de points d’entrée de build avec des règles strictes :
les scripts doivent utiliser #!/usr/bin/env bash, être en LF, ne pas supposer la disposition de /bin, et consigner leurs chemins résolus.
Chaque dépôt avait une vérification de sanity des chemins qui tournait en moins d’une seconde.
Un jour, une mise à jour Windows a changé un petit truc sur la façon dont un développeur lançait WSL depuis son IDE.
Un chemin relatif utilisé par un script auxiliaire a cassé—sur la machine de ce développeur uniquement.
La vérification de sanity a immédiatement affiché : « Répertoire de travail est /mnt/c/…; racine du repo attendue. Abandon. »
Ils n’ont pas perdu une demi-journée à une chasse aux fantômes. Ils n’ont pas « réparé » en demandant à tout le monde de réinstaller.
Ils ont modifié la tâche IDE pour faire un cd explicite et ont suivi leur route.
Leçon : les répertoires de travail explicites et les validations précoces sont ennuyeux. C’est pour ça qu’ils fonctionnent.
Listes de contrôle / plan étape par étape
Checklist A: When “No such file or directory” happens executing a script
- Exécuter
stat "path". Si ça échoue, c’est vraiment un problème de chemin. Si ça réussit, continuez. - Exécuter
head -n1 file | cat -A. Si vous voyez^M, corrigez les fins de ligne. - Exécuter
file file. Confirmez que c’est un script avec des terminators LF. - Vérifiez que l’interpréteur existe :
command -v bashouls -l /bin/bash. - Vérifiez le bit d’exécution :
ls -l file. Si sur/mnt/c, confirmez que les options de montage incluentmetadatasi vous dépendez de cela. - Si invoqué depuis Windows, définissez explicitement le répertoire de travail et passez des chemins absolus.
Checklist B: When “No such file or directory” happens executing a binary
stat ./binaryetls -lpour vous assurer qu’il existe et est exécutable.file ./binarypour confirmer l’architecture et le chemin de l’interpréteur.ldd ./binaryet cherchez « not found ».- Si l’interpréteur manque, vous exécutez probablement un binaire construit pour une autre distro/environnement ; recompilez dans WSL ou alignez l’image de base.
- Déplacez le binaire vers le système de fichiers Linux s’il est sur
/mnt/cet que le comportement est incohérent.
Checklist C: Standardize WSL mounts to reduce path-related flakiness
- Créez/vérifiez
/etc/wsl.confavec les options d’automount appropriées pour votre organisation. - Décidez si vous voulez
metadata. Si vous exécutez des scripts depuis/mnt/c, vous en aurez probablement besoin. - Redémarrez WSL (fermez les distributions, puis redémarrez le service WSL depuis Windows).
- Documentez un emplacement consacré pour les repos : soit le système de fichiers Linux pour build/exécution, soit le système Windows pour l’édition—mais n’ignorez pas qu’ils ne sont pas identiques.
Une seule citation, parce qu’on n’est pas là pour tapisser le problème de posters de sagesse :
« L’espoir n’est pas une stratégie. » — Gene Kranz
Blague 1 : les bugs de chemins WSL sont comme des chaussettes dans une machine à laver — tôt ou tard tout disparaît, et personne n’avoue avoir touché aux réglages.
FAQ
1) Pourquoi Linux dit-il « Aucun fichier ou dossier » alors que le fichier existe ?
Parce qu’ENOENT peut se référer à un interpréteur manquant (shebang), un chargeur dynamique manquant pour un binaire ELF, ou un composant de chemin manquant après traduction.
Dans WSL, les couches de traduction et le comportement de montage ajoutent d’autres façons de générer ENOENT.
2) Comment savoir rapidement si c’est du CRLF ?
Exécutez head -n1 script | cat -A et cherchez ^M, ou exécutez file script et vérifiez la présence de « with CRLF line terminators ».
3) Est-ce mauvais de garder le code sous /mnt/c ?
Ce n’est pas moralement mauvais. C’est risqué opérationnellement pour des workloads axés Linux. Si vous compilez, exécutez beaucoup de petites opérations sur fichiers, ou dépendez des permissions Unix, préférez $HOME (système de fichiers Linux).
Gardez /mnt/c pour l’interopérabilité et l’échange occasionnel de fichiers, pas comme moteur d’exécution.
4) Pourquoi ça marche depuis un terminal WSL mais échoue quand c’est lancé depuis Windows ?
Différent répertoire de travail, variables d’environnement différentes, règles de quoting différentes, et parfois traduction de chemin différente.
Les lanceurs Windows démarrent souvent WSL dans un répertoire par défaut auquel vous n’avez pas pensé.
5) Quelle est la manière la plus sûre de passer un chemin Windows dans WSL ?
Utilisez wslpath pour traduire puis quotez le résultat. Ne remplacez pas simplement \ par / et appelez ça de l’ingénierie.
6) Pourquoi les binaires échouent parfois avec « Aucun fichier » alors que ls les montre ?
Un interpréteur ELF manquant ou des bibliothèques partagées manquantes peuvent lancer ENOENT au moment de l’exec. Vérifiez file pour le chemin de l’interpréteur et ldd pour les dépendances manquantes.
7) Les options de montage importent-elles vraiment pour cette erreur ?
Oui. Les options de montage influencent le mappage des permissions et le stockage des métadonnées. Sans metadata, vous pouvez obtenir des apparences « exécutables » déroutantes qui ne correspondent pas à ce que vous vouliez.
Ce n’est pas toujours la cause directe d’ENOENT, mais ça contribue fréquemment à la chaîne de confusion.
8) Pourquoi les chemins avec espaces cassent-ils plus souvent dans WSL ?
Ils ne cassent pas « dans WSL ». Ils cassent dans les shells et aux frontières d’interop où les règles de quoting diffèrent.
Si vous quotez chaque chemin, vous réduisez drastiquement le taux d’échec.
9) Comment faire pour que cela cesse de se produire dans une équipe ?
Imposer LF dans les dépôts, ajouter une vérification rapide qui valide les shebangs et les attentes de chemins, standardiser la config de montage WSL, et consacrer un emplacement d’exécution (système de fichiers Linux).
Aussi : consignez les chemins absolus dans les scripts de build. Déboguer sans chemins, c’est comme répondre à un incident sans timestamps.
10) Est-ce WSL le problème ou mes scripts ?
Généralement vos scripts. WSL vous offre juste plus de façons de combiner par accident des hypothèses Windows et des sémantiques Linux dans une seule ligne de commande.
Traitez la frontière comme un saut réseau : validez, normalisez, et consignez.
Blague 2 : si votre build dépend de chemins non quotés, vous n’avez pas un pipeline—vous avez un roman à suspense.
Prochaines étapes réalisables cette semaine
- Ajoutez une porte shebang et fins de ligne : une étape CI qui rejette les CRLF dans les scripts exécutables et affiche la ligne en faute.
- Choisissez une politique « le build s’exécute ici » : soit sur le système de fichiers Linux (
$HOME), soit sur le système Windows, mais documentez les compromis et appliquez la cohérence. - Standardisez
/etc/wsl.conf: assurez-vous que les options de montage (surtoutmetadata) sont cohérentes entre les machines dev si vous exécutez depuis/mnt/c. - Rendez les chemins ennuyeux : évitez la ponctuation Unicode et utilisez des noms de fichiers ASCII sûrs pour les fichiers critiques d’automatisation.
- Consignez les chemins absolus : chaque point d’entrée de build devrait afficher
pwd -Pet le répertoire de script résolu avant d’exécuter quoi que ce soit de destructeur.
Le message « Aucun fichier ou dossier » n’a pas tort. Il ne vous dit juste pas quel fichier il ne trouve pas.
Une fois que vous commencez à vérifier les interpréteurs, les types de montage, et les frontières d’interop dans cet ordre, l’erreur cesse d’être un mystère et devient un élément de checklist.