CRLF vs LF El error de finalización de línea que rompe el CI
Tu script de shell funciona localmente, pero el CI arroja 'mal interpretador: /bin/bash^M'. Este es el problema de los saltos de línea CRLF. Aprende qué causa este problema, cómo detectarlo y cómo solucionarlo permanentemente con .gitattributes.
Tu script de shell funciona perfectamente en tu portátil. Lo subes a GitHub. El CI falla con un error confuso. /bin/bash^M: bad interpreter Has sido mordido por la falla más invisible en el desarrollo de software: los saltos de línea incorrectos.
Este guía explica qué son realmente CRLF y LF, por qué mezclarlos corrompe silenciosamente scripts y configuraciones, y los pasos exactos para evitar que los errores de saltos de línea lleguen a tu pipeline nuevamente.
¿Qué son CRLF y LF?
Cada archivo de texto necesita una forma de marcar el final de una línea. Dos convenciones existen, heredadas de la era de las máquinas de teletipo:
- LF (Line Feed) — un carácter (byte
\n). Utilizado por Linux, macOS y todos los sistemas derivados de Unix.0x0ACRLF (Carriage Return + Line Feed) - — dos caracteres, (bytes
\r\n). Utilizado por Windows y MS-DOS.0x0D 0x0ALos nombres provienen de la mecánica de las máquinas de escribir. Un
carriage return movía la cabeza de impresión al inicio de la línea. Un line feed avanzaba el papel una línea. Windows conservó ambos; Unix eliminó el redundante carriage return. ¿Por qué CRLF falla en los pipelines de CI?
En Linux (donde casi todos los ejecutores de CI funcionan), el
no es espacio en blanco — es un carácter literal. Cuando un script de shell se guarda con saltos de línea CRLF, cada línea termina con \r antes del salto de línea. El kernel interpreta la línea de comienzo como \r y busca un binario literalmente llamado #!/bin/bash\r . Ese binario no existe. bash\rEl error resultante se ve así:
es cómo los terminales muestran el carácter de retorno de carro. Es invisible en la mayoría de los editores de texto, lo que hace que esta falla sea tan desorientadora.
: bad interpreter: /bin/bash^M: No such file or directory
El ^M Otros lugares en los que CRLF causa daño silenciosamente
Dockerfiles
- — Una instrucción con saltos de línea CRLF insertará en cada comando, rompiendo comparaciones de cadenas y rutas de archivos.
RUNscripts de Python\rcuando - se sigue de —
SyntaxError: unexpected character after line continuation characterarchivos .env\— Los valores de variables de entorno adquieren un carácter de retorno final,\r\n. - por lo que nunca coincide con el esperado
\rarchivos CSV y de datosAPP_ENV=production\r— Los analizadores que leen línea por línea pueden incluirproduction. - en el último campo de cada fila. claves autorizadas SSH
\r— Un archivo de clave con saltos de línea CRLF será rechazado silenciosamente por el demonio SSH. - diferencias Git — Cada línea parece modificada, ocultando cambios reales en el ruido.
- Cómo detectar problemas de saltos de línea La mayoría de los editores ocultan los saltos de línea por defecto. Aquí hay formas confiables de verificar:
Usando cat o hexdump
Usando el comando file
Usando grep
# Show ^M characters
cat -A yourfile.sh | head -5
# Hex dump to see 0x0d (CR) characters
hexdump -C yourfile.sh | head -10
Cómo corregir los saltos de línea CRLF
file yourfile.sh
# CRLF output: yourfile.sh: ASCII text, with CRLF line terminators
# LF output: yourfile.sh: ASCII text
Opción 1: dos2unix (solución rápida y única)
# Returns exit code 0 (found) if CRLF endings exist
grep -rlP "\r" . --include="*.sh" --include="*.py" --include="*.yml"
elimina los retornos de carro de los archivos. Está disponible en todas las distribuciones principales de Linux:
Opción 2: sed (sin necesidad de herramientas adicionales)
dos2unix Opción 3: Corregir en VS Code o JetBrains
# 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
En VS Code, el modo de saltos de línea se muestra en la barra de estado (esquina inferior derecha). Haz clic para cambiar entre CRLF y LF para el archivo actual. Para cambiar el valor predeterminado para nuevos archivos, establece
# Remove carriage returns in-place
sed -i 's/\r//' yourscript.sh
# Or using tr
tr -d '\r' < input.sh > output.sh
en tu
En las IDEs JetBrains, ve a "files.eol": "\n" Archivo → Separadores de líneas settings.json.
para cambiar el archivo actual, o establecer el valor predeterminado en Edición → Estilo de código → Separador de líneas La solución correcta: .gitattributes Las soluciones de uno a uno no escalan. La solución correcta es un archivo.
que indica a Git exactamente qué saltos de línea deben imponerse, independientemente de qué editor o sistema usan los contribuyentes.
Después de agregar este archivo, ejecuta lo siguiente para normalizar todo el repositorio de una vez: .gitattributes La configuración autocrlf de Git — y por qué a menudo empeora las cosas
# .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
Git tiene una configuración que intenta convertir automáticamente los saltos de línea:
git add --renormalize .
git commit -m "chore: normalize line endings via .gitattributes"
— convierte LF a CRLF al recuperar (Windows), CRLF a LF al cometer (intendida para usuarios de Windows).
— convierte CRLF a LF al cometer, no hace nada al recuperar. Más segura para Mac/Linux. core.autocrlf — Git no hace nada. Lo que el editor guarda se comite tal cual.
core.autocrlf=trueEl problema:core.autocrlf=inputes una configuración local almacenada encore.autocrlf=false. Cada desarrollador del equipo tiene un valor diferente, por lo que los commits de máquinas diferentes producen saltos de línea diferentes. Esto genera ruido constante en las diferencias y fallos intermitentes en CI dependiendo de quién tocó último un archivo.
La regla general: core.autocrlf usa para establecer la política de saltos de línea en el repositorio. Deja que sea lo que cada desarrollador tenga — ~/.gitconfigla sobrescribe.
Añadir una verificación en CI Aunque .gitattributes esté en lugar, vale la pena añadir una verificación explícita en CI para capturar cualquier archivo que escape. Un paso de dos líneas cubre la mayoría de los casos: core.autocrlf Este paso falla de forma clara en la fuente — en la solicitud — en lugar de fallar silenciosamente en la implementación. .gitattributes Referencia rápida: CRLF vs LF
LF (
CRLF ( .gitattributes Bytes
# 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
Usado por
Linux, macOS, Unix
Windows, MS-DOS\n) | Seguro para scripts de shell\r\n) | |
|---|---|---|
| No — rompe el shebang | 0x0A | 0x0D 0x0A |
| Seguro para Dockerfile | Seguro para archivos .env | No — añade un \r al final de los valores |
| Recomendación de Git | Sí | Normalizar a LF en el repositorio |
| Solo para .bat/.cmd/.ps1 | Sí | No |
| CRLF vs LF: La falla de saltos de línea que rompe CI 2 | Sí | CRLF vs LF: La falla de saltos de línea que rompe CI 1 |
| Tu script de shell funciona localmente pero el CI lanza 'bad interpreter: /bin/bash^M'. Esta es la falla de saltos de línea CRLF. Aprende qué causa, cómo detectarlo y cómo corregirlo permanentemente con .gitattributes. | Normalizar a LF en el repositorio | Solo para .bat/.cmd/.ps1 |
Instalar extensiones
Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas
恵 ¡El marcador ha llegado!
Marcador es una forma divertida de llevar un registro de tus juegos, todos los datos se almacenan en tu navegador. ¡Próximamente habrá más funciones!
Herramientas clave
Ver todo Los recién llegados
Ver todoActualizar: Nuestro última herramienta se agregó el 28 abr. 2026
