Skrypt powłoki systemu Unix do obcięcia dużego pliku

87

Próbuję napisać skrypt uniksowy, który obetnie / opróżni plik, który jest ciągle zapisywany / otwierany przez aplikację, gdy osiągnie, powiedzmy, 3 GB miejsca. Wiem, że poniższe polecenie by to zrobiło:

cp /dev/null [filename]

Ale mam zamiar uruchomić to w środowisku produkcyjnym automatycznie jako zadanie cron - po prostu publikując tutaj, aby zobaczyć, czy napotkaliście jakieś problemy podczas robienia czegoś podobnego.

siusiu
źródło
To są prod. dzienniki nie mają wartości? Miałem szczęście przechowywać dzienniki produkcji przez rok + (w bzip2 -9 fmt) i miałem kilka małych narzędzi, które ułatwiały wyodrębnianie czasów wykonywania zadań, przetwarzane rekordy, a po załadowaniu do arkusza kalkulacyjnego były łatwe do obliczenia i wykresu współczynników obciążenia i sporo rzeczy. Odkryliśmy problem z hdwr z powodu spadku współczynnika obciążenia. Tak, istnieją świetne narzędzia do monitorowania, więc wszystko zależy od Twojej sytuacji. JAKO ODDZIELNA OPCJA, czy spojrzałeś na logrotateto, może to zapewnić ci jakąś wartość (ale denerwuj się przy jej ustawianiu (tylko zgadywanie)!).
shellter
5
Zwróć uwagę, że jeśli plik dziennika zostanie otwarty z flagą O_APPEND, to obcinanie będzie skuteczne. Jeśli nie zostanie otwarty z flagą O_APPEND, program będzie kontynuował zapis z przesunięciem 3 GiB (za pierwszym razem); system potraktuje pierwsze 3 GiB jako wszystkie bajty zerowe (co jest dobrze kompresowane), ale plik będzie się powiększał. Wszystko zależy od programu zapisującego log.
Jonathan Leffler,

Odpowiedzi:

116

Aby dodać kolejną odpowiedź,

: > filename

: nie jest operacją w bash (zgodnym z POSIX), więc zasadniczo otwiera plik do zapisu (co oczywiście obcina plik), a następnie natychmiast go zamyka.

EDYCJA: jak skomentował shellter, tak naprawdę nie potrzebujesz polecenia, aby wykonać przekierowanie:

$ echo foo > foo.txt
$ cat foo.txt
foo
$ > foo.txt
$ cat foo.txt
$

Samo proste przekierowanie wyczyści plik.

Chepner
źródło
25
lub po prostu > filename(jak na pewno wiesz). Powodzenia wszystkim.
shellter
5
@shelter "$> file" nie jest POSIX i nie jest przenośne. Powinieneś użyć polecenia „:” no-op przed przekierowaniem, jak początkowo sugerowano.
Aaron Toponce
2
+ plus za uśmiechniętą buźkę
Chris Suszyński
2
Jak wskazał @AaronToponce, "$> plik" rzeczywiście nie jest przenośny; w mojej konfiguracji Zsh powoduje zawieszenie się powłoki (prawdopodobnie oczekiwanie na wejście). "$:> file" działa dobrze w Zsh.
Linus Arver
1
@TechEnthusiast To zależy od Twoich oczekiwań. Samo obcięcie jest atomowe, ale tak naprawdę nie wiesz, kiedy nastąpi to w odniesieniu do konkretnego zapisu. Możesz na przykład zakończyć częściową linią na początku pliku.
chepner,
65

Użyłem następującego polecenia w debianie

truncate -s 0 filename
Ricardo Marimon
źródło
@SteveClay: sudo sh -c ': > filename'również obciętefilename
Perleone
2
@SteveClay Sugestia OP działa również bez zarzutu z sudo: sudo cp /dev/null filename. cpJest również przenośny, podczas gdy truncatejest tylko nowoczesny Linux.
Tino
11

Wydaje mi się to rozsądne. Oczywiście Unix pozwoliłby ci to zrobić na około 50 różnych sposobów. Na przykład,

echo -n "" >filename
cat /dev/null >filename
Don Branson
źródło
2

trunc filename

działa na wersji UNIX AIX

San
źródło