Jaki jest cel opóźnionego zawieszenia (Ctrl-Y) w Bash?

30

Pełna część strony podręcznika użytkownika Bash, która ma zastosowanie, mówi tylko:

Jeśli system operacyjny, na którym działa bash, obsługuje kontrolę zadań, bash zawiera narzędzia do korzystania z niego. Wpisanie znaku wstrzymania (zazwyczaj ^ Z, Control-Z) podczas działania procesu powoduje, że proces ten zostaje zatrzymany i przywraca kontrolę do bash. Wpisanie znaku opóźnionego zawieszenia (zwykle ^ Y, Control-Y) powoduje zatrzymanie procesu, gdy próbuje on odczytać dane wejściowe z terminala, i sterowanie zostaje zwrócone do bash. Użytkownik może następnie manipulować stanem tego zadania, używając bg polecenia, aby kontynuować je w tlefgpolecenie, aby kontynuować na pierwszym planie, lub polecenie zabicia, aby go zabić. ^ Z zaczyna działać natychmiast i ma dodatkowy efekt uboczny, powodując odrzucenie oczekujących danych wyjściowych i typów.

Nigdy nie korzystałem Ctrl- Y; Właśnie się o tym dowiedziałem. Zrobiłem dobrze tylko z Ctrl- Z(zawiesić).

Próbuję sobie wyobrazić, co ta opcja jest dla . Kiedy to byłoby przydatne?

(Zauważ, że ta funkcja nie istnieje we wszystkich wariantach Uniksa. Jest obecna w Solarisie i FreeBSD, ale nie w Linuksie. Odpowiednie ustawienie to stty dsusp.)

Być może mniej subiektywnie: czy jest coś, co można osiągnąć Ctrl- Yczego nie da się osiągnąć równie łatwo Ctrl- Z?

Dzika karta
źródło
@Gilles, choć wydaje się, że FreeBSD ma stty dsusp, nie udało mi się wysłać SIGTSTP po ^ Y (zrobiłem na Solarisie). Czy ty?
Stéphane Chazelas,

Odpowiedzi:

23

Z podręcznika 4BSD dla csh :

A ^Zdziała natychmiast i jest jak przerwanie w oczekującym wyniku, a nieprzeczytane dane wejściowe są odrzucane po ich wpisaniu. Istnieje inny specjalny klucz, ^Yktóry nie generuje sygnału STOP, dopóki program nie spróbuje go odczytać (2). Można to z łatwością wpisać, gdy przygotujesz kilka poleceń dla zadania, które chcesz zatrzymać po ich przeczytaniu.

Dlatego celem jest wpisanie wielu danych wejściowych podczas przetwarzania pierwszego i zatrzymanie zadania po ich zakończeniu.

Losowo 832
źródło
Ten opis różni się nieznacznie od podręcznika bash. „... nie generuje sygnału STOP do momentu próby programu do czytania go. To brzmi jak wszystko w wejściu strumieniowo do^Y zostaną odczytane pomyślnie, a następnie, gdy ^Yjest trafiony proces zostanie zatrzymany. Czy czytam to prawda?
Wildcard
@Wildcard w moim teście na Mac OS X proces zostaje zatrzymany, zanim funkcja read () powróci (ale po wywołaniu read (), które zwróciło wykonanie Y), a po wznowieniu odbiera dane wejściowe sprzed ^ Y . Wydaje mi się, że skoro miał być używany, to byłby używany na początku linii, więc zachowanie w tym przypadku nie miałoby znaczenia. Podejrzewam, że w rzeczywistym kodzie jest zawieszony, gdy ^ Y zostałoby skopiowane do bufora odczytu procesu użytkownika.
Random832
Miałem rację, w funkcji ttread oryginalnego jądra BSD można to zobaczyć i we współczesnym OSX
Random832 16.09.16
Ale po wznowieniu procesu połączenie zakończy się powodzeniem i będzie zawierało dane wpisane wcześniej w terminalu ^Y, nawet jeśli wyrzekłeś się procesu i zamknąłeś terminal przed wznowieniem. Dobrze? ( „... po wznowieniu otrzymuje dane wejściowe sprzed ^ Y.” To właśnie miałem na myśli; zwykle nie zajmuję się kodem C.) :)
Wildcard
Tak. I wraca bez nowego wiersza na końcu, co jest niezwykłe w przypadku czytania w trybie kanonicznym [podobnie jak w przypadku wpisania tekstu i naciśnięcia ^ D raz] Podejrzewam, że nie zastanawiali się zbytnio o tej sprawie, ponieważ naprawdę jest przeznaczony do pisania na początku wiersza.
Random832
11

Powiedzmy, że istnieje wejście do odczytu i wykonywania w pętli. Przydatne może być pozostawienie zadania do zakończenia bieżącej instrukcji, którą oblicza, bez przerywania go, zanim wróci do wiersza poleceń w celu uzyskania nowej. Tak więc, aby zakończyć cykl. To z wdziękiem kończy pętlę i zapobiega jej ponownemu uruchomieniu, jeśli readjest ograniczona limitem czasu.

Tomasz
źródło
Ale jeśli to będzie próbować odczytać dane wejściowe z terminala W każdym razie, to zatrzymać w tym punkcie (i czekać na wejście) i można ^Zgo wtedy .
Wildcard,
Tak. Zobacz aktualizację.
Tomasz
Sprawdź jeszcze raz. @Wildcard
Tomasz
1
Ale jeśli upłynie limit czasu, czy nie skończy się również z gracją, jeśli nie zrobisz nic specjalnego?
Daniel Wagner,
1
Może. Ale może również trwać i wykonywać jakąś domyślną pracę.
Tomasz
4

Mogę wymyślić jeden scenariusz, w którym może być przydatny, ale jest to coś w rodzaju wymyślonego przypadku.

Załóżmy, że debugujesz skrypt zapisujący pliki tymczasowe, które chcesz przeanalizować, zanim zostaną usunięte w ramach procedury czyszczenia.

Możesz dodać read foogdzieś po zapisaniu plików (ale przed czyszczeniem), uruchom skrypt i naciśnij Ctrl- Ypodczas ich generowania. Nastąpi wyświetlenie monitu ze skryptem zawieszonym w tle, aby zrobić wszystko, co musisz zrobić, a następnie możesz fgpozwolić na zakończenie skryptu.

DopeGhoti
źródło
1
Wydaje się mało prawdopodobne, ponieważ skrypt i tak czeka na dane wejściowe. Możesz więc równie łatwo sprawdzić, czy monituje o podanie danych, a następnie zawiesić ^Z. Innymi słowy: po wpisaniu fgtrzeba będzie dać skrypt pewien wkład w każdym razie , zanim będzie ona kontynuowana. Stąd moje pytanie; Nadal nie widzę sensu ^Y. (Dziękuję za odpowiedź!) :)
Wildcard
2

Jedynym scenariuszem, jaki mogę wymyślić (a nawet nie uważam tego za bardzo przekonujące), jest to, że chcesz użyć polecenia typu polecenie z wyprzedzeniem. Powiedzmy, że uruchomione jest polecenie, które w przyszłości odczyta dane wejściowe. Następnie możesz ^ Y to, a następnie natychmiast wpisać następne polecenie powłoki, które chcesz wykonać, gdy uruchomione polecenie zawiesi się. Nie sądzę, że kiedykolwiek tak naprawdę używałem tego od kilku dekad używania BSD Unix.

Olaf Seibert
źródło