Por que preciso colocar sh antes de executar arquivos .sh?


16

Quando quero executar .sharquivos no Terminal, preciso colocá- shlos na frente deles.

Existe alguma maneira de evitar isso e, assim, salvar a digitação?


3
Eu criei uma pasta em ~ / bin para colocar meus scripts de shell e colocá-la no meu $ PATH e também anexei uma Ação de Pasta à pasta ~ / bin para definir automaticamente as permissões de execução, porque é muito fácil esquecer isso.
Kaydell

Respostas:


22

Se você estiver executando seu script a partir do shell, na verdade não precisará do #!/bin/shshebang descrito nesta resposta - todo sistema semelhante ao Unix que usei, incluindo o OS X, será padronizado /bin/shse nenhum intérprete for especificado especificamente ( embora seja uma boa ideia, pois os não-shells não saberão como executar seu script, a menos que você dê o shebang.)

Você também não precisa de uma .shextensão. Você fazer necessidade de definir as permissões executáveis, por exemplo,

$ chmod +x script.sh

(O $prompt é o shell; estou usando-o para ilustrar os comandos que você fornece ao shell interativo. Não digite!)

No entanto, acho que sua confusão é que você criou um script, por exemplo script.sh, no diretório atual, e está tentando executá-lo simplesmente digitando script.sh. por exemplo

$ cat >script.sh
echo hello, world
^D
$ chmod +x script.sh
$ script.sh
-bash: script.sh: command not found

( ^Dsignifica control- D. Você encontrará essa notação em muitos artigos sobre o uso do Unix.)

O fato de script.sh, neste caso, ser um script de shell é apenas metade do problema; seu problema real é que, por padrão, o shell não pesquisará no diretório atual por um programa. No entanto, isso funciona:

$ sh script.sh
hello, world

porque shestá tomando o script como argumento.

Você pode executar um script - ou, novamente, qualquer executável - no diretório atual, se estiver marcado como executável (ou seja chmod +x), especificando que deseja executar o script no diretório atual:

$ ./script.sh
hello, world

Você também pode mover o script para um diretório no seu PATH. Eu recomendo /usr/local/binisso se o seu script se destina a ser usado em todo o sistema ou um bindiretório em sua casa, se o script for apenas para você. O último requer que você adicione $HOME/bin, o que se expande ao seu novo diretório bin, ao seu PATHadicionando as seguintes linhas ao seu .profileno seu diretório pessoal:

PATH=$HOME/bin:$PATH
export PATH

Por fim, você pode, se quiser, adicionar o diretório atual ao seu PATH, o que permitirá que você acesse um diretório que contenha script.sh–ou qualquer outro executável– e digite

$ script.sh

para executá-lo. No entanto, eu não recomendo esta prática , pois agora um invasor pode induzi-lo a executar um executável arbitrário soltando um script executável (nomeado, por exemplo ls) em um diretório em que você estará. Se você realmente deseja fazê-lo, basta adicionar o seguinte ao seu .profile:

PATH=.:$PATH
export PATH

Coloque o '.' no final de $ PATH, em vez de no começo, e agora você não precisa se preocupar com um fantasma 'ls'. (Embora se alguém pode entrar em seu sistema, você tem problemas maiores.)
TJ Luoma

2
@TJ, mas você não precisa se preocupar com coisas como slou llsou l... ou seja, erros de digitação. Apenas deixe de .fora $PATH. Além disso, você não pode (ou não deve) necessariamente confiar em todos no seu sistema. Por exemplo, suponha que haja alguma exploração que permita que um invasor solte um arquivo arbitrário em algum diretório, mas eles precisam que você execute esse arquivo para escalar para uma exploração melhor (por exemplo, coletar dados e telefonar para casa). Defesa em profundidade!
Reid

@TJLuoma O que o @Reid disse, além de ter em mente que existem muitos casos de uso para um sistema Unix além de um desktop OS X pessoal. Ainda não tentei, mas aposto que até a conta de convidado pode deixar um desses itens em /tmpalgum diretório gravável no mundo.
zigg

Se você estiver usando um sistema em que outras pessoas tenham acesso aos diretórios que você usa, você terá problemas maiores.
TJ Luoma

@TJLuoma É melhor você nunca usar várias contas em qualquer sistema Unix. /tmpet al. vem com o território.
zigg

10

Você não precisa ligar shse o arquivo de script estiver marcado como executável. Nesse caso, você pode chamá-lo de meu nome, como faria com qualquer outro comando do shell existente.


Para ser totalmente adequado, você deve fazer duas coisas:

  1. Edite seu script para incluir uma diretiva shebang na parte superior do seu script:

    #!/bin/sh

    ... Isso diria ao shell qual intérprete usar para executar o script; neste caso, o /bin/shexecutável.

  2. Marque o script como executável por você com o comando chmod :

    chmod u+x scriptname.sh

Depois de fazer os dois, você poderá executar seu script digitando o nome do arquivo do script na linha de comando. Você precisará estar no mesmo diretório do seu script, a menos que você também execute a etapa adicional de adicionar a pasta que contém sua variável PATH . Se você não se importa com o shell que executa o script, não precisa da etapa um para especificar, shmas geralmente é melhor ser preciso e definir o "shebangsh".


Shebangs não são realmente necessários /bin/sh, embora não machuquem.
zigg

@ zigg - Você está correto. Espero que Chris não se importe com minhas edições… Nuke ou
reedite

@bmike As edições funcionam para mim. Quanto aos shebangs, meu hábito era sempre especificar, porque eu costumava escrever muitos kshscripts nos meus dias no HP-UX - mas é bom saber que não é estritamente necessário.
Chris W. Rea

11
Acho que preciso me afastar da minha declaração anterior sobre a necessidade de shebang (embora o restante da minha resposta ainda permaneça.) Você pode executar um script sem shebang a partir de um shell, mas se você usar um execsyscall, obtém ENOEXEC(erro de formato exec ) Desculpe por isso, @bmike, @ ChrisW.Rea. Vou editar minha resposta agora.
zigg
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.