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?)

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;

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.


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.

<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

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
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.