Retour sur erreur dans shellscript au lieu de sortie en cas d'erreur

Je sais que set -e est mon ami afin de sortir sur erreur. Mais que faire si le script est source, par exemple une fonction est exécutée à partir de la console? Je ne veux pas fermer la console en cas d'erreur, je veux juste arrêter le script et afficher le message d'erreur.

Dois-je vérifier le $? de chaque command à la main pour rendre cela possible?

Voici un exemple de script myScript.sh pour montrer le problème:

 #!/bin/sh set -e copySomeStuff() { source="$1" dest="$2" cp -rt "$source" "$dest" return 0 } installStuff() { dest="$1" copySomeStuff dir1 "$dest" copySomeStuff dir2 "$dest" copySomeStuff nonExistingDirectory "$dest" } 

Le script est utilisé comme ça:

 $ source myScript.sh $ installStuff 

Cela va simplement fermer la console. L'erreur affichée par cp est perdue.

Je recommand d'avoir un script que vous exécutez en tant que sous-shell, en recherchant éventuellement un file à lire dans les définitions de fonction. Laissez ce script définir l'option de shell errexit pour lui-même.

Lorsque vous utilisez source partir de la command line, "le script" est effectivement votre shell interactif. La sortie signifie terminer la session shell. Il y a peut-être des façons de contourner cela, mais la meilleure option, si vous vouliez définir errexit pour une session, serait d'avoir simplement:

 #!/bin/bash set -o errexit source file_with_functions do_things_using_functions 

Avantage supplémentaire: Ne polluera pas la session interactive avec des fonctions.

Si vous la source, il ignorera le #! et appliquera set -e au shell appelant, donc s'appliquera à toutes les commands suivantes.

vous pourriez forcer un sous-shell:

 copySomeStuff() { ( set -e source="$1" dest="$2" cp -r "$source" "$dest" return 0 ) } 

Aussi pour la security:

  • N'utilisez pas le nom de variable de toutes les majuscules, car il est susceptible d'entrer en collision avec les noms d'environnement. (nous avions une question la semaine dernière sur la raison pour laquelle un script ne fonctionnait pas, il y avait une variable PATH)

  • Utilisez des citations.

  • Utilisez toujours l'option -t ou -T pour cp , mv , ln . par exemple

    • cp -t destination_directory source_files …
    • cp -T source_file destination_file

    notez que -t et -T sont des extensions Gnu et ne sont pas disponibles sur d'autres Unix, donc pour la portabilité vous pouvez replace l'option -t :

    • cp source_files … destination_directory/

    Je ne connais pas d'autre forme sûre pour -T