Corrigindo "bad interpreter" - Problemas de Shebang e CRLF
O que e o erro "bad interpreter"?
Conclusao: O shell nao consegue executar o interpretador indicado na linha shebang do script. Quase todos os casos sao terminacoes de linha CRLF ou um caminho shebang errado.
Voce tenta executar um shell script e encontra um erro como este:
$ ./deploy.sh -bash: ./deploy.sh: cannot execute: required file not found
O arquivo existe e tem permissao de execucao, mas se recusa a rodar. Este erro significa que o kernel nao consegue iniciar o interpretador declarado na linha 1 (o #!... shebang).
A mensagem acima e o que o bash 5.1 e posteriores exibem (Ubuntu 22.04+, Debian 11+, RHEL 9+, etc.). No bash 5.0 e anteriores (Ubuntu 20.04, Debian 10, RHEL 8, etc.) voce ve o caminho do interpretador e um ^M (CR), como -bash: ./deploy.sh: /bin/bash^M: bad interpreter: No such file or directory. A causa e identica em ambos os casos.
Reduza a duas causas primeiro
Quase sempre e uma de duas coisas:
- Terminacoes de linha CRLF se infiltraram (mais comum)
- O caminho do shebang nao existe
No bash 5.1 e posteriores ambas produzem o mesmo cannot execute: required file not found, entao o texto do erro sozinho nao consegue diferencia-las. Nao confie na mensagem; observe o arquivo diretamente com file e cat -A (abaixo) para decidir.
Note que Permission denied e um problema diferente: falta do bit de execucao (chmod +x). E facil confundir os dois, entao para o lado da permissao veja Corrigindo Permission denied.
Por que diz que nao encontra o interpretador?
Conclusao: O kernel usa a linha shebang literalmente como caminho do interpretador. Um
\rfinal do CRLF transforma/bin/bashem/bin/bash\r, um caminho que nao existe. O bash 5.1 e posteriores reportam comocannot execute: required file not found; o bash 5.0 e anteriores reportam comoNo such file or directory.
O kernel Linux le a primeira linha comecando com #! e trata o texto apos #! literalmente, como o caminho absoluto para um interpretador. Essa e a raiz do erro.
Arquivos salvos no Windows ou por alguns editores usam terminacoes de linha CRLF (\r\n) em vez de LF (\n). A linha shebang e entao lida como:
#!/bin/bash\r
este \r (CR) faz parte do "caminho"
Entao o kernel procura um arquivo literalmente chamado /bin/bash + retorno de carro. Esse arquivo nao existe, entao falha. O bash 5.1 e posteriores exibem cannot execute: required file not found; o bash 5.0 e anteriores exibem No such file or directory e mostram o CR como ^M (o ^M so aparece na mensagem do bash 5.0 e anteriores).
Mesmo quando o nome e o caminho estao corretos, um unico \r invisivel quebra tudo. Por isso a linha "parece certa mas nao roda."
O caminho do shebang em si tambem pode estar errado. Por exemplo, voce escreveu #!/usr/local/bin/python3 mas o Python so existe em /usr/bin/python3 naquela maquina.
Como saber se CRLF e a causa?
Conclusao: Use
filepara detectar o tipo de terminacao de linha ecat -Apara revelar^Mno final das linhas. Ambos expoe CRLF rapidamente.
Observe a causa antes de corrigir qualquer coisa.
Verificar terminacoes de linha com file
$ file deploy.sh
Quando CRLF esta presente, voce ve:
deploy.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators
with CRLF line terminators confirma que terminacoes de linha sao a causa. Um arquivo limpo mostra apenas ASCII text executable sem nota de CRLF.
Revelar finais de linha com cat -A
$ cat -A deploy.sh | head -3
#!/bin/bash^M$ ^M$ echo "deploy start"^M$
cat -A marca finais de linha com $ e CR com ^M. Se toda linha termina com ^M$, e CRLF. Um arquivo limpo mostra apenas $.
Inspecionar a linha shebang com precisao
$ head -1 deploy.sh | od -c
0000000 # ! / b i n / b a s h \r \n
\r \n juntos significa CRLF. \n sozinho significa LF (limpo).
Como corrigir terminacoes de linha CRLF?
Conclusao:
dos2unixe a correcao mais confiavel. Sem ele, usesed -i 's/\r$//'para remover o CR final de cada linha, depois re-verifique comfile.
Opcao 1: dos2unix (recomendado)
$ dos2unix deploy.sh
dos2unix: converting file deploy.sh to Unix format...
Uma ferramenta dedicada que converte CRLF para LF. Instale com sudo apt install dos2unix no Ubuntu/Debian ou sudo dnf install dos2unix em sistemas baseados em RHEL.
Opcao 2: sed (sem instalacao extra)
Se dos2unix nao estiver disponivel, sed resolve.
$ sed -i 's/\r$//' deploy.sh
s/\r$// significa "excluir o CR no final de cada linha." -i edita o arquivo in-place. Use -i.bak para manter um backup por precaucao.
$ sed -i.bak 's/\r$//' deploy.sh # mantem deploy.sh.bak
Com tr -d '\r', tr so le da entrada padrao, entao voce nao pode redirecionar de volta para o mesmo arquivo (ele ficaria vazio). Sempre escreva em um arquivo diferente.
$ tr -d '\r' < deploy.sh > deploy.unix.sh # OK $ tr -d '\r' < deploy.sh > deploy.sh # ERRADO: acaba vazio
Opcao 3: converter no vim
Se o arquivo ja esta aberto em um editor, corrija in-place.
:set fileformat=unix :w
Sempre confirme a correcao
$ file deploy.sh deploy.sh: Bourne-Again shell script, ASCII text executable $ ./deploy.sh deploy start
Se a nota CRLF line terminators desapareceu, esta feito.
Como corrigir um caminho shebang errado?
Conclusao: Confirme que o interpretador realmente existe no caminho do shebang com
which. Para portabilidade, use#!/usr/bin/env bash.
Este e o caso em que nenhum interpretador existe no caminho do shebang. No bash 5.0 e anteriores a mensagem mostra o caminho problematico, como bash: ./run.sh: /usr/local/bin/python3: bad interpreter. No bash 5.1 e posteriores um caminho ausente e CRLF parecem identicos -- ambos exibem cannot execute: required file not found sem mostrar o caminho. Em ambas as versoes, nao confie no texto do erro: descarte CRLF com file / cat -A, depois confirme se o interpretador existe com which.
Confirme que o interpretador existe
$ head -1 run.sh #!/usr/local/bin/python3 $ which python3 /usr/bin/python3
O shebang aponta para /usr/local/bin/python3, mas o binario real esta em /usr/bin/python3. Os caminhos divergem.
Resolva com env
Em vez de fixar o caminho real, deixe env encontrar o interpretador no PATH para melhor portabilidade.
#!/usr/bin/env python3
#!/usr/bin/env bash
env busca o interpretador no PATH, entao o script funciona independente de o binario estar em /usr/bin ou /usr/local/bin. E a forma moderna e resiliente ao ambiente.
Note que passar argumentos para o interpretador atraves de env e limitado (sistemas mais antigos nao suportam multiplos argumentos). Opcoes como set -euo pipefail pertencem ao corpo do script, nao ao shebang.
Como evitar que volte a acontecer?
Conclusao: Fixe arquivos
.shcomo LF com.gitattributese configure seu editor para salvar como LF. Esses dois passos bloqueiam quase toda reintroducao de CRLF.
Corrigir uma vez e inutil se CRLF volta a cada save ou commit. Corte na origem.
Fixar terminacoes de linha no Git
Coloque um .gitattributes na raiz do repositorio e fixe shell scripts como LF.
*.sh text eol=lf
Agora checkouts sempre usam LF, entao o arquivo sobrevive a edicoes de maquinas Windows.
Verifique tambem sua configuracao de core.autocrlf. No Linux/macOS, input e a escolha segura.
$ git config --global core.autocrlf input
core.autocrlf=true e comum entre desenvolvedores Windows, mas adiciona CRLF no checkout, criando condicoes para bad interpreter em shell scripts. Ao trabalhar com scripts, sobreponha explicitamente com eol=lf no .gitattributes.
Configure seu editor para salvar como LF
- VS Code: clique no indicador
CRLFno canto inferior direito e troque paraLF. Adicione um.editorconfigcomend_of_line = lfpara automatizar - vim: salve com
:set fileformat=unix - Windows Notepad: nao use para shell scripts (tende a adicionar CRLF)
Checklist final
file script.shnao mostraCRLF line terminators- O caminho do shebang em
head -1 script.shresolve para um interpretador real viawhich ls -l script.shmostra o bit de execucao (x) ativo
Com os tres em ordem, bad interpreter nao retornara.