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 ?
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 ?
Risposte:
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. -bash
Mentre normalmente lo sarebbe bash
. Le shell di login in genere leggono un file che cose come l'impostazione delle variabili d'ambiente: /etc/profile
e ~/.profile
per la tradizionale shell Bourne, ~/.bash_profile
inoltre per bash † , /etc/zprofile
e ~/.zprofile
per zsh † , /etc/csh.login
e ~/.login
per 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/profile
ed ~/.profile
esplicitamente, 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 ( ~/.bashrc
per bash invocato come bash
, /etc/zshrc
e ~/.zshrc
per zsh /etc/csh.cshrc
e ~/.cshrc
per csh, il file indicato dalla ENV
variabile per shell conformi a POSIX / XSI come dash, ksh e bash quando invocato come sh
, $ENV
se impostato e ~/.mkshrc
per 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_ENV
variabile, zsh corre /etc/zshenv
e ~/.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.
bash
come shell di login non interattiva?
echo $- | bash -lx
FOO
è una variabile d'ambiente (cioè .profile
contiene export FOO=something
) è disponibile per tutti i sottoprocessi, incluso foo.sh
. Se si cambia .profile
per export FOO=something_else
poi ./foo.sh
sarà ancora stampare something
fino alla prossima volta che si accede.
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 on
in 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_profile
verranno 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_login
e~/.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."
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".
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 " .
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 $0
inizia con -
, è la shell di login ( echo $0
esempio di output:) -bash
. Altrimenti è shell non di accesso ( echo $0
esempio 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"
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
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
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
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
-t
switchÈ possibile richiedere esplicitamente la shell interattiva quando si desidera eseguire il comando in remoto tramite ssh utilizzando -t
switch.
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 shell
ulteriori informazioni qui .