linha shebang não funciona com cr-lf

10

Por que as partes shebang dos seguintes scripts elementares não estão funcionando:

$ cat hello.sh
#! /bin/sh
echo Hello
$ ./hello.sh
bash: ./hello.sh: /bin/sh^M: bad interpreter: No such file or directory

$ cat hello.py
#! /usr/bin/env python3
print("Hello")
$ ./hello.py
: No such file or directory

enquanto a chamada manual do intérprete está funcionando:

$ sh hello.sh
Hello
$ python3 hello.py
Hello
jamadagni
fonte

Respostas:

11

Seus scripts provavelmente têm finais de linha CR-LF no estilo DOS e não finais de linha LF no estilo Unix. O ^ M visto na mensagem de erro no primeiro caso é uma indicação de que o caractere 0D foi interpretado como parte do nome do interpretador de script e não como parte da linha que termina (como seria de esperar). Como não há arquivo executável no seu sistema com um caminho que inclua o caractere 0D (^ M), o sistema não pode chamar o intérprete. Quando você chama o intérprete manualmente, ele consegue lidar com os dois tipos de terminações de linha presentes no script.

Se você converter os scripts para usar terminações de linha LF no estilo Unix, deverá ver o shebang funcionando. Leia para obter uma ilustração.

Na sessão abaixo, todos e fromdos são um utilitário (disponível no Ubuntu como pacote tofrodos) para converter as convenções de final de linha de CR-LF para LF. Qualquer utilidade equivalente (consulte esta pergunta unix.SE ) serviria para fins de demonstração.

A seguinte transcrição da sessão (executada com os mesmos arquivos de script) deve esclarecer a situação:

$ fromdos hello.sh
$ ./hello.sh
Hello
$ todos hello.sh
$ ./hello.sh
bash: ./hello.sh: /bin/sh^M: bad interpreter: No such file or directory
$
$ fromdos hello.py
$ ./hello.py
Hello
$ todos hello.py
$ ./hello.py
: No such file or directory
$

Ele parece que é o kernel que lê a linha shebang, e, aparentemente, o kernel Linux (pelo menos a partir da versão no meu sistema picante Kubuntu) não reconhece o CR como parte da linha CR-LF terminando convenção.

Se o shebang do seu script não parece estar funcionando (ou seja, chamar manualmente o intérprete no script funciona, mas você não pode executar o script usando o nome do arquivo mesmo que o tenha feito chmod +x), esse é um motivo possível.

NOTA: Obrigado aos outros que também comentaram. Também ficaria feliz em saber se existem respostas melhores!

jamadagni
fonte