Pourquoi le motif “commande || vrai ”utile?

79

J'explore actuellement les paquets Debian et je lis des exemples de code. Et sur chaque ligne, par exemple, le postinstscript est un motif.

some command || true
another command || true

Donc, si une commande échoue, la ligne retourne la valeur true, mais je ne vois pas en quoi cela affecterait la sortie du programme.

Charpentier
la source
5
FYI, ||:est une autre manière idiomatique d’écrire ceci (c’est :une autre entrée dans le tableau intégré qui pointe vers true- mais qui est garanti comme étant intégré même à Bourne; cela dit, pour POSIX sh, truec’est également garanti comme étant intégré - c’est donc plus concise que l'efficacité à l'époque moderne, même distante).
Charles Duffy

Réponses:

151

La raison de ce modèle est que les scripts de maintenance des paquets Debian ont tendance à commencer set -e, ce qui entraîne la fermeture du shell dès que toute commande (à proprement parler, pipeline, liste ou commande composée) se termine avec un statut différent de zéro. Cela garantit que les erreurs ne s'accumulent pas: dès que quelque chose ne va pas, le script est annulé.

Dans les cas où une commande du script est autorisée à échouer, l'ajout || truegarantit que la commande composée résultante se ferme toujours avec le statut zéro, afin que le script ne soit pas abandonné. Par exemple, la suppression d'un répertoire ne doit pas être une erreur fatale (empêchant la suppression d'un package); donc nous utiliserions

rmdir ... || true

depuis rmdirn'a pas la possibilité de lui dire d'ignorer les erreurs.

Stephen Kitt
la source
4
Eh bien, sans que set -ecela soit inutile || true, j’ai jugé important de fournir le contexte. Si vous remarquez des choses étranges sur POWER, je vous encourage fortement à déposer des bogues ( reportbug)!
Stephen Kitt
16
@MichaelFelt, ce set -en'est pas seulement une "convention Debian", c'est un bon modèle de programmation qu'il faut toujours utiliser. Voir. par exemple davidpashley.com/articles/writing-robust-shell-scripts~~V~~singular~~3rd
kay
2
par la question ici - pourquoi utiliser || trueset -e est le contexte probable et probablement le plus commun. Je m'incline devant cette réponse! Cependant, il est utile à tout moment que le statut de sortie soit considéré comme non pertinent ET (comme l'ajoute votre lien d'article), je n'utilise pas le statut de sortie dans le cadre de mon contrôle de script. Je vois utilité (dans set -e) mais n'irais pas aussi loin que l'article et dit "Chaque script que vous écrivez doit inclure set -e en haut". C'est un style de programmation. "TOUJOURS | Chaque" inclut son propre ensemble de pièges - alias - absolues re: les solutions de cartes ALWAYSgéniales vont se retourner contre, c’est-à-dire alias - aucune manœuvre gratuite.
Michael senti
1
@Kay C’est une perspective populaire à l’heure actuelle, mais de nombreuses hypothèses limitent la portabilité du script. Il y a des incohérences historiques dans le set -ecomportement. Cela ne vous concerne peut-être pas si vos seules cibles sont bashet celles des autres obus relativement récents /bin/sh, mais la situation est plus nuancée lorsque vous souhaitez prendre en charge les anciens obus / systèmes.
mtraceur
2
@StephenKitt Bien sûr. Il y a une très complète la page de la documentation shells set -ecomportements par Sven Mascheck , bien que cette page documente aussi beaucoup de coquilles historiques / anciens aujourd'hui hors de propos. Il y a aussi ces deux pages avec un accent moderne plus étroit (recherche de "set-e"): page "lintsh" , la documentation de shell portable d'AutoConf -> Limitation de Builtins sous
mtraceur
32

Bien que cela n’affecte pas la sortie du programme que vous venez d’exécuter, cela permet à l’appelant de procéder comme si tout allait bien, c’est-à-dire qui affecte la logique future.

Reformulé: il masque l' état d' erreur de la commande précédente.

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
la source
6
C'est vrai, mais cela ne dit pas pourquoi masquer le statut de sortie d'une commande est utile.
Moopet
4
set -e signifie que le script se terminera instantanément sur un retour non nul. Vous pourriez, dans cet endroit localisé, ne pas vouloir que cela se produise!
rackandboneman
Je suis une personne simple - et pour moi la seule raison pour masquer le statut d'erreur est qu'elle est "gênante". set -e commet une erreur "de la manière" si auparavant vous ne vous en souciiez pas. J'aime la discussion parce que je la vois comme un moyen agréable de m'aider à déboguer mes scripts et à écrire une logique supplémentaire pour répondre à une erreur (par exemple, || print - "xxx existait non-zéro ici". Plus probable si j'ai un fonction shell 'fatal' et j'ai "quelque chose || fatal" me malheureux ". un script doit signaler un échec, ou ne pas s'en soucier. -e plus || true masque les erreurs. Si c'est ce que je veux - bien, sinon, il me manque des erreurs
Michael Felt
ce que je dois me demander est: est || true - une béquille de codage (moyen paresseux de contourner / dépasser une erreur que je ne veux pas traiter maintenant; un outil de débogage (-e mais non || true) ou simplement le dogme de quelqu'un sur ce qu'est une bonne pratique de codage. En d'autres termes - Je le vois comme une caractéristique - avec des avantages potentiels. Je ne le vois pas comme une baguette magique pour guérir tout le monde. En bref - tout comme la beauté est dans l'œil du spectateur - set -eet l' || trueutilité sera définie par les traits et les objectifs de le programmeur.
Michael Felt
6
@MichaelFelt Considérez: git remote remove foo || true git remote add foo http://blah- nous voulons ignorer l'erreur si la télécommande n'existe pas.
user253751