Por que o padrão “comando || verdadeiro ”útil?

79

Atualmente, estou explorando pacotes Debian e tenho lido alguns exemplos de código. E em todas as linhas, por exemplo, o postinstscript é um padrão.

some command || true
another command || true

Portanto, se algum comando falhar, a linha retornará verdadeira, mas não vejo como isso afeta a saída do programa.

carpinteiro
fonte
5
Para sua informação, ||:é outra maneira idiomática de escrever isso ( :sendo outra entrada na tabela embutida apontando para true- mas garantida que é uma embutida mesmo de volta a Bourne; isto dito, para o POSIX sh, truetambém é garantido que ela é embutida - por isso é mais concisão do que eficiência em tempos até remotamente modernos).
Charles Duffy

Respostas:

151

A razão para esse padrão é que os scripts de mantenedor nos pacotes Debian tendem a começar set -e, o que faz com que o shell saia assim que qualquer comando (estritamente falando, pipeline, lista ou comando composto) sai com um status diferente de zero. Isso garante que os erros não se acumulem: assim que algo der errado, o script é interrompido.

Nos casos em que um comando no script pode falhar, a adição || truegarante que o comando composto resultante sempre saia com status zero, para que o script não seja interrompido. Por exemplo, remover um diretório não deve ser um erro fatal (impedir que um pacote seja removido); então nós usamos

rmdir ... || true

pois rmdirnão tem uma opção para dizer para ignorar erros.

Stephen Kitt
fonte
4
Bem, sem set -ea necessidade || true, achei importante fornecer o contexto. Se você notar coisas estranhas no POWER, recomendo fortemente que você arquive bugs ( reportbug)!
Stephen Kitt
16
@ MichaelFelt, na verdade set -enão é apenas "convenção Debian", mas um bom padrão de programação que sempre devemos usar. Vejo. por exemplo, davidpashley.com/articles/writing-robust-shell-scripts
kay
2
de acordo com a pergunta aqui - por que usar || trueset -e é o contexto provável e provavelmente o mais comum. Eu me curvo a esta resposta! Literalmente, porém, é útil sempre que o status de saída for considerado irrelevante E (como o link do artigo adiciona) Não estou usando o status de saída como parte do meu controle de script. Eu vejo utilidade (in set -e), mas não chegaria tão longe quanto o artigo diz e "Todo script que você escreve deve incluir set -e no topo". É um estilo de programação. "SEMPRE | Todo" inclui seu próprio conjunto de armadilhas - aka - absolutos re: as soluções de curingas vão ALWAYSsair pela culatra, eventualmente, aka - sem carona.
Michael feltro
1
@Kay Essa é uma perspectiva atualmente popular, mas, em última análise, está envolvida com inúmeras suposições que limitam a portabilidade do script. Existem inconsistências históricas com o set -ecomportamento. Pode não ser importante para você, se seus únicos alvos são bashe os outros shells relativamente recentes que vivem /bin/sh, mas a situação é mais sutil quando você deseja dar suporte a shells / sistemas antigos.
Mtraceur
2
@StephenKitt Claro que sim. Há uma páginaset -e muito minuciosa documentando os comportamentos de conchas diferentes de Sven Mascheck , embora essa página também documente muitas conchas históricas / antigas irrelevantes hoje em dia. Há também estas duas páginas com um foco mais estreito moderna (procura por "set -e"): página "lintsh" , documentação shell portátil da autoconf -> Limitação de builtins subpage
mtraceur
32

Embora não afete a saída do programa que acabou de ser executado, ele permite que o chamador continue como se estivesse tudo bem, ou seja, afeta a lógica futura.

Reformulado: mascara o status de erro do comando anterior.

michael@x071:[/usr/sbin]cat /tmp/false.sh
#!/bin/sh
false

michael@x071:[/usr/sbin]cat /tmp/true.sh 
#!/bin/sh
false || true

michael@x071:[/usr/sbin]sh /tmp/false.sh; echo $?
1
michael@x071:[/usr/sbin]sh /tmp/true.sh; echo $? 
0
Michael Felt
fonte
6
Isso é verdade, mas não responde por que mascarar o status de saída de um comando é útil.
moopet
4
set -e significa que o script será encerrado instantaneamente com um retorno diferente de zero. Você pode, naquele local localizado, não querer que isso aconteça!
rackandboneman
Eu sou uma pessoa simples - e para mim o único motivo para mascarar o status do erro é porque ele está "no caminho". set -e comete algum erro "no caminho" se antes você não se importava. Gosto da discussão porque a vejo como uma boa maneira de me ajudar a depurar meus scripts e escrever uma lógica adicional para responder a um erro (por exemplo, || print - "xxx existia diferente de zero aqui". função shell 'fatal' e eu tenho "algo || fatal" me infeliz ". imho um script deve relatar um status com falha ou não se importa. -e plus || true é mascarar erros. Se é isso que eu quero - tudo bem, se não, eu estou faltando erros
Michael feltro
o que eu tenho que me perguntar é: é || true - uma muleta de codificação (maneira preguiçosa de contornar / ultrapassar um erro com o qual não quero lidar agora; uma ferramenta de depuração (-e mas não || true) ou apenas o dogma de alguém sobre o que é uma boa prática de codificação. - Eu vejo isso como uma característica - com potencial benefício. Eu não a vejo como uma varinha mágica para curar tudo. Em suma - assim como a beleza está nos olhos de quem vê - set -ee a || trueutilidade será definida pelos traços e objetivos de o programador.
Michael feltro
6
@ MichaelFelt Considere: git remote remove foo || true git remote add foo http://blah- queremos ignorar o erro se o controle remoto não existir.
user253751