Por que todos os arquivos de script começam com
#!/bin/sh
ou com
#!/bin/csh
Isso é necessário? Qual é o propósito disso? E qual é a diferença entre os dois?
Por que todos os arquivos de script começam com
#!/bin/sh
ou com
#!/bin/csh
Isso é necessário? Qual é o propósito disso? E qual é a diferença entre os dois?
Respostas:
Isso é conhecido como Shebang
:
http://en.wikipedia.org/wiki/Shebang_(Unix)
#! intérprete [opcional-arg]
Um shebang só é relevante quando um script tem permissão de execução (por exemplo, chmod u + x script.sh).
Quando um shell executa o script, ele usa o interpretador especificado.
Exemplo:
#!/bin/bash
# file: foo.sh
echo 1
$ chmod u+x foo.sh
$ ./foo.sh
1
A #!
linha informa ao kernel (especificamente, a implementação da execve
chamada do sistema) que este programa foi escrito em uma linguagem interpretada; o caminho absoluto que segue identifica o intérprete. Os programas compilados em código de máquina começam com uma sequência de bytes diferente - na maioria dos Unixes modernos, 7f 45 4c 46
( ^?ELF) que os identifica como tal.
Você pode colocar um caminho absoluto para qualquer programa que desejar após o #!
, desde que esse programa não seja um #!
script. O kernel reescreve uma invocação de
./script arg1 arg2 arg3 ...
onde ./script
começa com, digamos, #! /usr/bin/perl
como se a linha de comando tivesse realmente sido
/usr/bin/perl ./script arg1 arg2 arg3
Ou, como você viu, você pode usar #! /bin/sh
para escrever um script para ser interpretado por sh
.
A #!
linha só é processada se você invocar diretamente o script ( ./script
na linha de comando); o arquivo também deve ser executável ( chmod +x script
). Se você fizer isso, sh ./script
a #!
linha não será necessária (e será ignorada se estiver presente), e o arquivo não precisa ser executável. O objetivo do recurso é permitir que você invoque diretamente programas em linguagem interpretada sem precisar saber em que idioma eles estão escritos. (Faça grep '^#!' /usr/bin/*
- você descobrirá que muitos programas de estoque estão de fato usando esse recurso.)
Aqui estão algumas regras para usar este recurso:
#!
devem ser os dois primeiros bytes do arquivo. Em particular, o arquivo deve estar em uma codificação compatível com ASCII (por exemplo, UTF-8 funcionará, mas UTF-16 não) e não deve começar com uma "marca de ordem de byte", ou o kernel não o reconhecerá como um #!
roteiro.#!
deve ser um caminho absoluto (começa com /
). Não pode conter espaço, tabulação ou caracteres de nova linha.#!
e o /
. Não coloque mais de um espaço lá.#!
linha, elas não serão expandidas.#! /usr/bin/awk -f
), às vezes é apenas útil ( #! /usr/bin/perl -Tw
). Infelizmente, você não pode colocar dois ou mais argumentos após o caminho absoluto.#! /usr/bin/env interpreter
vez de #! /absolute/path/to/interpreter
. Isso quase sempre é um erro. Isso faz com que o comportamento do seu programa dependa da $PATH
variável do usuário que invoca o script. E nem todos os sistemas têm, env
em primeiro lugar.setuid
ou setgid
não podem ser usados com privilégios #!
; eles devem ser compilados em código de máquina. (Se você não sabe o que setuid
é, não se preocupe com isso.)No csh
que diz respeito , refere-se sh
aproximadamente a como o Substituto Avançado de Chá Nutrimat se refere ao chá. Ele tem (ou melhor, teve; as implementações modernas do sh
alcançaram) várias vantagens em relação sh
ao uso interativo, mas usá-lo (ou seu descendente tcsh
) para scripts é quase sempre um erro . Se você é novo no shell scripting em geral, recomendo fortemente que você ignore e se concentre em sh
. Se você estiver usando um csh
parente como shell de login, mude para bash
ou zsh
, para que a linguagem de comando interativa seja a mesma que a linguagem de script que você está aprendendo.
#!
; nenhum comentário sobre se é um bom estilo. Veja esta pergunta e minha resposta para uma discussão sobre os prós e contras do #!/usr/bin/env
hack.
#!/usr/bin/env
era a coisa certa, mas continua sendo minha opinião que quase sempre é uma má ideia.
Isso define qual shell (interpretador de comando) você está usando para interpretar / executar seu script. Cada shell é ligeiramente diferente na maneira como interage com o usuário e executa scripts (programas).
Quando você digita um comando no prompt do Unix, está interagindo com o shell.
Por exemplo, #!/bin/csh
refere-se ao C-shell, /bin/tcsh
o t-shell, /bin/bash
o bash shell, etc.
Você pode dizer qual shell interativo está usando o
echo $SHELL
comando, ou alternativamente
env | grep -i shell
Você pode alterar seu shell de comando com o chsh
comando.
Cada um tem um conjunto de comandos ligeiramente diferente e uma maneira de atribuir variáveis e seu próprio conjunto de construções de programação. Por exemplo, a instrução if-else com bash parece diferente daquela no C-shell.
Esta página pode ser de interesse, pois "traduz" entre os comandos / sintaxe bash e tcsh.
Usar a diretiva no script de shell permite executar programas usando um shell diferente. Por exemplo, eu uso o tcsh
shell interativamente, mas geralmente executo scripts bash usando / bin / bash no arquivo de script.
A parte, de lado:
Este conceito se estende a outros scripts também. Por exemplo, se você programa em Python, você colocaria
#!/usr/bin/python
no topo do seu programa Python
#! $SHELL
? Isso colocaria a concha correta no Shebang?
!#/bin/bash
diretiva , por exemplo . Diz ao sistema qual shell usar para executar seu script de shell.
$SHELL
não indica necessariamente qual shell você está executando no momento; normalmente mostra seu shell padrão . conjuntos tcsh $version
e $tcsh
; conjuntos bash $BASH_VERSION
. Nem todas as conchas têm necessariamente mecanismos semelhantes.
#!
linha deve corresponder à sintaxe do script, não ao shell interativo usado por quem está executando o script.
#!/bin/csh -f
; o-f
diz ao shell para não fornecer o.login
e.cshrc
, o que torna o script executado mais rápido e evita dependências na configuração do usuário. (Ou melhor ainda, não escreva scripts csh.) Não use-f
para scripts sh ou bash; não tem o mesmo significado.