Bash: détecter exécuter vs source dans un script?

19

J'ai un script qui est jonché autour de mon système de fichiers (effet secondaire d'un processus de construction) qui définit certaines variables d'environnement globales (LD_LIBRARY_PATH, PATH, ROOTDIR, etc.) qui doivent être dans mon shell pour un fonctionnement correct. Bien sûr, cela signifie que je dois source script.shou . script.shpour le faire fonctionner, et non ./script.sh(ce qui engendrerait un nouveau shell et ne définirait pas les variables dans mon shell actuel).

Puis-je ajouter quelque chose au script pour empêcher (ou avertir) quelqu'un de courir ./script.sh?

Yeraze
la source

Réponses:

15

Dans un script shell, $0est le nom du script en cours d'exécution. Vous pouvez l'utiliser pour savoir si vous êtes originaire ou si vous exécutez comme ceci:

if [[ "$(basename -- "$0")" == "script.sh" ]]; then
    echo "Don't run $0, source it" >&2
    exit 1
fi
Mikel
la source
5

Le moyen le plus simple bashest:

if [ "$0" = "$BASH_SOURCE" ]; then
    echo "Error: Script must be sourced"
    exit 1
fi

$BASH_SOURCE contient toujours le nom / chemin du script.

$0 contient uniquement le nom / chemin du script lorsqu'il n'est PAS fourni.

Donc, quand ils correspondent, cela signifie que le script n'a PAS été fourni.

wisbucky
la source
1

Cela a été discuté sur SO . La réponse la plus votée par @barroyo dit d'utiliser

[[ "${BASH_SOURCE[0]}" != "${0}" ]] && echo "script ${BASH_SOURCE[0]} is being sourced ..."
serv-inc
la source
@will: Le manuel dit: Une variable de tableau dont les membres sont les noms de fichiers source où les noms de fonction shell correspondants dans la variable de tableau FUNCNAME sont définis. Comment une fonction?
serv-inc
1

Une autre option peut être de supprimer les autorisations d'exécution. Dans ce cas, il ne peut pas être exécuté, mais il peut toujours être obtenu.

Jelmer
la source
1
C'est incomplet. Vous pouvez toujours exécuter des scripts avec bash scriptindépendamment de l'indicateur d'exécution sur un script. Toujours sous Cygwin (cela compte-t-il?), Vous ne pouvez pas retirer les drapeaux d'exécution.
Tino
0

En plus de vérifier $ 0 ( réponse Mikel ) peut être utile pour changer l'extension de .sh en .src, par exemple. Cela aidera à comprendre quiconque ne devrait pas exécuter ce script.

Victor Sizov
la source
0

Créez un interpréteur personnalisé source_reminder:

#!/bin/sh
printf "%s\n" "Source me!" >&2
exit 1

N'oubliez pas de le rendre exécutable. Ensuite, utilisez-le simplement dans votre script:

#!/path/to/your/source_reminder
foo
bar
whatever

Maintenant, si vous exécutez le script sans sourcing, le rappel fera son travail.

Kamil Maciorowski
la source
Belle prise. #!/bin/echo do not executeou #!/bin/falseou #!/usr/bin/awk BEGIN { print "you must source " ARGV[1]; exit(1) }. Cependant, cela n'attrape pas le cas où le script est exécuté avec quelque chose comme sh script(car cela ignore le Shebang).
Tino