Les pubs vous déplaisent ? Aller Sans pub Auj.

CRLF vs LF L'erreur de fin de ligne qui fait échouer les pipelines CI

Publié le

Votre script shell fonctionne localement mais échoue dans le CI avec une erreur de lecteur cryptique. La cause est généralement les sauts de ligne CRLF. Apprenez ce qu'ils sont, pourquoi ils font planter les pipelines Linux, et comment les corriger de manière permanente avec .gitattributes et les paramètres de l'éditeur.

Votre script shell fonctionne localement mais le CI lance l'erreur 'bad interpreter: /bin/bash^M'. C'est l'erreur de fin de ligne CRLF. Apprenez ce qui la cause, comment la détecter et comment la corriger de manière permanente avec .gitattributes.
ANNONCE · Supprimer ?

Votre script shell fonctionne bien sur votre ordinateur portable. Vous le pousser sur GitHub, CI le détecte et le pipeline tombe avec une erreur cryptique — quelque chose comme /bin/bash^M: bad interpreter ou une tâche qui quitte avec le code 126 sans raison évidente. Le script est syntaxiquement correct. Vous n'avez pas modifié une ligne. Mais la compilation est brisée.

Neuf fois sur dix, l'origine est une fin de ligne. Plus précisément, des fins de ligne au format Windows CRLF cachées dans un fichier que Linux attend uniquement avec LF. Cet article explique ce que sont ces deux caractères, pourquoi la différence importe davantage que la plupart des développeurs le croient, et comment éliminer définitivement ce problème.

Ce que signifient CRLF et LF

Chaque fichier texte a besoin d'une manière de marquer la fin d'une ligne. Deux caractères de contrôle sont utilisés sur différents systèmes d'exploitation :

  • LF (Retour de ligne, \n, hexadécimal 0x0A) — le standard Unix et Linux. macOS l'a utilisé depuis OS X. Un octet par fin de ligne.
  • CRLF (Retour de chariot + Retour de ligne, \r\n, hexadécimal 0x0D 0x0A) — le standard Windows, hérité de DOS, qui l'a hérité des machines à écrire. Deux octets par fin de ligne.

Les noms proviennent des actions physiques d'une ancienne machine à écrire : un retour de chariot déplaçait la tête d'impression au début de la ligne ; un retour de ligne faisait avancer le papier d'une ligne. DOS a encodé les deux actions littéralement. Unix a choisi l'approche minimale et a conservé uniquement le retour de ligne.

Pourquoi CI échoue et votre ordinateur portable ne le fait pas

Si vous écrivez du code sur Windows et que votre éditeur enregistre les fichiers avec CRLF, tout fonctionne localement — les outils Windows gèrent les deux formats de manière transparente. Mais votre pipeline CI tourne probablement sur Linux, et les interprètes de shell Linux considèrent \r comme un caractère imprimable, et non comme un espace vide. Lorsque bash lit une ligne d'un script se terminant par \r\n, il voit la commande suivie d'un retour de chariot. Le résultat ressemble à cela :

/bin/bash^M: bad interpreter: No such file or directory

Le ^M dans cette erreur est la façon dont les terminaux affichent \r. Bash essaie d'exécuter une ligne de shebang se terminant par un retour de chariot, et bien sûr, aucun interprète à ce chemin n'existe.

Le même problème apparaît de manière plus subtile :

  • Les valeurs des variables d'environnement se terminant par \r détruisent silencieusement les comparaisons de chaînes.
  • Les scripts Docker échouent à démarrer car la ligne de shebang est corrompue. ENTRYPOINT Les scripts Python lisent des fichiers de configuration et obtiennent des clés comme
  • Les fichiers Make ignorent les règles car le caractère tab est suivi par "setting\r" au lieu de "setting".
  • Comment détecter le problème \r.

Avant de corriger quoi que ce soit, confirmez que le fichier a bien des fins de ligne CRLF. Quelques méthodes rapides :

cat -A (Linux/macOS)

Les lignes se terminant par CRLF apparaissent avec

cat -A deploy.sh

à la fin. Les lignes se terminant par LF montrent uniquement ^M$ file command $.

xxd ou hexdump

file deploy.sh
# deploy.sh: Bash script, ASCII text, with CRLF line terminators

Toute correspondance confirme CRLF. Si vous voyez uniquement

xxd deploy.sh | grep "0d 0a"

à la fin des lignes, vous êtes propre. 0a Comment le corriger

dos2unix (la solution la plus rapide)

Installez une fois, exécutez sur tout fichier :

sed (sans outil supplémentaire nécessaire)

# Install
sudo apt install dos2unix    # Debian/Ubuntu
brew install dos2unix        # macOS

# Convert a single file
dos2unix deploy.sh

# Convert all shell scripts in the repo
find . -name "*.sh" -exec dos2unix {} \;

tr (sécurisé POSIX)

sed -i "s/\r//" deploy.sh

Comment l'empêcher : configuration Git

tr -d "\r" < deploy.sh > deploy_fixed.sh && mv deploy_fixed.sh deploy.sh

Corriger les fichiers après le fait est réactif. La solution durable consiste à indiquer à Git la manière dont il doit gérer les fins de ligne afin que le problème ne parvienne jamais dans votre dépôt.

L'approche .gitattributes (recommandée)

Le fichier commis dans le dépôt impose des fins de ligne cohérentes pour tous, indépendamment de leurs paramètres locaux Git. Ajoutez cela au niveau racine de votre dépôt :

UN .gitattributes ligne indique à Git de détecter automatiquement les fichiers texte et de les stocker avec LF, quel que soit l'OS du développeur. Les lignes explicites ci-dessous bloquent les fichiers où CRLF causerait des erreurs en temps de fonctionnement.

# Normalize all text files to LF in the repo
* text=auto eol=lf

# Explicitly enforce LF for files that must never have CRLF
*.sh text eol=lf
*.bash text eol=lf
Makefile text eol=lf
Dockerfile text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
*.json text eol=lf

# Binary files — do not touch
*.png binary
*.jpg binary
*.gif binary
*.zip binary
*.gz binary

Le text=auto eol=lf Après avoir ajouté ou modifié

, rénormalisez les fichiers existants dans le dépôt : .gitattributesLa configuration core.autocrlf (seulement locale)

git add --renormalize .
git commit -m "normalize line endings"

Git a une configuration globale appelée

qui contrôle la conversion des fins de ligne lors du checkout et du commit. Les valeurs recommandées dépendent de votre système d'exploitation : core.autocrlf Le problème de dépendre uniquement de

# Windows — convert CRLF to LF on commit, LF to CRLF on checkout
git config --global core.autocrlf true

# Linux/macOS — convert CRLF to LF on commit, no conversion on checkout
git config --global core.autocrlf input

: elle s'applique uniquement à l'ordinateur où elle est définie. Un contributeur qui n'a jamais configuré cela peut encore pousser des fichiers CRLF. Un core.autocrlf est imposé par le dépôt lui-même, donc il est strictement plus fiable. .gitattributes Les paramètres de l'éditeur à bien configurer

Votre éditeur est la première ligne de défense. Quelques réglages rapides :

La fin de ligne du fichier actuel est affichée dans la barre d'état (en bas à droite). Cliquez dessus pour passer entre CRLF et LF. Pour définir la valeur par défaut pour les nouveaux fichiers, ajoutez cela dans votre

VS Code

Les IDEs JetBrains (IntelliJ, WebStorm, PyCharm) settings.json:

{
  "files.eol": "\n"
}

Allez à

Paramètres → Éditeur → Style de code et définissez Séparateur de ligne Unix et macOS (\n) à . Vous pouvez également ajouter unfichier au niveau racine du dépôt : .editorconfig La plupart des éditeurs modernes respectent

[*]
end_of_line = lf
insert_final_newline = true

naturellement ou via un plugin. En le commettant dans le dépôt, les contributeurs obtiennent des valeurs par défaut cohérentes sans configuration manuelle. .editorconfig La checklist complète

Si vous standardisez un dépôt qui a eu des problèmes de fins de ligne, passez par cette procédure dans l'ordre :

un fichier avec

  1. Ajoutez une .gitattributes et des règles explicites pour les scripts shell, les Dockerfiles et les fichiers de configuration. * text=auto eol=lf pour corriger les fichiers suivis dans le dépôt.
  2. Ajouter un .editorconfig et des règles explicites pour les scripts shell, les Dockerfiles et les fichiers de configuration. end_of_line = lf.
  3. Exécutez git add --renormalize . && git commit -m "normalize line endings" sur tous les scripts non suivis qui seront exécutés sur Linux.
  4. Exécutez dos2unix globalement sur les machines Linux/macOS;
  5. Ensemble core.autocrlf input sur Windows. true Ajoutez une étape de vérification dans CI — quelque chose comme
  6. — pour détecter toute régression avant qu'elle ne parvienne à une déploiement. grep -rUl $'\r' *.sh — pour détecter toute régression avant qu'elle ne parvienne à une déploiement.
Envie d'une expérience sans pub ? Passez à la version sans pub

Installez nos extensions

Ajoutez des outils IO à votre navigateur préféré pour un accès instantané et une recherche plus rapide

Sur Extension Chrome Sur Extension de bord Sur Extension Firefox Sur Extension de l'opéra

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 !

ANNONCE · Supprimer ?
ANNONCE · Supprimer ?
ANNONCE · Supprimer ?

Coin des nouvelles avec points forts techniques

Impliquez-vous

Aidez-nous à continuer à fournir des outils gratuits et précieux

Offre-moi un café
ANNONCE · Supprimer ?