Differenza tra Shell di accesso e Shell non di accesso?


318

Comprendo la differenza di base tra una shell interattiva e una shell non interattiva. Ma cosa differenzia esattamente una shell di login da una shell non di login?

Puoi fornire esempi per l'uso di una shell interattiva senza login ?


45
Penso che la domanda sia meglio formulata come " Perché / dovremmo preoccuparci di differenziare le shell di login e non login?" Molti luoghi sul web ci dicono già quali sono le differenze, in termini di quali file di avvio leggono ciascuno; ma nessuno di loro sembra rispondere al "perché" in modo soddisfacente e convincente. Esempi di casi in cui sicuramente non si desidera l' uno o l'altro comportamento sarebbero ottimi.
Kal,

2
@Kal Questa dovrebbe essere una domanda diversa, dal momento che nessuna risposta qui in realtà lo copre. Modifica: In realtà, eccolo qui: PERCHÉ una shell di login su una shell non di login ? .
Skippy le Grand Gourou,

Risposte:


304

Una shell di accesso è il primo processo che viene eseguito con il tuo ID utente quando accedi per una sessione interattiva. Il processo di login dice alla shell di comportarsi come una shell di login con una convenzione: passare l'argomento 0, che normalmente è il nome dell'eseguibile della shell, con un -carattere anteposto (ad es. -bashMentre normalmente lo sarebbe bash. Le shell di login in genere leggono un file che cose come l'impostazione delle variabili d'ambiente: /etc/profilee ~/.profileper la tradizionale shell Bourne, ~/.bash_profileinoltre per bash , /etc/zprofilee ~/.zprofileper zsh , /etc/csh.logine ~/.loginper csh, ecc.

Quando si accede a una console di testo, tramite SSH o con su -, si ottiene una shell di accesso interattiva . Quando si accede in modalità grafica (su un display manager X ), non si ottiene una shell di accesso, ma si ottiene un gestore sessioni o un gestore finestre.

È raro eseguire una shell di accesso non interattiva , ma alcune impostazioni X lo fanno quando si accede con un display manager, in modo da organizzare la lettura dei file del profilo. Altre impostazioni (questo dipende dalla distribuzione e dal display manager) le leggono /etc/profileed ~/.profileesplicitamente, o non le leggono. Un altro modo per ottenere una shell di accesso non interattiva è quello di accedere in remoto con un comando passato attraverso l'input standard che non è un terminale, ad esempio ssh example.com <my-script-which-is-stored-locally(al contrario di ssh example.com my-script-which-is-on-the-remote-machine, che esegue una shell non interattiva, non di accesso).

Quando si avvia una shell in un terminale in una sessione esistente (schermata, terminale X, buffer del terminale Emacs, shell all'interno di un'altra, ecc.), Si ottiene una shell interattiva senza accesso . Quella shell potrebbe leggere un file di configurazione della shell ( ~/.bashrcper bash invocato come bash, /etc/zshrce ~/.zshrcper zsh /etc/csh.cshrce ~/.cshrcper csh, il file indicato dalla ENVvariabile per shell conformi a POSIX / XSI come dash, ksh e bash quando invocato come sh, $ENVse impostato e ~/.mkshrcper mksh, ecc.).

Quando una shell esegue uno script o un comando passato sulla sua riga di comando, è una shell non interattiva e non di accesso . Tali shell funzionano sempre: è molto comune che quando un programma chiama un altro programma, esegua davvero un piccolo script in una shell per invocare quell'altro programma. Alcune shell leggono un file di avvio in questo caso (bash esegue il file indicato dalla BASH_ENVvariabile, zsh corre /etc/zshenve ~/.zshenv), ma questo è rischioso: la shell può essere invocata in tutti i tipi di contesti, e difficilmente c'è qualcosa che puoi fare che potrebbe non rompere qualcosa.

Sto semplificando un po ', vedi il manuale per i dettagli cruenti.


2
Potresti fare un esempio su come eseguire bashcome shell di login non interattiva?
Piotr Dobrogost,

13
@PiotrDobrogostecho $- | bash -lx
Gilles

1
Non so se questo sia vero in generale, ma voglio notare che quando apro un nuovo terminale (su osx usando le impostazioni predefinite), ottengo una shell di accesso anche se non scrivo mai il mio nome utente o password.
Kevin Wheeler,

4
@KevinWheeler Su OSX, per impostazione predefinita, l'applicazione Terminale esegue una shell di accesso. (Come spiego, il programma che avvia la shell decide se la shell funge da shell di login.) Questo non è il modo normale di fare le cose.
Gilles,

2
@IAmJulianAcosta Se FOOè una variabile d'ambiente (cioè .profilecontiene export FOO=something) è disponibile per tutti i sottoprocessi, incluso foo.sh. Se si cambia .profileper export FOO=something_elsepoi ./foo.shsarà ancora stampare somethingfino alla prossima volta che si accede.
Gilles

48

Per sapere se sei in una shell di login:

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.

In Bash puoi anche usare shopt login_shell:

prompt> shopt login_shell
login_shell     off

(o onin una shell di login).

Informazioni sono disponibili in man bash(cerca Invocazione). Ecco un estratto:

Una shell di login è quella il cui primo carattere dell'argomento zero è un -, oppure uno è iniziato con l'opzione --login.

Puoi provarlo tu stesso. Ogni volta che SSH, stai usando una shell di login. Per esempio:

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

L'importanza dell'uso di una shell di accesso è che tutte le impostazioni in /home/user/.bash_profileverranno eseguite. Ecco qualche informazione in più se sei interessato (da man bash)

"Quando bash viene invocato come shell di login interattiva o come shell non interattiva con l'opzione --login, legge ed esegue prima i comandi dal file / etc / profile, se quel file esiste. Dopo aver letto quel file, cerca i ~/.bash_profile, ~/.bash_logine ~/.profile, in questo ordine, e legge ed esegue comandi dal primo che esiste ed è leggibile. l'opzione --noprofile può essere utilizzato quando il guscio viene avviato per inibire questo comportamento."


23

In una shell di login, argv[0][0] == '-'. Ecco come sa che è una shell di login.

E poi in alcune situazioni si comporta in modo diverso a seconda del suo stato di "shell di accesso". Ad esempio una shell, che non è una shell di login, non eseguirà un comando "logout".


4
Secondo man bash, con l'enfasi aggiunta, "Una shell di login è quella il cui primo carattere dell'argomento zero è un -, o uno è iniziato con l'opzione --login " .
Wildcard

18

Una shell avviata in un nuovo terminale in una GUI sarebbe una shell interattiva senza accesso. Provocherebbe il tuo .bashrc, ma non il tuo .profile, per esempio.


4

Elaborerò la grande risposta di Gilles, combinata con il metodo di Timothy per controllare il tipo di shell di login.

Se ti piace vedere le cose da solo, prova i seguenti frammenti e scenari.

Verifica se la shell è (non) interattiva

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

Verifica se la shell è (non) login

Se l'output di echo $0inizia con -, è la shell di login ( echo $0esempio di output:) -bash. Altrimenti è shell non di accesso ( echo $0esempio di output:) bash.

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

Uniamo le due sopra insieme per ottenere entrambe le informazioni contemporaneamente:

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"

scenari:

Sessione SSH tipica senza opzioni speciali

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

Esecuzione di script o esecuzione esplicita tramite nuova shell

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

Esecuzione di script locali in remoto

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

Esecuzione di un comando su ssh da remoto

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

Esecuzione di un comando su ssh in remoto con -tswitch

È possibile richiedere esplicitamente la shell interattiva quando si desidera eseguire il comando in remoto tramite ssh utilizzando -tswitch.

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

Nota: sull'argomento perché l'esecuzione del comando in remoto non contiene login shellulteriori informazioni qui .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.