Dlaczego niektóre polecenia „zawieszają” terminal, dopóki nie skończą?


22

Czasami uruchamiasz program z terminala, powiedzmy lxpanel . Terminal nie odeśle cię z powrotem do monitu, zawiesi się. Możesz nacisnąć Ctrl+, Caby wrócić do monitu, ale to zabije lxpanel. Jednak naciśnięcie Alt+ F2(które wyskakuje okno, aby wykonać polecenie) i uruchomienie lxpaneldziała z wdziękiem.

Dlaczego to? Czym różni się uruchamianie polecenia z terminala i od okna „uruchom”, które pojawia się po naciśnięciu Alt+ F2?

lxpanel został tutaj użyty jako przykład. Doświadczyłem tego z wieloma programami


1
Wskazówka: GNU Screen ( screen) może między innymi służyć do „zawijania” dłuższych procesów. Możesz się od niego odłączyć, wracając do powłoki, a następnie ponownie podłączyć i zobaczyć dane wyjściowe z uruchomionego procesu. Ponowne podłączenie można wykonać nawet z innego terminala, SSH itp. Mogą też istnieć inne programy, które pozwalają ci robić takie rzeczy.
poplitea

Odpowiedzi:


28

Domyślnie terminal uruchomi program na pierwszym planie, więc nie skończysz w powłoce, dopóki program się nie zakończy. Jest to przydatne dla programów, które czytają ze standardowego wejścia i / lub zapisują na standardowe wyjście - generalnie nie chcesz, aby wiele z nich działało jednocześnie. Jeśli chcesz, aby program działał w tle, możesz uruchomić go w następujący sposób:

$ lxpanel &

Lub jeśli już działa, możesz go zawiesić za pomocą Ctrl+, Za następnie uruchomić, bgaby przenieść go w tło. Tak czy inaczej skończy się nowy monit powłoki, ale program nadal działa, a jego dane wyjściowe pojawią się w terminalu (więc może nagle pojawić się, gdy jesteś w trakcie pisania)

Niektóre programy (zwykle demony) rozwidlają osobny proces podczas uruchamiania, a następnie pozwalają procesowi głównemu natychmiast wyjść. Dzięki temu program będzie działał bez blokowania powłoki


Co właściwie robi system, gdy uruchamiasz program za pomocą okna „uruchom”, naciskając klawisze Alt + f2? (przynajmniej na gnome i openbox, robi to alt + f2). Pytam, bo jak tylko wpiszesz polecenie, program się uruchomi, a okno zniknie. czy to tylko dodanie do niego znaku &?
sqram

2
@lyrae: domyślnie powłoka czeka na zakończenie działania programu przed kontynuowaniem sesji powłoki, nie „zawiesza się”, przy żadnej definicji „zawiesić”; Alt + F2 nie czeka na program. Powodem, dla którego powłoka czeka na zakończenie programu, jest to, że powłoka może przekierowywać wszystko, co użytkownik wpisał do powłoki, na standardowe wejście programu i / lub wyświetlać standardowe wyjście programu. Ponieważ alt + f2 jest używany przede wszystkim do uruchamiania programu GUI, alt + f2 nie zapewnia możliwości użycia standardowego wejścia / wyjścia, więc nie trzeba czekać.
Lie Ryan,

1
@lyrae: alt + f2 nie robi nic specjalnego, aby uruchomić program w tle; to powłoka robi coś specjalnego, dodanie „&” to funkcjonalność powłoki. Podczas uruchamiania polecenia bez znaku „&” powłoka przekierowuje standardowe wejście programu na własne standardowe wejście, a standardowe wyjście programu na własne standardowe wyjście (nieco wymyślone, ponieważ powłoka udostępnia również wiele innych usług, takich jak przechwytywanie Ctrl -C, aby wysłać polecenie sygnału SIGINT do programu pierwszego planu). „&” Mówi powłoce, aby tego nie robiła i po prostu uruchamia program (również zaprojektowany).
Lie Ryan,

1
@LieRyan część tego, co mówisz, że robi powłoka, jest w rzeczywistości obsługiwana przez sterownik terminalu jądra, a „with &” jest ogólnie bardziej „specjalne” niż „bez &”, poza tym, że powłoka wywołuje funkcję wait () [lub waitpid lub równoważny], którego nie robi alt-f2.
Random832

6

Po uruchomieniu programu w terminalu terminal „zawiesi się”, dopóki program się nie zatrzyma. Naciskając Ctrl+ czamykasz program, a tym samym wracasz do monitu. Zobaczysz to we wszystkich aplikacjach GUI, na przykład wypróbuj Firefox.

Kiedy użyjesz innej metody, takiej jak Alt + F2 lub klikniesz menu, twój program zostanie uruchomiony w tle, więc nic dziwnego się nie wydarzy (i tak czy inaczej nie ma wiersza polecenia).

Jeśli nadal chcesz uruchamiać aplikacje GUI z terminala, dołącz &na końcu polecenia, tak jak to

lxpanel &

Mówi to terminalowi, aby działał lxpanelw tle i natychmiast wyświetla kolejny monit.


3

Programy domyślnie uruchamiane są przez powłokę na pierwszym planie tej powłoki. Powoduje to, że powłoka zawiesza działanie i kieruje stdin / stdout / sterr z terminala do programu. Programy uruchamiane za pomocą środowiska pulpitu są rozwidlone , co powoduje, że działają niezależnie od programu, który je uruchomił. Można to zasymulować w większości powłok, dodając a &do polecenia, chociaż to wciąż połączy std * z terminalem (chociaż czytanie ze stdin w programie w tle ma dalsze komplikacje).


2

Tła i dobrze, z wyjątkiem programów, które powracają w późniejszym czasie wymagających interakcji z konsolą (na przykład „apt -y update &”, który ostatecznie przechodzi w stan STOP, ponieważ chce poprosić użytkownika o pytanie „naprawdę naprawdę wymuszać?” Znacznie później .... kiedy nikt już nie patrzy).

Aby podłączyć tę dziurę i poinformować proces, że terminal nigdy tak naprawdę nigdy nie będzie dla niego dostępny, dołączam <& - do niektórych moich poleceń, całkowicie odłączając je od aktywnego terminala informując, że STDIN nie jest już możliwe. Upewnij się jednak, że / bin / bash jest twoją powłoką, jeśli z niej korzystasz. Skrypt będzie rejestrował wszelkie błędy związane z brakiem dostępu do pseudoterminalu, na którym można by rzucić dowolny monit.

Na przykład:

`./runme.sh &> runme.log <&- & disown`

to mój najlepszy sposób na odłączenie się od bieżącej sesji terminala. Zarówno STDOUT, jak i STDERR zostają zalogowane do runme.log, nie będzie miało znaczenia, czy konsola lub powłoka zakończą się wcześniej, czy wylogujesz się / su na inne konto (bez śmieci terminali z runme), a dzięki odrzuceniu nawet rodzic-dziecko Relacja PID została usunięta.

AKTUALIZACJA: nawet z tym miałem problem z semaforem powiązanym z nazwą oryginalnego rodzica, więc teraz polecam zamiast tego:

at now <<< "(cmd1; cmd2; etc.) &> logfile.log"

Oczywiście, usuń &>, jeśli chcesz otrzymać dane wyjściowe z CRON w e-mailu lub przekieruj wszystko do / dev / null zamiast pliku.


Nieco mniej skomplikowanym sposobem na osiągnięcie tego, z którego zacząłem korzystać, jestat now <<< "(cmd1; cmd2; etc.) &> logfile.log"
Marcos
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.