Como executar um script de shell em um console Unix ou terminal Mac?

507

Eu sei, esqueça e reaprenda novamente. Hora de anotá-la.

PA
fonte
15
escrevendo o trem upvote todo o caminho para a estação de reputação
DivideByZer0
não vou votar apenas para admirar o erro incrível que você chegou lá!
BRHSM

Respostas:

942

Para executar um shscript não executável , use:

sh myscript

Para executar um bashscript não executável , use:

bash myscript

Iniciar um executável (que é qualquer arquivo com permissão executável); você apenas especifica pelo caminho:

/foo/bar
/bin/bar
./bar

Para tornar um script executável, dê a permissão necessária:

chmod +x bar
./bar

Quando um arquivo é executável, o kernel é responsável por descobrir como executá-lo. Para não binários, isso é feito observando a primeira linha do arquivo. Deve conter um hashbang:

#! /usr/bin/env bash

O hashbang informa ao kernel qual programa executar (nesse caso, o comando /usr/bin/envé executado com o argumento bash). Em seguida, o script é passado ao programa (como segundo argumento) junto com todos os argumentos que você forneceu ao script como argumentos subsequentes.

Isso significa que todo script que é executável deve ter um hashbang . Caso contrário, você não está dizendo ao kernel o que é e, portanto, o kernel não sabe qual programa usar para interpretá-lo. Poderia ser bash, perl, python, sh, ou qualquer outra coisa. (Na realidade, o kernel geralmente usa o shell padrão do usuário para interpretar o arquivo, o que é muito perigoso porque pode não ser o intérprete certo ou pode ser capaz de analisar parte dele, mas com diferenças sutis de comportamento, como o caso entre she bash).

Uma nota sobre /usr/bin/env

Geralmente, você verá hash bangs assim:

#!/bin/bash

O resultado é que o kernel executará o programa /bin/bashpara interpretar o script. Infelizmente, bashnem sempre é enviado por padrão e nem sempre está disponível no /bin. Enquanto em máquinas Linux, geralmente existe, há uma variedade de outras máquinas POSIX onde são bashenviadas em vários locais, como /usr/xpg/bin/bashou /usr/local/bin/bash.

Para escrever um script bash portátil, não podemos, portanto, confiar na codificação do local do bashprograma. POSIX já tem um mecanismo para lidar com isso: PATH. A idéia é que você instale seus programas em um dos diretórios existentes PATHe o sistema possa encontrar seu programa quando desejar executá-lo pelo nome.

Infelizmente, você não pode simplesmente fazer isso:

#!bash

O kernel não fará (alguns podem) fazer uma PATHbusca por você. Existe um programa que pode fazer uma PATHpesquisa para você, porém, é chamado env. Felizmente, quase todos os sistemas possuem um envprograma instalado /usr/bin. Então, começamos a envusar um caminho codificado, que faz uma PATHpesquisa bashe o executa para que ele possa interpretar seu script:

#!/usr/bin/env bash

Essa abordagem tem uma desvantagem: de acordo com o POSIX, o hashbang pode ter um argumento . Nesse caso, usamos bashcomo argumento para o envprograma. Isso significa que não temos espaço para transmitir argumentos bash. Portanto, não há como converter algo parecido #!/bin/bash -exucom esse esquema. Você terá que colocar set -exudepois do hashbang.

Essa abordagem também tem outra vantagem: alguns sistemas podem ser fornecidos com a /bin/bash, mas o usuário pode não gostar, pode achar que está com defeito ou desatualizado e pode ter instalado o seu próprio bashem outro lugar. Esse é geralmente o caso no OS X (Macs), em que a Apple envia uma versão desatualizada /bin/bashe os usuários instalam uma atualização /usr/local/bin/bashusando algo como o Homebrew. Ao usar a envabordagem que faz uma PATHpesquisa, você leva em consideração a preferência do usuário e usa o bash preferido dele sobre aquele enviado com o sistema.

lhunath
fonte
66
Obrigado por escrever uma boa resposta para uma pergunta simples.
PA
5
Se eu usar zshcomo meu shell, eu usaria o hashbang #! /usr/bin/env zsh?
2131212 stefmikhail
6
@stefmikhail: Não importa qual interpretador de shell você usa para invocar o script, você deve usar #! /usr/bin/env zshse (e somente se) o código dentro do script deve ser executado pelo shell Z.
precisa saber é o seguinte
1
+1 para explicação. costumo esquecer, mas saber o significado do comando me ajudará a lembrar.
Angelin Nadar
2
@Carpetsmoker Isso está correto e não se limita ao hashbang. Os scripts bash sempre devem usar terminações de linha UNIX, caso contrário, o último argumento de cada comando terá um \ r anexado a ele, assim como o nome do comando hashbang.
precisa saber é o seguinte
80

Para iniciar o shell-script 'file.sh':

sh file.sh

bash file.sh

Outra opção é definir permissão executável usando o comando chmod:

chmod +x file.sh

Agora execute o arquivo .sh da seguinte maneira:

./file.sh
PA
fonte
16

Para a casca de bourne:

sh myscript.sh

Para o bash:

bash myscript.sh

fonte
Obrigado por responder a essa pergunta bastante óbvia. Para um cara do Mac como eu, é fácil esquecer os velhos comandos do Unix entre as voltas.
PA
10

Se você deseja que o script seja executado no shell atual (por exemplo, você deseja que ele possa afetar seu diretório ou ambiente), você deve dizer:

. /path/to/script.sh

ou

source /path/to/script.sh

Observe que /path/to/script.shpode ser relativo, por exemplo, . bin/script.shexecuta o script.shno bindiretório sob o diretório atual.

Chas. Owens
fonte
7
Tenha muito cuidado ao procurar ou pontilhar nomes de caminhos relacionados. Você deve sempre iniciá-los com ./ Se você não fizer isso, e o nome do caminho relativo não contiver nenhuma barra, você estará procurando algo no PATH, ANTES de algo no diretório atual! Muito perigoso por abuso.
Lhunath 09/04/09
0

Primeiro, dê permissão para execução: -
chmod +x script_name

  1. Se o script não for executável: -
    Para executar o arquivo sh script: -
    sh script_name
    Para executar o arquivo bash script: -
    bash script_name
  2. Se o script for executável: -
    ./script_name

NOTA : -Você pode verificar se o arquivo é executável ou não, usando 'ls -a'

Vineet Jain
fonte
0

A extensão do arquivo .command é atribuída ao Terminal.app. Clicar duas vezes em qualquer arquivo .command o executará.

benwiggy
fonte
0

Pouca adição, para executar um intérprete da mesma pasta, ainda usando #! Hashbang nos scripts.

Como exemplo, um executável do php7.2 copiado de / usr / bin está em uma pasta ao longo de um script hello .

#!./php7.2
<?php

echo "Hello!"; 

Para executá-lo:

./hello

Que se comportam da mesma forma que:

./php7.2 hello
NVRM
fonte