Jak ograniczyć liczbę linii dostępnych w poleceniu bash?

11

Zacząłem pobierać duży plik w tle, używając

$ nohup wget http://example.tld/big.iso &

co daje mi również nohup.outplik zawierający dane wyjściowe wget.

Teraz, jeśli później chcę obejrzeć proces pobierania, mógłbym użyć, $ tail -f nohup.outale to wypełnia okno terminala szybciej, niż bym sobie tego życzył. To, co chciałbym zobaczyć, to ostatnia linia stale aktualizowana (tak jak w przypadku używania wgetsamego).

Próbowałem, $ tail -n 1 -f nohup.outale wydaje się, że wpływa to tylko na początkowe dopasowanie.

Ogólnie rzecz biorąc, jeśli możliwe jest ograniczenie (w tym przypadku do 1) liczby linii dostępnych / widocznych na wyjściu polecenia, rozwiązałoby to problem. Tak jakby mieć wyjście w buforze cyklicznym - wystarczy pomyśleć o normalnym pasku postępu $ wget example.tld/big.iso.

Czy istnieje takie rozwiązanie?

A może wspinam się na drzewo w niewłaściwy sposób? (Czy to znaczy, czy łatwiej byłoby ograniczyć nohupwydajność lub zrobić coś innego?)

Jari Keinänen
źródło

Odpowiedzi:

10

Jeśli nie chcesz ograniczać przewijanego regionu (patrz moja inna odpowiedź), możesz także użyć znaku powrotu karetki, aby wrócić do początku linii przed wydrukowaniem następnej linii. Istnieje sekwencja ucieczki, która usuwa resztę linii, co jest konieczne, gdy bieżąca linia jest krótsza niż poprzednia linia.

nohup wget http://cdimage.debian.org/debian-cd/6.0.3/amd64/iso-dvd/debian-6.0.3-amd64-DVD-1.iso &
el="$(tput el)"; # Clear to the end of the line
tail -n 1 -f nohup.out | while read -r line; do echo -n $'\r'"$el$line"; done;
janmoesen
źródło
6

Możesz użyć watchtutaj:

watch -n 0.5 -e "tail -n 1 nohup.out"

Edycja : Opcja -e(alias --exec) wygląda tutaj dobrze. Zwłaszcza jeśli dążysz do biegania watchw bardzo małych odstępach czasu, zmniejsza to narzut związany z bieganiem sh -cwewnętrznie watchw każdym cyklu.

rozcietrzewiacz
źródło
2
Pamiętaj, że tailco sekundę powstaje nowy proces, który może, ale nie musi, być czymś, na czym ci zależy. Pamiętaj też, aby podać przedział poniżej sekundy (np. watch -n 0.1), Aby zasymulować „ciągłą aktualizację” części. (To oczywiście zwiększa także liczbę procesów i wywołuje otwarte pliki.) Wreszcie, jeśli używasz OS X, możesz uzyskać watchz MacPorts, ponieważ nie jest on domyślnie dostępny.
janmoesen
Jest to trochę obejście, ale świetne jako takie. Spodziewałem się odpowiedzi nie w trybie pełnoekranowym, aby zobaczyć poprzednie wyniki - ale tak naprawdę mogłem użyć watchw nowym oknie terminala. Dowiedziałem się również, że używanie tail -n 2jest bardziej przydatne niż -n 1z wget, przynajmniej w watchodstępie 1 sekundy, ponieważ w przeciwnym razie ostatni procent może nie być widoczny; nie jest to wada w twojej odpowiedzi, ale wspomniałem o tym, jeśli ktoś inny zdecyduje się obejrzeć wyjście wgets tailed nohup.
Jari Keinänen,
@janmoesen W tym konkretnym scenariuszu nowy tailproces prawdopodobnie nie oznacza zbyt dużej nadmiaru; ale jako ogólną odpowiedź warto wziąć to pod uwagę. Zauważyłem również, że watch -n 0.1nie działało, ale watch -n 0,1działało - mogą być zastosowane ustawienia narodowe, chociaż nie widziałem wcześniej ustawień narodowych stosowanych do opcji poleceń terminala. Na marginesie: brew install watchdziałał również świetnie :-)
Jari Keinänen
Uwaga dodatkowa: To watch, czy będzie działać z ustawieniami regionalnymi 0,1lub 0.1zależy od nich (używa symbolu dziesiętnego zdefiniowanego dla ustawień regionalnych). Sprawdzić LC_ALL=C watch -n 0.1 "date +%S.%N".
rozcietrzewiacz
3

Istnieją pewne sekwencje kontrolne Xterm, których można użyć do ograniczenia przewijania linii terminala. Poszukaj „Ustaw region przewijania”. Ale to trochę kłopot. Pamiętaj, aby zresetować terminal później:

nohup wget http://cdimage.debian.org/debian-cd/6.0.3/amd64/iso-dvd/debian-6.0.3-amd64-DVD-1.iso &
clear; echo -n $'\e[1;2r'; tail -f nohup.out | grep --line-buffered .
# The "grep" line is to ensure a single line; you can also use "awk 1" or "sed" etc.
janmoesen
źródło
<Wstaw tutaj zwykłą notatkę o braku możliwości przenoszenia>
janmoesen,
Jest to kolejna świetna alternatywa, ale najlepiej ją stosować również w dedykowanym oknie, ponieważ tail -fnadal wypełnia bufor, a także dlatego, że terminal i tak wymaga zresetowania. Nie jest to tak proste, jak się spodziewałem, ale w przeciwnym razie może być tym, czego szukałem.
Jari Keinänen
0

Jeśli nie chcesz, aby wyjście zajmowało całe bieżące okno terminala, możesz użyć prostej whilepętli:

while true; do 
  XXX=$( tail -n1 my.log )
  echo -en " \r$XXX\r"
  sleep 0.5
done; echo
rozcietrzewiacz
źródło
1
Zauważ, że aby móc przewijać wyjście terminala podczas działania dowolnego polecenia generującego dane wyjściowe, musisz edytować ustawienia emulatora terminala i wyłączyć scrollTtyOutput(lub podobną) opcję.
rozcietrzewiacz