Definiuję skrypt powłoki, który użytkownik powinien source
raczej wykonać niż wykonać.
Czy istnieje konwencjonalny lub inteligentny sposób, aby poinformować użytkownika, że tak jest, na przykład poprzez rozszerzenie pliku?
Czy istnieje kod powłoki, który mogę napisać w samym pliku, co spowoduje, że wyświetli komunikat i zakończy działanie, jeśli zostanie wykonany zamiast źródła, aby pomóc użytkownikowi uniknąć tego oczywistego błędu?
x
, który zawiera tylko polecenie. your-script-to-be-sourced
, jest w porządku, ale jeśli chce go wykonaćbash your-script-to-be-sourced
, powinien być zabroniony? Jaki jest sens tego ograniczenia?env
zmiennych i pozostawia je jako de facto wyjście skryptu. Nowicjusz utknie na kilka dni z układanką, jeśli pozwolisz jej wykonać.if __name__ == '__main__'
?Odpowiedzi:
Zakładając, że uruchamiasz bash, umieść następujący kod na początku skryptu, który chcesz pobrać, ale nie wykonać:
Pod bash
${BASH_SOURCE[0]}
będzie zawierać nazwę bieżącego pliku, który odczytuje powłoka, niezależnie od tego, czy jest pobierana czy wykonywana.Natomiast
$0
nazwa bieżącego pliku, który jest wykonywany.-ef
sprawdza, czy te dwa pliki są tym samym plikiem. Jeśli tak, ostrzegamy użytkownika i wychodzimy.POSIX też
-ef
nieBASH_SOURCE
jest. Chociaż-ef
jest obsługiwany przez ksh, yash, zsh i Dash,BASH_SOURCE
wymaga bash. Wzsh
jednakże${BASH_SOURCE[0]}
można zastąpić${(%):-%N}
.źródło
echo "Usage: source \"$myfile\""
source
nie jest przenośny. Biorąc pod uwagę, że ta odpowiedź jest specyficzna dla bash, nie jest tak źle, ale dobrym zwyczajem jest korzystanie z przenośnego.
Plik niewykonywalny może być pozyskiwany, ale nie wykonywany, więc jako pierwsza linia obrony nie ustawianie flagi wykonywalnej powinno być dobrą wskazówką ...
Edycja: trik, na który się natknąłem: spraw, aby shebang był dowolnym plikiem wykonywalnym, który nie jest interpreterem powłoki,
/bin/false
powoduje , że skrypt zwraca błąd (rc! = 0)źródło
bash somefile.sh
...bash
(vd perl, python, awk ...), to poszukałeś źródła i zobaczyłeś komentarz, który mówi, aby tego nie robić :)somefile.pl
i Pythonsomefile.py
, więc nie, prawdopodobnie nie przeczytałem komentarzy (abash somefile.sh
chmod +x somefile.sh; ./somefile.sh
bash
, najpierw spróbująexecve
utworzyć plik, ale jeśli to się nie powiedzie, sprawdzają plik ręcznie i ręcznie interpretują#!
i wywołują go przez tego interpretera: jest to dziedzictwo z czasów, gdy#!
była to czysto przestrzeń użytkownika konwencja, zamiast być obsługiwanym przez samo jądro. I pomyślećbash
, co najmniej, będzie nie to zrobić dla plików niewykonywalnych, ale nie wiem, czy to przenośny oczekiwać takiego zachowania sane ze wszystkich skorup, że użytkownik może być wywoływania skryptu z.bash
którebash script.sh
mogą być niebezpieczne.W tym wpisie przepełnienia stosu zasugerowano kilka metod , z których najbardziej podobała mi się ta oparta na funkcjach, sugerowana przez Wirawana Purwanto i mr.spuratic najlepiej:
Możesz więc dodać na początku skryptu:
źródło
Zakładając, że wykonanie skryptu jest po prostu bezużyteczne, a nie szkodliwe, możesz dodać
do końca skryptu.
return
poza funkcją ma niezerowy kod wyjścia, chyba że plik jest pobierany.źródło
return 2>/dev/null; echo "$0: This script must be sourced" 1>&2; exit 1
Gdy pozyskujesz skrypt powłoki, linia shebang jest ignorowana. Wprowadzając nieprawidłowy shebang, możesz ostrzec użytkownika, że skrypt został błędnie wykonany:
Komunikat o błędzie będzie następujący:
(Dowolna) nazwa argumentu już zapewnia silną wskazówkę, ale komunikat o błędzie nadal nie jest w 100% wyraźny. Możemy to naprawić za pomocą skryptu narzędzia
source-this-script
umieszczonego gdzieś w twoimPATH
:Teraz komunikat o błędzie będzie następujący:
Porównanie z innymi podejściami
W porównaniu z innymi odpowiedziami to podejście wymaga jedynie minimalnych zmian w każdym skrypcie (a posiadanie linii shebang pomaga w wykrywaniu typów plików w edytorach i określa dialekt skryptu powłoki, więc są nawet korzyści). Minusem jest nieco niejasny komunikat o błędzie lub (jednorazowe) dodanie innego skryptu powłoki.
Nie zapobiega to
bash path/to/script.sh
jednak jawnemu wywoływaniu za pośrednictwem (dzięki @muru!).źródło
bash some/script.sh
, co również zignoruje snbang.#!/bin/echo 'You must source this script!'
lub coś w tym rodzaju.