Widzenie „Broken pipe” w tej sytuacji jest rzadkie, ale normalne.
Po uruchomieniu type rvm | head -1
bash wykonuje się type rvm
w jednym procesie, head -1
w innym. 1 Stdout type
jest podłączony do końca „zapisu” potoku , a stdin head
do końca „odczytu”. Oba procesy działają w tym samym czasie.
head -1
Proces odczytuje dane ze standardowego wejścia (zwykle kawałki 8 KB) drukuje jednej linii (w zależności od -1
wariantu) i wyjścia, co powoduje „Czytaj” koniec rury, która ma być zamknięty. Ponieważ rvm
funkcja jest dość długa (około 11 kB po przeanalizowaniu i zrekonstruowaniu przez bash), oznacza to, że head
kończy działanie, type
wciąż mając kilka kB danych do zapisania.
W tym momencie, ponieważ type
próbuje napisać do potoku, którego drugi koniec został zamknięty - zepsuty potok - funkcja write (), którą skalował, zwróci błąd EPIPE, przetłumaczony jako „zepsuty potok”. Oprócz tego błędu jądro wysyła również sygnał SIGPIPE type
, który domyślnie zabija proces natychmiast.
(Sygnał jest bardzo przydatny w interaktywnych powłokach, ponieważ większość użytkowników nie chce, aby pierwszy proces działał dalej i próbował pisać do nikąd. Tymczasem usługi nieinteraktywne ignorują SIGPIPE - nie byłoby dobrze, aby długo działający demon umierają na tak prosty błąd - dlatego uważają, że kod błędu jest bardzo przydatny).
Jednak dostarczanie sygnału nie jest w 100% natychmiastowe i mogą wystąpić przypadki, gdy write () zwraca EPIPE, a proces kontynuuje działanie przez krótką chwilę przed otrzymaniem sygnału. W takim przypadku type
dostaje wystarczająco dużo czasu, aby zauważyć nieudany zapis, przetłumaczyć kod błędu, a nawet wydrukować komunikat o błędzie do stderr, zanim zostanie zabity przez SIGPIPE. (Komunikat o błędzie brzmi „-bash: type:”, ponieważ type
jest to wbudowane polecenie samego basha.)
Wydaje się, że jest to bardziej powszechne w systemach wieloprocesorowych, ponieważ type
proces i kod dostarczania sygnału jądra mogą działać na różnych rdzeniach, dosłownie w tym samym czasie.
Byłoby możliwe usunięcie tego komunikatu przez załatanie type
wbudowanego (w kodzie źródłowym bash), aby natychmiast wyjść, gdy otrzyma EPIPE z funkcji write ().
Nie należy się jednak tym przejmować i nie ma to żadnego związku z rvm
instalacją.
ls
przezhead -1
lata, a dziś otrzymuję komunikat zepsutej rury.Możesz naprawić zepsutą rurę kosztem innego procesu , wstawiając
tail -n +1
do niej rurkę w następujący sposób:+1
Mówitail
do wydrukowania pierwszej linii wejścia i wszystkiego, co następuje. Dane wyjściowe będą dokładnie takie same, jak gdyby ichtail -n +1
nie było, ale program jest wystarczająco inteligentny, aby sprawdzić standardowe dane wyjściowe i dokładnie zamyka potok. Nigdy więcej połamanych rur .źródło
find /var/lib/mysql -xdev -type f -daystart -mmin +5 -print0 | xargs -0 ls -ldt | tail -n +1 | head
niezawodnie dajexargs: ls: terminated by signal 13
. Jak wiemy, problemem jest wyczerpanie danych wejściowych i tak naprawdę tylko jedno polecenie zajmuje się buforowaniem: dd. Dodanie| dd obs=1M
do potoku naprawia SIGPIPE dla mojego przypadku użycia.type rvm | (head -1 ; dd of=/dev/null)
To, oczywiście, jest podobne do innych sugestii, ponieważ powoduje przetwarzanie wszystkich danych wejściowych , aledd
powinien być najbardziej wydajnym programem do obsługi takich rzeczy.write error: Broken pipe
Wiadomość odnosi się do procesu pisania, który próbuje pisać do potoku bez pozostawionych na koniec czytania tej rury i szczególną okoliczność, że czytelnikówSIGPIPE
sygnał ma zostać zignorowany albo przez prąd lub procesu macierzystego. Jeśli był to proces nadrzędny, którySIGPIPE
został zignorowany, proces podrzędny nie może go cofnąć ponownie w powłoce nieinterakcyjnej.Możliwe jest jednak zabijanie
type rvm
pohead -1
zakończeniu przy użyciu jawnych podpowłok. W ten sposób możemy w tletype rvm
, wysłaćtypepid
dohead -1
podpowłoki, a następnie zaimplementować tam pułapkę,EXIT
abytype rvm
jawnie zabić .źródło
type
dostaje wystarczająco dużo czasu, aby zauważyć nieudany zapis, przetłumaczyć kod błędu, a nawet wydrukować komunikat o błędzie do stderr, zanim zostanie zabity przez SIGPIPE . Myślę, że twoje rozwiązanie nie zapobiega reakcji producenta (type
tutaj) na nieudany zapis (z powodu zamkniętego potoku), prawda?