Dlaczego miałbyś cat / dev / null na czymkolwiek?
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:
rm file
touch file
lub podobny:
mv file file.old
gzip file.old
touch file
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, jej cat /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:
cat / dev / null> wtmp # ':> wtmp' i '> wtmp' mają ten sam efekt.
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
i sh
rodziny):
cd /var/log
: > messages
: > wtmp
echo "Log files cleaned up."
i to będzie działać ze wszystkimi muszli przy użyciu składni Bourne, jak ash
, bash
, ksh
, zsh
i lubi:
cd /var/log
> messages
> wtmp
echo "Log files cleaned up."
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.
echo > file
echo "" > file
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
”:
echo -n > file
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
”:
echo "\c" > file
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.
truncate -s 0
Wreszcie, oto kilka alternatyw, które są przenośne i właściwie wykonają zadanie:
Jawne drukowanie pustego ciągu do pliku:
printf "" > file
Za pomocą true
polecenia, które jest ściśle równoważne poleceniu no-op, :
choć bardziej czytelne:
true > file