Wolne miejsce na dysku lubi bardzo często się kurczyć. Nieważne jak duży dysk posiadasz, w pewnym momencie zacznie Ci brakować miejsca na dysku. Logi serwera zaczynasz rotować, pakujesz je a w ostateczności kasujesz bardzo stare pliki. Mimo wielkiego wysiłku miejsce zaczyna ubywać coraz szybciej. Zajętość partycji z logami zaczyna zbliżać się do 100%! Pojawia się problem, gdyż sumaryczna wielkość plików jest zdecydowanie mniejsza od tego co pokazuje zajętość dysku. Czary czy jakiś poważny błąd systemowy?

Aby zobrazować problem, wykonamy symulację takiej sytuacji. W pierwszym kroku sprawdzamy wielkość partycji, na której zacznie ubywać nam miejsce:

[root@seiken ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vg_seiken-lvol00
                      5.0G  2.0G  2.9G  41% /
tmpfs                 250M  112K  249M   1% /dev/shm
/dev/sda1              97M   39M   54M  42% /boot
/dev/mapper/vg_seiken-lvol01
                     1008M   50M  907M   6% /home
<strong>/dev/mapper/vg_seiken-lvol02
                     1008M  133M  825M  14% /var</strong>

W tym przypadku będzie to katalog /var. Ponieważ partycja jest prawie pusta, stworzymy w niej duży plik, aby ją troszkę zapchać. Do tego celu wykorzystamy następujące polecenie:

[root@seiken httpd]# dd if=/dev/zero of=/var/log/httpd/access_log bs=1024 count=802400
802400+0 records in
802400+0 records out
821657600 bytes (822 MB) copied, 4.76944 s, 172 MB/s

Stworzyliśmy plik access_log wypełniony zerami. Użycie dysku wzrosło nam do 96%. Teraz uruchamiamy serwer Apache HTTP, którego logi zaczną zapychać nam system plików. Prostym skryptem będziemy wywoływać stronę główną naszego serwera.

#!/bin/bash
while true;
do
	wget -U "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 ( .NET CLR 3.5.30729)" -q -O /dev/null http://127.0.0.1/
done

W ten sposób doszliśmy do momentu, w którym log serwera zaczyna szybko puchnąć. A co się stanie jeżeli go nagle skasujemy? Czy odzyskamy utracone miejsce? Sprawdźmy.

[root@seiken httpd]# df -h /var
Filesystem            Size  Used Avail Use% Mounted on
<strong>/dev/mapper/vg_seiken-lvol02
                     1008M  918M   40M  96% /var</strong>
[root@seiken /]# <strong>rm -vf /var/log/httpd/access_log</strong>
removed `/var/log/httpd/access_log'
[root@seiken /]# df -h /var
Filesystem            Size  Used Avail Use% Mounted on
<strong>/dev/mapper/vg_seiken-lvol02
                     1008M  925M   32M  97% /var</strong>
[root@seiken /]# du -hs /var/
<strong>100M    /var/</strong>

Niestety miejsca nadal ubywa! Natomiast cały katalog /var zajmuje tylko 100M. Gdzie się zatem podziała reszta? Otóż jak już wiadomo, wykonując polecenie rm nie usunęliśmy pliku, a jedynie informacje o nim.

Kiedy korzystasz z plików (czytasz lub piszesz), system operacyjny otwiera deskryptor i przypisuje go do pliku. Jest to uchwyt, do którego system sięga podczas każdej operacji. W naszym wypadku następuje ciągły zapis logów serwera do pliku. W pewnym momencie następuje usunięcie pliku. Niestety system nie zamknął deskryptora, ponieważ nie otrzymał takiego polecenie. Mimo, że pliku nie ma na dysku – deskryptor jest nadal otwarty i można z niego korzystać. Zatem zapis na dysk jest możliwy.

W takim wypadku wystarczy odszukać proces, który trzyma deskryptor i go zatrzymać. W tym wypadku jest to serwer Apache. Ale co zrobić jeżeli nie znamy procesu? Posłuży nam do tego polecenie lsof.

[root@seiken httpd]# lsof -n | grep deleted
httpd     14700      root    7w      REG      253,3 826014904       7678 /var/log/httpd/access_log (deleted)
httpd     14703    apache    7w      REG      253,3 826014904       7678 /var/log/httpd/access_log (deleted)
httpd     14704    apache    7w      REG      253,3 826014904       7678 /var/log/httpd/access_log (deleted)
httpd     14705    apache    7w      REG      253,3 826014904       7678 /var/log/httpd/access_log (deleted)
httpd     14706    apache    7w      REG      253,3 826014904       7678 /var/log/httpd/access_log (deleted)
httpd     14707    apache    7w      REG      253,3 826015272       7678 /var/log/httpd/access_log (deleted)
httpd     14708    apache    7w      REG      253,3 826015272       7678 /var/log/httpd/access_log (deleted)
httpd     14709    apache    7w      REG      253,3 826015272       7678 /var/log/httpd/access_log (deleted)
httpd     14710    apache    7w      REG      253,3 826015272       7678 /var/log/httpd/access_log (deleted)

Teraz wystarczy zatrzymać serwer Apache, aby deskryptor został zamknięty i miejsce zostało zwolnione. W przyrodzie nic nie ginie – w systemie Linux również.

  • Greg

    No to ja chyba mam poważny problem bo mam sporo takich plików :/

  • marcel

    A wykonanie reseta nie przyniesie takiego samego efektu jak zatrzymanie procesu?

  • Greg

    Może niewystarczyć. Przeładowanie aplikacji nie koniecznie musi zamknąć pliki logów. Baaa… może cały czas pisać np, że właśnie zrestartował się.