Mam program, który kończy działanie automatycznie po odczytaniu EOF w danym strumieniu (w następującym przypadku stdin).
Teraz chcę utworzyć skrypt powłoki, który tworzy nazwaną potok i podłącza do niego standardowe wejście programu. Następnie skrypt zapisuje do potoku kilka razy przy użyciu echo
i cat
(oraz innych narzędzi, które automatycznie generują EOF po wyjściu). Problem, z którym się zmagam, polega na tym, że gdy pierwszy raz się echo
zakończy, wysyła EOF do potoku i powoduje, że program się kończy. Jeśli użyję czegoś takiego, tail -f
nie mogę wysłać EOF, gdy zamierzam wyjść z programu. Poszukuję zrównoważonego rozwiązania, ale bezskutecznie.
Znalazłem już zarówno sposoby zapobiegania EOF, jak i ręczne wysyłanie EOF, ale nie mogę ich połączyć. Czy jest jakaś wskazówka?
#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg
exec 3>P
powoduje zawieszenie się, dlaczego?exec 2>P
, a masz włączony tryb śledzenia (set -x
), w którym bash będzie zapisywał na potoku, ale nie ma czytnika, więc blokuje czekanie na coś do przeczytania.exec 3>P
wisi na mojej maszynie. Wynika to z faktu, że nie ma procesu odczytu zP
. Tak więc rozwiązaniem było zamiana liniiexec 3>P
iprogram < P &
(dodanie znaku handlowego i tak, aby program działał w tle).Potok otrzymuje EOF, gdy ostatni pisarz odejdzie. Aby tego uniknąć, upewnij się, że zawsze istnieje program piszący (proces, w którym potok jest otwarty do pisania, ale tak naprawdę nic nie pisze). Aby wysłać EOF, spraw, aby pisarz rezerwowy odszedł.
źródło
Nie ma sposobu, aby program rozróżniał EOF, co oznacza „nadszedł czas, aby wyjść” od EOF, który oznacza, że „program piszący jest gotowy, ale może być więcej danych od kogoś innego”.
Jeśli masz możliwość modyfikowania zachowania programu, wykonaj odczyt w nieskończonej pętli (jedna iteracja trwa do EOF) i wyślij mu określony ciąg poleceń, który oznacza „czas wyjść”. Wysłanie tego ciągu byłoby zadaniem
send_eof
polecenia w twoim pytaniu.Inna opcja:
lub
źródło