Come verificare se una shell è login / interattivo / batch


145

Penso di comprendere le differenze tra una shell interattiva, un login e una batch. Vedere i seguenti collegamenti per ulteriori informazioni:

La mia domanda è: come posso testare con un comando / condizione se mi trovo su una shell interattiva, di accesso o batch?

Sto cercando un comando o una condizione (che ritorna trueo false) e che potrei anche inserire in un'istruzione if. Per esempio:

if [[ condition ]]
   echo "This is a login shell"
fi

3
C'è ancora un'altra domanda: STDIN e / o STDOUT sono collegati a un tty (terminale) o una pipe (file o processo)? Questo è un test correlato ma distinto, come descritto in alcuni dei commenti seguenti.
— Mark Hudson,

Risposte:


162

Sto assumendo una bashshell, o simile, dal momento che non c'è nessuna shell elencata nei tag.

Per verificare se ci si trova in una shell interattiva:

[[ $- == *i* ]] && echo 'Interactive' || echo 'Not interactive'

Per verificare se ci si trova in una shell di accesso:

shopt -q login_shell && echo 'Login shell' || echo 'Not login shell'

Per "batch", suppongo che intendi "non interattivo", quindi il controllo per una shell interattiva dovrebbe essere sufficiente.


12
Per gli zshutenti, è possibile verificare la presenza di una shell di accesso con:if [[ -o login ]] ...
— chb,

1
Se vuoi sapere se un "utente" ha eseguito il tuo programma contro "cron". [[TERM == "dumb"]] && echo "In esecuzione in cron.
— Erik Aronesty,

10
@ErikAronesty Non tutti i terminali stupidi sono sessioni cron.
— Chris Down,

2
"Sto assumendo una shell bash, o simile, dal momento che non esiste alcuna shell elencata nei tag." - La logica di questa affermazione è davvero meravigliosa! :)
— Michael Le Barbier Grünewald,

2
@antonio Questo perché il tuo preventivo è sbagliato, $-viene espanso nella shell corrente. Se usi le virgolette singole intorno all'espressione completa otterrai il risultato corretto:bash -c '[[ $- == *i* ]] && echo "Interactive" || echo "Not interactive"'
— Chris Down

33

In qualsiasi shell in stile Bourne, l' iopzione indica se la shell è interattiva:

case $- in
  *i*) echo "This shell is interactive";;
  *) echo "This is a script";;
esac

Non esiste un modo portatile e completamente affidabile per testare una shell di accesso. Ksh e zsh si aggiungono la $-. Bash imposta l' login_shellopzione, con cui è possibile eseguire una query shopt -q login_shell. Portabilmente, verifica se $0inizia con a -: le shell normalmente sanno di essere shell di login perché il chiamante ha aggiunto un -prefisso all'argomento zero (normalmente il nome o il percorso dell'eseguibile). Questo non riesce a rilevare modi specifici della shell di invocare una shell di login (ad es ash -l.).


(...) perché il chiamante - penso che manchi qualcosa in questo frammento.
— Piotr Dobrogost,

Sarebbe l'ideale se $0inizia sempre con -non importa come è stato avviato. Ma c'è almeno un'eccezione: questo non è sempre vero con bash anche se si suppone che sia una shell di login. Provalo nella tua scatola: invoca bash --login, poi $0legge ancora bash.
— Wirawan Purwanto,

@WirawanPurwanto Non sono sicuro di aver capito il tuo commento. Non è quello che ho scritto nella mia ultima frase?
— Gilles,

@Gilles: hai ragione. Scusa, ho perso la tua ultima frase.
— Wirawan Purwanto,

24

conchiglia di pesce

Ecco la risposta fishnel caso in cui altri utenti si imbattessero in questa pagina.

if status --is-interactive
    # ...
end

if status --is-login
    # ...
end

echo "darn, I really wanted to have to use globs or at least a case statement"

Documentazione sui pesci: inizializzazione


1
-1 per editoria non necessaria.
— Nick Bastin,

6
Se qualcuno si domanda al commento di @ NickBastin, ha avuto un buon punto, quindi ho fatto una modifica. La quantità originale di snarkiness è stata ora dimezzata.
— oh

18

csh / tcsh

Per cshe tcshho il seguente nel mio .cshrcfile:

if($?prompt) then               # Only interactive shells set $prompt
    ...
endif

In particolare per tcsh, la variabile loginshè impostata per una shell di login:

if($?loginsh) then              # A login shell..
    ...
endif

( tcshha anche una variabile shlvlche è impostata sul numero di shell nidificate, dove la shell di login ha un valore di 1.)


2
PS1non funziona per testare una shell interattiva. È quasi sempre impostato in modo interattivo, ma è possibile annullarlo. Molto spesso è impostato in una shell non interattiva, perché molti sistemi vengono forniti con export PSin /etc/profile.
— Gilles,

@Gilles Grazie per la correzione e la modifica
— Andrew Stein,

17

Un altro modo è verificare il risultato di tty

if [ "`tty`" != "not a tty" ]; then

10
... oppure usa [ -t 0 ]per verificare se STDIN è un valore. Puoi anche usare 1 (STDOUT) o 2 (STDERR) in base alle tue esigenze.
— derobert,

@derobert - grazie per avermi mostrato qualcosa di nuovo
— Adrian Cornish,

10
Questo è un test diverso. È possibile avere una shell non interattiva il cui input è un terminale (ogni volta che si esegue uno script in un terminale!), Ed è possibile (anche se raro) avere una shell interattiva che prende input non da un terminale.
— Gilles,

@Gilles se la shell era interattiva e chiusa lasciando un bambino disownvivo, ttyfunzionava meglio per sapere che non era più interattiva, mentre $-non cambiava; Sono ancora perplesso su quale sia l'approccio migliore.
— Aquarius Power il

5
@AquariusPower Quindi quello che vuoi testare non è per una shell interattiva, ma se l'input standard è un terminale. Usa [ -t 0 ]. PS Nel mio precedente commento, ho scritto che "esiste una forte correlazione" - ho dimenticato "a parte il caso estremamente comune di uno script iniziato con #!/bin/sho simili", che non è interattivo ma può essere collegato a un terminale.
— Gilles,

8

UNIX / Linux ha un comando per verificare se ci si trova su un terminale.

if tty -s
then
echo Terminal
else
echo Not on a terminal
fi

1
Questo funziona dashanche in.
— Ken Sharp,

7

Puoi verificare se stdin è un terminale:

if [ -t 0 ]
then
    echo "Hit enter"
    read ans
fi

3

Per verificare se uno script viene eseguito in una shell interattiva o non interattiva, controllo nei miei script la presenza di un prompt memorizzato nella $PS1variabile:

if [ -z $PS1 ] # no prompt?
### if [ -v PS1 ]   # On Bash 4.2+ ...
then
  # non-interactive
  ...
else
  # interactive
  ...
fi

Questo l'ho imparato qui: https://www.tldp.org/LDP/abs/html/intandnonint.html


1

inon è l'opzione corretta da cercare. -iè forzare una shell altrimenti non interattiva a diventare interattiva. L'opzione auto-abilitata corretta è -s, ma purtroppo Bash non la gestisce correttamente.

È necessario verificare se $-contiene s(questo è concesso per essere attivato automaticamente) o se contiene i(questo non è concesso per essere attivato automaticamente ma ufficialmente accoppiato solo con l' -iopzione della riga di comando della shell).


1
ssarebbe se la shell legge i comandi da stdin, non se è interattiva. Una shell interattiva non legge necessariamente i comandi di stdin (prova zsh -i < /dev/null, anche se qui zsh sembra essere l'eccezione). E una shell può leggere comandi da stdin e non essere interattiva (come sh < fileo echo 'echo "$1"' | sh -s foo bar).
— Stéphane Chazelas,

2
Quello che volevo sottolineare è che l'originale Bourne Shell non ha "i" in $, anche quando è inteso essere interattivo.
— schily,

OK, ma su U&L, "shell" tende a riferirsi a shell moderne . La shell Bourne è generalmente considerata un relitto e la tua variante non è abbastanza mainstream da aspettarti che le persone sappiano di cosa stai parlando a meno che non lo rendi esplicito. La domanda menzionata [[...]]che implica ksh / bash / zsh. Hai un punto come nota storica che il check- iin $-non funzionerà nella shell Bourne. Ma poi anche il controllo per snon funzionerà in modo affidabile. Vorresti anche controllare per [ -t 0 ]o i; anche allora sarebbe stato ingannato in casi d'angolo comeecho 'exec < /dev/tty; that-check' | sh'
— Stéphane Chazelas il

Solaris fino a Solaris 10 viene fornito con l'originale Bourne Shell e anche il davanzale include aprox. 10 bug noti per essere nella shell da SVr4. Quindi aggiungere un suggerimento su Bourne Shell non è un cappello subdolo come si potrebbe credere. zsh dall'altro lato non è sufficientemente compatibile, ad esempio non riesce quando si tenta di eseguire "configura" con zsh, quindi attenzione a impostare / bin / sh per puntare a zsh. A proposito: la mia Bourne Shell imposta -i di default nel caso in cui decida di essere interattivo.
— schily,

3
Ho notato che POSIX non sembra richiedere $ - contiene i (che sembra richiedere s), solleverò la domanda sull'ML del gruppo austin.
— Stéphane Chazelas,
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.