Qual é a diferença entre ./ e sh para executar um script?

71

Eu escrevi um script simples. Quando executo sh <myscriptname.sh>, obtive a saída correta, mas quando executo ./<myscriptname.sh>, recebi um erro.

Qual a diferença entre quando eu faço she ./?

mr_eclair
fonte
15
Em vez de apenas dizer "Recebo um erro", ajudaria se você colasse o que o erro dizia.
SpashHit

Respostas:

67

Ao executar qualquer script, passando o nome do arquivo para o programa interpretador de scripts, você está executando o programa interpretador com o script como um argumento passado para ele. Por exemplo, isso seria parecido com o processo 'sh' com o argumento 'filename.sh'. O shintérprete está abrindo o arquivo.

Por outro lado, se você executar o próprio script, o sistema chamará o programa interpretador especificado e alimentará o conteúdo do script. Nesse caso, o processo se parece com 'filename.sh' sem argumentos.

Você deve ter uma linha de estrondo:

#!/bin/bash
# bash script here

Uma linha de estrondo é a primeira linha do script e começa com os mesmos dois caracteres #!; é isso que o sistema lê quando tenta executar o script e, em seguida, o sistema passa o script para o programa imediatamente depois. Observe que essa linha não tem nada a ver com o bash e funciona tão bem com python quanto perl, mesmo que sejam linguagens muito diferentes. Você usaria, #!/usr/bin/pythonpor exemplo, e o seguiria com código python.

Depois de ter seu script, verifique se você definiu permissões de execução:

chmod a+x filename.sh

Então você pode executar o script como seu próprio processo:

./filename.sh

Ou coloque o arquivo em um local conhecido com um bom nome de programa, curta /usr/sbine execute de qualquer lugar:

sudo cp filename.sh /usr/sbin/program-name
program-name

E esse é realmente o benefício prático de usar a linha de bate-papo com as permissões corretas - é tudo sobre implantação . É muito difícil fazer com que os usuários executem um script se precisarem se lembrar de qual programa executar o script. Lembre-se de fornecer um caminho completo para o script sempre que ele quiser executá-lo. Onde, /usr/local/binpor exemplo, colocá-lo em executável e torná-lo executável, pode economizar muito sofrimento para as pessoas que tentam usar seu script. Esses programas ficam disponíveis para todos os usuários no seu computador.

Também é bom para identificação. Se você entrar no topprograma, um script executado sem a linha de interrupção terá apenas o nome do intérprete bash, perlou seja , ou python. Mas se um script for executado com as permissões corretas, o nome do script será exibido.

Nota: Se você deseja distribuir um script acessível a todos, crie uma página de manual e um pacote deb para instalá-lo. Precisamos reduzir o número de scripts aleatórios online e aumentar o número de debs que podem ser desinstalados.

Martin Owens -doctormo-
fonte
11
Você também pode usar uma pasta bin pessoal: crie uma pasta bin na sua pasta pessoal, efetue logout e logon novamente e, em seguida, você poderá executar qualquer script nessa pasta sem sh ou ./.
papukaija
Obviamente, mas adicionar sua pasta pessoal ao PATH pode parecer um pouco de dor de cabeça. Melhor instalar as coisas. Embora tenha havido alguma conversa sobre adicionar ~ / .local / bin ao caminho por padrão, para permitir a instalação de pacotes por usuários locais.
precisa saber é o seguinte
Observe que o intérprete padrão bashnão é sh.
Nathan Osman
11
Não coloque extensões em scripts, especialmente quando você o inserir PATH.
geirha
11
/usr/local/binprovavelmente é melhor então /usr/sbin- indica que o programa é local para esta máquina, em vez de fazer parte da distribuição.
Glenn Jackman
41

A versão curta:

  • shé o intérprete da linha de comandos (traço).
    A execução sh my_scriptfaz o traço interpretar o script.

  • ./tenta descobrir qual intérprete usar, observando a primeira linha. Por exemplo #!/bin/bash, ou mesmo #!/bin/ruby(em oposição à execução ruby my_script).

Stefano Palazzo
fonte
7
Não é realmente o ./que encontra alguma coisa, é o método de execução do sistema que analisa os dois primeiros bytes do arquivo.
precisa saber é o seguinte
9
Absolutamente. Aqui está uma explicação muito longa de tudo. Estou sendo pragmático :)
Stefano Palazzo
Quando você usa she o arquivo contém um sha-bang, isso significa que o sha-bang será ignorado ou abrirá o shell onde os shlinks também estão e, em seguida, talvez algum outro shell ou o que ele faz :)?
Ini
5

A diferença que você faz é

  • com sh, você está executando um programa que interpretará as linhas do seu script da mesma forma que as digitaria no prompt interativo do terminal,

  • com ./você criando um atalho, assumindo que o script esteja exatamente aqui no diretório atual em que está sentado E será executável (porque, por exemplo, você o emitiu chmod +x myscript.sh), economizando um tempo inestimável para tempos futuros :-)

meduz
fonte
3
+1 por ser o único a declarar concisamente que o arquivo deve ser executável.
Mikel
2
Observe que sho arquivo não deve ser necessariamente executável.
Ini
3

Há três razões principais para você estar recebendo um erro:

  • o arquivo não é executável
    prazo chmod +x <myscriptname.sh>para corrigir isso
  • a partição não permite a execução de scripts (está montada " noexec")
    copia o script para/usr/local/bin
  • a #!linha tem um erro,
    verifique se a primeira linha é #!/bin/shou#!/bin/bash

Se sua primeira linha parecer correta, mas ainda não estiver funcionando, verifique se o arquivo não possui terminações de linha do DOS.

O erro seria algo como isto:

$ ./myscript.sh
bash: ./myscript.sh: /bin/bash^M: bad interpreter: No such file or directory

Você pode corrigi-lo executando dos2unix <myscriptname.sh>ou, se não tiver
perl -p -i -e 's/\r\n$/\n/' <myscriptname.sh>,.

Mikel
fonte
0

E a resposta é que sh é o nome do shell muito popular. Mas desatualizado e substituído por outros. Atualmente, o sh está vinculado a outros shells instalados na máquina. por exemplo, eu bash putted lá. A execução de qualquer shell a partir do sh geralmente aciona algum modo de 'compatibilidade' com o comportamento original do 'shell'.

Portanto, a solução é bastante simples. Veja o que está por trás do comando sh (ls -al / bin / sh) e coloque #! / Bin / Whatever_you_find_there como primeira linha (ou se houver algo assim no seu script, edite-o).

E, como alternativa, pode haver algum bug no próprio script. Como dependência que é atendida por sh, mas não intérprete que é realmente usado.

przemo_li
fonte
0
mkdir ~/bin ; cp myscript.sh ~/bin/

echo "export PATH="$PATH:/home/$USER/bin" >> ~/.profile ; source ~/.profile ; 

Não /usr/sbin, isso é para ferramentas administrativas não essenciais, /usr/local/biné uma escolha melhor se você não quiser ~/bin/, mas sudoé aconselhável evitar o máximo possível.

Joey1978
fonte
No Ubuntu, o padrão ~/.profilejá possui código para adicionar ~/bin, se existir, a PATH. Em outra nota, não coloque extensões nos scripts.
precisa saber é o seguinte
11
Eu estava referenciando o <myscriptname.sh>, mas qual é a justificativa para não colocar extensões nos scripts? Eu costumo fazer isso porque ter os arquivos de texto sem formatação visíveis assim me impede de tentar editar binários que eu também mantenho em ~ / bin /. ( ls ~/bin/|wc -l = 428) Eu coloquei um monte de coisas lá dentro;)
Joey1978
Imagine que você escreva um script para realizar uma tarefa específica. Então você percebe que escrever esse script específico em python o tornará muito mais eficiente; portanto, você o reescreve em python. Agora você tem duas opções. 1) Deixe a extensão .sh agora muito enganadora ou 2) renomeie o script e pesquise e substitua todos os usos do script para usar o novo nome. Se você olhar os scripts /bine /usr/binperceber que eles não usam extensões.
geirha