Echo postępu z procesu w tle bez przechwytywania monitu

10

Rozważ prosty skrypt hello:

#!/bin/bash

echo 'hello world!'

Teraz z bash, jeśli spróbuję uruchomić to w tle:

$ hello &
[1] 12345
$ hello world!
 <--- prompt is stuck here until I hit enter!
[1]+ Done
$  <--- prompt back to normal

Co wolałbym zobaczyć:

$ hello &
[1] 12345
[1]+ hello world!
[1]+ Done
$  <--- prompt normal the whole time

Jak mogę zmienić zachowanie?

Dave Johnson
źródło

Odpowiedzi:

13

To kwestia czasu: bash uruchamia hellopolecenie w tle, następnie wyświetla monit o wprowadzenie nowego polecenia, a następnie polecenie tła drukuje dane wyjściowe. Po wejściu do następnego wiersza poleceń (pusty wiersz polecenia, po prostu naciśnięty Enter), bash wyświetla powiadomienie o zakończeniu zadania w tle, a następnie następny monit.

Możesz poeksperymentować ze skryptem, który zaczyna się sleep 3i zacząć pisać zaraz po uruchomieniu skryptu w tle, aby zobaczyć, co dzieje się w tempie, które możesz śledzić.

Możesz ustawić bash, aby powiadamiał cię natychmiast po zakończeniu zadania w tle, ustawiając notifyopcję za pomocą set -b. Wtedy zobaczysz:

$ set -b
$ hello &
[1] 12345
$ hello world!
[1]+ Done

W tym przypadku Bash nie przerysowuje monitu. Nadal edytujesz wiersz polecenia w wierszu polecenia, który pojawił się przed wydrukowaniem zadania w tle hello world!. Możesz przerysować bieżącą linię, naciskając Esc 1 Ctrl+ L. Możesz powiązać polecenie redraw-current-linez wygodniejszym klawiszem; na przykład, aby Ctrl+ Lprzerysować bieżącą linię i Ctrl+ Alt+ Lwyczyścić ekran, dodaj następujące linie do ~/.inputrc:

"\C-l": redraw-current-line
"\e\C-l": clear-screen

Nie znam sposobu na automatyczne przerysowanie linii poleceń przez bash. Zsh robi to domyślnie.

Gilles „SO- przestań być zły”
źródło