Maneira correta de distribuir scripts de shell

8

Qual é a maneira mais adequada de distribuir scripts de shell, se os comportamentos dos shells puderem ser modificados sete, portanto, imprevisíveis?

Por exemplo, rm *.txtnão seria executado conforme o esperado nos ambientes em que set -ffoi executado. Como devo garantir que rm *.txttodos os arquivos de texto sejam removidos em um diretório atual em qualquer ambiente?

Como garantir que os scripts do shell sejam executados conforme o esperado antes de distribuí-los em geral?

hoge
fonte
shell_state=$(set +o) ... script ...eval "$shell_state"
mikeserv
Você pode executar esses comandos na parte superior do próprio script ou modificar #!para especificar quais opções de shell você deseja.
HalosGhost

Respostas:

6

Os scripts de shell normalmente são tratados como se fossem iguais a qualquer outro tipo de arquivo executável, como binários, scripts Python, scripts Perl ou qualquer outro tipo de script. Eles têm um shebang no topo que direciona o kernel para executá-los através do shell. Espera-se que eles sejam invocados da mesma maneira que qualquer outro comando.

Como tal, um novo shell é iniciado toda vez que o script é chamado, e quaisquer configurações como set -fpresentes no shell de chamada ou em qualquer outra instância do shell no sistema são irrelevantes.

Obviamente, é possível para os usuários obterem seu script em vez de executá-lo, por exemplo:

. /path/to/your/script

ou para executá-lo em um shell que tenha configurações não padrão como esta:

sh -f /path/to/your/script

mas essas não são consideradas formas normais ou invocando seu script, e os usuários que fazem isso devem esperar o que receberem como resultado.

Observe que existem alguns scripts que devem ser originados, não executados, porque seu objetivo é alterar coisas do cwd ou definir variáveis ​​de ambiente que devem ser refletidas no ambiente do shell de origem, mas estas são minoria e geralmente é feito como parte de um protocolo acordado. Esses arquivos podem ser considerados mais como "plugins" para qualquer sistema que eles esperem que sejam originados, não tanto quanto scripts independentes. Por exemplo, arquivos /etc/rc*.dcom nomes que terminam em .shsão originados pelo subsistema de script de inicialização, não são executados e está documentado que é isso que acontecerá se você colocar um arquivo com esse nome em/etc/rc*.de quando é feito, é feito de propósito. A convenção de nomear arquivos destinados a serem originados em vez de executados dessa maneira também é seguida em outros lugares, mas não universalmente.

É verdade que os arquivos destinados a serem obtidos dessa maneira precisam cuidar de quais configurações podem estar presentes no ambiente do chamador que podem afetar o comportamento do shell, mas o protocolo acordado deve idealmente prometer um ambiente de execução previsível.

Celada
fonte
1
zshpossui um recurso que permite restaurar as opções para um conjunto de informações em um contexto local ( emulate -L zsh) que é amplamente utilizado em todas as extensões enviadas com zsh e gravadas como código zsh. Veja como o sistema de conclusão do bash falha miseravelmente se você definir algumas opções como failglob.
Stéphane Chazelas
Alguns shells lêem seu arquivo de personalização, mesmo quando chamados para interpretar scripts. É por isso que você geralmente usa em #! /bin/csh -fvez de, #! /bin/cshpor exemplo.
Stéphane Chazelas
@ StéphaneChazelas Haha, sim, de fato. Claro que isso faz parte do porquê usar o csh é uma má ideia , certo? :-) Mas acho que o zsh também tem isso, na forma de zshenv. Cuidado com o que você coloca zshenvpor esse motivo!
Celada
@ StéphaneChazelas, a propósito, não é a primeira vez que você me ensina algo que eu não sabia ( emulate -Lneste caso) comentando uma das minhas respostas, e eu aprecio isso.
Celada
Bem, ~/.zshenv(onde você deseja forçar as configurações (geralmente env vars) para todos os zshs (interativos ou não) chamados sob seu nome e geralmente não usados, exceto para solucionar algum outro problema não-zsh) é separado do ~/.zshrc(o arquivo interativo shell de personalização), portanto, é um recurso, não um bug. (você pode usar zsh -f) Um erro ocorre quando alguns shells bash não interativos lêem o seu ~/.bashrc(como over ssh e você precisa adicionar código para se proteger contra isso), ou alguns bash interativos (os de login) não o lêem. (e, novamente, você deve adicionar código ao seu ~/.bash_profilepara solucionar esse problema).
Stéphane Chazelas