Czy powłoka interaktywna może stać się nieinteraktywna lub odwrotnie?
Uwaga: Przeprowadziłem wiele badań dotyczących podstawowego pytania „Jaka jest różnica między interaktywnym a nieinteraktywnym?”, A wyniki moich badań skłoniły mnie do zadania tego pytania.
To pytanie ma długą preambułę, ponieważ kluczowe znaczenie ma to, jakiego rodzaju definicji używamy do określenia „interaktywny”, aby na nie odpowiedzieć. Definicja może być dowolną etykietą dla określonego zestawu; może opisywać różne właściwości; lub może dać ci informacje, których możesz użyć, aby przewidzieć zachowanie i zrozumieć cel. Ten ostatni typ możemy nazwać „definicją akcji” lub „definicją dynamiczną” i jest najbardziej przydatny.
W man 1p sh
podana jest następująca definicja interaktywnej powłoki:
If the -i option is present, or if there are no operands and the shell’s standard input and standard error are attached to a terminal, the shell is considered to be interactive.
Od wzmianki o „opcji -i” i użyciu słowa „operandy”, odnosi się to do wywołania powłoki , a nie atrybutów, które można zbadać w działającej powłoce.
Strona podręcznika użytkownika Bash wyraża to nieco inaczej:
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
Definicja w pierwszym zdaniu ponownie odnosi się tylko do początku powłoki.
Drugie zdanie (w moim czytaniu) określa warunki, które są używane jako proxy do ustalenia, czy powłoka została uruchomiona w określony sposób, który jest zdefiniowany jako „interaktywny”.
Zauważ, że ja nie interpretują to zdanie jako: „bash powłoka jest interaktywna wtedy i tylko wtedy $-
, zawiera«i»” $-
wydaje się po prostu przydatnym wskaźnikiem, a nie definicją interaktywnego. Ma to zasadnicze znaczenie dla mojego pytania.
Oba ( sh
definicja POSIX i Bash) są definicjami mechanicznymi, które określają, w jakich okolicznościach etykieta „interaktywna” dotyczy powłoki, którą uruchomiłeś. Nie są to definicje akcji, ponieważ nie dają żadnych implikacji tej etykiety.
Widzę jednak, że w pozostałej części strony podręcznika Bash są posypane odniesienia do powłoki zachowującej się w określony sposób „chyba, że jest to powłoka interaktywna” lub „tylko w powłokach interaktywnych lub jeśli ustawiona jest opcja _____”. (Istnieje wiele przykładów i to nie jest główny punkt tego pytania).
Przyjmuję więc do wiadomości, że „interaktywny” jest po prostu wygodną etykietą do zbioru domyślnych „interaktywnych” zachowań (ustawień opcji) opisanych na pozostałej stronie strony man. Sam w sobie nie jest podstawowym terminem ani przedmiotem; nie ma autorytatywnej definicji poza kodem źródłowym powłoki. (W przeciwieństwie do na przykład terminów „otwarty deskryptor pliku” lub „zatrzymany proces”, które odnoszą się do abstrakcji wbudowanych w projekt samego jądra.)
(Chociaż jest to również zdefiniowane w definicji POSIX sh
, ta strona man [ man 1p sh
] ma znacznie mniej zastosowań „chyba, że powłoka jest interaktywna” i podobnych instrukcji niż man bash
, i prawie wyłącznie skupia się na różnicach czasu wywołania, więc skupię się na Bash od tego momentu.)
Niektóre z implikacji, że powłoka jest „interaktywna”, i tak są istotne tylko w czasie wywołania , na przykład pliki, które są pozyskiwane przez powłokę przed odczytaniem innych poleceń. Jednak nie są implikacje (przynajmniej w Bash), które są istotne w każdej chwili. Dlatego musi istnieć sposób na określenie, dla dowolnej działającej powłoki, czy jest ona interaktywna czy nie.
Uruchomienie set +i
w interaktywnej powłoce Bash powoduje usunięcie „i” z zawartości $-
.
Pytanie brzmi: czy to faktycznie oznacza, że powłoka nie jest już interaktywna?
Dokładna definicja Basha nie powinna, ponieważ nigdzie w definicji nie jest wymagane, aby „i” występował w $-
:
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option.
Dokładne odczytanie dokładnej definicji rodzi również pytanie: jeśli przekierowanie stdin lub stderr terminala interaktywnego zostanie przekierowane, aby nie były już podłączone do terminali, to czy powłoka stanie się nieinteraktywna?
( Wygląda na to, że odpowiedź na to pytanie brzmi „nie”, a strona podręcznika mogła zawierać modyfikator: „którego standardowe wejście i błąd są podłączone do terminali ... w momencie wywołania ”, ale nie wiem ostatecznie.)
Jeśli odpowiedź brzmi: „Nie, powłoka nie może stać się nieinteraktywna ani odwrotnie”, to jaki jest ostateczny sposób ustalenia, czy powłoka jest interaktywna?
Mówiąc jeszcze inaczej: Jeśli istnieją zachowania „interaktywnej powłoki”, które utrzymują się po set +i
, to co jest używane do ustalenia, że te zachowania powinny nadal obowiązywać?
Aby ktokolwiek w to wątpił: istnieją zachowania powłoki wywoływane interaktywnie, które trwają po set +i
i zachowania powłoki wywoływane nieinteraktywnie, które utrzymują się później set -i
. Na przykład rozważ następujący fragment man bash
:
COMMENTS In a non-interactive shell, or an interactive shell in which the inter- active_comments option to the shopt builtin is enabled (see SHELL BUILTIN COMMANDS below), a word beginning with # causes that word and all remaining characters on that line to be ignored. An interactive shell without the interactive_comments option enabled does not allow comments. The interactive_comments option is on by default in interac- tive shells.
Tak więc, wyłączając tę interactive_comments
opcję, widzimy różnicę między powłokami interaktywnymi i nieinteraktywnymi. Trwałość tej różnicy pokazuje następujący skrypt:
#!/bin/bash
# When the testfile is run interactively,
# all three comments will produce an error
# (even the third where 'i' is not in '$-').
# When run noninteractively, NO comment will
# produce an error, though the second comment
# is run while 'i' IS in '$-'.
cat >testfile <<'EOF'
shopt interactive_comments
shopt -u interactive_comments
shopt interactive_comments
echo $-
#first test comment
set -i
echo $-
#second test comment
set +i
echo $-
#third test comment
EOF
echo 'running bash -i <testfile'
bash -i <testfile
echo 'running bash <testfile'
bash <testfile
Potwierdza to, że „interaktywne” i „ma i
wartość $-
„ nie są równoważne.
Podobny test ${parameter:?word}
z użyciem parametru nieustawionego daje podobne wyniki, ponownie potwierdzając, że $-
nie jest to „źródło prawdy” dla interaktywności powłoki.
Wreszcie, gdzie jest przechowywana ostateczna cecha „interaktywności” powłoki?
I czy interaktywna powłoka może stać się nieinteraktywna lub odwrotnie? (... zmieniając tę cechę?)
źródło
Odpowiedzi:
Pytanie, które zadałbym, brzmiałoby: dlaczego ktoś miałby to zrobić?
Możesz wyłączyć niektóre aspekty interaktywnych powłok, takie jak:
PS1= PS2=
aby wyłączyć monityset +m
aby wyłączyć kontrolę zadańzle
i wszystkie moduły ukończenia dozsh
.Ale jeśli chcesz, aby powłoka przestała być interaktywna, możesz zamiast tego:
Aby przekazać resztę poleceń
/some/file
(zamień na,/dev/tty
jeśli nadal chcesz, aby polecenia były odczytywane z urządzenia tty), choć nadal istnieją pewne różnice w stosunku do nieinteraktywnych powłok, na przykład zachowaniereturn
lub fakt że nadal będzie kontrolować pracę lub:Aby zastąpić bieżącą powłokę interaktywną powłoką nieinteraktywną, która nadal odczytuje polecenia z urządzenia tty.
Zauważ, że w przypadku bash 4.4,
set +i
zwraca zbash: set: +i: invalid option
podobnym w większości innych powłok.źródło
exec < <(sleep infinity)
w interaktywnej powłoce, masz interaktywną powłokę, która nie jest bardzo interaktywna. Powłoka nadal uważałaby się za interaktywną,$-
która zawierałabyi
, ale może nie. Nie jestem pewien, czy jest o wiele więcej do omówienia.interactive
, pozostanie taka. Fakt, że można to zrobićset +i
w starszych wersjach bash, był błędem.bash
, prawdopodobnie zauważysz, że istniejeinteractive
globalna zmienna boolowska, która jest odwzorowana nai
flagę$-
. Zmiana wartości logicznej nie spowoduje automatycznej zmiany wszystkich zachowań interaktywnych powłok. Zmiana z interaktywnej na nieinteraktywną nie jest obsługiwana.set +i
i przestaje wyświetlać monit. Jest to coś, czego użytkownik nie powinien robić, więc nie jest zaskakujące, że zachowanie zależy od powłoki i często jest przypadkowe, a nie wynikiem świadomej decyzji implementatora powłoki.