Nieblokowana buforowana nazwana rura?

20

Szukam czegoś, co, jak podejrzewam, nie istnieje: nieblokowana buforowana nazwana potok (fifo) do użytku z wiersza poleceń. Czy jest coś takiego?

Oto przypadek użycia: Załóżmy, że mam proces, który będzie działał przez długi czas w tle i wyrzuci wiele wyników stdout. Tak naprawdę nie dbam o wynik i nie chcę go przechowywać (być może nie mam wystarczająco dużo miejsca), ale chciałbym okresowo „wpaść” i śledzić, co robi, a następnie zrezygnować ponownie i zostaw to do wykonania. Chciałbym więc przekierować swoje wyjście do tej teoretycznie buforowanej, nieblokującej nazwanej potoki, a następnie okresowo się z nią korzystać.

Zasadniczo chcę zacząć w ten sposób ( 10Mponieważ jest to rozmiar bufora):

mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &

... i okresowo przychodzę, aby zobaczyć, co się dzieje ...

tail -f magicfifo

... bez magicfifo zapisywania wszystkich danych wyjściowych (więc nie jest to zwykły plik) i bez blokowania procesu wyrzucania, gdy się zapełnia i nie jest podsłuchiwany (więc nie całkiem normalna nazwana rura).

Nie sądzę, aby rozwiązania obejmowały taillub zrobiłyby pruneto (cóż, mogę wymyślić obejście obejmujące tail), ponieważ tailnadal wymagałoby to przechowywania gdzieś wszystkich danych (jeśli chcę wpaść i zrezygnować z patrzenia na nie), i prunemusi przepisać plik, prawdopodobnie (przyznam, że tego nie próbowałem / nie udowodniłem), przerywając przekierowanie procesu generującego wszystkie dane wyjściowe.

Spodziewam się, że mógłbym napisać jakieś narzędzie do tego, ale * nix ma tak wiele fajnych aspektów plików i potoków, i tak, po prostu nie mogę przestać myśleć, że to istnieje i po prostu o tym nie wiem.

Więc: czy istnieje coś takiego, a jeśli tak, to co to jest?

TJ Crowder
źródło
1
Opisujesz „bufor pierścieniowy” lub „bufor okrągły”. Nie znam żadnych narzędzi wiersza poleceń do utrzymywania takich rzeczy, chociaż tworzenie ich byłoby trywialne.
Shawn J. Goff,
2
Zapoznaj się z rozwiązaniami opisanymi w „Linuksowym nieblokującym fifo (rejestrowanie na żądanie)”, stackoverflow.com/questions/7360473/… .
1
Wygląda na to, że zostało to rozwiązane na StackOverflow: stackoverflow.com/questions/7360473/…
James Blackburn
@JamesBlackburn: Dzięki! Bardzo interesujące.
TJ Crowder

Odpowiedzi:

16

Myślę, że szukasz GNU screen. Utrzymuje bufor, aby pomieścić ostatni ekran pełny lub dwa wyjścia z jednego lub więcej programów i umożliwia rozłączenie i powrót później.

psusi
źródło
+1 za zasugerowanie ekranu. BTW, możesz go skonfigurować tak, aby zawierał wiele „linii historii”.
Pan Shunz
1
Dzięki. Czy możesz podać przykład zastosowania tego polecenia do poleceń, które pokazałem w moim pytaniu? Strona podręcznika mówi, że jest to menedżer okien (myślę, że oznaczają one w sensie terminalnym, a nie graficznym, ale nadal). I czy nadal będę mógł wpaść (przez ssh) i zrezygnować w razie potrzeby? (Np. Operuje na zdalnych serwerach.)
TJ Crowder
Tak, możesz w ten sposób używać ekranu GNU. Utworzyłbyś nową (potencjalnie nazwaną) sesję, uruchomiłeś komendę w tej sesji, a następnie rozłączyłeś się.
TML
2
Jest też tmuxi dtach- cokolwiek w tej samej klasie terminali / aplikacji do zarządzania sesją powinno być w stanie osiągnąć to samo.
jw013,
5

Możesz użyć pv, zapewnia tyle buforowania, ile chcesz w potoku. Możesz użyć tego w następujący sposób:

sprewingprocess | pv -B 1g > ordinaryfifo &

Dałoby to do 1 GB buforowania między spewingprocessi fifo. Większość dystrybucji Linuksa oferuje pvpakiet zwany, wierz lub nie pv,.

David Schwartz
źródło
Dzięki, ale czy nie blokowałby się, gdy bufor byłby pełny, gdybym nie czytał celu o nazwie potok?
TJ Crowder
1
Tak, ale jaki masz wybór? W skończonym wszechświecie nie można dosłownie nieograniczonego buforowania.
David Schwartz
Drugi wybór jest taki, jak opisałem w moim pytaniu: Nie zapisuję wszystkich wyników. Gdy bufor jest pełny, najstarsze rzeczy są wyrzucane.
TJ Crowder
Hmm, przetestowałem to i niestety nie do końca działa. Jeśli proces odczytu fifo przestaje na chwilę czytać, bloki PV próbują zapisywać do fifo, a ponieważ nie są wielowątkowe, blokuje również odczyt danych do bufora pv. Bufor pv będzie więc nadal wypełniał się tylko podczas czytania przez system fifo. pv może być w stanie odczytać i buforować niektóre dane, ale nie zapobiega to całkowitemu blokowaniu programu piszącego.
Daniel S. Sterling
1

Miałem ten sam problem. To jest moje pierwsze rozwiązanie. Najpierw zapisz dane wyjściowe do pliku, który obcinamy po każdej linii, aby nie wzrastał w nieskończoność:

spewingprocess | while read line; do echo $line > buffer.txt ; done

Następnie odczytaj z pliku za pomocą tail (gdzie 2> /dev/nullpozbywa się komunikatu o błędzie „plik obcięty”):

tail -f ./buffer.txt 2> /dev/null

W ten sposób bufor nie rośnie i możemy multipleksować, np. Uruchamiać tyle ogonów, ile chcemy. Jednak problem z tym podejściem polega na tym, że możemy utracić dane, gdy obciemy się szybciej niż ogon może odczytać, jak pokazuje ten test:

for ((i=0; ; i++)) ; do echo "$i" ; done | while read line; do  echo $line > buffer.txt ; done
tail -f ./buffer.txt 2> /dev/null > log.txt

Po dłuższym uruchomieniu pierwsza i ostatnia linia to:

$ head -n 1 log.txt
0
$ tail -n 1 log.txt
78783

Ale plik ma mniej wierszy, więc niektóre są tracone:

$ wc log.txt
67087  67087 392819 log.txt

Mimo to wydaje się to dobrym rozwiązaniem, jeśli nie przejmujesz się tak bardzo utratą danych lub gdy proces wyrzucania nie jest wystarczająco szybki, aby nastąpiła utrata danych.

bterwijn
źródło