Estou estudando o conteúdo deste arquivo preinst que o script executa antes que o pacote seja descompactado do seu arquivo Debian (.deb).
O script tem o seguinte código:
#!/bin/bash
set -e
# Automatically added by dh_installinit
if [ "$1" = install ]; then
if [ -d /usr/share/MyApplicationName ]; then
echo "MyApplicationName is just installed"
return 1
fi
rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf
rm -Rf $HOME/.local/share/file-manager/actions/*
fi
# End automatically added section
Minha primeira consulta é sobre a linha:
set -e
Eu acho que o restante do script é bastante simples: verifica se o gerenciador de pacotes Debian / Ubuntu está executando uma operação de instalação. Se for, verifica se meu aplicativo acabou de ser instalado no sistema. Se houver, o script imprimirá a mensagem "MyApplicationName acabou de instalar" e termina ( return 1
significa que termina com um "erro", não é?).
Se o usuário solicitar ao sistema de pacotes Debian / Ubuntu que instale meu pacote, o script também excluirá dois diretórios.
Isso está certo ou estou faltando alguma coisa?
man set
set +e
Respostas:
De
help set
:Mas isso é considerado uma prática ruim para alguns (autores de perguntas frequentes sobre o bash FAQ e irc freenode #bash FAQ). É recomendável usar:
para executar a
do_something
função quando ocorrerem erros.Veja http://mywiki.wooledge.org/BashFAQ/105
fonte
trap 'exit' ERR
ERR
armadilha não é herdada pelas funções do shell, portanto, se você tiver funções,set -o errtrace
ouset -E
permitirá que você defina a armadilha apenas uma vez e a aplique globalmente.trap 'exit' ERR
fazer qualquer coisa diferenteset -e
?set -e
interrompe a execução de um script se um comando ou pipeline tiver um erro - que é o oposto do comportamento padrão do shell, que é ignorar erros nos scripts. Digitehelp set
um terminal para ver a documentação deste comando interno.fonte
set -o pipefail
que pode ser usada para propagar erros para que o valor de retorno do comando pipeline seja diferente de zero se um dos comandos anteriores sair com um status diferente de zero.-o pipefail
significa apenas que o status de saída do primeiro-o errexit
comando diferente de zero (ou seja, com erro em termos) do pipeline é propagado até o fim. Os comandos restantes no pipeline ainda são executados , mesmo comset -o errexit
. Por exemplo:echo success | cat - <(echo piping); echo continues
, ondeecho success
representa um, mas de comando bem-sucedido falível, imprimirásuccess
,piping
econtinues
, masfalse | cat - <(echo piping); echo continues
, comfalse
representando o comando agora erroring silenciosamente, ainda será impressopiping
antes de sair.Conforme bash - o manual Set Builtin , se
-e
/errexit
for definido, o shell será encerrado imediatamente se um pipeline que consiste em um único comando simples , uma lista ou um comando composto retornar um status diferente de zero.Por padrão, o status de saída de um pipeline é o status de saída do último comando no pipeline, a menos que a
pipefail
opção esteja ativada (está desativada por padrão).Nesse caso, o status de retorno do pipeline do último comando (mais à direita) para sair com um status diferente de zero ou zero se todos os comandos forem encerrados com êxito.
Se você deseja executar algo na saída, tente definir
trap
, por exemplo:onde
onexit
está sua função de fazer algo na saída, como abaixo, que está imprimindo o rastreamento de pilha simples :Existe uma opção semelhante
-E
/errtrace
que trava no ERR, por exemplo:Exemplos
Exemplo de status zero:
Exemplo de status diferente de zero:
Negando exemplos de status:
Teste com
pipefail
a desativação:Teste com
pipefail
a ativação:fonte
Encontrei esta postagem enquanto tentava descobrir qual era o status de saída para um script que foi interrompido devido a um
set -e
. A resposta não me pareceu óbvia; daí esta resposta. Basicamente,set -e
interrompe a execução de um comando (por exemplo, um script de shell) e retorna o código de status de saída do comando que falhou (ou seja, o script interno, não o script externo) .Por exemplo, suponha que eu tenha o script de shell
outer-test.sh
:O código para
inner-test.sh
é:Quando corro
outer-script.sh
da linha de comando, meu script externo termina com o código de saída do script interno:fonte
Acredito que a intenção é que o script em questão falhe rapidamente.
Para testar você mesmo, basta digitar
set -e
em um prompt do bash. Agora, tente correrls
. Você receberá uma listagem de diretório. Agora digitelsd
. Esse comando não é reconhecido e retornará um código de erro; portanto, seu prompt do bash será fechado (devido aset -e
).Agora, para entender isso no contexto de um 'script', use este script simples:
Se você executá-lo como está, obterá a lista de diretórios
ls
na última linha. Se você descomentarset -e
e executar novamente, não verá a lista de diretórios, pois o bash interrompe o processamento quando encontrar o errolsd
.fonte
Esta é uma pergunta antiga, mas nenhuma das respostas aqui discute o uso de
set -e
akaset -o errexit
nos scripts de manipulação de pacotes Debian. O uso desta opção é obrigatório nesses scripts, de acordo com a política Debian; aparentemente, a intenção é evitar qualquer possibilidade de uma condição de erro não tratado.O que isso significa na prática é que você precisa entender sob quais condições os comandos executados podem retornar um erro e tratar explicitamente cada um desses erros.
Os truques comuns são, por exemplo,
diff
(retorna um erro quando há uma diferença) egrep
(retorna um erro quando não há correspondência). Você pode evitar os erros com manipulação explícita:(Observe também como tomamos o cuidado de incluir o nome do script atual na mensagem e gravar mensagens de diagnóstico em erro padrão em vez de saída padrão.)
Se nenhum tratamento explícito for realmente necessário ou útil, não faça nada explicitamente:
(O uso do
:
comando no-op do shell é um pouco obscuro, mas geralmente visto.)Apenas para reiterar,
é uma abreviação de
ou seja, dizemos explicitamente que
other
deve ser executado se e somente sesomething
falhar. A mão longaif
(e outras instruções de controle de fluxo do shell comowhile
,until
) também é uma maneira válida de lidar com um erro (de fato, se não fosse, os scripts do shellset -e
nunca poderiam conter instruções de controle de fluxo!)E também, apenas para ser explícito, na ausência de um manipulador como esse,
set -e
faria com que o script inteiro falhasse imediatamente com um erro sediff
encontrasse uma diferença ou segrep
não encontrasse uma correspondência.Por outro lado, alguns comandos não produzem um status de saída de erro quando você deseja. Os comandos geralmente problemáticos são
find
(o status de saída não reflete se os arquivos foram realmente encontrados) esed
(o status de saída não revela se o script recebeu alguma entrada ou se executou algum comando com êxito). Uma proteção simples em alguns cenários é canalizar para um comando que grita se não houver saída:Deve-se observar que o status de saída de um pipeline é o status de saída do último comando nesse pipeline. Portanto, os comandos acima mascaram completamente o status de
find
esed
, e apenas informam segrep
finalmente foi bem-sucedido.(É claro que o Bash tem
set -o pipefail
; mas os scripts de pacotes do Debian não podem usar os recursos do Bash. A política dita firmemente o uso do POSIXsh
para esses scripts, embora esse nem sempre tenha sido o caso.)Em muitas situações, isso é algo a ser observado separadamente ao codificar na defensiva. Às vezes, você precisa, por exemplo, passar por um arquivo temporário para ver se o comando que produziu essa saída foi concluído com êxito, mesmo quando o idioma e a conveniência o direcionariam a usar um pipeline de shell.
fonte
fonte