É #! / bin / sh lido pelo intérprete?

60

Em bash ou sh , acho que tudo o que começa com # é um comentário .

Mas em scripts bash , escrevemos:

#!/bin/bash

E em scripts Python, existe:

#!/bin/python

Isso significa que # por si só é um comentário, enquanto #! não é?

    
por Gaurav Sharma 09.01.2013 / 07:04

4 respostas

88

A linha #! é usada antes de o script ser executado e, em seguida, ignorado quando o script é executado.

Você está perguntando qual é a diferença entre uma linha shebang e um comentário comum.

Uma linha que começa com #! é tanto um comentário quanto qualquer outra linha que comece com # . Isso será verdadeiro se o #! for a primeira linha do arquivo ou em qualquer outro lugar. #!/bin/sh tem um efeito , mas não é lido pelo próprio intérprete .

# não é um comentário em todas as linguagens de programação, mas, como você sabe, é um comentário em shells estilo Bourne incluindo sh e bash (assim como a maioria dos shells não Bourne, como% código%). É também um comentário em Python . E é um comentário em uma variedade de arquivos de configuração que não são realmente scripts (como csh ).

Suponha que um script de shell comece com /etc/fstab . Isso é um comentário, e o interpretador (o shell) ignora tudo na linha após o caractere #!/bin/sh .

O propósito de uma linha # não é fornecer informações ao intérprete. O objetivo da linha #! é informar ao sistema operacional (ou qualquer processo que inicie o interpretador) o que usar como intérprete .

  • Se você invocar o script como um arquivo executável, por exemplo, executando #! , o sistema consultará a primeira linha para ver se começa com ./script.sh , seguido por zero ou mais espaços, seguido por um comando. Em caso afirmativo, ele executa esse comando com o nome do script como seu argumento. Neste exemplo, ele executa #! (ou, tecnicamente, /bin/sh script.sh ).

  • Se você invocar o script explicitamente chamando o interpretador, a linha /bin/sh ./script.sh nunca será consultada. Então, se você executar #! , a primeira linha não terá efeito. Se a primeira linha de sh script.sh for script2.sh , executar #!/usr/games/nibbles não tentará abrir o script em sh script2.sh (mas nibbles will).

Você notará que, em nenhum dos casos, a extensão do script ( ./script2.sh ), se tiver um, afeta o modo como ele é executado. Em um sistema similar ao Unix, isso normalmente não afeta a maneira como o script é executado. Em alguns outros sistemas, como o Windows, a linha .sh shebang pode ser totalmente ignorada pelo sistema e a extensão pode determinar o que executa os scripts. (Isso não significa que você precisa fornecer extensões de scripts, mas é uma das razões pelas quais, se você fizer isso, elas devem estar corretas.)

#! foi escolhido para atender a essa finalidade com precisão porque #! começa um comentário. A linha # é para o sistema, não para o intérprete, e deve ser ignorada pelo intérprete.

Shebang Line for Bash Scripts

Você (originalmente) disse usar #! para #!/bin/sh scripts. Você só deve fazer isso se o script não exigir nenhuma das extensões bash - bash precisa ser capaz de executar o script. sh nem sempre é um link simbólico para sh . Frequentemente, incluindo em todos os sistemas Debian e Ubuntu remotamente recentes, bash é um symlink para sh .

Shebang Line para scripts em Python

Você também disse (na primeira versão da sua pergunta, antes de editar) que inicia seus scripts Python com dash . Se você quer dizer isso literalmente, então você definitivamente deveria parar de fazer isso. Se #!/bin/sh read by the interpretor começar com essa linha, executar hello.py será executado:

/bin/sh read by the interpretor hello.py

./hello.py tentará executar um script chamado /bin/sh (com read como seus argumentos), by the interpretor hello.py (esperançosamente) não será encontrado, e seu script Python nunca será visto por um interpretador Python.

Se você cometer esse erro, mas não tiver o problema que estou descrevendo, provavelmente estará invocando os scripts do Python especificando explicitamente o interpretador (por exemplo, read ), fazendo com que a primeira linha seja ignorada. Quando você distribui seus scripts para outras pessoas ou os utiliza muito tempo depois, pode não estar claro se isso é necessário para que funcionem. É melhor corrigi-los agora. Ou, pelo menos, remova a primeira linha completamente, para que, quando não funcionarem com python hello.py , a mensagem de erro faça sentido.

Para scripts em Python, se você souber onde o interpretador Python está (ou será), poderá escrever a linha ./ da mesma maneira:

#!/usr/bin/python

Ou, se for um script do Python 3, você deve especificar #! , pois python3 é quase sempre Python 2 :

#!/usr/bin/python3

No entanto, o problema é que, enquanto python deve sempre existir, e /bin/sh quase sempre existe em sistemas em que /bin/bash vem com o SO, o Python pode existir em uma variedade de locais.

Portanto, muitos programadores Python usam isso:

#!/usr/bin/env python

(Ou bash para o Python 3.)

Isso faz com que o script dependa de #!/usr/bin/env python3 estar no "lugar certo", em vez de depender de env estar no lugar certo. Isso é bom, porque:

  • python está quase sempre localizado em env .
  • Na maioria dos sistemas, qualquer que seja o /usr/bin deve executar seu script é o que aparece primeiro no python . A partir de PATH com hello.py make #!/usr/bin/env python run ./hello.py , que é (virtualmente) equivalente a executar /usr/bin/env python hello.py .

O motivo pelo qual você não pode usar python hello.py é isso:

  • Você deseja que o interpretador especificado seja fornecido por um caminho absoluto (por exemplo, começando com #!python ).
  • O processo de chamada executaria / no diretório atual. O comportamento de pesquisar o caminho quando o comando não contém uma barra é um comportamento específico do shell.

Ocasionalmente, um script em Python ou outro que não seja um script de shell terá uma linha shebang começando com python , em que #!/bin/sh ... é algum outro código. Isso às vezes está correto, porque há algumas maneiras de invocar o shell compatível com Bourne ( ... ) com argumentos para fazer com que ele invoque um interpretador Python. (Um dos argumentos provavelmente conterá sh .) No entanto, para a maioria dos propósitos, python é mais simples, mais elegante e mais provável de funcionar da maneira que você deseja.

Shebang Lines em outros idiomas

Muitas linguagens de programação e script, e alguns outros formatos de arquivo, usam #!/usr/bin/env python como um comentário. Para qualquer um deles, um arquivo no idioma pode ser executado por um programa que o utiliza como argumento especificando o programa na primeira linha após # .

Em algumas linguagens de programação, #! normalmente não é um comentário, mas como um caso especial, a primeira linha é ignorada se começar com # . Isso facilita o uso da sintaxe #! , mesmo que #! não torne uma linha um comentário.

Shebang Lines para arquivos que não são executados como scripts

Embora seja menos intuitivo, qualquer arquivo cujo formato de arquivo possa acomodar uma primeira linha que comece com # seguido pelo caminho completo de um executável pode ter uma linha shebang. Se você fizer isso, e o arquivo estiver marcado como executável, você poderá executá-lo como um programa ... fazendo com que ele seja aberto como um documento.

Algumas aplicações usam esse comportamento intencionalmente. Por exemplo, no VMware, #! arquivos definem máquinas virtuais. Você pode "executar" uma máquina virtual como se fosse um script porque esses arquivos são marcados como executáveis e possuem uma linha shebang, fazendo com que eles sejam abertos em um utilitário VMware.

Shebang Lines para arquivos que não são executados como scripts, mas funcionam como scripts, de qualquer forma

.vmx remove arquivos. Não é uma linguagem de script. No entanto, um arquivo que inicia rm e é marcado como executável pode ser executado e, quando você o executa, #!/bin/rm é invocado, excluindo-o.

Isso é frequentemente conceituado como "o arquivo é excluído". Mas o arquivo não está realmente rodando. Isso é mais parecido com a situação descrita acima para rm arquivos.

Ainda assim, como a linha .vmx facilita a execução de um comando simplista (incluindo argumentos da linha de comando), é possível executar alguns scripts dessa maneira. Como um exemplo simples de um "script" mais sofisticado que #! , considere:

#!/usr/bin/env tee -a

Isso leva a entrada do usuário de forma interativa, ecoa de volta para o usuário linha por linha e a anexa ao final do arquivo "script".

Útil? Não muito. Conceitualmente interessante? Totalmente! Sim. (Um pouco).

Conceitualmente Conceitos Semelhantes de Programação / Criação de Scripts (apenas por diversão)

por Eliah Kagan 09.01.2013 / 08:30
7

Um shebang é a sequência de caracteres que consiste no sinal numérico e no ponto de exclamação (por exemplo, "#!") quando ocorre como os dois caracteres iniciais na linha inicial de um script.

Em sistemas operacionais * nix, quando um script que inicia com um shebang é executado, o carregador de programas analisa o restante da linha inicial do script como uma diretiva de intérprete; o programa de intérprete especificado é executado em vez disso, passando para ele como um argumento o caminho que foi inicialmente usado ao tentar executar o script. Por exemplo, se um script é nomeado com o caminho "caminho / para / seu-script", e ele começa com a seguinte linha:

#!/bin/sh

ent o carregador de programas instruo a executar o programa "/ bin / sh" em vez de, e. o shell Bourne ou um shell compatível, passando "path / to / your-script" como o primeiro argumento.

Assim, um script é nomeado com o caminho "path / to / python-script" e começa com a seguinte linha:

#!/bin/python

ent o programa carregado instruo para executar o programa "/ bin / python" em vez de, e. Intérprete Python, passando "path / to / python-script" como o primeiro argumento.

Em suma, "#" irá comentar uma linha enquanto a sequência de caracteres "#!" ocorrendo como os dois primeiros caracteres na linha inicial de um script tem o significado descrito acima.

Para detalhes, veja Por que alguns scripts começam com #! ...?

Fonte: Algumas seções desta resposta são derivadas (com pequenas modificações) de Shebang (Unix) em Wikipédia em inglês (por contribuidores da Wikipedia ). Este artigo é licenciado sob o CC-BY-SA 3.0 , da mesma forma que o conteúdo do usuário aqui na AU, portanto, essa derivação é permitida com atribuição.

    
por Goran Miskovic 09.01.2013 / 07:57
4

#! é chamado de shebang quando ocorre como os dois caracteres iniciais na linha inicial de um script. É usado em scripts para indicar um intérprete para execução. O shebang é para o sistema operacional (kernel), não para o shell; por isso não será interpretado como um comentário.

Cortesia: link

  

Em geral, se um arquivo é executável, mas na verdade não é um executável   programa (binário), e tal linha está presente, o programa especificado   depois de #! é iniciado com o scriptname e todos os seus argumentos. Estes   dois personagens # e! tem que ser os dois primeiros bytes no arquivo!

Informações detalhadas: link

    
por saji89 09.01.2013 / 07:34
0

Não, ele é usado apenas pela chamada de sistema exec do kernel do Linux e tratado como um comentário pelo intérprete

Quando você faz no bash:

./something

no Linux, isso chama a chamada do sistema exec com o caminho completo para something .

Esta linha do kernel é chamada no arquivo passado para exec : link

  

if ((bprm- & gt; buf [0]! = '#') || (bprm- & gt; buf [1]! = '!'))

Isto lê os primeiros bytes do arquivo e compara-os com #! .

Se isso for verdade, então o resto da linha é analisada pelo kernel do Linux, o que faz outra chamada de exec com o caminho /usr/bin/env python e o arquivo atual como o primeiro argumento:

/usr/bin/env python /path/to/script.py

e isso funciona para qualquer linguagem de script que use # como um caractere de comentário.

E sim, você pode fazer um loop infinito com:

#!/a

e um arquivo executável em /a

#! simplesmente é legível por humanos, mas isso não é necessário.

Se o arquivo foi iniciado com bytes diferentes, a chamada do sistema exec usaria um manipulador diferente. O outro manipulador integrado mais importante é o dos arquivos executáveis do ELF: link que verifica os bytes 7f 45 4c 46 (que também é legível por .ELF ). Isso lê o arquivo ELF, coloca-o na memória corretamente e inicia um novo processo com ele. Veja também: link

Finalmente, você pode adicionar seus próprios manipuladores shebang com o mecanismo binfmt_misc . Por exemplo, você pode adicionar um manipulador personalizado para .jar files . Este mecanismo ainda suporta manipuladores por extensão de arquivo. Outro aplicativo é executar executáveis de forma transparente uma arquitetura diferente com o QEMU .

No entanto, não acredito que o POSIX especifique shebangs: link , embora ele mencione nas seções de lógica, e na forma "se scripts executáveis são suportados pelo sistema, algo pode acontecer".