Dlaczego przekierowanie wyjścia sed do tego samego pliku wejściowego powoduje, że mój komputer nie reaguje?

13

Próbowałem sedzamienić niektóre słowa kluczowe w dużym pliku (100 MB). Nie wiedziałem o opcji -i(na miejscu), więc moją pierwszą próbą było przekierowanie w następujący sposób:

sed 's/original/edited/g' file.log >> file.log

potem stało się, że mój komputer się zatrzymał, prawie bez klawiatury. Próbowałem innej konsoli Ctrl+ Alt+, F1ale po powolnym wprowadzeniu nazwy użytkownika również się zatrzymała. Bez klawiatury moją jedyną opcją było resetowanie sprzętowe urządzenia. Po zalogowaniu zobaczyłem, że plik file.log ma około 8 GB.

Naprawdę chciałbym zrozumieć, dlaczego wykonanie tego polecenia spowodowało, że system przestał reagować, a jeśli na poziomie systemu istnieją mechanizmy do wywoływania alertów i zabijania przestępców?

cesarpachon
źródło
7
Czy to jest maszyna jednordzeniowa? Wydaje się bardzo dziwne, że powinien był on powalić nowoczesny komputer na kolana. Tak, zapełniłeś dysk. Tak, zużyłeś 100% jednego z twoich rdzeni. Ale pełna katastrofa?
terdon
Czy w tym pliku jest coś osobliwego? jeśli to nie jest problem, czy możesz opublikować jego zawartość na pastebin?
Sergiy Kolodyazhnyy
Jaka jest ilość twojej pamięci? Czy możesz podać nam dane wyjściowe free -h ?
Sergiy Kolodyazhnyy
Po co używać edytora strumieniowego, jeśli chcesz zmienić plik? ex -sc '%s/original/edited/ge|x' file.logpowinieneś robić to, co chcesz w idiomatyczny sposób w systemie UNIX bez sed -iskutków ubocznych.
David Ongaro,
Zauważ, że nawet jeśli robisz to poprawnie (przy użyciu dowolnej z metod, które ludzie udostępniają), może to być bardzo niebezpieczne w przypadku pliku dziennika należącego do aktywnego procesu.
Random832

Odpowiedzi:

10

Jak już powiedziano, >>dołącza się do pliku, więc twoje sedpolecenie będzie tam siedzieć i czytać wiersze, które właśnie wypisał, a następnie wypisywać je jeszcze więcej. Jeśli chcesz zastąpić plik w miejscu, >nadal nie będzie działać, ale jesteś świadomy sed„s -iopcją, która jest zdecydowanie jeden chcesz.

Jeśli jednak jesteś absolutnie pewien, że chcesz dołączyć do pliku, który czytasz jako strumień, i chcesz zrobić tylko jedno przejście tego, rozważ użycie spongez moreutilspakietu;

sed 's/original/edited/g' file.log | sponge >> file.log

spongeodczytuje ze standardowego wejścia do pamięci aż do EOF, a następnie zrzuca całą zawartość na standardowe wyjście, więc seduderzy w koniec pliku, przestanie go czytać, zamknie, a następnie zacznie się do niego dołączać gąbka.

ymbirtt
źródło
2
spongeJest to miłe narzędzie wiedzieć, ale sedjuż ma -iopcję: -i[SUFFIX], --in-place[=SUFFIX], edit files in place (makes backup if SUFFIX supplied).
Joshua Taylor
@JoshuaTaylor, OP używało, które uzupełnia, >>a nie >zastępuje. To prawda, że ​​OP wspomniał konkretnie -iw poście i wydaje się, że jest to o wiele bardziej powszechny przypadek użycia niż ten, ale pomyślałem, że warto wskazać, że konkretna operacja, którą opublikował OP, była możliwa bez zbytniego zamieszania, jeśli naprawdę pewnie to właśnie chcesz zrobić.
ymbirtt
1
Wspomniałem o tym tutaj, ponieważ był to klucz w zaakceptowanej odpowiedzi . Powiedział, że jestem naprawdę szczęśliwy, aby dowiedzieć się o gąbką ; jest to nowe narzędzie do mojego zestawu narzędzi i właśnie za to zasługuję na opinię.
Joshua Taylor
1
Ach! Widzę. Poprawię moją odpowiedź, aby była nieco jaśniejsza. Ponadto, jeśli podobało ci się sponge, spójrz na vipe. moreutilsto tylko magiczna paczka wypełniona rzeczami, o których nigdy nie wiedziałeś, że potrzebujesz
ymbirtt,
18

Twoje sedpolecenie próbowało odczytać plik, do którego się dołączało. Nigdy nie osiągnie końca pliku, ale zużyje dużo czasu procesora. Właśnie dlatego wynaleziono ^ C (proces przerywania prądu).

waltinator
źródło
Nie sądzę, aby ^ C było tam opcją ... przeszło do HALT, tzn. Nie migał kursor, utknął!
EKons,
18

Powrót do pliku, który odczytujesz, w żadnym wypadku nie jest dobrym pomysłem, ponieważ skończysz na stale rosnącym pliku. Jeśli naprawdę chcesz ponownie zapisać do pliku, powinieneś użyć -iflagi:

sed -i 's/original/edited/g' file.log

lub jeśli chcesz utworzyć kopię zapasową przed wprowadzeniem zmian, możesz dodać sufiks pliku do -iflagi:

sed -i.bak 's/original/edited/g' file.log

Spowoduje to utworzenie pliku o nazwie, file.log.baka następnie dokonanie zmian. To, co zrobiłeś, próbując dołączyć do pliku, który odczytujesz, wzywamy programistą do wyścigu danych, w którym różne procesy ścigają się dla tego samego źródła danych, czy to wejścia, czy wyjścia . Z tego powodu maszyna się zatrzymała.

Videonauth
źródło
1
Dziwi mnie, że to zaakceptowana odpowiedź, ponieważ nawet nie odnosi się do pytania OP"I really would like to understand why the execution of that command was able to make the system so unresponsive, and if mechanisms exist at the system level to trigger alerts and kill the offending process?"
Steve
@ Steve Do jakiego powodu się zatrzymałem, zwróciłem się do niego, ale w drugiej części masz rację. Nie odniosłem się do tego, ponieważ nie znam na to odpowiedzi. Przetestowaliśmy to polecenie po dyskusji na czacie i doszliśmy do zupełnie różnych wyników na różnych maszynach i systemach operacyjnych. Przykład: na komputerze z łukiem pozwala on tylko powiększać plik na zawsze, ale nie powoduje, że maszyna przestanie odpowiadać. Na moim komputerze Ubuntu uzyskiwałem ten sam wynik co pytający, bez szans na zabicie procesu. Druga maszyna testująca to samo na maszynie Wirtualnej Ubuntu zatrzymała się.
Videonauth,
straceCałego procesu po drugiej stronie didtn odtworzyć wynik i to na moim komputerze i na komputerze z innym użytkownikiem. Pewnie, że istnieje mechanizm, za pomocą którego możesz zabijać niereagujące aplikacje, ale jeśli twoja maszyna przestaje odpowiadać, pozostaje Ci tylko jedna opcja, resetowanie. Wciąż testuję to i zanim nie w pełni zrozumiem, co powoduje opisywane zachowanie, nie jestem w stanie odpowiedzieć na tę część pytania.
Videonauth,
Prawdopodobnie jest to różnica w konfiguracjach jądra, taka jak inny harmonogram, który nadaje priorytet IO, lub różnice w sterowniku dysku / systemu plików między systemami. Dobrze jest zobaczyć śledztwo, które przeprowadziliście, to dobra informacja.
Steve
Jeśli interesuje Cię inny punkt danych; Próbowałem tego na maszynie CentOS z dość małym plikiem i zrobiło to dokładnie to samo, co moje rozwiązanie gąbki poniżej. Wyobrażam sobie, że w przypadku małego pliku sedbuforuje całą pamięć do pamięci, a następnie ją zamyka, zamiast trzymać uchwyt. Z plikiem ~ 100 MB, podobnie jak w OP, rozrastał się w nieskończoność, ale nie zepsuł maszyny.
ymbirtt