Pracując z różnego rodzaju aplikacjami, serwerami – bardzo często mamy do czynienia z logami. Jak to zwykle z nimi bywa, potrafią urosnąć do kolosalnych wielkości, zajmując nam cenną przestrzeń dyskową. W takim wypadku czyścimy system ze zbędnych plików logów. Najczęściej po prostu kasujemy stare pliki. A co się stanie jeżeli przypadkiem usuniemy plik, do którego aplikacja aktualnie pisze? Czy dane straciliśmy bezpowrotnie? Otóż nie! Dopóki działa daemon tej aplikacji, możemy przywrócić plik.

Dla przykładu weźmiemy serwer Apache HTTP. W domyślnej konfiguracji w systemie Fedora 13 – Goddard zapisuje on pliki logów w ścieżce /var/log/httpd.

[root@seiken httpd]# ls -l
total 2528
-rw-r--r--  1 root root  326536 Jun  3 18:52 access_log
-rw-r--r--. 1 root root  553888 Jan 16 22:46 access_log-20100124
-rw-r--r--. 1 root root 1149789 Jun  3 14:14 access_log-20100603
-rw-r--r--  1 root root     324 Jun  3 14:14 error_log
-rw-r--r--. 1 root root  234778 Jan 16 22:47 error_log-20100124
-rw-r--r--. 1 root root  293605 Jun  3 14:14 error_log-20100603

Plikiem, do którego aktualnie pisze serwer jest access_log. Skasujemy go za pomocą polecenia:

[root@seiken httpd]# rm -fv access_log
removed `access_log'

Tak naprawdę polecenie rm nie usuwa pliku. Dane nie są faktycznie niszczone. Zostaje skasowana jedynie informacja, która wskazuje, gdzie dany plik jest przechowywany. Miejsce po pliku zostaje udostępnione do ponownego wykorzystania. Jeżeli serwer nasz ma mało miejsca i jest mocno obciążony, możemy być pewni, że miejsce to zaraz zostanie nadpisane i stracimy dane.

Jeżeli nie, to możemy spróbować odzyskać plik. Istnieje kilka metod odzyskania plików pod Linuksem. W tym przypadku postaramy się odbudować deskryptor pliku i uzyskać do niego dostęp.

W pierwszej kolejności szukamy numer głównego PID serwera Apache.

[root@seiken ~]# ps -efww | grep httpd
root      1198     1  0 13:20 ?        00:00:02 /usr/sbin/httpd
apache    2804  1198  0 14:14 ?        00:00:00 /usr/sbin/httpd
apache    2805  1198  0 14:14 ?        00:00:00 /usr/sbin/httpd
apache    2806  1198  0 14:14 ?        00:00:00 /usr/sbin/httpd
apache    2807  1198  0 14:14 ?        00:00:00 /usr/sbin/httpd
apache    2808  1198  0 14:14 ?        00:00:00 /usr/sbin/httpd
apache    2809  1198  0 14:14 ?        00:00:00 /usr/sbin/httpd
apache    2810  1198  0 14:14 ?        00:00:00 /usr/sbin/httpd
apache    2811  1198  0 14:14 ?        00:00:00 /usr/sbin/httpd
root     11105 11066  0 19:27 pts/3    00:00:00 grep httpd

Korzystając z systemu plików procesów możemy obejrzeć deskryptor plików dla tego procesu. Przeglądając katalog /proc/1198/fd dowiemy się jakie otwarte pliki posiada proces.

[root@seiken ~]# ls -l /proc/1198/fd
total 0
lr-x------ 1 root root 64 Jun  3 18:56 0 -> /dev/null
l-wx------ 1 root root 64 Jun  3 18:56 1 -> /dev/null
l-wx------ 1 root root 64 Jun  3 18:56 2 -> /var/log/httpd/error_log
lrwx------ 1 root root 64 Jun  3 18:56 3 -> socket:[10043]
lrwx------ 1 root root 64 Jun  3 18:56 4 -> socket:[10044]
lr-x------ 1 root root 64 Jun  3 18:56 5 -> pipe:[16756]
l-wx------ 1 root root 64 Jun  3 18:56 6 -> pipe:[16756]
l-wx------ 1 root root 64 Jun  3 18:56 7 -> /var/log/httpd/access_log (deleted)
lr-x------ 1 root root 64 Jun  3 18:56 8 -> /dev/urandom

Jak można zobaczyć, znajdują się dam dowiązania symboliczne do plików. Teraz wystarczy przepisać plik z deskryptora do pliku loga. Można do tego celu wykorzystać polecenie:

[root@seiken ~]# cat /proc/1198/fd/7 > /var/log/httpd/access_log

Plik wrócił na swoje miejsce i można znowu odczytać z niego dane.

  • Greg

    No nawet nie wiedziałem, że tak można! Fajne. Można też dane odczytać bezpośrednio z tego deskryptora:

    <code>tail -f /proc/1198/fd/7</code>

  • Pablo

    Oooo! Bardzo fajne! Właśnie się zastanawiałem jak to jest. Bo skasowałem kiedyś duży plik, a miejsce na dysku nadal umykało mi.

  • Amy

    No nawet nie wiedziałem, że tak można! Fajne. Można też dane odczytać bezpośrednio z tego deskryptora:

    <code>tail -f /proc/1198/fd/7</code>

  • Pingback: Znikające miejsce na dysku! | thecamels.org()

  • Ciekawe, bardzo ciekawe rozwiązanie na pewno się przyda.