Zazwyczaj, cat /dev/null > [something]
gdy chcesz wyczyścić zawartość pliku, zapewniając absolutnie zerowe ryzyko zakłócenia rzeczywistego stanu pliku. Zawartość pliku zostanie wyczyszczona przez cat /dev/null
sam plik - ponieważ istnieje i jest znany systemowi plików, w którym rezyduje - nadal będzie miał ten sam numer i-węzła, własność i uprawnienia.
W przypadku pliku dziennika może być tak, że sam plik dziennika jest oznaczony jako „w użyciu” przez inny proces. Takie postępowanie, na przykład, rm /var/log/messages && touch /var/log/messages
może zakłócać inne procesy i może powodować dławienie uruchomionych procesów. Oznacza to, że proces, który w jakiś sposób jest powiązany z określonym numerem i-węzła podłączonym do pliku, /var/log/messages
może nagle wpaść w panikę i powiedzieć: „Hej! Co się stało /var/log/messages
! ”, Nawet jeśli plik nadal tam jest. Nie wspominając już o potencjalnych problemach z nieprawidłowym odtwarzaniem własności i uprawnień.
Z powodu tej niepewności w użyciu / stanie pliku, korzystanie z niego cat /dev/null > [something]
jest preferowane przez administratorów systemu, którzy chcą wyczyścić dziennik, ale nie chcą potencjalnie zakłócać działania już istniejących procesów.
Ponadto w kontekście strony, do której prowadzi link do autora, stwierdza:
Nie ma tu nic niezwykłego, tylko zestaw poleceń, które równie łatwo można było wywoływać jeden po drugim z wiersza poleceń na konsoli lub w oknie terminala. Zalety umieszczania poleceń w skrypcie wykraczają daleko poza to, że nie trzeba ich wielokrotnie wpisywać.
Zatem „nic niezwykłego”, o którym wspomina autor, dotyczy całej koncepcji tego konkretnego skryptu bash: jest to tylko zestaw prostych poleceń, które można równie łatwo uruchomić z wiersza poleceń, ale umieszcza się w pliku tekstowym, aby unikaj powtarzania ich w kółko.
truncate -s 0
zrobiłby to samo i byłby mniej idiomatyczny. Jednak programiści powłoki są konserwatywną grupą i można napotkać systemy wystarczająco stare lub wystarczająco zwariowane, aby nie mieć tego polecenia.cat /dev/null > /foo/bar
obcina plik;echo "" > /foo/bar
obcina go, a następnie zapisuje pojedynczy znak nowej linii.Zrobisz to, aby obciąć zawartość pliku, zachowując nienaruszony i-węzeł. Wszystkie programy, które mają ten plik otwarty do odczytu lub zapisu, nie miałyby wpływu poza tym, że rozmiar pliku zostałby zresetowany do zera.
Fałszywą często znajdowaną alternatywą jest usunięcie pliku, a następnie utworzenie go ponownie:
lub podobny:
Problem polega na tym, że te metody nie zapobiegają zapisywaniu starego pliku przez jakiekolwiek procesy, w których usunięty plik jest otwarty podczas usuwania. Powodem jest to, że w systemach plików Unix, kiedy usuwasz plik, odłączasz tylko jego nazwę (ścieżkę) od jego zawartości (i-węzła). I-węzeł jest utrzymywany przy życiu tak długo, jak istnieją procesy, które otwierają go do czytania lub pisania.
Prowadzi to do kilku negatywnych skutków: dzienniki zapisane po usunięciu pliku są tracone, ponieważ nie ma prostego / przenośnego sposobu otwarcia usuniętego pliku. Tak długo, jak proces zapisuje do usuniętego pliku, jego zawartość nadal zajmuje miejsce w systemie plików. Oznacza to, że jeśli usuniesz / utworzysz plik, ponieważ wypełniał on dysk, dysk pozostanie wypełniony. Jednym ze sposobów rozwiązania tego ostatniego problemu jest ponowne uruchomienie procesów rejestratora, ale możesz tego nie chcieć w przypadku krytycznych usług, a dzienniki pośredniczące zostaną ostatecznie utracone. Istnieją również skutki uboczne, ponieważ tworzony plik może nie mieć takich samych uprawnień, właściciela i grupy jak oryginalny. Może to na przykład uniemożliwić analizatorowi dziennika odczytanie nowo utworzonego pliku lub, co gorsza, uniemożliwić procesowi zapisywania własnych dzienników.
Pierwsza metoda,
cat /dev/null > file
osiągnij cel właściwie, jednak pomimo wytrwałej miejskiej legendy, jejcat /dev/null
część nie robi absolutnie nic pożytecznego. Otwiera pseudoplik, który z założenia jest pusty, niczego nie czyta, a na koniec wychodzi. Użycie tego polecenia jest wówczas marnotrawstwem naciśnięć klawiszy, bajtów, wywołań systemowych i cykli procesora, i można je zastąpić bez żadnych zmian funkcjonalnych niewątpliwie szybszym poleceniem no-op,:
a nawet, w przypadku większości powłok, żadnym poleceniem.Pozwól mi spróbować metafory, aby wyjaśnić, jak bezużyteczne
cat /dev/null
jest. Powiedzmy, że Twoim celem jest opróżnienie szklanki.Najpierw usuwasz z niego płyn. Jest to wystarczające i właśnie to (
> file
) robi, biorąc pod uwagę fakt, że przekierowania są zawsze przetwarzane jako pierwsze.Następnie wybierz pustą butelkę (
/dev/null
) i wlej ją do pustej szklanki (cat
). To bezcelowy krok ...Jeśli czytasz połączony dokument do końca, możesz zauważyć komentarze w tym wierszu z ulepszonej wersji skryptu:
Oni rzeczywiście; szkoda
cat /dev/null
była trzymana w kodzie.To oznacza, że następujący kod będzie działać we wszystkich wspólnych muszli (zarówno
csh
ish
rodziny):i to będzie działać ze wszystkimi muszli przy użyciu składni Bourne, jak
ash
,bash
,ksh
,zsh
i lubi:Zauważ jednak, że w starożytnych powłokach Bourne'a sprzed POSIX-a dowolne z tych poleceń, w tym
cat /dev/null
nie obcinają pliku, jeśli zostanie on później napisany przez wciąż działający skrypt powłoki dołączający się do niego. Zamiast pliku z bajtami zerowymi byłby to plik rzadki z niezmienionym rozmiarem. To samo stałoby się, gdyby plik został napisany przez proces dążący do pozycji, którą uważa za aktualną przed zapisaniem.Uwaga: niektóre alternatywne rozwiązania często sugerowane do obcięcia pliku mają wady.
Oba poniższe po prostu nie wykonują zadania. Wynikowy plik nie jest pusty, ale zawiera pustą linię. Spowodowałoby to uszkodzenie plików dziennika takich jak te,
wtmp
które przechowują rekordy o stałej szerokości.Kolejny oparty na
sh
opcji BSD nie jest przenośny, POSIX nie określa żadnych dozwolonych opcji echa, więc możesz skończyć z plikiem zawierającym wiersz z „-n
”:Ten też nie jest przenośny przy użyciu
sh
sekwencji ucieczki Systemu V. Niektóre powłoki utworzą plik zawierający wiersz z „\c
”:Ten używa polecenia zaprojektowanego do wykonania zadania. Problem polega na
truncate
tym, że nie można go przenosić, ponieważ w systemie Unix / Linux może brakować tego polecenia, które nie zostało określone przez POSIX.Wreszcie, oto kilka alternatyw, które są przenośne i właściwie wykonają zadanie:
Jawne drukowanie pustego ciągu do pliku:
Za pomocą
true
polecenia, które jest ściśle równoważne poleceniu no-op,:
choć bardziej czytelne:źródło
csh
wdrożeń, chociaż niekoniecznie jest to udokumentowane. Ze stronycsh
podręcznika Solaris: Null command. This command is interpreted, but performs no action.
. Nie znalazłem żadnej wzmianki o tym samym ani natcsh
stronie podręcznika, ani na stronie BSDcsh
, ale ta składnia mogła zawsze działać.cat /dev/null
jest wyraźne zamierzenie./dev/null
skutecznego sposobu wprowadzania zerowych bajtów, zresztą bardziej niezawodnego niż używanie:
lub nic. W tym samym stronie Cyrus odpowiedź co było lakoniczne, ale prosto do punktu, miał zero głosów, podczas gdy jeden JakeGould za który kwestionuje faktcat /dev/null
był no-op (zobacz nasze komentarze) już co najmniej cztery głosy.>
lub:
nie jest jasne. Zgadzam się, że szkoda, że mity zostały rozpowszechnione z powodu ich użycia.printf "" > file
który jest zarówno przenośny (POSIX), jak i lekki tak często, jak wbudowany w powłokę.Jest to nieporęczny sposób na doprowadzenie pliku do zera.
źródło
csh
.: > messages
działa również.:
lubtrue
są bardziej oczywistymi wyborami dla poleceń, które nie wypisują niczego i zwracają wartość true.Aby obciąć otwarty plik. Jest to równoważne i bardziej zrozumiałe:
(Dodano -n, aby uniknąć nowej linii)
źródło
wtmp
przypadku. Zobacz moją zaktualizowaną odpowiedź.bash
, w-n
przeciwnym razie nie będzie działać we wszystkich powłokach Bourne'a.