Etkileşimli bir kabuk etkileşimli olmayabilir veya tersi olabilir mi?


16

Etkileşimli bir kabuk etkileşimli olmayabilir veya tersi olabilir mi?

Not: "İnteraktif ve interaktif olmayanlar arasındaki fark nedir?" Temel sorusu hakkında çok fazla araştırma yaptım ve araştırmamın sonuçları beni bu soruyu sormaya yöneltti.

Bu sorunun kısmen uzun bir önsözü vardır, çünkü cevaplamak için "interaktif" için ne tür bir tanım kullandığımız çok önemlidir . Bir tanım, belirli bir küme için rastgele bir etiket olabilir; çeşitli özellikleri tanımlayıcı olabilir; veya size davranışı tahmin etmek ve amacı anlamak için kullanabileceğiniz bilgiler verebilir . Bu son türe "eylem tanımı" veya "dinamik tanım" diyebiliriz ve en faydalı olanıdır.


'De man 1p sh, aşağıdaki etkileşimli kabuğun tanımı verilmiştir:

   If the -i option is present, or  if  there  are  no  operands  and  the
   shells  standard  input and standard error are attached to a terminal,
   the shell is considered to be interactive.

"-İ seçeneği" ifadesinden ve "işlenenler" kelimesinin kullanılmasından bu, çalışan bir kabukta incelenebilecek niteliklerden değil , bir kabuğun çağrılması anlamına gelir.

Bash man sayfası bunu biraz farklı ifade eder:

   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.

İlk cümledeki tanım yine sadece bir kabuğun başlangıcını ifade eder .

İkinci cümle (okumamda) , kabuğun "etkileşimli" yapması olarak tanımlanan belirli yollarla başlatılıp başlatılmadığını belirlemek için vekil olarak kullanılan koşulları tanımlar .

O Not ben do not olarak bu cümleyi yorumlamak: "Bir bash kabuk eğer etkileşimli ve ancak $-. 'İ' içeren" etkileşimli $-bir tanım değil, sadece kullanışlı bir gösterge gibi görünüyor . Bu benim sorumla çok ilgili.


Bunların her ikisi de (POSIX shtanımı ve Bash), "interaktif" etiketinin hangi koşullarda başlattığınız bir kabuk için geçerli olduğunu belirten mekanik tanımlardır. Bu etiketin herhangi bir anlamını vermedikleri için eylem tanımları değildirler .

Ancak, Bash man sayfasının geri kalanında, "etkileşimli bir kabuk olmadıkça" veya "yalnızca etkileşimli kabuklarda veya _____ seçeneği ayarlanmışsa" belirli şekillerde davranan kabuğa atılan referanslar olduğunu görüyorum. (Çok sayıda örnek var ve bu sorunun ana konusu bu değil.)

Bu yüzden "interaktif" in, man sayfasının geri kalanında açıklanan varsayılan "interaktif" davranışların (seçenek ayarları) toplanması için uygun bir etiket olduğunu kabul edeceğim. Bu kendi içinde temel bir terim ya da nesne değildir; kabuğun kaynak kodunun dışında yetkili bir tanımı yoktur. (Örneğin, çekirdeğin tasarımında yerleşik soyutlamaları ifade eden "açık dosya tanımlayıcı" veya "durdurulmuş işlem" terimlerinin aksine).

(POSIX tanımında da tanımlanmış olsa da sh, bu man sayfasının [ man 1p sh] "kabuk etkileşimli olmadıkça" ve benzer ifadelerden çok daha az kullanımı man bashvardır ve neredeyse tamamen çağırma zamanı farklılıklarına odaklanır, bu yüzden Bash'a odaklanacağım bu noktadan itibaren.)


Bir kabuğun "etkileşimli" olmasının bazı etkileri, yalnızca diğer komutları okumadan önce hangi dosyaların kabuk tarafından kaynaklandığı gibi çağırma zamanında ilişkilidir . Ancak, orada olan herhangi bir zamanda alakalı (en azından Bash) etkileri. Bu nedenle, herhangi bir çalışan kabuk için etkileşimli olup olmadığını anlamanın bir yolu olmalıdır .

Çalıştırma set +iinteraktif Bash kabuğu 'i' içeriklerinden, uzaklaştırılmasına neden olmaktadır $-.

Soru şu: Bu aslında kabuğun artık etkileşimli olmadığı anlamına mı geliyor?

Bash'in kesin Tanım olarak, bu , olmamalı hiçbir yerde tanımında beri olduğu o gerekli o 'i' olmak hediyesi $-:

   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.

Kesin tanımın sıkı bir şekilde okunması da şu soruyu gündeme getirir: Etkileşimli bir terminalin stdin veya stderr'ı artık terminallere bağlı olmayacak şekilde yönlendirilirse, kabuk etkileşimli olmaz mı?

(Bunun cevabının "hayır" olduğu ve man sayfasının değiştirici ekleyebileceği anlaşılıyor : "standart girişi ve hatası hem terminallere bağlı ... hem de çağrılma anında " ama bilmiyorum kesin.)


Eğer cevap, "Hayır, bir kabuk etkileşimli olmayan olamaz, ne de tersi," o zaman ne kesin kabuk etkileşimli olup olmadığını belirlemek için bir yol?

Başka bir deyişle , sonradan devam eden bir "etkileşimli kabuğun" davranışları varsa , bu davranışların uygulanmaya devam etmesi gerektiğini belirlemek için ne kullanılır ?set +i


Diye kimse şüphe onu: Orada olan bir kabuk davranışları sonra kalıcı olan etkileşimli çağrılan set +ive bir kabuğun davranışları olmayan etkileşimli sonra devam hangi çağrılan set -i. Örnek olarak, aşağıdaki alıntıyı göz önünde bulundurun 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.

Böylece interactive_commentsseçeneği ayarlayarak etkileşimli ve etkileşimli olmayan mermiler arasındaki farkı görebiliriz. Bu farkın kalıcılığı aşağıdaki komut dosyası tarafından gösterilmiştir:

#!/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

Bu, "etkileşimli" ve " ideğerinin $-" değerinde eşdeğer olmadığını doğrular .

${parameter:?word}Unset parametresiyle kullanılan benzer bir test benzer sonuçlar üretir ve yine $-kabuk etkileşimi için "gerçeğin kaynağı" olmadığını doğrular.


Son olarak, bir kabuğun kesin 'interaktiflik' özelliği nerede saklanıyor?

Ve etkileşimli bir kabuk etkileşimli olmayabilir veya tersi olabilir mi? (... bu özelliği değiştirerek mi?)


Yanıtlar:


9

Sorduğum soru neden bunu yapmak isteyesiniz ki?

Etkileşimli kabukların bazı yönlerini devre dışı bırakabilirsiniz:

  • PS1= PS2= istemleri devre dışı bırakmak için
  • set +m iş kontrolünü devre dışı bırakmak
  • bazı kabuklarda geçmişi devre dışı bırak
  • zleve içindeki tüm tamamlama modüllerini kaldırabilirsiniz zsh.

Ancak kabuğun etkileşimli olarak durmasını istiyorsanız, şunları yapabilirsiniz:

. /some/file; exit

Komutların geri kalanını almasını söylemek için /some/file( komutların /dev/ttyhala tty cihazından okunmasını istiyorsanız değiştirin ), ancak yine de etkileşimli olmayan kabuklardan davranış returnveya gerçek gibi bazı farklılıklar olabilir. hala iş kontrolü yapacağını veya:

exec myshell /dev/tty

Geçerli etkileşimli kabuğunuzu, tty aygıtından hala komutları okuyan etkileşimli olmayan bir kabukla değiştirmek için.

Bash 4.4 set +iile bash: set: +i: invalid optiondiğer kabuklarda benzer bir değerle geri döndüğünü unutmayın .


Kesinlikle bunun saçma bir şey olacağına karar verdiler . Bahsettiğim gibi "interaktif" kavramım, kabuğunuzla etkileşime girdiğinizde yararlı olan varsayılan davranışların bir koleksiyonudur . Bu davranışların her birini ayrı ayrı değiştirebilir ve her birini değiştirirseniz, "Hala etkileşimli bir kabuk mu?" sadece saçma bir anlambilimdir; önemli bir soru bile değil. Ancak ....
Wildcard

1
@Wildcard, exec < <(sleep infinity)etkileşimli bir kabukta yaparsanız, çok etkileşimli olmayan bir etkileşimli kabuğunuz var. Kabuk hala kendisini $-içerecek olan etkileşimli olarak düşünür i, ancak olmayabilir. Tartışacak çok şey olduğundan emin değilim.
Stéphane Chazelas

2
@Wildcard, kabuk olarak başlatılmışsa interactive, öyle kalır. set +iEski bash versiyonlarında yapabileceğiniz bir hataydı.
Stéphane Chazelas

1
@Wildcard, Eğer kaynak koduna bakarsanız, bashbüyük olasılıkla bayrağını interactiveeşleyen küresel bir boole değişkeni olduğunu göreceksiniz . Bu booleanın değiştirilmesi, etkileşimli kabukların tüm davranışlarını otomatik olarak değiştirmez. İnteraktiften interaktif olmayana geçiş desteklenmez. i$-
Stéphane Chazelas

4
@Wildcard Dash, set +ibir istem görüntülemeyi kabul eder ve durdurur. Bu, kullanıcının yapmaması gereken bir şeydir, bu nedenle davranışın kabuğa bağlı olması ve kabuk uygulayıcısı tarafından kasıtlı bir kararın sonucu olmaktan ziyade kazara olması şaşırtıcı değildir.
Gilles 'SO- kötü olmayı bırak'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.