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.
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>
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.
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>
[…] 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. […]
Ciekawe, bardzo ciekawe rozwiązanie na pewno się przyda.