Różnica między powłoką logowania a powłoką niezalogowaną?

318

Rozumiem podstawową różnicę między powłoką interaktywną a powłoką nieinteraktywną. Ale co dokładnie odróżnia powłokę logowania od powłoki niezalogowanej?

Czy możesz podać przykłady zastosowań interaktywnej powłoki bez logowania ?

Igorio
źródło
45
Wydaje mi się, że pytanie jest lepiej sformułowane jako „ Dlaczego powinniśmy / powinniśmy dbać o to, aby odróżnić powłoki logowania i powłoki, które się nie logują?” Wiele miejsc w Internecie już mówi nam, jakie są różnice, jeśli chodzi o to, jakie pliki startowe czytają; ale żaden z nich nie wydaje się odpowiadać na „dlaczego” w zadowalający i przekonujący sposób. Przykładowe przypadki użycia, w których zdecydowanie nie chcesz jednego lub drugiego zachowania, byłyby świetne.
Kal
2
@Kal To musiałoby być inne pytanie, ponieważ żadna odpowiedź tutaj nie obejmuje tego. Edit: Właściwie, to jest tutaj: dlaczego logowanie shell nad non-logowania powłoki? .
Skippy le Grand Gourou

Odpowiedzi:

304

Powłoka logowania jest pierwszym procesem, który jest wykonywany w ramach identyfikatora użytkownika podczas logowania do sesji interaktywnej. Proces logowania mówi powłoce, aby zachowywała się jak powłoka logowania z konwencją: przekazanie argumentu 0, który jest zwykle nazwą pliku wykonywalnego powłoki, z -poprzedzającym znakiem (np. -bashPodczas gdy normalnie byłoby bash. Powłoki logowania zwykle czytają plik, który robi takie rzeczy jak ustawienie zmiennych środowiskowych: /etc/profilei ~/.profiledla tradycyjnego Bourne shell, ~/.bash_profiledodatkowo dla bash , /etc/zprofilei ~/.zprofiledla zsh , /etc/csh.logina ~/.logindla csh, etc.

Kiedy logujesz się na konsoli tekstowej, przez SSH lub za pomocą su -, otrzymujesz interaktywną powłokę logowania . Kiedy logujesz się w trybie graficznym (na X menedżerze wyświetlania ), nie dostajesz powłoki logowania, zamiast tego dostajesz menedżera sesji lub menedżera okien.

Rzadko uruchamia się nieinteraktywną powłokę logowania , ale niektóre ustawienia X robią to po zalogowaniu się za pomocą menedżera wyświetlania, aby zorganizować odczyt plików profilu. Inne ustawienia (zależy od dystrybucji i menedżera wyświetlania) czytają /etc/profilei ~/.profilejawnie lub nie czytają ich. Innym sposobem na uzyskanie nieinteraktywnej powłoki logowania jest zalogowanie zdalne za pomocą polecenia przekazanego przez standardowe wejście, które nie jest terminalem, np. ssh example.com <my-script-which-is-stored-locally(W przeciwieństwie do tego ssh example.com my-script-which-is-on-the-remote-machine, który uruchamia nieinteraktywną powłokę, która się nie loguje).

Kiedy uruchamiasz powłokę w terminalu w istniejącej sesji (screen, terminal X, bufor terminala Emacs, powłoka wewnątrz innej itp.), Otrzymujesz interaktywną powłokę , która nie jest zalogowana . Że powłoka może odczytać pliku konfiguracyjnego powłoki ( ~/.bashrcdla bash wywoływany jako bash, /etc/zshrca ~/.zshrcdla zsh, /etc/csh.cshrci ~/.cshrcdla csh, plik wskazywany przez ENVzmienną do muszli POSIX / XSI zgodnych takich jak deski rozdzielczej, ksh i bash przy wywołaniu jako sh, $ENVjeśli ustawiony i ~/.mkshrcdla mksh itp.).

Gdy powłoka uruchamia skrypt lub polecenie przekazane w wierszu poleceń, jest to nieinteraktywna powłoka , która nie loguje się . Takie powłoki działają cały czas: bardzo często zdarza się, że gdy program wywołuje inny program, tak naprawdę uruchamia mały skrypt w powłoce, aby wywołać ten inny program. W tym przypadku niektóre powłoki odczytują plik startowy (bash uruchamia plik wskazany przez BASH_ENVzmienną, działa zsh /etc/zshenvi ~/.zshenv), ale jest to ryzykowne: powłokę można wywoływać w różnych kontekstach, a nic nie można zrobić, co by nie złamać coś.

Upraszczam trochę, zobacz szczegóły dotyczące krwawych szczegółów.

Gilles
źródło
2
Czy możesz podać przykład działania bashjako nieinteraktywna powłoka logowania?
Piotr Dobrogost
13
@PiotrDobrogostecho $- | bash -lx
Gilles
1
Nie wiem, czy to prawda, ale chcę zauważyć, że kiedy otwieram nowy terminal (w systemie OSX przy użyciu ustawień domyślnych), otrzymuję powłokę logowania, mimo że nigdy nie wpisuję nazwy użytkownika ani hasła.
Kevin Wheeler
4
@KevinWheeler W systemie OSX domyślnie aplikacja terminalowa uruchamia powłokę logowania. (Jak wyjaśniam, program uruchamiający powłokę decyduje, czy powłoka działa jak powłoka logowania.) To nie jest normalny sposób wykonywania różnych czynności.
Gilles
2
@IAmJulianAcosta Jeśli FOOjest zmienną środowiskową (tzn. .profileZawiera export FOO=something), to jest dostępna dla wszystkich podprocesów, w tym foo.sh. Jeśli zmienisz .profilena, export FOO=something_elseto ./foo.shnadal będzie drukowany somethingdo następnego logowania.
Gilles
48

Aby stwierdzić, czy jesteś w powłoce logowania:

prompt> echo $0
-bash # "-" is the first character. Therefore, this is a login shell.

prompt> echo $0
bash # "-" is NOT the first character. This is NOT a login shell.

W Bash możesz także użyć shopt login_shell:

prompt> shopt login_shell
login_shell     off

(lub onw powłoce logowania).

Informacje można znaleźć w man bash(Wyszukaj wywołanie). Oto fragment:

Powłoka logowania to taka, której pierwszym znakiem argumentu zero jest - lub rozpoczęty z opcją --login.

Możesz to przetestować samodzielnie. Za każdym razem, gdy korzystasz z SSH, używasz powłoki logowania. Na przykład:

prompt> ssh user@localhost
user@localhost's password:
prompt> echo $0
-bash

Ważne jest użycie powłoki logowania, aby wszelkie ustawienia w niej /home/user/.bash_profilezostały wykonane. Oto trochę więcej informacji, jeśli jesteś zainteresowany (z man bash)

„Gdy bash jest wywoływany jako interaktywna powłoka logowania lub jako nieinteraktywna powłoka z opcją --login, najpierw czyta i wykonuje polecenia z pliku / etc / profile, jeśli plik ten istnieje. Po odczytaniu tego pliku szuka ~/.bash_profile, ~/.bash_logini ~/.profile, w tej kolejności, a odczytuje i wykonuje polecenia z pierwszego, który istnieje i jest czytelny. opcja --noprofile może być stosowany, gdy powłoka jest zaczął hamować ten problem.”

Timothy Pulliam
źródło
23

W powłoce logowania argv[0][0] == '-'. W ten sposób wie, że to powłoka logowania.

W niektórych sytuacjach zachowuje się inaczej w zależności od statusu „powłoki logowania”. Na przykład powłoka, która nie jest powłoką logowania, nie wykona polecenia „wylogowania”.

BOPOHOK
źródło
4
Zgodnie man bashz dodanym podkreśleniem: „Powłoka logowania to taka, której pierwszym znakiem argumentu zero jest - lub zaczyna się od opcji --login.
Wildcard
18

Powłoka uruchomiona w nowym terminalu w GUI byłaby interaktywną powłoką bez logowania. Byłby źródłem twojego .bashrc, ale nie na przykład twojego .profile.

juliański
źródło
4

Omówię świetną odpowiedź Gillesa w połączeniu z metodą Timothy'ego do sprawdzania typu powłoki logowania.

Jeśli chcesz zobaczyć rzeczy na własne oczy, wypróbuj poniższe fragmenty i scenariusze.

Sprawdzanie, czy powłoka jest (nie) interaktywna

if tty -s; then echo 'This is interactive shell.'; else echo 'This is non-interactive shell.'; fi

Sprawdzanie, czy powłoka jest (nie-) loginem

Jeśli wyjście echo $0zaczyna się od -, to jest to powłoka logowania ( echo $0przykład wyjścia:) -bash. W przeciwnym razie jest to powłoka niezalogowana ( echo $0przykład wyjściowy:) bash.

if echo $0 | grep -e ^\- 2>&1>/dev/null; then echo "This is login shell."; else echo "This is non-login shell."; fi;

Połączmy dwa powyższe razem, aby uzyskać obie informacje jednocześnie:

THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; 
THIS_SHELL_LOGIN_TYPE='non-login'; 
if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; 
if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi;
echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"

Scenariusze:

Typowa sesja SSH bez specjalnych opcji

ssh ubuntu@34.247.105.87
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

ubuntu@ip-172-31-0-70:~$ THIS_SHELL_INTERACTIVE_TYPE='non-interactive';
ubuntu@ip-172-31-0-70:~$ THIS_SHELL_LOGIN_TYPE='non-login';
ubuntu@ip-172-31-0-70:~$ if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi;
ubuntu@ip-172-31-0-70:~$ if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi;
ubuntu@ip-172-31-0-70:~$ echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"

interactive/login

Uruchamianie skryptu lub jawne wykonywanie za pomocą nowej powłoki

ubuntu@ip-172-31-0-70:~$  bash -c 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; 
echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

interactive/non-login

Zdalne uruchamianie lokalnego skryptu

ssh ubuntu@34.247.105.87 < checkmy.sh
Pseudo-terminal will not be allocated because stdin is not a terminal.
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-1083-aws x86_64)

non-interactive/login

Zdalne uruchomienie polecenia nad ssh

ssh ubuntu@34.247.105.87 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

non-interactive/non-login

Uruchamianie polecenia ssh zdalnie za pomocą -tprzełącznika

Możesz jawnie zażądać interaktywnej powłoki, gdy chcesz uruchomić polecenie zdalnie przez ssh za pomocą -tprzełącznika.

ssh ubuntu@34.247.105.87 -t 'THIS_SHELL_INTERACTIVE_TYPE='non-interactive'; THIS_SHELL_LOGIN_TYPE='non-login'; if tty -s; then THIS_SHELL_INTERACTIVE_TYPE='interactive'; fi; if echo $0 | grep -e ^\- 2>&1>/dev/null; then THIS_SHELL_LOGIN_TYPE='login'; fi; echo "$THIS_SHELL_INTERACTIVE_TYPE/$THIS_SHELL_LOGIN_TYPE"'

interactive/non-login

Uwaga: na ten temat, dlaczego zdalne uruchamianie polecenia nie ma tutajlogin shell więcej informacji .

Patrik Stas
źródło