Eu tenho um projeto composto por cerca de 20 .sh
arquivos pequenos . Eu os chamo de "pequenos" porque, geralmente, nenhum arquivo tem mais de 20 linhas de código. Adotei uma abordagem modular porque, portanto, sou fiel à filosofia Unix e é mais fácil para mim manter o projeto.
No início de cada .sh
arquivo, eu coloquei #!/bin/bash
.
Simplificando, entendo que as declarações de script têm dois propósitos:
- Eles ajudam o usuário a lembrar qual shell é necessário para executar o arquivo (digamos, depois de alguns anos sem usá-lo).
- Eles garantem que o script seja executado apenas com um determinado shell (nesse caso, Bash) para evitar comportamentos inesperados no caso de outro shell ser usado.
Quando um projeto começa a crescer, digamos 5 arquivos para 20 arquivos ou de 20 para 50 arquivos (não neste caso, mas apenas para demonstrar), temos 20 linhas ou 50 linhas de declarações de script. Admito que, embora possa ser engraçado para alguns, parece um pouco redundante usar 20 ou 50 em vez de dizer apenas 1 por projeto (talvez no arquivo principal do projeto).
Existe uma maneira de evitar essa suposta redundância de 20 ou 50 ou um número muito maior de linhas de declarações de script usando alguma declaração de script "global", em algum arquivo principal?
fonte
/bin/bash -x "$script"
Respostas:
Embora seu projeto agora possa consistir apenas de 50 scripts Bash, mais cedo ou mais tarde ele começará a acumular scripts escritos em outros idiomas, como Perl ou Python (pelos benefícios que essas linguagens de script têm que o Bash não possui).
Sem uma
#!
linha adequada em cada script, seria extremamente difícil usar os vários scripts sem também saber qual intérprete usar. Não importa se todos os scripts são executados a partir de outros scripts , isso apenas move a dificuldade dos usuários finais para os desenvolvedores. Nenhum desses dois grupos de pessoas precisa saber em que idioma o script foi escrito para poder usá-lo.Os scripts de shell executados sem uma
#!
linha e sem um intérprete explícito são executados de maneiras diferentes, dependendo de qual shell os chama (consulte, por exemplo, a pergunta Qual interpretador de shell executa um script sem shebang? E especialmente a resposta de Stéphane ), que não é o que você deseja em um ambiente de produção (você deseja um comportamento consistente e possivelmente até portabilidade).Os scripts executados com um intérprete explícito serão executados por esse intérprete, independentemente do que
#!
diz a linha. Isso causará problemas mais adiante, se você decidir reimplementar, digamos, um script Bash em Python ou em qualquer outro idioma.Você deve gastar essas teclas extras e sempre adicionar uma
#!
linha a cada script.Em alguns ambientes, há textos legais padronizados com vários parágrafos em cada script em cada projeto. Fique muito feliz porque é apenas uma
#!
linha que parece "redundante" em seu projeto.fonte
#!
linha assim que o arquivo tiver permissão executável e não for carregado por um intérprete, mas pelo shell. Ou seja,/path/to/myprog.pl
executa um programa perl se a#!
linha estiver presente (apontando para o interpretador perl) e o arquivo tiver permissão de execução.Você entende mal o ponto
#!
. Na verdade, é uma diretiva para o sistema operacional executar este programa com o intérprete definido.Portanto, pode haver um script
#!/usr/bin/perl
e o programa resultante pode ser executado como./myprogram
o interpretador perl. Semelhante#!/usr/bin/python
faria com que um programa fosse executado em python.Portanto, a linha
#!/bin/bash
diz ao sistema operacional para executar este programa no bash.Aqui está um exemplo:
Portanto, apesar de meu shell ser ksh, o programa "x" é executado no bash por causa da
#!
linha, e podemos ver isso explicitamente na lista de processos.fonte
ps -aux
pode dar aviso,ps
dá o avisoWarning: bad syntax, perhaps a bogus '-'?
.ps
suporta a sintaxe de argumento BSD e UXIX .-aux
está errado UNIX Stephen provavelmente quer dizeraux
qual é o BSD corretops
mostra o chamadobash
) e não na sintaxe explícita; (2)ps -aux
funciona perfeitamente no CentOS 7 e Debian 9 sem avisos; esse cut'n'paste era exatamente o resultado da minha máquina; toda a discussão sobre se-
é necessário ou não é aplicável a versões mais antigas dos procs do linux, e não às versões atuais.Em
.sh
O que é ruim é o
.sh
final do nome do arquivo.Imagine que você reescreve um dos scripts em python.
Bem, agora você precisa alterar a primeira linha para
#!/usr/bin/python3
isso não é tão ruim, pois você também precisa alterar todas as outras linhas de código no arquivo. No entanto, você também deve alterar o nome do arquivo deprog.sh
paraprog.py
. E então você precisa encontrar em todos os outros scripts e todos os scripts de usuário (os que você nem sabia que existiam) e alterá-los para usar o novo script.sed -e 's/.sh/.py/g'
pode ajudar aqueles que você conhece. Mas agora sua ferramenta de controle de revisão está mostrando uma alteração em muitos arquivos não relacionados.Alternativamente fazer isso da maneira Unix eo nome do programa
prog
nãoprog.sh
.Em
#!
Se você tiver o correto
#!
, e defina a permissão / modo para incluir execute. Então você não precisa conhecer o intérprete. O computador fará isso por você.Para sistemas não-gnu, leia o manual
chmod
(e aprenda octal), talvez o leia de qualquer maneira.fonte
.image
para fotos..audio
para som etc. Assim, dizendo o que é, mas não sobre a implementação / codificação.launch-missiles
oudelete-project-and-make-manager-pissed
eu não quero fazer "basta executá-lo" quando eu tinha apenas curioso sobre a linguagem :)file
comando reconhece a maioria dos tipos de arquivo.Provavelmente vale ressaltar que isso está completamente errado. A linha hashbang de forma alguma impede que você tente alimentar o arquivo com um shell / intérprete incorreto:
(ou similarmente com
awk -f array.sh
etc.)Mas, em qualquer caso, outra abordagem da modularidade seria definir funções de shell nos arquivos, uma função por arquivo, se você preferir, e depois
source
os arquivos do programa principal. Dessa forma, você não precisaria de hashbangs: eles seriam tratados como quaisquer outros comentários e tudo seria executado usando o mesmo shell. A desvantagem seria que você precisariasource
dos arquivos com as funções (por exemplofor x in functions/*.src ; do source "$x" ; done
), e todos eles rodariam usando o mesmo shell, para que você não pudesse substituir diretamente um deles por uma implementação em Perl.fonte
Existe - é chamado portabilidade ou conformidade com POSIX. Procure sempre escrever scripts de maneira portátil e neutra em shell, origine-os somente de um script que use
#!/bin/sh
ou quando você use/bin/sh
interativamente (ou pelo menos um shell compatível com POSIX, comoksh
).No entanto, scripts portáteis não o salvam de:
/bin/sh
scriptcsh
.Se eu posso expressar minha opinião, "evitar redundância" eliminando
#!
é uma meta errada. O objetivo deve ser um desempenho consistente e, na verdade, um script de trabalho que funcione, e considere casos extremos, segue certas regras gerais, como não analisar ls ou sempre citar variáveis, a menos que seja necessário dividir palavras .Eles não são realmente para o usuário - são para o sistema operacional executar o interpretador adequado. "Adequado", neste caso, significa que o SO encontra o que está em shebang; se o código abaixo for incorreto - isso é culpa do autor. Quanto à memória do usuário, acho que o "usuário" de programas como o Microsoft Word ou o Google Chrome nunca precisou saber em que programas de idiomas estão escritos; autores podem precisar.
Por outro lado, scripts escritos de maneira portável podem eliminar a necessidade de lembrar qual shell você usou originalmente, porque os scripts portáteis devem funcionar em qualquer shell compatível com POSIX.
Eles não. O que realmente impede um comportamento inesperado é escrever scripts portáteis.
fonte
A razão pela qual você precisa colocar
#!/bin/bash
no topo de cada script é que você está executando-o como um processo separado.Quando você executa um script como um novo processo, o sistema operacional vê que é um arquivo de texto (em oposição a um executável binário) e precisa saber qual interpretador executar. Se você não contar, o sistema operacional só pode adivinhar, usando sua configuração padrão (que um administrador pode alterar). Portanto, a
#!
linha (além de adicionar permissões de executáveis, é claro) transforma um simples arquivo de texto em um executável que pode ser executado diretamente, com a confiança de que o sistema operacional sabe o que fazer com ele.Se você deseja remover a
#!
linha, suas opções são:Execute o script diretamente (como você está fazendo agora) e espere que o intérprete padrão corresponda ao script - você provavelmente está seguro na maioria dos sistemas Linux, mas não é portátil em outros sistemas (por exemplo, Solaris) e pode ser alterado para qualquer coisa (eu poderia até configurá-lo para executar
vim
no arquivo!).Execute o script usando
bash myscript.sh
. Isso funciona bem, mas você precisa especificar o caminho para o script, e é confuso.Origem do script usando
. myscript.sh
, que executa o script no processo atual do intérprete (ou seja, não como um subprocesso). Mas isso quase certamente exigirá modificações nos seus scripts e os tornará menos modulares / reutilizáveis.Nos casos 2 e 3, o arquivo não precisa (e não deveria ter) executar permissões, e fornecer um
.sh
(ou.bash
) sufixo é uma boa idéia.Mas nenhuma dessas opções parece boa para o seu projeto, como você disse que deseja manter seus scripts modulares (=> independentes e independentes), portanto, você deve manter sua
#!/bin/bash
linha no topo dos scripts.Na sua pergunta, você também disse que está seguindo a filosofia do Unix. Se isso for verdade, você deve aprender para que
#!
serve realmente a linha e continuar usando-a em todos os scripts executáveis!fonte
then you should learn what the #! line is really for, and keep using it in every executable script!
. Pode-se seguir a filosofia da universidade até certo ponto do conhecimento. Depois de todas essas respostas, entendi por que ela pode ser incluída nesse termo. Sugiro editar a resposta, substituindo-a por "Veja o shebang como uma parte interna da filosofia do Unix que você respeita e adota".