Warunkowe czyszczenie cache systemu

Każdy, kto kiedyś administrował maszyną zarządzaną przez system z rodziny Linux (szczególnie taką, która na swoim pokładzie miała nieco mniej RAM) zetknął się pewnie z problemem zajmowania pamięci operacyjnej przez elementy cache systemu. W internecie krąży wiele prostych poradników, jakich komend użyć, aby usunąć te dane. Na potrzeby infrastruktury, którą administruję obudowałem te komendy skryptem, który pozwala ustalić warunki dla czyszczenia cache.


Skrypt, który tradycyjnie dostępny jest na końcu notki, wywołujemy w następujący sposób:

./freemem $1 $2 $3

Funkcjonalność czyszczenia cache, do której mamy dostęp przez /proc wdrożona została od jądra w wersji  2.6.16. W związku z tym ani skrypt, ani opisane niżej metody nie zadziałają w dystrybucjach pracujących w oparciu o starsze jajko.

Pierwszym parametrem niezbędnym do wywołania skryptu jest poziom czyszczenia cache. Jądro oferuje nam 3 takie poziomy:

  1. zwalnianie cache stronnicowania:
    echo 1 > /proc/sys/vm/drop_caches
  2. zwalnianie cache dentries i inodes:
    echo 2 > /proc/sys/vm/drop_caches
  3. zwalnianie cache dentries i inodes oraz stronnicowania:
    echo 3 > /proc/sys/vm/drop_caches

Operacja drop_caches jest bezpieczna dla systemu, żadne używane aktualnie elementy cache nie zostaną usunięte. Jednak, aby zwiększyć bezpieczeństwo całego procesu, przed wyczyszczeniem cache warto  uruchomić program sync:

sync

Program ten odpowiedzialny jest za czyszczenie buforów systemu plików. Jego uruchomienie wymusi zapisanie wszystkich zmian na dysku i nadpisanie super bloku.

Operacja ta również wiąże się ze zwolnieniem pewnej ilości miejsca w pamięci RAM, dzięki jej wykonaniu zyskujemy jednak przede wszystkim pewność, że wszystkie poczynione przez nas zmiany (o ile takie było ich przeznaczenie) zostały zapisane na dysku.

W moim skrypcie wymuszam wykonanie obu komend (sync przed drop_caches) z uwzględnieniem poziomu czyszczenia cache podanego przez użytkownika:

sync; echo $1 > /proc/sys/vm/drop_caches

Drugim parametrem, którego podania wymaga skrypt jest limit zajętości pamięci, po przekroczeniu którego wykonane zostanie czyszczenie cache. Tutaj z pomocą przychodzi nam grep i awk, więc limit możemy podawać wraz z jednostką wielkości (zarówno w formie skróconej: G,M,k; jak i pełnej: GB, MB, kB) w formacie [liczba][jednostka], skrypt sam odpowiednio przemnaża podaną wartość do kilobajtów, które są także domyślną jednostką pamięci dla skryptu.

Podany przez nas limit porównywany jest z aktualnym stanem systemu. Stan ten możemy uzyskać przez dostęp do /proc, a konkretnie:

cat /proc/meminfo

skąd jako wyjście otrzymamy informację o stanie pamięci systemu – nie tylko RAM, ale także SWAP, cache czy też pewne informacje o plikach stronicowania.  Z tych systemowych informacji filtrujemy dane o stanach pamięci i przekazujemy je do zmiennych w celu porównania z naszym limitem.

Trzeci argument, który musimy podać podczas wywołania skryptu przyjmuje dwie wartości 1 albo 0. W zależności od podanej wartości przekroczenie podanego wcześniej limitu będzie liczone względem:

  1. całej zajętej pamięci operacyjnej w przypadku ustawienia wartości argumentu na 0
  2. zajętości danych cache w przypadku ustawienia wartości argumentu na 1

Podsumowując, przykładowe wywołanie skryptu dla czyszczenia cache na poziomie 3, przy limicie 3GB liczonym względem całej zajętej pamięci wyglądałoby następująco:

./freemem 3 3G 0

Tak przygotowany skrypt możemy umieścić w cron‚ie i wykonywać co jakiś czas.

Wprowadzenie limitów dla wykonania czyszczenia cache zapobiega niepotrzebnemu kasowaniu zapamiętanych danych, kiedy ich ilość nie przekracza bezpiecznego limitu zaplanowanego przez administratora. Skrypt pozwala także na szybką zmianę wszystkich ustawień czyszczenia pamięci w zależności do naszych aktualnych potrzeb.

Mikołaj Niedbała

I'm a Poland based IT administrator, linux administrator and IT engineer creating professional IT infrastructure solutions based on Linux and virtual environments.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *