Swap inrichten en crashes door geheugengebrek voorkomen
Dienst weg, geen crashrapport, logbestand houdt midden in een zin op: zo toont u een OOM-kill aan, maakt u een swapbestand netjes aan en ziet u wanneer swap het probleem alleen uitstelt.
De dienst is weg. Geen crashrapport, geen stacktrace, het logbestand houdt midden in een regel op. MariaDB reageert niet meer, nginx levert een 502, de Minecraft-server is offline, en in de applicatie zelf staat niets bijzonders. Bijna altijd is het hetzelfde patroon: de kernel had geen vrij geheugen meer en heeft een proces beëindigd om het systeem in leven te houden. Dit artikel laat zien hoe u dat sluitend aantoont, hoe u een swapbestand netjes aanmaakt en blijvend vastlegt, en in welke gevallen swap het probleem slechts een paar minuten uitstelt.
Bewijs verzamelen: dmesg en journalctl
Voordat er ook maar iets wordt ingericht, hebt u het bewijs nodig. De kernel schrijft bij elke OOM-kill (Out of Memory) een uitvoerig blok in de ringbuffer:
dmesg -T | grep -iE 'out of memory|oom-kill'
Komt er geen regel terug en eindigt het commando met exitcode 1, dan is er sinds de laatste systeemstart geen kernel-OOM geweest. Die exitcode is geen fout, maar gewoon de gebruikelijke melding van grep zonder treffers. Komt er wel iets terug, dan ziet dat er op alle vier de hier behandelde systemen zo uit:
mariadbd invoked oom-killer: gfp_mask=0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=0
oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/system.slice/mariadb.service,task=mariadbd,pid=1043,uid=107
Out of memory: Killed process 1043 (mariadbd) total-vm:2894760kB, anon-rss:1583204kB, file-rss:0kB, shmem-rss:0kB, UID:107 pgtables:3820kB oom_score_adj:0
Drie dingen zijn daaraan van belang. Ten eerste: invoked oom-killer noemt het proces dat het geheugen heeft aangevraagd, niet per se de schuldige. Ten tweede: het beëindigde proces staat in de regel Killed process. Ten derde: bepalend is anon-rss, oftewel het werkelijk bezette anonieme geheugen. total-vm is gereserveerde adresruimte en bij Java of Go regelmatig een veelvoud daarvan, die waarde zegt niets.
Draait dmesg zonder root, dan antwoordt het op Debian 12, Debian 13, Ubuntu 22.04 en Ubuntu 24.04 met dmesg: read kernel buffer failed: Operation not permitted, omdat kernel.dmesg_restrict overal op 1 staat. Werk dus met sudo of als root. Blijft die melding ook als root staan, dan zit u in een LXC- of OpenVZ-container die geen toegang heeft tot de ringbuffer van het hostsysteem. Dan helpt alleen de tweede route via journalctl -k.
Na een herstart is de ringbuffer leeg. Vandaar de tweede route via het journal, en daar zit precies de valkuil waar de meeste handleidingen aan voorbijgaan:
journalctl -k --grep "Out of memory"
-k impliceert -b en toont dus uitsluitend de huidige bootcyclus. Is de machine na het voorval opnieuw opgestart, dan levert dit commando niets op, ook al is de gebeurtenis wel degelijk vastgelegd. Voor de vorige start of voor een bepaalde periode:
journalctl -k -b -1 --grep "Out of memory"
journalctl --since "7 days ago" --grep "Out of memory|oom-kill"
Antwoordt het eerste van beide commando's met No journal boot entry found for the specified boot (-1), dan is er in het journal simpelweg geen eerdere bootcyclus opgeslagen. Ook dat is geen fout, maar het normale beeld op een systeem waarvan het journal pas sinds de huidige start meeschrijft.
Dit werkt alleen wanneer het journal daadwerkelijk persistent is. Controleer dat:
ls -d /var/log/journal
Op Debian en Ubuntu bestaat deze map standaard, de test levert dus vrijwel altijd een treffer op en de mkdir hieronder doet dan niets en breekt ook niets. Ontbreekt de map bij uitzondering toch, dan staat het journal alleen in /run en is het na elke herstart verdwenen. Dat haalt u met twee commando's in:
mkdir -p /var/log/journal
systemctl restart systemd-journald
Kernel-OOM of systemd-limiet? Twee verschillende oorzaken
Dit onderscheid bepaalt of swap hier eigenlijk wel iets oplevert. Let op het veld constraint in de kernelmelding.
CONSTRAINT_NONE betekent: het hele systeem zat zonder geheugen. Hier helpt swap.
CONSTRAINT_MEMCG betekent: alleen één afzonderlijke control group is over haar limiet gegaan, terwijl de rest van het systeem ruim voldoende lucht had. Hier helpt swap niet, hier moet de limiet omhoog of moet de applicatie zuiniger worden. Zulke kills herkent u ook aan de dienst zelf:
systemctl status mariadb
Staat daar Main process exited, code=killed, status=9/KILL en verderop Failed with result 'oom-kill', dan was het een OOM-kill. Of er een cgroup-limiet in het spel was, verraadt een tellerbestand. Dat veronderstelt cgroup v2, wat op alle vier de distributies de standaard is; onder het oudere cgroup v1 bestaat het pad niet:
cat /sys/fs/cgroup/system.slice/mariadb.service/memory.events
systemctl show mariadb -p MemoryMax -p MemoryHigh
Een waarde groter dan nul bij oom_kill in combinatie met een ingestelde MemoryMax is het bewijs van een lokale limiet.
Er is nog een derde kandidaat die vaak over het hoofd wordt gezien, omdat hij helemaal niets in dmesg schrijft: systemd-oomd. Die dienst draait in userspace, leest de drukindicator PSI uit en beëindigt hele control groups nog voordat de kernel er zelf aan te pas komt. Zijn melding in het journal luidt ongeveer Killed /system.slice/... due to memory pressure for /system.slice being 60.00% > 50.00% for > 20s with reclaim activity. Controleer of hij draait:
systemctl is-active systemd-oomd
Op Ubuntu is systemd-oomd sinds 22.04 standaard geïnstalleerd en actief, op Debian hoort hij niet bij de standaarduitrusting. Een inactive op een Debian-server is dus te verwachten en geen aanwijzing voor een fout.
Belangrijk voor verderop: systemd-oomd kan ook aanslaan omdat de swap vol loopt. Bij een actieve oomd kan meer swap de afbrekingen dus juist eerder veroorzaken in plaats van later.
Vóór de swap: hoeveel geheugen ontbreekt er werkelijk
Twee minuten meten voorkomt een verkeerde beslissing.
free -h
Alleen de kolom available is interessant, niet free. Cache telt mee als beschikbaar en wordt vrijgegeven zodra dat nodig is. Wie naar de kolom free kijkt, houdt elk gezond systeem voor overbelast.
ps -eo pid,comm,rss,%mem --sort=-rss | head -n 11
systemd-cgtop --order=memory -b -n 1
De eerste regel toont de grootste afzonderlijke processen, de tweede groepeert per dienst. In de praktijk staan daar bijna altijd dezelfde drie verdachten: MariaDB met een te groot gekozen innodb_buffer_pool_size, PHP-FPM met een te hoge pm.max_children en een JVM met een te royale -Xmx.
Als uitgangspunt voor de grootte van het swapbestand volstaat deze tabel. Groter is op een server niet beter, want swap die u werkelijk volledig gebruikt, maakt de machine onbedienbaar.
| Werkgeheugen | Zinvol swapbestand |
|---|---|
| 1 GB | 1 tot 2 GB |
| 2 GB | 2 GB |
| 4 tot 8 GB | 2 tot 4 GB |
| 16 GB en meer | 4 GB, zelden meer |
Swapbestand aanmaken
Kijk eerst of er al swap bestaat. Ubuntu-servers uit het ISO-installatieprogramma brengen vaak al een /swap.img mee, Debian uit het installatieprogramma meestal een echte swappartitie. Cloud-images van beide distributies hebben doorgaans helemaal niets.
swapon --show
Blijft de uitvoer leeg, dan is er geen swap. Controleer vervolgens het bestandssysteem, want daarvan hangt de aanpak af:
findmnt -no FSTYPE -T /
Bij ext4 of xfs kunt u meteen door. Maak het bestand aan met dd, niet met fallocate. fallocate is sneller, maar levert afhankelijk van bestandssysteem en kernel een bestand met niet-geschreven gebieden op, en swapon weigert dat vervolgens. dd schrijft echte nullen en werkt overal:
dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
chmod 600 /swapfile
Vóór de volgende stap loont een controle die velen overslaan. Ligt onder /swapfile al een ingeschakelde swap, bijvoorbeeld uit een eerdere poging of uit de standaardinstelling van het image, dan weigert mkswap dienst met mkswap: error: /swapfile is mounted; will not make swapspace. Bepalend is daarbij alleen of het pad in /proc/swaps als actief vermeld staat. Kijk dus na en schakel het zo nodig uit:
swapon --show
swapoff /swapfile
Verschijnt er in swapon --show geen regel met /swapfile, dan kunt u het swapoff overslaan. Leg daarna het swapgebied aan:
mkswap /swapfile
mkswap antwoordt met Setting up swapspace version 1, size = 2 GiB (2147479552 bytes) en een nieuwe UUID. Pas daarna inschakelen:
swapon /swapfile
De volgorde staat niet ter discussie. chmod vóór mkswap, mkswap vóór swapon, en een eventuele swapoff vóór al het andere.
Zo weet u zeker dat het echt gelukt is
Dat swapon zonder foutmelding doorloopt, is nog geen bewijs. Deze twee controles leveren het bewijs:
swapon --show
free -h
swapon --show moet een regel tonen met /swapfile, file, de grootte en een prioriteit. In free -h moet de regel Swap: van 0B naar de nieuwe grootte zijn gesprongen. Blijft een van beide onveranderd, dan is de swap niet actief, wat het commando daarvoor ook meldde.
Blijvend vastleggen zonder de boot in gevaar te brengen
Een swapon overleeft geen herstart. De regel hoort in /etc/fstab, en juist daar gaan servers stuk. Maak eerst een back-up:
cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' >> /etc/fstab
Let op de twee groter-dan-tekens. Eén enkele > overschrijft het hele bestand, en dan start de machine niet meer netjes op. Controleer daarna de syntaxis, voordat u herstart:
findmnt --verify
Eén waarschuwing is daarbij volstrekt normaal en geen reden om de regel weer te verwijderen: [W] non-bind mount source /swapfile is a directory or regular file. Bij een swapbestand kan dat niet anders, het commando eindigt toch met retourwaarde 0. Ontbreekt in het bestand daarnaast een geldige swapheader, dan komt [W] cannot detect on-disk filesystem type erbij, en dan bent u werkelijk een mkswap vergeten.
Hebt u de swap hierboven al met de hand ingeschakeld via swapon /swapfile, dan is hij nu al actief. Zo niet, dan activeert swapon -a alle regels uit de fstab zonder dat u hoeft te herstarten. De eigenlijke test is echter een andere. systemd maakt van elke fstab-regel een eigen unit, voor /swapfile heet die swapfile.swap. Verschijnt deze unit en is ze actief, dan wordt de swap bij de volgende start gegarandeerd geactiveerd:
systemctl daemon-reload
systemctl list-units --type swap
Verwacht wordt een regel swapfile.swap loaded active active Swap. Ontbreekt die, dan klopt de fstab-regel niet en zou een herstart zonder swap eindigen. Pas als dit klopt, loont de herstart met aansluitend een controle via swapon --show.
swappiness goed instellen
De kernelparameter vm.swappiness regelt hoe bereidwillig de kernel anonieme pagina's naar de swap schrijft in plaats van bestandscache weg te gooien. De standaardwaarde is op Debian 12, Debian 13, Ubuntu 22.04 en Ubuntu 24.04 identiek 60:
cat /proc/sys/vm/swappiness
Het waardebereik loopt sinds kernel 5.8 van 0 tot 200, en alle vier de distributies zitten met hun kernel daarboven. Twee wijdverbreide misverstanden: vm.swappiness=0 schakelt swap niet uit, het voorkomt alleen het preventief wegschrijven en laat de kernel alsnog naar de swap grijpen voordat hij een proces beëindigt. En een lage waarde maakt een systeem niet sneller wanneer het geheugen er domweg niet is.
Zinvolle waarden: 10 tot 20 op databaseservers, 60 op gemengde webservers, 100 en meer wanneer u zram inzet. Blijvend hoort dit in een eigen bestand onder /etc/sysctl.d/, niet in de /etc/sysctl.conf, die bij pakketupdates in de weg zit:
echo 'vm.swappiness = 10' > /etc/sysctl.d/99-swappiness.conf
sysctl --system
cat /proc/sys/vm/swappiness
Het derde commando is de controle op succes. sysctl --system leest alle mappen in een vaste volgorde, en een al bestaand bestand met een hoger nummer kan uw waarde overschrijven.
Als het misgaat: de foutmeldingen letterlijk
swapon: /swapfile: insecure permissions 0644, 0600 suggested. Slechts een waarschuwing, de swap draait toch. Los het desondanks op, anders kan elke gebruiker de inhoud van weggeschreven processen meelezen: chmod 600 /swapfile.
swapon: /swapfile: swapon failed: Invalid argument De meest voorkomende fout. Ofwel is mkswap vergeten, ofwel bevat het bestand gaten. In het kernellogboek staat dan bovendien swapon: swapfile has holes. Oplossing: het bestand verwijderen en met dd in plaats van fallocate opnieuw aanmaken.
Op btrfs geldt dezelfde fout plus BTRFS warning: swapfile must not be copy-on-write. Hier is de volgorde anders: het bestand moet leeg worden aangemaakt en vóór het vullen als niet-copy-on-write worden gemarkeerd. Eerst nog een aanwijzing die over een draaiende server kan beslissen: truncate -s 0 en rm lopen ook door wanneer onder dat pad nog een actieve swap gekoppeld is. De kernel wijst daarna naar blokken die niet meer bestaan. Vermeldt swapon --show het pad als actief, dan moet er dus zonder uitzondering eerst een swapoff /swapfile overheen.
truncate -s 0 /swapfile
chattr +C /swapfile
Daarna zoals gebruikelijk vullen met dd, chmod 600, mkswap, swapon. Op gecomprimeerde subvolumes en in snapshots werkt swap nog steeds niet.
swapon: /swapfile: swapon failed: Operation not permitted U zit in een container. LXC, OpenVZ en Docker delen de kernel van de host en mogen geen eigen swap inschakelen. Controleren met:
systemd-detect-virt
Meldt het commando kvm, qemu of none, dan draait er een eigen kernel en is swap mogelijk. Meldt het lxc, openvz of docker, dan helpt alleen meer werkgeheugen of een product met volwaardige virtualisatie. De KVM-rootservers en dedicated servers van KernelHost hebben een eigen kernel, daar kunt u swap zonder beperkingen inrichten.
dd: error writing '/swapfile': No space left on device De schijf is te vol. Eerst df -h, daarna het half geschreven bestand met rm /swapfile verwijderen, anders blijft het ruimte innemen. Ook hier geldt: toont swapon --show het pad als actief, dan hoort er een swapoff /swapfile vóór het verwijderen.
Het systeem start niet meer op, de noodconsole verschijnt. Bijna altijd een typefout in /etc/fstab. Log in via de console in het klantenpaneel, voer daarna mount -o remount,rw / uit, verwijder de foutieve regel of kopieer /etc/fstab.bak terug en herstart. Precies daarvoor is de back-up eerder aangemaakt.
Verschillen tussen Debian 13, Debian 12, Ubuntu 24.04 en 22.04
De commando's zijn op alle vier de systemen identiek, de uitgangssituatie niet.
- Aanwezige swap: Ubuntu Server uit het ISO-installatieprogramma maakt vaak een
/swap.imgaan, Debian uit het installatieprogramma een swappartitie. Cloud-images van beide distributies komen zonder swap. Begin dus altijd metswapon --show. - systemd-oomd: op Ubuntu sinds 22.04 standaard geïnstalleerd en actief, op beide Debian-versies geen onderdeel van de standaarduitrusting. Dat verklaart waarom identieke software op twee ogenschijnlijk gelijke systemen op verschillende manieren kan sterven.
- Database: Debian 12 en Debian 13 leveren geen
mysql-server, daar draait altijd MariaDB (10.11 onder Debian 12, 11.8 onder Debian 13). Op Ubuntu 22.04 en 24.04 zijn beide beschikbaar. De standaardwaarden voorinnodb_buffer_pool_sizeverschillen navenant, en precies die waarde is op kleine servers de meest voorkomende oorzaak van een OOM. - Java: Debian 12 kent alleen OpenJDK 17, Debian 13 alleen OpenJDK 21, Ubuntu 22.04 en 24.04 dekken 8 tot en met 21 af. Een JVM zonder ingestelde
-Xmxneemt standaard een kwart van het werkgeheugen, bij meerdere instanties is de OOM-kill dan voorgeprogrammeerd. - Kernelmeldingen: opmaak en formulering van de OOM-melding zijn op alle vier de systemen gelijk, de voorbeelden hierboven passen overal.
- swappiness: overal 60 als standaardwaarde.
Wanneer swap helpt en wanneer het probleem alleen wordt uitgesteld
Swap helpt betrouwbaar bij korte pieken, bijvoorbeeld tijdens een back-up, een pakketupgrade of een nachtelijke import. Swap helpt bij diensten die veel geheugen bezetten en daarna dagenlang niets doen, want die pagina's mogen gerust op de schijf staan. En in het ergste geval levert swap u de minuten op waarin de SSH-sessie nog reageert en u kunt ingrijpen, in plaats van dat u voor een dode server staat.
Swap helpt niet wanneer de blijvende behoefte domweg boven het werkgeheugen ligt. Dan begint het systeem te thrashen: het schrijft onophoudelijk weg en leest weer terug, de load loopt op tot tweecijferige waarden, het CPU-gebruik blijft laag en alles wacht op I/O. In de praktijk is dat erger dan een nette OOM-kill, omdat ook het inloggen er niet meer doorheen komt. Twee commando's laten zien of u in die toestand zit:
vmstat 1 5
test -e /proc/pressure/memory && cat /proc/pressure/memory
Bij vmstat tellen de kolommen si en so. Aanhoudend driecijferige waarden betekenen dat er actief wordt weggeschreven en teruggelezen. In /proc/pressure/memory is full avg10 doorslaggevend: waarden boven 10 betekenen dat het hele systeem tien procent van de tijd op geheugen wacht. Boven 40 is de machine praktisch dood. Het bestand bestaat echter alleen wanneer Pressure Stall Information in de kernel actief is. De standaardkernels van Debian en Ubuntu hebben dat aan boord, andere kernels niet per se. Vandaar de afscherming met test -e: ontbreekt het bestand, dan blijft de uitvoer leeg in plaats van dat u een No such file or directory voor een defect aanziet. PSI valt achteraf in te schakelen via de kernel-bootparameter psi=1.
Welke processen daadwerkelijk in de swap staan, beantwoordt deze regel:
grep VmSwap /proc/*/status | sort -k2 -rn | head
Swap levert evenmin iets op tegen een cgroup-limiet (CONSTRAINT_MEMCG), tegen geheugen dat met mlock is vastgezet en tegen een JVM waarvan de heap groter is geconfigureerd dan het aanwezige RAM. De garbage collector loopt regelmatig over de volledige heap en haalt elke weggeschreven pagina meteen weer terug.
De drie hulpmiddelen voor het geval swap niet volstaat
zram maakt een gecomprimeerd swapgebied in het RAM zelf aan. Dat is ordes van grootte sneller dan een bestand op de schijf en levert afhankelijk van de data 20 tot 40 procent effectief meer geheugen op:
apt update
apt install -y zram-tools
Configureren doet u in /etc/default/zramswap via ALGO=zstd en PERCENT=50, daarna volgt systemctl restart zramswap. Controle met zramctl en opnieuw swapon --show, daar verschijnt dan /dev/zram0. Met zram hoort vm.swappiness omhoog naar 100 tot 180, omdat het wegschrijven hier goedkoop is.
earlyoom grijpt in voordat de kernel het systeem laat vastlopen, en beëindigt gericht in plaats van op basis van een heuristiek:
apt install -y earlyoom
In /etc/default/earlyoom stelt u via EARLYOOM_ARGS de drempels in en beschermt u belangrijke processen, bijvoorbeeld met -m 5 -s 5 --avoid '(^|/)(sshd|systemd)$'. Daarmee blijft het inloggen via SSH bereikbaar terwijl de geheugenvreter sneuvelt.
Vaste grenzen per dienst zijn de netste oplossing wanneer een bepaalde dienst regelmatig uit de band springt. Via systemctl edit mariadb legt u MemoryHigh=1200M en MemoryMax=1500M vast. De dienst wordt dan afgeremd en zo nodig in zijn eentje beëindigd, in plaats van dat hij de hele server meesleurt. Controle via systemctl show mariadb -p MemoryMax.
De eigenlijke oplossing blijft in de meeste gevallen echter de configuratie van de applicatie: innodb_buffer_pool_size op een realistische maat, pm.max_children op basis van de werkelijke geheugenbehoefte per worker, en een ingestelde -Xmx voor elke JVM. Swap is het vangnet, niet de oplossing.
Terugdraaien als het toch niet bevalt
De weg terug is kort en hoort in deze volgorde te verlopen:
swapoff /swapfile
Bij een sterk gevulde swap kan dat commando meerdere minuten duren, omdat alle pagina's terug het RAM in moeten. Loopt het vast op swapoff: /swapfile: swapoff failed: Cannot allocate memory, dan is er in het RAM geen plaats voor dat terugtransport en moeten er eerst diensten worden gestopt. Pas na een geslaagde swapoff verwijdert u de fstab-regel en het bestand:
rm /swapfile
swapon --show
Het bestand verwijderen terwijl het nog gekoppeld is, levert een systeem op waarvan het geheugenbeheer naar een niet meer bestaande inode wijst. Dat loopt slecht af. Sluit af met nog een keer free -h en een herstart als tegenproef.
Veelgestelde vragen
Hoeveel swap heb ik nodig op een server?
Waarom toont journalctl -k geen OOM-kill terwijl er wel een was?
Hoe zie ik of de kernel of een systemd-limiet het proces heeft beëindigd?
Waarom mislukt swapon met "Invalid argument"?
Kan ik swap inrichten in een container?
Betekent vm.swappiness=0 dat er helemaal niets meer wordt weggeschreven?
2026 KernelHost GmbH. Alle rechten voorbehouden. Deze handleiding is auteursrechtelijk beschermd. Publicatie op andere websites, geheel, gedeeltelijk of in bewerkte vorm, is zonder onze schriftelijke toestemming niet toegestaan. Citeren met bronvermelding en link is uitdrukkelijk welkom.

