2017-09-12 10 views
1

J'ai un script simple avec une fonction simple qui peut conduire à une erreur. Définissons cette fonction, et la rendre brisée:Conserver le paramètre -e à l'intérieur || ou &&

brokenFunction() { 
    ls "non-existing-folder" 
} 

Si nous exécutons cette fonction dans un bloc de détecter si elle est cassée, il fonctionne bien:

brokenFunction || printf "It is broken\n" 

impression « Il est cassé »

maintenant, nous allons faire fonctionner un peu plus complexe, en ajoutant une commande correcte à la fin:

#!/bin/sh 

brokenFunction() { 
    ls "non-existing-folder" 
    printf "End of function\n" 
} 

brokenFunction || printf "It is broken\n" 

Cette impression de script:

$ ./script.sh 
ls: cannot access 'non-existing-folder': No such file or directory 
End of function 

alors que je m'y attendais la fonction d'arrêter avant l'instruction printf, et le bloc suivant pour afficher « Il est cassé ».

Et en effet, si je vérifie le code d'état de sortie de brokenFunction, il est égal à 0.

J'ai essayé d'ajouter set -e au début du script. Le comportement est toujours le même, mais le code de sortie de brokenFunction s'il est appelé sans || devient maintenant 2. S'il est appelé avec, le code d'état est toujours 0.

Est-il possible de conserver le paramètre set -e dans une fonction appelée avec ||?

EDIT: Je viens de me rendre compte que la fonction dans l'exemple était inutile. Je rencontre le même problème avec un bloc simple et une condition.

#!/bin/sh 
set -e 
{ 
    ls "non-existing-dir" 
    printf "End of block\n" 
} || { 
    printf "It is broken\n" 
} 

impressions

$ ./script.sh 
ls: cannot access 'non-existing-dir': No such file or directory 
End of block 
+1

J'ai trouvé pourquoi il ne fonctionne pas comme prévu: https://unix.stackexchange.com/questions/65532/why-does-set-e-not-work-inside Maintenant, je cherche juste une solution propre. – Dunatotatos

Répondre

0

Comme écrit dans man bash, set -e est ignoré dans certains contextes. Une commande avant || ou && est un tel contexte.

trap ressemble à une solution possible ici. Une alternative de travail au dernier script en utilisant trap ressemblerait que:

#!/bin/sh 
abort() { 
    printf "It is broken\n" 
} 
trap 'abort' ERR 
(
    set -e 
    false 
    printf "End of block\n" 
) 
trap - ERR 

Certaines choses doivent être remarqué ici:

  • trap 'abort' ERR se fixe la fonction abort à toute erreur relevée;
  • le bloc brisé est exécuté dans une sous-coque pour 2 raisons. La première consiste à conserver le paramètre -e à l'intérieur du bloc et à limiter les effets de bordure. La deuxième est de quitter ce sous-shell sur erreur (effet set -e), et non le script entier; À la fin, la liaison trap est réinitialisée, ce qui signifie que la partie suivante du script est exécutée comme précédemment.

Pour tester les effets de la frontière, nous pouvons ajouter la partie précédemment non-travail:

#!/bin/sh 
abort() { 
    printf "It is broken\n" 
} 

trap 'abort' ERR 
(
    set -e 
    false 
    printf "End of block\n" 
) 
trap - ERR 

{ 
    false 
    printf "End of second block\n" 
} || { 
    printf "It is broken too\n" 
} 

impressions:

It is broken 
End of second block 
+0

'trap ERR' n'est pas POSIX. Je devrais probablement le changer en 'trap EXIT' avec les paramètres' set -e'. – Dunatotatos