Para um script csh, você deve usar #!/bin/csh -f; o -fdiz ao shell para não fornecer o .logine .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 -fpara scripts sh ou bash; não tem o mesmo significado.
@Kolob Canyon você não precisa, mas pode ajudar alguns editores com realce de sintaxe (embora geralmente haja outras maneiras de conseguir a mesma coisa): unix.stackexchange.com/a/88730/193985
Braham Snyder
42
A #!linha informa ao kernel (especificamente, a implementação da execvechamada 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 ./scriptcomeça com, digamos, #! /usr/bin/perlcomo se a linha de comando tivesse realmente sido
/usr/bin/perl ./script arg1 arg2 arg3
Ou, como você viu, você pode usar #! /bin/shpara escrever um script para ser interpretado por sh.
A #!linha só é processada se você invocar diretamente o script ( ./scriptna linha de comando); o arquivo também deve ser executável ( chmod +x script). Se você fizer isso, sh ./scripta #!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:
A #!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.
O caminho após #!deve ser um caminho absoluto (começa com /). Não pode conter espaço, tabulação ou caracteres de nova linha.
É um bom estilo, mas não obrigatório, colocar um espaço entre o #!e o /. Não coloque mais de um espaço lá.
Você não pode colocar variáveis de shell na #!linha, elas não serão expandidas.
Você pode colocar um argumento de linha de comando após o caminho absoluto, separado dele por um único espaço. Como o caminho absoluto, este argumento não pode conter espaço, tabulação ou caracteres de nova linha. Às vezes, isso é necessário para fazer as coisas funcionarem ( #! /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.
Algumas pessoas dirão para você usar em #! /usr/bin/env interpretervez de #! /absolute/path/to/interpreter. Isso quase sempre é um erro. Isso faz com que o comportamento do seu programa dependa da $PATHvariável do usuário que invoca o script. E nem todos os sistemas têm, envem primeiro lugar.
Programas que precisam setuidou setgidnã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 cshque diz respeito , refere-se shaproximadamente a como o Substituto Avançado de Chá Nutrimat se refere ao chá. Ele tem (ou melhor, teve; as implementações modernas do shalcançaram) várias vantagens em relação shao 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 cshparente como shell de login, mude para bashou zsh, para que a linguagem de comando interativa seja a mesma que a linguagem de script que você está aprendendo.
Versões recentes do Linux permitem que o interpretador especificado seja um script. É prática comum omitir o espaço após o #!; 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/envhack.
Keith Thompson
@KeithThompson Tenho a impressão de que o Linux é a única variante comum do Unix que permite que o interpretador seja um script, então ainda não é algo em que se possa confiar. Desde que escrevi isso, eu mesmo encontrei uma situação em que #!/usr/bin/envera a coisa certa, mas continua sendo minha opinião que quase sempre é uma má ideia.
zwol
4
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/cshrefere-se ao C-shell, /bin/tcsho t-shell, /bin/basho 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 chshcomando.
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 tcshshell 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
Então, é necessário? Como posso saber qual shell estou realmente usando?
One Two Three
Portanto, se estou escrevendo os scripts para alguém usar em sua máquina e não sei qual shell eles estão usando. (Essa pessoa, infelizmente, não tem ideia sobre essas coisas, portanto, tudo o que ela pode fazer é executar o script sem alterar nada). Posso fazer algo assim #! $SHELL? Isso colocaria a concha correta no Shebang?
One Two Three
1
@OneTwoThree A maioria dos sistemas possui shells padrão, se você escrever um script bash ou csh, não terá problemas. O shell que eles estão usando interativamente não importa, essa é a beleza da !#/bin/bashdiretiva , por exemplo . Diz ao sistema qual shell usar para executar seu script de shell.
Levon
O valor de $SHELLnão indica necessariamente qual shell você está executando no momento; normalmente mostra seu shell padrão . conjuntos tcsh $versione $tcsh; conjuntos bash $BASH_VERSION. Nem todas as conchas têm necessariamente mecanismos semelhantes.
Keith Thompson
1
@OneTwoThree: A #!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.Respostas:
Isso é conhecido como
Shebang
:http://en.wikipedia.org/wiki/Shebang_(Unix)
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
fonte
A
#!
linha informa ao kernel (especificamente, a implementação daexecve
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 deonde
./script
começa com, digamos,#! /usr/bin/perl
como se a linha de comando tivesse realmente sidoOu, como você viu, você pode usar
#! /bin/sh
para escrever um script para ser interpretado porsh
.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çagrep '^#!' /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
ousetgid
não podem ser usados com privilégios#!
; eles devem ser compilados em código de máquina. (Se você não sabe o quesetuid
é, não se preocupe com isso.)No
csh
que diz respeito , refere-sesh
aproximadamente a como o Substituto Avançado de Chá Nutrimat se refere ao chá. Ele tem (ou melhor, teve; as implementações modernas dosh
alcançaram) várias vantagens em relaçãosh
ao uso interativo, mas usá-lo (ou seu descendentetcsh
) para scripts é quase sempre um erro . Se você é novo no shell scripting em geral, recomendo fortemente que você ignore e se concentre emsh
. Se você estiver usando umcsh
parente como shell de login, mude parabash
ouzsh
, para que a linguagem de comando interativa seja a mesma que a linguagem de script que você está aprendendo.fonte
#!
; 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
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
fonte
#! $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.