Co sprawdza [-t 1]?

Odpowiedzi:

14

[]jest skrótem testpolecenia.

Według man test:

-t FD
Prawda, jeśli FD jest deskryptorem pliku powiązanym z terminalem.

Jeśli więc uruchomisz bash jako interaktywną powłokę (terminal - objaśnienie terminologii znajdziesz w tym wątku), bash zostanie zastąpiony przez zsh.

Więcej informacji o plikach .bash *:

Kiedy 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_login i ~ / .profile, w tej kolejności, i odczytuje i wykonuje polecenia z pierwszego, który istnieje i jest możliwy do odczytu. Opcji --noprofile można użyć, gdy powłoka zostanie uruchomiona w celu zahamowania tego zachowania.

Po wyjściu z powłoki logowania bash czyta i wykonuje polecenia z plików ~ / .bash_logout i /etc/bash.bash_logout, jeśli pliki istnieją.

Po uruchomieniu interaktywnej powłoki, która nie jest powłoką logowania , bash czyta i wykonuje polecenia z ~ / .bashrc , jeśli plik istnieje. Można temu zapobiec, używając opcji --norc. Opcja --rcfile pliku zmusi bash do odczytu i wykonywania poleceń z pliku zamiast ~ / .bashrc.

Komentarz Stéphane Chazelas:
Zauważ, że powłoka może być interaktywna bez stdout jako terminala, a powłoka może być nieinteraktywna z terminalem na stdout (jak za każdym razem, gdy uruchamiasz skrypt w terminalu bez przekierowywania / przesyłania potokowego jego danych wyjściowych) i bashmoże czytać, .bashrcnawet gdy nie jest interaktywny (np. ssh host cmdgdzie bashznajduje się powłoka logowania użytkownika na hoście lub bash --login -c 'some code'). case $- in *i*)...jest poprawnym sposobem sprawdzenia, czy powłoka jest interaktywna.

mrc02_kr
źródło
4
Zauważ, że powłoka może być interaktywna bez stdout jako terminala, a powłoka może być nieinteraktywna z terminalem na stdout (jak za każdym razem, gdy uruchamiasz skrypt w terminalu bez przekierowywania / przesyłania potokowego danych wyjściowych), i bashmoże czytać, .bashrcnawet jeśli nie jest interaktywne (np. ssh host cmdgdzie bashznajduje się powłoka logowania użytkownika na hoście lub bash --login -c 'some code'gdzie .bash_profileźródła .bashrc). case $- in *i*)...jest poprawnym sposobem sprawdzenia, czy powłoka jest interaktywna.
Stéphane Chazelas
@ StéphaneChazelas dobry punkt. W odpowiedzi
zawrę
Istnieje wiele różnych definicji „interaktywnych”. Jeśli powłoka uważa, że jest interaktywna, izostanie ustawiona (i we współczesnych powłokach, które można przetestować ifzamiast używać case). Ale istnieje wiele przypadków użycia, w których obchodzi się tylko, jeśli stdout (lub stdin lub stderr ...) jest podłączony do terminala.
Mark Reed
9

Polecenie testowe [ -t 1 ] sprawdza, czy wyjście bash jest w terminalu. Celem tej linii jest oczywiście uruchomienie zsh podczas otwierania terminala, bez zakłócania innych zastosowań bash. Ale zrobiono to bardzo źle.

Plik .bashrcjest odczytywany w trzech okolicznościach:

  • Gdy bash jest wykonywany jako interaktywna powłoka, tj. Do uruchamiania poleceń wpisanych przez użytkownika, a nie do wykonywania poleceń wsadowych.
  • Gdy bash jest nieinteraktywną powłoką, która jest uruchamiana przez demona RSH lub SSH (zazwyczaj dlatego, że działasz ssh host.example.com somecommandi bash jest twoją powłoką logowania host.example.com).
  • Gdy jest wywoływany jawnie, np. U użytkownika .bash_profile( wybór plików startowych przez bash jest nieco dziwny ).

[ -t 1 ]jest złym sposobem wykrywania interaktywnych powłok. Możliwe jest, ale rzadko, uruchamianie basha interaktywnie ze standardowym wyjściem, który nie przechodzi do terminala. Częściej zdarza się, że standardowe wyjście trafia do terminala w nieinteraktywnej powłoce; nieinteraktywna powłoka nie działa, .bashrcale niestety powłoki bash wywoływane przez SSH do. Jest o wiele lepszy sposób: bash (i każda inna powłoka w stylu sh) zapewnia wbudowaną, niezawodną metodę tego.

case $- in
  *i*) echo this shell is interactive;;
  *) echo this shell is not interactive;;
esac

Dlatego należy napisać „uruchom zsh, jeśli jest to powłoka interaktywna”

case $- in
  *i*) exec zsh;;
esac

Ale nawet to nie jest dobry pomysł: zapobiega otwieraniu powłoki bash, co jest przydatne, nawet jeśli używasz zsh. Zapomnij o tym wpisie na blogu i zamiast tego skonfiguruj skrót otwierający terminal do uruchamiania zsh zamiast bash. Nie układaj rzeczy w taki sposób, aby „za każdym razem, gdy otworzysz aplikację Bash w systemie Windows, uruchomi się ona z powłoką Zsh”: kiedy chcesz zsh, otwórz aplikację Zsh.

Gilles „SO- przestań być zły”
źródło
Dla rsh/ sshi na interaktywnej powłoki, to czy to nie powłoka logowania. W przypadku powłok logowania ( sshdnie uruchamiałoby się nieinteraktywnej powłoki logowania, ale można to zrobić za pomocą ssh host exec bash -l), .bash_profileczytane jest zamiast. Zauważ też, że dla rsh/ ssh, musisz także $SHLVLbyć rozbrojony lub 0.
Stéphane Chazelas
5

test człowieka 1 :

-t FD

deskryptor pliku FD jest otwarty na terminalu

Twój przykład jest wykonywany (w tym przypadku zastępuje działający proces bash) przez zshon, jeśli stdout jest otwarty na terminalu (nie w pliku / potoku / itp.).

sebasth
źródło