CRLF vs LF L'erreur de fin de ligne qui fait échouer les pipelines CI
Votre script shell fonctionne localement, mais le CI affiche l'erreur « mauvaise interprétation : /bin/bash^M ». C'est le problème de saut de ligne CRLF. Apprenez ce qui le cause, comment le détecter et comment le corriger de manière permanente avec .gitattributes.
Votre script shell fonctionne parfaitement sur votre ordinateur portable. Vous le pousser sur GitHub. Le pipeline CI échoue avec un message cryptique /bin/bash^M: bad interpreter erreur. Vous venez d'être attaqué par la plus invisible des erreurs en développement logiciel : les fins de ligne incorrectes.
Ce guide explique ce que sont réellement CRLF et LF, pourquoi le mélange silencieux corrompt les scripts et les configurations, et les étapes exactes pour éviter que les erreurs de fin de ligne ne parviennent jamais à votre pipeline.
Qu'est-ce que CRLF et LF ?
Chaque fichier texte a besoin d'une manière de marquer la fin d'une ligne. Deux conventions existent, héritées de l'époque des machines à écrire physiques :
- LF (Line Feed) — un seul
\ncaractère (byte0x0A). Utilisé sur Linux, macOS et tous les systèmes dérivés de Unix. - CRLF (Carriage Return + Line Feed) — deux caractères,
\r\n(bytes0x0D 0x0A). Utilisé sur Windows et MS-DOS.
Les noms proviennent des mécanismes des machines à écrire. Un carriage return déplaçait la tête d'impression vers le début de la ligne. Un line feed avançait le papier d'une ligne. Windows conservait les deux ; Unix supprimait le retour de chariot redondant.
Pourquoi CRLF fait échouer les pipelines CI
Sur Linux (où presque tous les exécutants CI s'exécutent), le \r n'est pas un espace blanc — c'est un caractère littéral. Quand un script shell est enregistré avec des fins de ligne CRLF, chaque ligne se termine par \r avant la nouvelle ligne. Le noyau interprète la ligne de commande comme #!/bin/bash\r et cherche littéralement un binaire nommé bash\r. Ce binaire n'existe pas.
L'erreur résultante ressemble à cela :
: bad interpreter: /bin/bash^M: No such file or directory
Le ^M est la manière dont les terminaux affichent le caractère carriage return. Il est invisible dans la plupart des éditeurs de texte, ce qui rend cette erreur si déroutante.
Autres endroits où le CRLF cause silencieusement des dommages
- Dockerfiles — Une instruction avec des fins de ligne CRLF injectera
RUNdans chaque commande, brisant les comparaisons de chaînes et les chemins de fichiers.\rScripts Python - quand —
SyntaxError: unexpected character after line continuation characterest suivie par\.env files\r\n. - — Les valeurs des variables d'environnement prennent un caractère de fin , donc
\rne correspond jamais à l'attenduAPP_ENV=production\rFichiers CSV et donnéesproduction. - — Les lecteurs qui lisent ligne par ligne peuvent inclure dans le dernier champ de chaque ligne.
\rClés SSH authorized_keys - — Un fichier de clés encodé en CRLF sera rejeté silencieusement par le daemon SSH. Diff Git
- — Chaque ligne semble modifiée, cachant les changements réels dans du bruit. Comment détecter les problèmes de fins de ligne
Les éditeurs masquent généralement les fins de ligne par défaut. Voici des méthodes fiables pour les vérifier :
Utilisation de cat ou de hexdump
Utilisation de la commande file
# Show ^M characters
cat -A yourfile.sh | head -5
# Hex dump to see 0x0d (CR) characters
hexdump -C yourfile.sh | head -10
Utilisation de grep
file yourfile.sh
# CRLF output: yourfile.sh: ASCII text, with CRLF line terminators
# LF output: yourfile.sh: ASCII text
Comment corriger les fins de ligne CRLF
# Returns exit code 0 (found) if CRLF endings exist
grep -rlP "\r" . --include="*.sh" --include="*.py" --include="*.yml"
Option 1 : dos2unix (solution rapide et unique)
supprime les retours de chariot des fichiers. Elle est disponible sur toutes les distributions Linux principales :
dos2unix Option 2 : sed (sans outil supplémentaire nécessaire)
# Fix a single file
dos2unix yourscript.sh
# Fix all shell scripts recursively
find . -name "*.sh" -exec dos2unix {} \;
# Reverse: convert LF to CRLF (unix2dos)
unix2dos yourfile.sh
Option 3 : Correction dans VS Code ou JetBrains
# Remove carriage returns in-place
sed -i 's/\r//' yourscript.sh
# Or using tr
tr -d '\r' < input.sh > output.sh
Dans VS Code, le mode des fins de ligne est affiché dans la barre d'état (en bas à droite). Cliquez dessus pour passer entre CRLF et LF pour le fichier actuel. Pour changer la valeur par défaut pour les nouveaux fichiers, définissez
dans votre "files.eol": "\n" Dans les IDEs JetBrains, allez à settings.json.
Fichier → Séparateurs de lignes pour modifier le fichier actuel, ou définissez la valeur par défaut dans Éditeur → Style de code → Séparateur de ligne La solution correcte : .gitattributes.
Les solutions ponctuelles ne s'adaptent pas à l'échelle. La solution correcte est un fichier
qui indique à Git exactement quelles fins de ligne doivent être imposées, indépendamment de l'éditeur ou du système d'exploitation utilisé par les contributeurs. .gitattributes Après avoir ajouté ce fichier, exécutez la commande suivante pour normaliser entièrement votre référentiel en une seule étape :
# .gitattributes — commit this to the root of your repository
# Default: normalize all text files to LF in the repo
* text=auto eol=lf
# Explicitly enforce LF for scripts and configs
*.sh text eol=lf
*.bash text eol=lf
*.py text eol=lf
*.rb text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.json text eol=lf
*.env text eol=lf
Dockerfile text eol=lf
Makefile text eol=lf
# Windows-only files can keep CRLF
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
# Binary files — never touch line endings
*.png binary
*.jpg binary
*.gif binary
*.zip binary
*.pdf binary
La configuration autocrlf de Git — et pourquoi elle aggrave souvent les choses
git add --renormalize .
git commit -m "chore: normalize line endings via .gitattributes"
Git possède une
configuration qui vise à convertir automatiquement les fins de ligne : core.autocrlf — convertit LF en CRLF lors du checkout (Windows), CRLF en LF lors du commit. Intendue pour les utilisateurs de Windows.
core.autocrlf=true— convertit CRLF en LF lors du commit, ne fait rien lors du checkout. Plus sûre pour Mac/Linux.core.autocrlf=input— Git ne fait rien. Ce que l'éditeur enregistre est ce qui est commis.core.autocrlf=falseLe problème :
est une core.autocrlf configuration locale stockée dans . Chaque développeur de l'équipe a une valeur différente, donc les commits provenant de machines différentes produisent des fins de ligne différentes. Cela crée une constante de bruit dans les diffs et des échecs intermittents des pipelines CI selon le dernier fichier modifié. ~/.gitconfigRègle de base :
utilisez pour définir la politique des fins de ligne dans le référentiel. Laissez .gitattributes être ce que chaque développeur a — core.autocrlf l'override. .gitattributes Ajout d'une vérification dans CI
Même avec
en place, il est utile d'ajouter une vérification explicite dans CI pour détecter les fichiers qui glissent. Une étape de deux lignes couvre la plupart des cas : .gitattributes Cette étape échoue de manière claire à l'origine — dans la demande de PR — plutôt qu'au moment de déploiement.
# In your CI workflow (GitHub Actions example)
- name: Check for CRLF line endings
run: |
if grep -rlP "\r" . --include="*.sh" --include="*.py" --include="*.yml" --include="Dockerfile"; then
echo "ERROR: CRLF line endings found. Run dos2unix on the above files."
exit 1
fi
Référence rapide : CRLF vs LF
LF (
CRLF (\n) | Bytes\r\n) | |
|---|---|---|
| Utilisé par | 0x0A | 0x0D 0x0A |
| Linux, macOS, Unix | Windows, MS-DOS | Sécurisé pour les scripts shell |
| Non — brise le shebang | Oui | Sécurisé pour Dockerfile |
| Sécurisé pour les fichiers .env | Oui | Non |
| Non — ajoute un \r à la fin des valeurs | Oui | Recommandation Git |
| Normaliser en LF dans le référentiel | Seulement pour .bat/.cmd/.ps1 | CRLF vs LF : L'erreur de fin de ligne qui fait échouer les pipelines CI 2 |
Installez nos extensions
Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide
恵 Le Tableau de Bord Est Arrivé !
Tableau de Bord est une façon amusante de suivre vos jeux, toutes les données sont stockées dans votre navigateur. D'autres fonctionnalités arrivent bientôt !
Outils essentiels
Tout voir Nouveautés
Tout voirMise à jour: Notre dernier outil a été ajouté le 28 avr. 2026
