Czy wpisanie innego polecenia w STDIN jest bezpieczne, gdy poprzednie polecenie zapisuje w STDOUT?


21

Być może już na to odpowiedziano, z przyjemnością powitam link do innej odpowiedzi ...

Jeśli wykonam polecenie powłoki (w bashpowłoce) w następujący sposób:

make

Wtedy, gdy odtwarzany makejest przez przewijanie z STDOUTtego makepolecenia, jeśli typ make checki naciśnij enterprzed pierwszym wykonaniem polecenia jest zakończone, gdy makepolecenie ostatecznie zakończy następnego polecenia make checkodbierze prawo i uruchomić.

Moje pytania są po prostu:

  1. Czy to niebezpieczne?
  2. Czy są jakieś potencjalne nieoczekiwane zachowania z tego rodzaju pisania w pośpiechu?
  3. Dlaczego to działa tak, jak działa?

2
1. Mam nadzieję, że to nie ... Robię to od lat!
John WH Smith

Odpowiedzi:


20

Działa tak, jak działa, ponieważ Unix ma pełny dupleks. Jak powiedział Ritchie Systemie dzielenia czasu UNIX: Retrospektywa :

Jedną rzeczą, która wydaje się trywialna, ale robi zaskakującą różnicę, gdy się do niej przyzwyczaimy, jest pełno-dupleksowy terminal I / O wraz z funkcją odczytu z wyprzedzeniem. Mimo że programy zazwyczaj komunikują się z użytkownikiem w kategoriach linii, a nie pojedynczych znaków, terminal I / O z pełnym dupleksem oznacza, że ​​użytkownik może pisać w dowolnym momencie, nawet jeśli system pisze ponownie, bez obawy utraty lub pomieszania znaków . Dzięki czytaniu z wyprzedzeniem nie trzeba czekać na odpowiedź na każdą linię. Dobra maszyna do pisania wchodząca w dokument staje się niezwykle sfrustrowana koniecznością pauzy przed rozpoczęciem każdej nowej linii; dla każdego, kto wie, co chce powiedzieć, każda spowolnienie w reakcji zostaje powiększone psychicznie, jeśli informacje muszą być wprowadzane krok po kroku zamiast z pełną prędkością.

[koniec cytatu]

To powiedziawszy, istnieją pewne nowoczesne programy, które pochłaniają lub odrzucają jakiekolwiek typy; sshi apt-getsą dwoma przykładami. Jeśli wpiszesz naprzód, gdy są uruchomione, może się okazać, że pierwsza część wpisu zniknęła. To może być problem.

ssh remotehost do something that takes 20 seconds
mail bob
Dan has retired. Feel free to save any important files and then do
# ssh exits here, discarding the previous 2 lines
rm -fr *
.

Czy po bash fork()s i execs pierwsze polecenie jest nadal dołączone do STDINpowłoki bash? Wygląda na to, że odpowiedź brzmi nie, bash wydaje się buforować następną komendę. Czy to jest poprawne?
111 ---

O ile nie powiesz powłoce, aby przekierowała stdin polecenia, polecenie będzie miało ten sam stdin co shell. Wszystko, co wpiszesz, jest odczytywane przez pierwszy proces, który to czyta. Powłoka celowo nie próbuje niczego odczytać, gdy polecenie jest uruchomione, i czeka, aż polecenie się zatrzyma. Sprawa staje się bardziej złożona, jeśli umieścisz polecenie w tle za pomocą &.
Mark Plotnick,

Więc jest STDINtraktowany w sposób fifo? I przypuszczam, że chyba że proces potomny basha jawnie zamyka odziedziczony uchwyt pliku, STDINto nadal mógłby czytać z dodatkowego pisania?
111 ---

Tak, wszystkie wejścia są obsługiwane przez FIFO. Nie jestem pewien, czy rozumiem twoje drugie pytanie. Proces potomny - polecenie, które wywołała powłoka - zwykle nie zamyka jawnie standardowego wejścia; powłoka wychodzi z drogi i pozwala komendzie czytać wszystko, czego chce, a następnie dziecko zatrzymuje się i powłoka wznawia czytanie.
Mark Plotnick

Tak, bardzo wyraźnie odpowiedziałeś na oba moje pytania uzupełniające, dzięki!
111 ---

12

Podstawowe zachowanie, które widzisz, polega na tym, że dane wejściowe znajdują się gdzieś w buforze, dopóki nie zostaną odczytane (cóż, jeśli wpiszesz wystarczająco dużo, w końcu bufory się zapełnią i coś zostanie utracone, to byłoby dużo pisania). Większość rzeczy uruchamianych przez make nie odczytuje ze STDIN, więc pozostaje w buforze.

Niebezpieczeństwo polega na tym, że niewłaściwe polecenie odczytuje dane wejściowe. Na przykład makewywołuje coś, co decyduje o wyświetleniu monitu, a następnie może odczytać następne polecenie jako odpowiedź. To, jak niebezpieczne jest to zależy oczywiście od polecenia. (Mogą również najpierw wyczyścić wszystkie dane wejściowe, po prostu odrzucając poprzednie dane).

Jednym z poleceń, powszechnie używanym w Makefiles, które może to zrobić, jest TeX. Jeśli napotka błąd (i nie otrzyma flagi, aby nigdy nie pytać użytkownika), wyświetli monit o kontynuację.

Lepszym rozwiązaniem jest chyba do biegu: make && make check.


8
  1. Cóż, oczywiście nie powinieneś uruchamiać drugiego polecenia, które zależy od makepomyślnego wykonania pierwszego polecenia ( w twoim przykładzie). Na przykład make foo Enter> ./foo Enter może powodować problem. Możesz spróbować przyzwyczaić się do pisania takich rzeczy, jak np. make && make checkGdzie drugie polecenie zostanie wykonane tylko wtedy, gdy pierwsze się powiedzie.
  2. Jest teoretycznie możliwe, że pierwsze polecenie (procesy) może odczytać część drugiego polecenia lub w inny sposób usunąć je z bufora wejściowego terminala. Gdyby zjadł sześć pierwszych znaków make check, skończyłbyś wykonywaniem polecenia heck, które prawdopodobnie nie istnieje w twoim systemie (ale może być czymś paskudnym). Jeśli pierwsze polecenie jest czymś łagodnym, co znasz i którym ufasz, nie widzę od razu żadnego problemu.
  3. Jak / dlaczego to działa? System buforuje dane z klawiatury. To trochę jak e-mail: możesz wysłać osobie pięć wiadomości w krótkim czasie, a oni będą siedzieć w jego skrzynce odbiorczej, czekając, aż je przeczyta. Podobnie, dopóki pierwsze polecenie nie odczytuje z klawiatury, polecenie (polecenia), które wpisujesz, będzie siedzieć i czekać, aż powłoka zacznie je czytać. Istnieje limit określający, ile „buforowania typu” można buforować, ale zwykle jest to kilkaset znaków (jeśli nie kilka tysięcy).

2
W punkcie 1 wyobraź sobie, że polecenia nie są ze sobą powiązane, tj. lsI mountna przykład. Próbuję zrozumieć, jak obsługiwane jest buforowane wejście. Dziękuję za odpowiedź.
111 ---
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.