Jak sprawdzić, czy powłoka jest login / Interactive / Batch


143

Wydaje mi się, że rozumiem różnice między interaktywną, login i powłoką wsadową. Aby uzyskać pomoc, zobacz następujące łącza:

Moje pytanie brzmi: w jaki sposób mogę przetestować polecenie / warunek, jeśli korzystam z powłoki interaktywnej, logowania lub powłoki wsadowej?

Szukam polecenia lub warunku (które zwraca truelub false) i które mógłbym również umieścić w instrukcji if. Na przykład:

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

3
Jest jeszcze inne pytanie: czy STDIN i / lub STDOUT są podłączone do tty (terminal) lub potoku (plik lub proces)? Jest to powiązany, ale odrębny test, jak opisano w niektórych z poniższych komentarzy.
Mark Hudson,

Odpowiedzi:


160

Przyjmuję bashpowłokę lub podobną, ponieważ w tagach nie ma powłoki.

Aby sprawdzić, czy jesteś w interaktywnej powłoce:

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

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

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

Przez „partię” zakładam, że masz na myśli „nieinteraktywny”, więc sprawdzenie interaktywnej powłoki powinno wystarczyć.


12
W przypadku zshużytkowników sprawdzanie powłoki logowania można wykonać za pomocą:if [[ -o login ]] ...
chb

1
Jeśli chcesz wiedzieć, czy „użytkownik” uruchomił Twój program w porównaniu z „cron”. [[TERM == "głupi"]] && echo "Uruchamianie w cron.
Erik Aronesty,

10
@ErikAronesty Nie wszystkie głupie terminale to sesje cron.
Chris Down,

2
„Przyjmuję powłokę bash lub podobną, ponieważ w tagach nie ma powłoki.” - Logika tego stwierdzenia jest naprawdę piękna! :)
Michael Le Barbier Grünewald

2
@antonio To dlatego, że twoje cytowanie jest błędne, $-jest rozwijane w bieżącej powłoce. Jeśli użyjesz pojedynczych cudzysłowów wokół pełnego wyrażenia, otrzymasz poprawny wynik:bash -c '[[ $- == *i* ]] && echo "Interactive" || echo "Not interactive"'
Chris Down

33

W dowolnej powłoce typu Bourne'a iopcja wskazuje, czy powłoka jest interaktywna:

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

Nie ma przenośnego iw pełni niezawodnego sposobu przetestowania powłoki logowania. Ksh i zsh dodają ldo $-. Bash ustawia login_shellopcję, za pomocą której można wykonać zapytanie shopt -q login_shell. Przenośnie, sprawdź, czy $0zaczyna się od -: powłoki zwykle wiedzą, że są to powłoki logowania, ponieważ program wywołujący dodał -prefiks do argumentu zero (zwykle nazwa lub ścieżka pliku wykonywalnego). Nie wykrywa to specyficznych dla powłoki sposobów wywoływania powłoki logowania (np ash -l.).


(...) ponieważ dzwoniący - myślę, że w tym fragmencie czegoś brakuje.
Piotr Dobrogost

Byłoby idealnie, gdyby $0zawsze zaczynał się -bez względu na to, jak się zaczął. Ale jest co najmniej jeden wyjątek: nie zawsze jest to prawdą w przypadku bash, nawet jeśli ma to być powłoka logowania. Wypróbuj w swoim pudełku: wywołaj bash --login, a następnie $0nadal czyta bash.
Wirawan Purwanto

@WirawanPurwanto Nie jestem pewien, czy rozumiem twój komentarz. Czy nie to napisałem w ostatnim zdaniu?
Gilles

@Gilles: Masz rację. Przepraszam, że przegapiłem twoje ostatnie zdanie.
Wirawan Purwanto

24

skorupa ryby

Oto odpowiedź na fishwypadek, gdyby inni użytkownicy natknęli się na tę stronę.

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"

Dokumentacja ryb: inicjalizacja


1
-1 za niepotrzebną redakcję.
Nick Bastin,

6
Jeśli ktoś zastanawia się nad komentarzem @ NickBastin, miał rację, więc dokonałem edycji. Pierwotna wstrętność została teraz zmniejszona o połowę.
ohspite

18

csh / tcsh

Do cshi tcshmam w swoim .cshrcpliku:

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

W szczególności dla tcshzmiennej loginshustawiana jest powłoka logowania:

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

( tcshma również zmienną shlvlustawioną na liczbę zagnieżdżonych powłok, przy czym powłoka logowania ma wartość 1.)


2
PS1nie działa w celu przetestowania interaktywnej powłoki. Prawie zawsze jest ustawiony na interaktywny, ale możesz go rozbroić. To bardzo często się w nieinteraktywnym powłoki, ponieważ wiele systemów statku z export PSw /etc/profile.
Gilles

@Gilles Dziękujemy za korektę i edycję
Andrew Stein,

17

Innym sposobem jest sprawdzenie wyniku tty

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

10
... lub użyj, [ -t 0 ]aby sprawdzić, czy STDIN jest tty. Możesz także użyć 1 (STDOUT) lub 2 (STDERR) w zależności od potrzeb.
derobert

@derobert - dzięki za pokazanie mi czegoś nowego
Adrian Cornish,

10
To jest inny test. Możliwe jest posiadanie nieinteraktywnej powłoki, której wejściem jest terminal (za każdym razem, gdy uruchamiasz skrypt w terminalu!), I możliwe jest (choć rzadko), że interaktywna powłoka pobiera dane wejściowe nie z terminala.
Gilles

@Gilles, jeśli powłoka była interaktywna i zamknięta, pozostawiając dziecko disowni żywe, ttydziałała najlepiej, aby wiedzieć, że nie jest już interaktywna, chociaż $-się nie zmieniła; Nadal zastanawiam się, jakie jest najlepsze podejście.
Aquarius Power

5
@AquariusPower To, co chcesz przetestować, nie dotyczy interaktywnej powłoki, ale czy standardowe wejście jest terminalem. Użyj [ -t 0 ]. PS W moim poprzednim komentarzu napisałem, że „istnieje silna korelacja” - zapomniałem „oprócz niezwykle powszechnego przypadku skryptu, który zaczął się od #!/bin/shlub podobnego”, który nie jest interaktywny, ale można go podłączyć do terminala.
Gilles

8

UNIX / Linux ma polecenie sprawdzające, czy korzystasz z terminala.

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

1
To działa dashrównież w.
Ken Sharp

7

Możesz sprawdzić, czy stdin jest terminalem:

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


1

inie jest właściwą opcją do wyszukiwania. -ijest wymuszenie, by w przeciwnym razie nieinteraktywna powłoka stała się interaktywna. Prawidłowa opcja automatycznego włączania to -s, ale Bash niestety nie obsługuje tego poprawnie.

Musisz sprawdzić, czy $-zawiera s(jest to przyznane w celu automatycznej aktywacji) lub czy zawiera i(nie jest to przyznane w celu automatycznej aktywacji, ale oficjalnie jest sprzężone tylko z -iopcją wiersza poleceń powłoki).


1
sbyłoby, gdyby powłoka odczytywała polecenia ze standardowego wejścia, a nie czy jest interaktywna. Interaktywna powłoka niekoniecznie odczytuje polecenia ze standardowego wejścia (spróbuj zsh -i < /dev/null, choć zsh wydaje się tutaj wyjątkiem). Powłoka może odczytywać polecenia ze standardowego wejścia i nie może być interaktywna (jak sh < filelub echo 'echo "$1"' | sh -s foo bar).
Stéphane Chazelas,

2
Chciałem zwrócić uwagę na to, że oryginalny Bourne Shell nie ma „i” w $ - nawet jeśli ma być interaktywny.
schily,

OK, ale w U&L „shell” zwykle odnosi się do nowoczesnych powłok. Powłoka Bourne'a jest ogólnie uważana za reliktę, a twój własny wariant nie jest na tyle popularny, aby oczekiwać od ludzi wiedzy o tym, o czym mówisz, chyba że wyrazisz to wyraźnie. Wspomniane pytanie, [[...]]które sugeruje ksh / bash / zsh. Masz punkt jako nutą historii , że sprawdzanie iIN $-nie będzie działać w powłoce Bourne'a. Ale sprawdzanie, sczy też tam nie działa. Chciałbyś również sprawdzić, [ -t 0 ]czy i; nawet wtedy byłoby to echo 'exec < /dev/tty; that-check' | sh'
oszukane

Solaris do Solaris 10 są dostarczane z oryginalną powłoką Bourne Shell, a nawet parapet zawiera ok. 10 błędów znanych z powłoki od SVr4. Tak więc dodanie podpowiedzi do Skorupy Bourne'a nie jest kapryśne, jak można by wierzyć. Zsh po drugiej stronie nie jest wystarczająco kompatybilny, np. kończy się niepowodzeniem, gdy próbujesz uruchomić „config” z zsh, więc uważaj, aby ustawić / bin / sh, aby wskazywał na zsh. BTW: moja Bourne Shell domyślnie ustawia -i na wypadek, gdyby zdecydowała się być interaktywna.
schily

3
Zauważyłem, że POSIX nie wymaga $ - zawiera i (co wydaje się wymagać s), zadam pytanie o ML grupy austin.
Stéphane Chazelas,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.