CRLF versus LF O Erro de Final de Linha que Quebra o CI
Seu script de shell funciona localmente, mas o CI lança 'interprete inválido: /bin/bash^M'. Este é o problema de terminação de linha CRLF. Aprenda o que o causa, como detectá-lo e como corrigi-lo permanentemente com .gitattributes.
Seu script de shell executa perfeitamente no seu laptop. Você o pusha para o GitHub. O CI falha com um erro obscuro /bin/bash^M: bad interpreter Você acabou sendo mordido pela maior bug invisível no desenvolvimento de software: os terminadores de linha errados.
Este guia explica o que CRLF e LF realmente são, por que misturar os dois corrompe silenciosamente scripts e configurações, e os passos exatos para prevenir que erros de terminador de linha nunca cheguem ao seu pipeline novamente.
O que são CRLF e LF?
Todo arquivo de texto precisa de uma forma de marcar o final de uma linha. Duas convenções existem, herdadas da era das máquinas de telegrafia físicas:
- LF (Line Feed) — um caractere (byte
\n). Usado por Linux, macOS e todos os sistemas derivados do Unix.0x0ACRLF (Carriage Return + Line Feed) - — dois caracteres, (bytes
\r\n). Usado por Windows e MS-DOS.0x0D 0x0AOs nomes vêm da mecânica de máquinas de escrever. Um
carriage return movia a cabeça de impressão de volta ao início da linha. Um line feed avaliava o papel uma linha. Windows mantinha os dois; Unix eliminou o carro de retorno redundante. Por que CRLF quebra pipelines de CI?
Em Linux (onde praticamente todos os executadores de CI operam), o
não é espaço em branco — é um caractere literal. Quando um script de shell é salvo com terminadores CRLF, cada linha termina com \r antes da quebra de linha. O kernel interpreta a linha de início como \r e procura por um binário literal chamado #!/bin/bash\r . Esse binário não existe. bash\rO erro resultante parece assim:
é a forma como terminais exibem o caractere de retorno de carro. Ele é invisível na maioria dos editores de texto, o que torna esse bug tão desorientador.
: bad interpreter: /bin/bash^M: No such file or directory
O ^M Outros locais onde CRLF causa danos silenciosamente
Dockerfiles
- — Uma instrução com terminadores CRLF injeta em cada comando, quebrando comparações de strings e caminhos de arquivos.
RUNScripts em Python\rquando - é seguida por —
SyntaxError: unexpected character after line continuation characterarquivos .env\— Os valores das variáveis de ambiente adquirem um caractere de retorno final,\r\n. - não corresponde ao esperado arquivos CSV e de dados
\r— Analisadores que leem linha por linha podem incluirAPP_ENV=production\rno último campo de cada linha.production. - Chaves autorizadas SSH — Um arquivo de chave com terminadores CRLF será rejeitado silenciosamente pelo servidor SSH.
\rDiferenças Git - — Cada linha parece alterada, escondendo mudanças reais sob ruído. Como detectar problemas com terminadores de linha
- A maioria dos editores oculta terminadores de linha por padrão. Aqui estão métodos confiáveis para verificar: Usando cat ou hexdump
Usando o comando file
Usando grep
Como corrigir terminadores de linha CRLF
# Show ^M characters
cat -A yourfile.sh | head -5
# Hex dump to see 0x0d (CR) characters
hexdump -C yourfile.sh | head -10
Opção 1: dos2unix (correção rápida e única)
file yourfile.sh
# CRLF output: yourfile.sh: ASCII text, with CRLF line terminators
# LF output: yourfile.sh: ASCII text
remove os retornos de carro dos arquivos. Está disponível em todas as principais distribuições Linux:
# Returns exit code 0 (found) if CRLF endings exist
grep -rlP "\r" . --include="*.sh" --include="*.py" --include="*.yml"
Opção 2: sed (sem necessidade de ferramentas adicionais)
Opção 3: Corrigir no VS Code ou JetBrains
dos2unix No VS Code, o modo de terminador de linha é exibido na barra de status (canto inferior direito). Clique para alternar entre CRLF e LF para o arquivo atual. Para alterar o padrão para novos arquivos, defina
# 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
no seu
# Remove carriage returns in-place
sed -i 's/\r//' yourscript.sh
# Or using tr
tr -d '\r' < input.sh > output.sh
No IDEs JetBrains, vá para
Arquivo → Separadores de Linha "files.eol": "\n" para alterar o arquivo atual, ou defina o padrão em settings.json.
Editor → Estilo de Código → Separador de Linha A Correta Solução: .gitattributes Correções pontuais não escalam. A solução correta é um arquivo que informa ao Git quais terminadores de linha devem ser exigidos, independentemente do editor ou do sistema usado pelos contribuidores..
Após adicionar esse arquivo, execute o seguinte para re-normalizar todo o repositório de uma vez:
A configuração autocrlf do Git — e por que ela muitas vezes piora as coisas .gitattributes O Git tem uma configuração que tenta converter automaticamente os terminadores de linha:
# .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
— converte LF para CRLF em checkout (Windows), CRLF para LF em commit. Intendida para usuários do Windows.
git add --renormalize .
git commit -m "chore: normalize line endings via .gitattributes"
— converte CRLF para LF em commit, não faz nada em checkout. Mais segura para Mac/Linux.
— O Git não faz nada. O que o editor salva é o que é commitado. core.autocrlf O problema:
core.autocrlf=trueé uma configuração local armazenada emcore.autocrlf=input. Cada desenvolvedor da equipe tem um valor diferente, então os commits de máquinas diferentes produzem terminadores de linha diferentes. Isso cria ruído constante nas diferenças e falhas intermitentes no CI dependendo de quem ultimamente tocou em um arquivo.core.autocrlf=falseRegra geral:
use core.autocrlf para definir a política de terminadores de linha no repositório. Deixe ser o que cada desenvolvedor tem — sobrescreve isso. ~/.gitconfigAdicionando uma verificação no CI
Mesmo com em lugar, vale a pena adicionar uma verificação explícita no CI para capturar quaisquer arquivos que passarem. Um passo de duas linhas cobre a maioria dos casos: .gitattributes Este passo falha de forma clara na fonte — a solicitação — em vez de falhar silenciosamente na implantação. core.autocrlf Referência rápida: CRLF versus LF .gitattributes LF (
CRLF (
Bytes .gitattributes Usado por
# 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
Linux, macOS, Unix
Windows, MS-DOS
Seguro para scripts de shell\n) | Não — quebra a linha de início\r\n) | |
|---|---|---|
| Seguro para Dockerfile | 0x0A | 0x0D 0x0A |
| Seguro para arquivos .env | Não — adiciona \r ao final dos valores | Recomendação do Git |
| Normalizar para LF no repositório | Sim | Apenas para arquivos .bat/.cmd/.ps1 |
| CRLF versus LF: O Erro de Terminador de Linha que Quebra o CI 2 | Sim | Não |
| CRLF versus LF: O Erro de Terminador de Linha que Quebra o CI 1 | Sim | Não — adiciona \r no final dos valores |
| Recomendação do Git | Normalizar para LF no repositório | Apenas para .bat/.cmd/.ps1 |
Instale nossas extensões
Adicione ferramentas de IO ao seu navegador favorito para acesso instantâneo e pesquisa mais rápida
恵 O placar chegou!
Placar é uma forma divertida de acompanhar seus jogos, todos os dados são armazenados em seu navegador. Mais recursos serão lançados em breve!
Ferramentas essenciais
Ver tudo Novas chegadas
Ver tudoAtualizar: Nosso ferramenta mais recente foi adicionado em 29 abr 2026
