Je suis récemment tombé sur cette liste de codes de sortie avec des significations spéciales dans le guide avancé de Bash-Scripting. Ils se réfèrent à ces codes comme étant réservés et recommandent que:
Selon le tableau ci-dessus, les codes de sortie 1-2, 126-165 et 255 ont des significations spéciales et doivent donc être évités pour les paramètres de sortie spécifiés par l'utilisateur.
Il y a quelque temps, j'ai écrit un script qui utilisait les codes d'état de sortie suivants:
- 0 - succès
- 1 - nom d'hôte incorrect
- 2 - arguments non valides spécifiés
- 3 - Privilèges utilisateur insuffisants
Lorsque j'ai écrit le script, je ne connaissais aucun code de sortie spécial, j'ai donc simplement commencé à 1 pour la première condition d'erreur et j'ai incrémenté l'état de sortie pour chaque type d'erreur successif.
J'ai écrit le script avec l'intention qu'à un stade ultérieur, il puisse être appelé par d'autres scripts (qui pourraient vérifier les codes de sortie non nuls). Je ne l'ai pas encore fait; Jusqu'à présent, je n'ai exécuté le script qu'à partir de mon shell interactif (Bash) et je me demandais quels problèmes / si des problèmes pouvaient être causés par l'utilisation de mes codes de sortie personnalisés. Quelle est la pertinence / l’importance de la recommandation du Guide de création de scripts avancés?
Je n'ai trouvé aucun conseil corroborant dans la documentation de Bash; sa section sur l' état de sortie répertorie simplement les codes de sortie utilisés par Bash, mais ne précise pas que ceux-ci sont réservés ou déconseille de les utiliser pour vos propres scripts / programmes.
la source
Réponses:
Il y a eu plusieurs tentatives pour normaliser la signification des codes de sortie de processus. En plus de celle que vous mentionnez, je connais:
les BSD ont
sysexits.h
qui définit la signification des valeurs à partir de 64.Les
grep
documents GNU indiquant que le code de sortie 0 signifie qu'au moins une correspondance a été trouvée, 1 signifie qu'aucune correspondance n'a été trouvée et 2 signifie qu'une erreur d'E / S s'est produite; cette convention est évidemment également utile pour d'autres programmes pour lesquels la distinction entre "rien ne s'est mal passé mais je n'ai rien trouvé" et "une erreur d'E / S s'est produite" est significative.De nombreuses implémentations de la fonction de bibliothèque C
system
utilisent le code de sortie 127 pour indiquer que le programme n'existe pas ou n'a pas pu démarrer.Sous Windows, les
NTSTATUS
codes (qui sont dispersés de manière gênante sur tout l'espace numérique 32 bits) peuvent être utilisés comme codes de sortie, en particulier ceux qui indiquent qu'un processus a été interrompu en raison d'une mauvaise conduite catastrophique (par exempleSTATUS_STACK_OVERFLOW
).Vous ne pouvez pas compter sur un programme donné obéissant à l'une quelconque de ces conventions. La seule règle fiable est que le code de sortie 0 est un succès et tout le reste est une sorte d'échec. (Notez que les C89 ne
EXIT_SUCCESS
sont pas garantis d'avoir la valeur zéro; cependant, ilsexit(0)
doivent se comporter de manière identiqueexit(EXIT_SUCCESS)
même si les valeurs ne sont pas les mêmes.)la source
Aucun code de sortie n'a une signification spéciale, mais la valeur dans
$?
peut avoir une signification spéciale.La manière dont Bourne Shell et ksh93 ont traité et transmis les codes de sortie et les situations d'erreur à la variable shell
$?
est le problème. Contrairement à ce que vous indiquez, seules les valeurs suivantes$?
ont une signification particulière:De plus, il existe un shell non spécifié et une plage de
$?
codes spécifiques à la plate-forme > 128 qui sont réservés à un programme interrompu par un signal:Les autres valeurs ne posent pas de problème car elles peuvent être distinguées des
$?
valeurs shell-special .En particulier, les valeurs 1 et 2 ne sont pas utilisées pour des conditions spéciales, mais ne sont que des codes de sortie utilisés par des commandes intégrées qui pourraient agir de la même manière lorsqu'elles ne sont pas intégrées. Il semble donc que le pointeur vers le guide de script bash que vous avez fourni ne soit pas un bon manuel car il répertorie simplement les codes utilisés par bash sans commenter si un code spécifique est une valeur spéciale qui devrait être évitée pour ses propres scripts.
Les versions plus récentes de Bourne Shell utilisent
waitid()
au lieu d'waitpid()
attendre la fin du programme etwaitid()
(introduit en 1989 pour SVr4) utilise une meilleure interface syscall (similaire à celle qu'UNOS utilisait déjà en 1980).Comme les nouvelles versions de Bourne Shell codent le motif de sortie dans une variable distincte
${.sh.code}
/${.sh.codename}
du code de sortie qui se trouve dans${.sh.status}
/${.sh.termsig}
, voir http://schillix.sourceforge.net/man/man1/bosh.1.html , le code de sortie n'est pas surchargé avec des états spéciaux, et, en raison de l'utilisation de `waitid (), le Bourne Shell prend désormais en charge le retour des 32 bits du code de sortie - pas seulement les 8 bits les plus faibles.BTW: faites attention à ne pas
exit(256)
ressembler à un programme C ou à un script shell, car cela se traduit par$?
être interprété comme 0 dans un shell classique.la source
waitid()
bogue vers la fin mai. Les gens de FreeBSD ont résolu le problème en 20 heures, les gens de Linux ne sont pas intéressés à corriger leur bogue. ... et les gens de Cygwin disent qu'ils sont compatibles bug par bug Linux ;-)_exit
. Veuillez lier le rapport de bogue FreeBSD auquel vous faites référence, peut-être que je comprends mal le problème que vous décrivez.${.sh.}
variables. Il est vrai, cependant, que vous dites "Bourne" et non "dérivé de Bourne" (bien que vous incluiez ksh93)./bin/sh
pouvez vous fier à un comportement cohérent par rapport à ces codes de sortie spéciaux multiplateforme, ce qui n'est pas vrai. (Je me fiche de savoir si un système particulier/bin/sh
peut être considéré comme un "vrai Bourne shell". Il est beaucoup plus important de savoir que rien de tout cela n'est dans POSIX, et que la plupart des choses que vous citez en tant que "vrais systèmes Unix" ne font pas ' t fournir un POSIX conforme de/bin/sh
toute façon.)Pour les scripts shell, j'ai parfois source l'équivalent shell
sysexist.h
avec des codes de sortie réservés au shell (préfixés parS_EX_
), que j'ai nommésexit.sh
C'est essentiellement:
Et peut être généré avec:
Je ne l'utilise pas beaucoup, cependant, mais ce que j'utilise est une fonction shell qui inverse les codes d'erreur à leurs formats de chaîne. Je l'ai nommé
exit2str
. En supposant que vous avez nommé leexit.sh
générateur ci-dessusexit.sh.sh
, le code pourexit2str
peut être généré avec (exit2str.sh.sh
):J'utilise ceci dans le
PS1
de mon shell interactif pour qu'après chaque commande que j'exécute, je puisse voir son état de sortie et sa forme de chaîne (s'il a une forme de chaîne connue):Pour les obtenir, vous avez besoin d'un câble insourcable pour la fonction exit2str:
puis l'utiliser dans votre
~/.bashrc
pour enregistrer et traduire le code de sortie sur chaque invite de commande et l'afficher votre invite (PS1
):C'est assez pratique pour observer comment certains programmes suivent les conventions de code de sortie et d'autres non, pour en savoir plus sur les conventions de code de sortie ou simplement pour voir ce qui se passe plus facilement. Après l'avoir utilisé pendant un certain temps, je peux dire que de nombreux scripts shell orientés système suivent les conventions.
EX_USAGE
est particulièrement assez commun, bien que d'autres codes, pas beaucoup. J'essaie de suivre les conventions de temps en temps, bien qu'il y ait toujours$S_EX_ANY
(1) pour les paresseux (j'en suis un).la source
Tant que vous documentez vos codes de sortie afin de vous en souvenir dans un an, lorsque vous devrez revenir et modifier le script, tout ira bien. L'idée de "codes de sortie réservés" ne s'applique plus vraiment, si ce n'est de dire qu'il est habituel d'utiliser
0
comme code de réussite et quoi que ce soit d'autre comme code d'échec.la source
La meilleure référence que j'ai pu trouver était la suivante: http://tldp.org/LDP/abs/html/exitcodes.html
Selon ce:
1
est un fourre-tout général pour les erreurs, et je l'ai toujours vu utilisé pour les erreurs définies par l'utilisateur.2
est pour une mauvaise utilisation des commandes intégrées au shell, comme une erreur de syntaxePour répondre directement à votre question, votre script sera correct en utilisant les codes d'erreur réservés, il fonctionnera comme prévu en supposant que vous traitez l'erreur en fonction du code d'erreur = 1/2/3.
Cependant, cela pourrait être déroutant si vous rencontrez quelqu'un qui connaît et utilise les codes d'erreur réservés, ce qui semble assez rare.
Une autre option qui s'offre à vous est de faire écho à l'erreur s'il y en a une, puis de quitter, en supposant que votre script respecte la convention Linux "aucune nouvelle n'est une bonne nouvelle" et écho n'a rien en cas de succès.
la source
D'après les réponses que j'ai reçues (il était difficile d'en choisir une parmi les autres), il n'est pas dangereux d'indiquer certains types d'erreurs en utilisant un code de sortie que Bash utilise également. Bash (ou tout autre shell Unix) ne fera rien de spécial (comme l'exécution de gestionnaires d'exceptions) si un script utilisateur se termine avec l'un de ces codes d'erreur.
Il semble que l'auteur du Guide de script Bash avancé soit d'accord avec les tentatives de BSD de normaliser les codes de sortie (
sysexits.h
) et recommande simplement que lorsque les utilisateurs écrivent des scripts shell, ils ne spécifient pas déjà les codes de sortie qui entrent en conflit avec les codes de sortie prédéfinis en cours d'utilisation, c'est-à-dire qu'ils limitent leurs codes de sortie personnalisés aux 50 codes d'état disponibles dans la plage 64-113.J'apprécie l'idée (et la justification) mais j'aurais préféré que l'auteur soit plus explicite qu'il ne soit pas nuisible d'ignorer les conseils - à l'exception des cas où le consommateur d'un script vérifie les erreurs comme l'exemple cité de 127 (
command not found
).Spécifications POSIX pertinentes
J'ai recherché ce que POSIX a à dire sur les codes de sortie et la spécification POSIX semble être en accord avec l'auteur du Advanced Bash-Scripting Guide. J'ai cité les spécifications POSIX pertinentes (je souligne):
Statut de sortie pour les commandes
L'
exit
utilitéPlus d'informations
Pour ce que ça vaut, j'ai pu vérifier tout sauf un de la liste des codes de sortie avec des significations spéciales . Ce tableau des codes de sortie est utile car il fournit plus de détails et des exemples sur la façon de générer les codes d'erreur documentés dans la référence Bash .
Tentative de génération d'un état de sortie de 128
En utilisant les versions 3.2.25 et 4.2.46 de Bash, j'ai essayé de lancer une
128 Invalid argument to exit
erreur mais à chaque fois que j'ai reçu un 255 (état de sortie hors plage). Par exemple, s'ilexit 3.14159
est exécuté dans le cadre d'un script shell ou dans un shell enfant interactif, le shell se termine avec un code de255
:Pour encore plus de plaisir, j'ai également essayé d'exécuter un programme C simple mais dans ce cas, il semble que la
exit(3)
fonction ait simplement converti le float en int (3 dans ce cas) avant de quitter:la source