¿Odias los anuncios? Ir Sin publicidad Hoy

CRLF vs LF El error de finalización de línea que rompe el CI

Publicado el

Tu script de shell funciona localmente pero falla en el entorno CI con un error de intérprete confuso. La causa suele ser los saltos de línea CRLF. Aprende qué son, por qué rompen las pipelines de Linux y cómo solucionarlo permanentemente con .gitattributes y configuraciones de editores.

CRLF vs LF: El error de los saltos de línea que rompe el CI 1
ANUNCIO · ¿ELIMINAR?

Tu script de shell funcionó bien en tu portátil. Lo subes a GitHub, el CI lo detecta y el pipeline muere con un error confuso — algo como /bin/bash^M: bad interpreter o una tarea que termina con código 126 por razones obvias. El script es sintácticamente correcto. No has modificado ninguna línea. Pero la compilación está rota.

Nueve veces de cada diez, el culpable es un salto de línea. Específicamente, salto de línea en formato Windows (CRLF) oculto dentro de un archivo que Linux espera encontrar solo con LF. Este artículo explica qué son esas dos letras, por qué la diferencia importa más de lo que muchos desarrolladores creen y cómo eliminar el problema para siempre.

Qué significan realmente CRLF y LF

Cada archivo de texto necesita una forma de marcar el final de una línea. Dos caracteres de control se usan en diferentes sistemas operativos:

  • LF (Salto de línea, \n, hex 0x0A) — el estándar de Unix y Linux. macOS lo ha usado desde OS X. Un byte por salto de línea.
  • CRLF (Salto de carro + salto de línea, \r\n, hex 0x0D 0x0A) — el estándar de Windows, heredado de DOS, que a su vez lo heredó de máquinas de teletipo. Dos bytes por salto de línea.

Los nombres provienen de las acciones físicas de una antigua máquina de escribir: un salto de carro movía la cabeza de impresión al inicio de la línea; un salto de línea giraba el papel una línea. DOS codificó ambas acciones literalmente. Unix eligió el enfoque mínimo y conservó solo el salto de línea.

Por qué CI falla y tu portátil no

Si escribes código en Windows y tu editor guarda los archivos con CRLF, todo funciona localmente — las herramientas de Windows manejan ambos formatos de forma transparente. Pero tu pipeline de CI casi seguramente corre en Linux, y los interpretadores de shell de Linux tratan \r como un carácter imprimible, no como espacio en blanco. Cuando bash lee una línea de un script que termina en \r\n, ve el comando más un salto de carro al final. El resultado es este:

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

El ^M en ese error es cómo los terminales renderizan \r. Bash está tratando de ejecutar una línea de shebang que termina con un salto de carro, y, por supuesto, no existe ningún intérprete en esa ruta.

El mismo problema aparece de formas más sutiles:

  • Valores de variables de entorno con caracteres de salto de carro al final que rompen silenciosamente comparaciones de cadenas. \r Scripts de Docker que no arrancan porque la línea de shebang está corrupta.
  • Scripts de Python que leen archivos de configuración y obtienen claves como ENTRYPOINT Makefiles ignoran reglas porque el carácter de tab está seguido por
  • Cómo detectar el problema "setting\r" en lugar de "setting".
  • Antes de arreglar cualquier cosa, confirma que el archivo realmente tenga salto de línea CRLF. Algunas formas rápidas: \r.

cat -A (Linux/macOS)

Las líneas que terminan en CRLF mostrarán

al final. Las líneas que terminan en LF solo mostrarán

cat -A deploy.sh

file command ^M$ xxd o hexdump $.

Cualquier coincidencia confirma CRLF. Si ves solo

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

al final de las líneas, estás limpio.

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

Cómo arreglarlo 0a dos2unix (la solución más rápida)

Instálalo una vez, ejecútalo en cualquier archivo:

sed (sin necesidad de herramientas adicionales)

tr (seguro para POSIX)

# 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 {} \;

Cómo prevenirlo: configuración de Git

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

Arreglar archivos después de que ocurra el problema es reactiva. La solución duradera es indicar a Git cómo manejar los salto de línea para que el problema nunca llegue a tu repositorio.

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

El enfoque con .gitattributes (recomendado)

El archivo commitado al repositorio impone salto de línea consistentes para todos, independientemente de sus configuraciones locales. Añade esto en la raíz de tu repositorio:

line indica a Git que detecte automáticamente archivos de texto y los almacene con LF, independientemente del sistema operativo del desarrollador. Las líneas explícitas a continuación aseguran que los archivos con CRLF causen fallos en tiempo de ejecución.

A .gitattributes Después de añadir o modificar

# 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

El text=auto eol=lf , renormaliza los archivos existentes en el repositorio:

La configuración core.autocrlf (solo local) .gitattributesGit tiene una configuración global llamada

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

que controla la conversión de salto de línea en el momento de la revisión y el commit. Los valores recomendados dependen de tu sistema operativo:

El problema de depender de core.autocrlf solo: se aplica solo en la máquina donde se establece. Un contribuyente que nunca la haya configurado aún puede empujar archivos con CRLF. Un

# 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

se enforces por el repositorio en sí, por lo que es mucho más confiable. core.autocrlf Configuraciones del editor para obtener bien .gitattributes Tu editor es la primera línea de defensa. Algunas configuraciones rápidas:

El salto de línea actual del archivo se muestra en la barra de estado (esquina inferior derecha). Haz clic en él para cambiar entre CRLF y LF. Para establecer el valor predeterminado para nuevos archivos, añade esto a tu

Editores JetBrains (IntelliJ, WebStorm, PyCharm)

(CLI)

Ve a settings.json:

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

Configuración → Editor → Estilo de código

y establece Separador de líneas Unix y macOS (\n) . También puedes añadir un a archivo en la raíz del repositorio:La mayoría de los editores modernos lo respetan nativamente o mediante un complemento. Compartirlo en el repositorio significa que los contribuyentes obtienen valores predeterminados consistentes sin necesidad de configuración manual. .editorconfig La lista completa de verificación

[*]
end_of_line = lf
insert_final_newline = true

Si estás estandarizando un repositorio que ha tenido problemas con salto de línea, sigue este orden: .editorconfig archivo con

y reglas explícitas para scripts de shell, Dockerfiles y archivos de configuración.

Añade un

  1. Agrega una .gitattributes para arreglar los archivos ya trazados. * text=auto eol=lf en cualquier script no trazado que se ejecute en Linux.
  2. globalmente en máquinas Linux/macOS; .editorconfig para arreglar los archivos ya trazados. end_of_line = lf.
  3. Ejecuta git add --renormalize . && git commit -m "normalize line endings" en Windows.
  4. Ejecuta dos2unix Añade un paso de validación en CI — algo como
  5. Conjunto core.autocrlf input — para capturar cualquier regresión antes de que llegue a una implementación. true en Windows.
  6. Agregar un paso de revisión de CI — algo como grep -rUl $'\r' *.sh — para detectar cualquier regresión antes de que llegue a una implementación.

También te puede interesar

¿Quieres eliminar publicidad? Adiós publicidad hoy

Instalar extensiones

Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas

añadir Extensión de Chrome añadir Extensión de borde añadir Extensión de Firefox añadir Extensión de Opera

¡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!

ANUNCIO · ¿ELIMINAR?
ANUNCIO · ¿ELIMINAR?
ANUNCIO · ¿ELIMINAR?

Noticias Aspectos técnicos clave

Involucrarse

Ayúdanos a seguir brindando valiosas herramientas gratuitas

Invítame a un café
ANUNCIO · ¿ELIMINAR?