Bash: wykryć wykonanie skryptu względem źródła?

19

Mam skrypt zaśmiecony wokół mojego systemu plików (efekt uboczny procesu kompilacji), który ustawia niektóre globalne zmienne środowiskowe (LD_LIBRARY_PATH, PATH, ROOTDIR itp.), Które muszą znajdować się w mojej powłoce, aby poprawnie działać. Oczywiście oznacza to, że muszę to zrobić source script.shlub . script.shsprawić, by działało, a nie ./script.sh(co spowoduje odrodzenie nowej powłoki i nie ustawianie zmiennych w mojej bieżącej powłoce).

Czy jest coś, co mogę dodać do skryptu, aby zapobiec (lub ostrzec) przed uruchomieniem ./script.sh?

Yeraze
źródło

Odpowiedzi:

15

W skrypcie powłoki $0jest nazwą aktualnie uruchomionego skryptu. Możesz użyć tego, aby określić, czy jesteś pozyskiwany, czy biegać w ten sposób:

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

Najprostszym sposobem bashjest:

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

$BASH_SOURCE zawsze zawiera nazwę / ścieżkę skryptu.

$0 zawiera tylko nazwę / ścieżkę skryptu, gdy NIE jest pozyskiwany.

Kiedy więc się zgadzają, oznacza to, że skrypt NIE został pobrany.

wisbucky
źródło
1

Zostało to omówione na SO . Najbardziej upvoted odpowiedź przez @barroyo mówi do użytku

[[ "${BASH_SOURCE[0]}" != "${0}" ]] && echo "script ${BASH_SOURCE[0]} is being sourced ..."
serv-inc
źródło
@will: Instrukcja mówi: Zmienna tablicowa, której elementami są źródłowe nazwy plików, w których zdefiniowane są odpowiednie nazwy funkcji powłoki w zmiennej tablicowej FUNCNAME. Jak funkcja?
serv-inc
1

Inną opcją może być usunięcie uprawnień do wykonywania. W takim przypadku nie można go wykonać, ale nadal można go uzyskać.

Jelmer
źródło
1
To jest niekompletne. Nadal możesz uruchamiać skrypty bash scriptniezależnie od flagi wykonania na skrypcie. Również pod Cygwin (czy to się liczy?) Nie można zabrać flag wykonawczych.
Tino
0

Oprócz sprawdzenia $ 0 ( odpowiedź Mikela ) może być przydatna na przykład zmiana rozszerzenia z .sh na .src. Pomoże to zrozumieć każdego, kto nie powinien wykonać tego skryptu.

Victor Sizov
źródło
0

Utwórz niestandardowego interpretera source_reminder:

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

Nie zapomnij, aby był wykonywalny. Następnie użyj go w skrypcie:

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

Teraz, jeśli uruchomisz skrypt bez źródła, przypomnienie wykona swoją pracę.

Kamil Maciorowski
źródło
Dobry chwyt. #!/bin/echo do not executelub #!/bin/falselub #!/usr/bin/awk BEGIN { print "you must source " ARGV[1]; exit(1) }. Jednak nie wychwytuje to przypadku, w którym skrypt jest wykonywany z czymś podobnym sh script(ponieważ ignoruje to Shebang).
Tino