W moim .profile
używam następującego kodu, aby upewnić się, że aliasy i funkcje związane z Bash są pozyskiwane tylko wtedy, gdy powłoką logowania jest Bash :
# If the current (login) shell is Bash, then
if [ "${BASH_VERSION:-}" ]; then
# source ~/.bashrc if it exists.
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
Obecnie jestem w trakcie kontroli plików konfiguracyjnych powłoki, skryptów i funkcji pod kontrolą wersji. Ja również niedawno rozpoczęła proces usuwania przypadkowych Bashisms ze skryptów powłoki, które nie korzystają z Bash-specyficzne cechy, np wymianie function funcname()
z funcname()
.
Dla mojego repozytorium plików powłoki skonfigurowałem hak wstępnego zatwierdzania, który uruchamia checkbashisms
narzędzie z pakietu devscripts Debiana na każdymsh
pliku w repozytorium, aby upewnić się, że nie wprowadzę przypadkowo składni specyficznej dla Bash. Rodzi to jednak błąd dla mojego .profile
:
possible bashism in .profile line 51 ($BASH_SOMETHING):
if [ "${BASH_VERSION:-}" ]; then
Zastanawiałem się, czy istnieje sposób sprawdzenia, która powłoka jest uruchomiona, co nie wywołałoby ostrzeżenia checkbashisms
.
Sprawdziłem listę zmiennych związanych powłoką wymienionych przez POSIX w nadziei, że jedna z nich mogłaby posłużyć do wyświetlenia bieżącej powłoki. Przyjrzałem się również zmiennym ustawionym w interaktywnej powłoce Dash, ale znowu nie udało mi się znaleźć odpowiedniego kandydata.
W tej chwili wykluczyłem .profile
przetwarzanie checkbashisms
; to mały plik, więc nie jest trudno go sprawdzić ręcznie. Jednak po zbadaniu problemu nadal chciałbym wiedzieć, czy istnieje metoda zgodna z POSIX, aby określić, która powłoka działa (lub przynajmniej sposób, który nie powoduje checkbashisms
awarii).
Dalsze informacje / wyjaśnienia
Jednym z powodów, dla których poddaję pliki konfiguracyjne powłoki kontroli wersji, jest konfiguracja środowiska we wszystkich systemach, na których obecnie loguję się regularnie: Cygwin, Ubuntu i CentOS (zarówno 5, jak i 7, używając Active Directory dla użytkownika poświadczenie). Najczęściej loguję się za pośrednictwem środowisk X Windows / Desktop i SSH dla hostów zdalnych. Chciałbym jednak, aby był to dowód na przyszłość i jak najmniej polegał na zależnościach systemu i innych narzędziach.
Używam checkbashisms
jako prostego, automatycznego sprawdzania poprawności składni plików związanych z powłoką. Nie jest to idealne narzędzie, np. Już nałożyłem na niego łatkę, aby nie narzekała na użycie command -v
w moich skryptach. Podczas badań dowiedziałem się, że rzeczywistym celem programu jest zapewnienie zgodności z polityką Debiana, która, jak rozumiem, opiera się na POSIX 2004, a nie na 2008 (lub jego wersji z 2013 roku).
źródło
.bash_profile
źródło, które zarówno.profile
(i warunkowo).bashrc
.Odpowiedzi:
Twój
kod jest całkowicie zgodny z POSIX i jest to najlepszy sposób na sprawdzenie, czy aktualnie działasz
bash
. Oczywiście$BASH_VERSION
zmienna jest specyficzna dla basha, ale właśnie dlatego jej używasz! Aby sprawdzić, czy biegnieszbash
!Pamiętaj, że
$BASH_VERSION
zostanie ustawione, czybash
będzie wywoływane jakobash
czysh
. Po upewnieniu się, że działaszbash
, możesz użyć[ -o posix ]
jako wskaźnika, że powłoka została wywołana jakosh
(chociaż ta opcja jest również ustawiona, gdy POSIXLY_CORRECT znajduje się w środowisku lubbash
jest wywoływane z-o posix
, lub z SHELLOPTS = posix w środowisku. Ale we wszystkich tych przypadkachbash
zachowuje się tak, jakby był nazywany jaksh
).Inna zmienna, której możesz użyć zamiast
$BASH_VERSION
icheckbashism
wydaje się, że nie narzeka, chyba że zostanie podana-x
opcja$BASH
. Jest to również specyficzne dlabash
tego, z którego powinieneś być w stanie określić, czy biegasz,bash
czy nie.Twierdziłbym również, że tak naprawdę nie jest to właściwe użycie
checkbashisms
.checkbashisms
jest narzędziem pomagającym pisać przenośnesh
skrypty (zgodnie zesh
specyfikacją w polityce Debiana, nadzbiorem POSIX), pomaga zidentyfikować niestandardową składnię wprowadzoną przez osoby piszące skrypty w systemach, w którychsh
znajduje się dowiązanie symboliczne dobash
.A
.profile
jest interpretowane przez różne powłoki, z których wiele nie jest zgodnych z POSIX. Ogólnie rzecz biorąc, nie należy używaćsh
jako powłokę logowania, ale muszle podobazsh
,fish
czybash
z bardziej zaawansowanych funkcji interaktywnych.bash
izsh
gdy nie są wywoływane jakosh
i kiedy ich odpowiedni plik sesji profilu (.bash_profile
,.zprofile
) nie jest zgodny z POSIX (szczególniezsh
), ale nadal jest czytany.profile
.Więc nie jest to składnia POSIX, którą chcesz,
.profile
ale składnia zgodna z POSIX (dlash
),bash
azsh
jeśli kiedykolwiek będziesz używać tych powłok (być może nawet Bourne, ponieważ powłoka Bourne również czyta,.profile
ale nie jest powszechnie spotykana w systemach Linux) ).checkbashisms
na pewno pomogłoby ci znaleźć baszty, ale może nie wskazywać składni POSIX, która nie jest kompatybilna zzsh
lubbash
.Tutaj, jeśli chcesz użyć
bash
kodu -specyficznego (jak obejście tegobash
błędu, dzięki któremu nie czyta się~/.bashrc
w interaktywnych powłokach logowania), lepszym rozwiązaniem byłoby to~/.bash_profile
zrobić (przed lub po sourcowaniu,~/.profile
gdzie umieszczasz swoją wspólną sesję inicjalizacje).źródło
checkbashisms
powodu zastosowanej zmiennej.$0
z tego konkretnego przypadku?sh
a inną powłoką o nazwie assh
.dash
niepoprawnie wywołano inną powłokę niebędącą powłoką bashargv[0] == "bash"
, co jest całkowicie legalne, jeśli jest mało prawdopodobne.Zwykle używa się
$0
do tego celu. Na stronie, którą podlinkowałeś, stoi:źródło
$0
nazwy skryptu powłoki, więc czyściłem, zapomniałem, że może ona również odnosić się do bieżącej powłoki. Dzięki!exec
rodziny, ponieważ pozwalają programowi wywołującemu zidentyfikować uruchomienie pliku binarnego oddzielnie od łańcucha przekazywanego jako argument 0.Zwykle zmienna środowiskowa SHELL informuje o domyślnej powłoce. Nie powinno być konieczne ręczne źródło pliku .bashrc (nieprawda, patrz aktualizacja poniżej), bash powinien to zrobić automatycznie, po prostu upewnij się, że znajduje się on w katalogu $ HOME.
Inną opcją jest zrobienie czegoś takiego:
która powie ci polecenie (bez argumentów, = bez wartości nie wyświetli nagłówków kolumn) bieżącego procesu. Przykładowe dane wyjściowe:
AKTUALIZACJA:
Poprawiono mnie! :)
Plik .bashrc nie zawsze jest pozyskiwany, jak wspomniano w komentarzach poniżej /programming/415403/whats-the-difference-between-bashrc-bash-profile-and-environment
Możesz więc przenieść .bashrc do .bash_profile i sprawdzić, czy to działa bez konieczności wykonywania testu. Jeśli nie, masz powyższy test.
źródło
.bashrc
nie jest faktycznie pozyskiwany przez powłokę logowania, ale.profile
(jeśli istnieje) lub.bash_profile
są.SHELL
nie jest określony przez POSIX i niestety nie ma teżcmd
opcji formatowania dlaps
.ps -o cmd= $$
powinno działać prawie wszędzie,$SHELL
zmienna jest całkowicie nieistotna. Jest to domyślna powłoka użytkownika i nie ma wpływu na to, która powłoka jest obecnie uruchamiana lub jaka powłoka uruchamia skrypt powłoki.~/.profile
po uruchomieniu jako powłoki logowania. Na przykład możesz$SHELL
byćcsh
i biegnieszbash -l
. To zacznie bash jako powłokę logowania, więc będzie czytać~/.profile
, ale$SHELL
nadal będziesz wskazywaćcsh
. Ponadto.profile
może być pozyskiwany jawnie przez inny skrypt. Ponieważ PO dąży do maksymalnej niezawodności, należy rozważyć wszystkie rodzaje przypadków. W każdym razie$SHELL
nie dostarcza żadnych użytecznych informacji o aktualnie działającej powłoce.SHELL
tym, że nie został określony przez POSIX: pubs.opengroup.org/onlinepubs/9699919799/basedefs/...Pytanie dotyczy powłoki logowania użytkownika oraz bieżącej powłoki w sposób, który uspokaja
checkbashisms
. Jeśli ma to być powłoka, na której zalogował się użytkownik, użyłbym tej z/etc/passwd
np.Użytkownicy mogą oczywiście uruchomić nową powłokę po zalogowaniu. Oczywiście, jeśli jedna jest bash, a druga nie, testy zmiennych środowiskowych bash mogą nie pomóc.
Niektórzy mogą chcieć użyć
getent
zamiastpasswd
pliku (ale nie byłoby to objęte pytaniem).W oparciu o komentarz na temat LDAP i sugestię
logname
można użyć tej alternatywnej formy:Podczas testowania zauważyłem, że
logname
nie podoba mi się przekierowanie danych wejściowych (więc zostawiłem wyrażenie podzielone). Pokazy szybkiej kontroligetent
powinny działać na wymienionych platformach (choć powinno to być zawarte w pierwotnym pytaniu):źródło
$(logname)
).id
czy modyfikować przez użytkownika zmienną, to inny wybór.$(logname)
, nie$LOGNAME
. Identyfikator użytkownika i powłoka logowania pochodzą z nazwy użytkownika użytej podczas logowania. Nie można wrócić z identyfikatora użytkownika do powłoki logowania, z wyjątkiem systemów, w których istnieje tylko jedna nazwa użytkownika na identyfikator użytkownika. Lub IOW, kluczem podstawowym w bazie danych użytkowników jest nazwa użytkownika, a nie identyfikator użytkownika.