J'étudie le contenu de ce fichier preinst que le script exécute avant que ce paquet ne soit décompressé de son fichier d'archive Debian (.deb).
Le script a le code suivant:
#!/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
Ma première requête concerne la ligne:
set -e
Je pense que le reste du script est assez simple: il vérifie si le gestionnaire de paquets Debian / Ubuntu exécute une opération d'installation. Si c'est le cas, il vérifie si mon application vient d'être installée sur le système. Si c'est le cas, le script affiche le message "MyApplicationName vient d'être installé" et se termine (cela return 1
signifie que cela se termine par une "erreur", n'est-ce pas?).
Si l'utilisateur demande au système de paquets Debian / Ubuntu d'installer mon paquet, le script supprime également deux répertoires.
Est-ce vrai ou ai-je raté quelque chose?
man set
set +e
Réponses:
De
help set
:Mais c'est considéré comme une mauvaise pratique par certains (auteurs bash FAQ et irc freenode #bash FAQ). Il est recommandé d'utiliser:
pour exécuter la
do_something
fonction lorsque des erreurs se produisent.Voir http://mywiki.wooledge.org/BashFAQ/105
la source
trap 'exit' ERR
ERR
trap n'est pas hérité par les fonctions shell, donc si vous avez des fonctions,set -o errtrace
ouset -E
vous permettra de simplement définir le trap une fois et de l'appliquer globalement.trap 'exit' ERR
faire quoi que ce soit différent deset -e
?set -e
arrête l'exécution d'un script si une commande ou un pipeline a une erreur - ce qui est l'opposé du comportement par défaut du shell, qui est d'ignorer les erreurs dans les scripts. Tapezhelp set
un terminal pour voir la documentation de cette commande intégrée.la source
set -o pipefail
qui peut être utilisée pour propager des erreurs afin que la valeur de retour de la commande de pipeline soit non nulle si l'une des commandes précédentes s'est terminée avec un état non nul.-o pipefail
signifie uniquement que l' état de sortie de la première commande non nulle (c'est-à-dire en-o errexit
termes d' erreur ) du pipeline est propagé à la fin. Les commandes restantes dans le pipeline fonctionnent toujours , même avecset -o errexit
. Par exemple :,echo success | cat - <(echo piping); echo continues
oùecho success
représente une commande réussie, mais faillible, s'imprimerasuccess
,piping
etcontinues
, maisfalse | cat - <(echo piping); echo continues
, avec lafalse
représentation de la commande maintenant en erreur silencieusement, s'imprimera toujourspiping
avant de quitter.Selon bash - Le manuel Set Builtin , si
-e
/errexit
est défini, le shell se ferme immédiatement si un pipeline composé d'une seule commande simple , d' une liste ou d' une commande composée renvoie un état non nul.Par défaut, l'état de sortie d'un pipeline est l'état de sortie de la dernière commande du pipeline, sauf si l'
pipefail
option est activée (elle est désactivée par défaut).Si tel est le cas, l'état de retour du pipeline de la dernière commande (la plus à droite) pour quitter avec un état différent de zéro, ou zéro si toutes les commandes se terminent avec succès.
Si vous souhaitez exécuter quelque chose à la sortie, essayez de définir
trap
, par exemple:où
onexit
est votre fonction pour faire quelque chose à la sortie, comme ci-dessous qui imprime la trace de pile simple :Il existe une option similaire
-E
/errtrace
qui intercepterait plutôt l'ERR, par exemple:Exemples
Exemple de statut zéro:
Exemple de statut différent de zéro:
Exemples de statut négatif:
Test avec
pipefail
désactivation:Test avec
pipefail
activation:la source
J'ai trouvé ce message en essayant de comprendre quel était le statut de sortie d'un script abandonné en raison d'un
set -e
. La réponse ne m'a pas paru évidente; d'où cette réponse. Fondamentalement,set -e
abandonne l'exécution d'une commande (par exemple un script shell) et renvoie le code d'état de sortie de la commande qui a échoué (c'est-à-dire le script interne, pas le script externe) .Par exemple, supposons que j'ai le script shell
outer-test.sh
:Le code pour
inner-test.sh
est:Lorsque j'exécute à
outer-script.sh
partir de la ligne de commande, mon script externe se termine avec le code de sortie du script interne:la source
Je crois que l'intention est que le script en question échoue rapidement.
Pour tester cela vous-même, tapez simplement
set -e
à l'invite bash. Maintenant, essayez de courirls
. Vous obtiendrez une liste de répertoires. Maintenant, tapezlsd
. Cette commande n'est pas reconnue et renverra un code d'erreur, et donc votre invite bash se fermera (en raison deset -e
).Maintenant, pour comprendre cela dans le contexte d'un «script», utilisez ce script simple:
Si vous l'exécutez tel quel, vous obtiendrez la liste des répertoires
ls
sur la dernière ligne. Si vous décommentez leset -e
et réexécutez, vous ne verrez pas la liste des répertoires car bash arrête le traitement une fois qu'il rencontre l'erreurlsd
.la source
C'est une vieille question, mais aucune des réponses ici ne traite de l'utilisation de
set -e
akaset -o errexit
dans les scripts de gestion des paquets Debian. L'utilisation de cette option est obligatoire dans ces scripts, selon la politique Debian; l'intention est apparemment d'éviter toute possibilité de condition d'erreur non gérée.En pratique, cela signifie que vous devez comprendre dans quelles conditions les commandes que vous exécutez peuvent renvoyer une erreur et gérer chacune de ces erreurs de manière explicite.
Les pièges courants sont par exemple
diff
(retourne une erreur quand il y a une différence) etgrep
(retourne une erreur quand il n'y a pas de correspondance). Vous pouvez éviter les erreurs avec une gestion explicite:(Remarquez également comment nous prenons soin d'inclure le nom du script actuel dans le message et d'écrire des messages de diagnostic sur l'erreur standard au lieu de la sortie standard.)
Si aucune manipulation explicite n'est vraiment nécessaire ou utile, ne faites rien explicitement:
(L'utilisation de la
:
commande no-op du shell est légèrement obscure, mais assez courante.)Juste pour réitérer,
est un raccourci pour
c'est-à-dire que nous disons explicitement
other
devrait être exécuté si et seulement sisomething
échoue. Le longhandif
(et d'autres instructions de contrôle de flux shell commewhile
,until
) est également un moyen valide de gérer une erreur (en effet, si ce n'était pas le cas, les scripts shell avecset -e
ne pourraient jamais contenir d'instructions de contrôle de flux!)Et aussi, juste pour être explicite, en l'absence d'un gestionnaire comme celui-ci,
set -e
le script entier échouerait immédiatement avec une erreur s'ildiff
trouvait une différence ou s'ilgrep
ne trouvait pas de correspondance.D'un autre côté, certaines commandes ne produisent pas d'état de sortie d'erreur lorsque vous le souhaitez. Les commandes généralement problématiques sont
find
(l'état de sortie ne reflète pas si les fichiers ont été réellement trouvés) etsed
(l'état de sortie ne révélera pas si le script a reçu une entrée ou s'il a effectivement exécuté des commandes avec succès). Un simple garde dans certains scénarios consiste à diriger vers une commande qui crie s'il n'y a pas de sortie:Il convient de noter que l'état de sortie d'un pipeline est l'état de sortie de la dernière commande de ce pipeline. Les commandes ci-dessus masquent donc complètement l'état de
find
etsed
, et vous indiquent uniquement si vous avezgrep
finalement réussi.(Bash, bien sûr,
set -o pipefail
mais les scripts de paquets Debian ne peuvent pas utiliser les fonctionnalités de Bash. La politique dicte fermement l'utilisation de POSIXsh
pour ces scripts, bien que ce ne soit pas toujours le cas.)Dans de nombreuses situations, c'est quelque chose à surveiller séparément lors du codage défensif. Parfois, vous devez par exemple parcourir un fichier temporaire pour voir si la commande qui a produit cette sortie s'est terminée avec succès, même si l'idiome et la commodité vous inciteraient autrement à utiliser un pipeline shell.
la source
la source