W przeszłości, w systemach Linux, byłem w stanie obcinać duże, otwarte pliki dziennika (to znaczy plik, który jest aktywnie zapisywany przez proces) przy użyciu cat /dev/null > file.log
.
Jednak w wersji 10.9 (Mavericks) tak nie jest. Mam plik 11 GB, do którego loguje się aplikacja, ale kiedy wykonuję to samo polecenie z tym plikiem, wydaje się, że nic się nie dzieje.
Kiedy próbuję tego na trywialnym pliku, to działa.
Oto ls -l /dev/null
:
crw-rw-rw- 1 root wheel 3, 2 Dec 16 12:49 /dev/null
Próbowałem też cp /dev/null file.log
bezskutecznie.
Myśląc, że mógłbym skorzystać z funkcji obcinania ( man 2 truncate
w Darwin), skompilowałem to i uruchomiłem na dwóch plikach, jednym o trywialnym rozmiarze, a drugim na prawdziwym pliku dziennika. Ponownie działało to przeciwko trywialnemu plikowi i nie działało na znacznie większym dzienniku.
/*
* Copyright (c) 2013 Thomas de Grivel <[email protected]>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
...
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <unistd.h>
int main (int argc, const char **argv)
{
int e = 0;
while (--argc) {
argv++;
if (truncate(*argv, 0)) {
e = 4;
warn("%s", *argv);
}
}
return e;
}
Proces powraca 0
niezależnie od używanego pliku.
du
lubdu -h
powiesz? Czy to możliwe, że plik jest plikiem rzadkim?du -h /tmp/file.log
wyniki w11G /tmp/file.log
Odpowiedzi:
cat /dev/null
jest nieco skomplikowanym sposobem na napisanie polecenia, które nie generuje danych wyjściowych.:
lubtrue
są bardziej oczywiste.We wszystkich
cat /dev/null > file
,: > file
a nawet> file
w większości powłok, powłoka otwiera plik z użycia znacznika O_TRUNC na standardowe wyjście, a następnie uruchamia aplikację, która nie ma nic wyjściowej, a następnie plik zostanie zamknięty i lewo obcięty.Jednak w takim przypadku lub podczas korzystania z
truncate
wywołania systemowego, jeśli proces wypełniający ten plik nie otworzył go flagą O_APPEND, następnym razem zapisze się w deskryptorze pliku, który ma w pliku, zapisze dane z przesunięciem znajdowały się w pliku.Ponieważ HFS + nie obsługuje plików rzadkich, oznacza to, że przestrzeń przed tym przesunięciem będzie musiała zostać ponownie przydzielona i wypełniona zerami przez system.
Musisz więc zabić aplikację, która pisze do tego pliku, zanim go obetniesz. Lub musisz upewnić się, że aplikacja otwiera plik za pomocą
O_APPEND
(podobnie jak w>>
przypadku korzystania z przekierowania powłoki).Jeśli chcesz z tym eksperymentować:
Teraz fd 3 mojej powłoki ma 100 000 bajtów w pliku
Teraz plik jest obcinany (rozmiar 0, brak miejsca na dysku).
Zapisując 1 bajt do pliku z przesunięciem 100000, plik ma teraz 100001 bajtów, pierwsze zera wszystkie, zużyłyby ponad 100 000 na HFS +, ale około jednego bloku dysku w większości innych systemów plików Unix
Z drugiej strony:
Zapis 1 bajtu do pliku nie z przesunięciem 100000, ale na końcu pliku z powodu
O_APPEND
. Plik ma 1 bajt i zajmuje miejsce potrzebne do przechowywania tego jednego bajtu.źródło