Server monitoringbeginner6 min lezen

Ubuntu-server monitoren zonder agent-wildgroei: wat je écht moet meten

Vier metingen die 90 % van de incidenten vooraf zichtbaar maken, met alleen wat er standaard op een Ubuntu 24.04- of Debian 12-server staat: sysstat, journalctl, df en een cron-script van dertig regels dat naar je telefoon pusht. Plus waarom "CPU boven 90 %" een slechte alert is.

Inhoud
  1. Stap 1: weet wat er nú gebeurt (de vijf commando's)
  2. Stap 2: zet historie aan (sysstat)
  3. Stap 3: de vier metingen die er toe doen
  4. Stap 4: een cron-script dat je telefoon aanspreekt
  5. Stap 5: schijfgroei voorspellen in plaats van ontdekken
  6. Valkuilen
  7. Wat je hiermee nog niet hebt
  8. Zo doet monsys het
  9. FAQ

De meeste servers gaan niet plat door iets exotisch. Ze gaan plat door een volle schijf, een proces dat langzaam al het geheugen opeet, een service die na een update niet meer opkwam, of een journal dat de root-partitie volschrijft. Alle vier zijn dagen van tevoren zichtbaar, als iemand kijkt. Deze how-to zet dat kijken op met wat er al op de machine staat: geen agent, geen SaaS, geen Grafana. Daarna lees je wat je dan nog mist.

Stap 1: weet wat er nú gebeurt (de vijf commando's)

Voor je iets automatiseert, moet je de handmatige versie kennen. Dit zijn de vijf commando's die je bij elke "de server is traag"-melding als eerste draait.

# 1. Wie eet de CPU en het geheugen?
top -bn1 | head -20

# 2. Is het CPU, I/O of swap? (sysstat)
sudo apt install -y sysstat
vmstat 1 5          # kolommen r (wachtrij), si/so (swap in/out), wa (I/O-wait)
iostat -xz 1 3      # %util per schijf, await in ms

# 3. Schijf: bytes én inodes
df -h --output=target,pcent,avail | sort -k2 -rn | head
df -i | awk 'NR==1 || $5+0 > 80'

# 4. Wat faalde er?
systemctl --failed
journalctl -p err -b --no-pager | tail -30

# 5. Werd er iets doodgeschoten door de OOM-killer?
journalctl -k -b | grep -iE 'out of memory|oom-kill' | tail

Twee dingen die beginners hier verkeerd lezen:

  • free -m toont "free" bijna altijd laag. Kijk naar de kolom available. Linux gebruikt vrij geheugen als page cache en geeft dat terug wanneer nodig.
  • load average is geen percentage. Een load van 4 op een 8-core machine is rustig; op een 2-core machine betekent het dat er permanent processen staan te wachten. Vergelijk altijd met nproc.

Stap 2: zet historie aan (sysstat)

Zonder historie kun je nooit zeggen "dit is sinds dinsdag". sysstat verzamelt elke 10 minuten een snapshot en bewaart standaard 28 dagen.

sudo apt install -y sysstat
# Ubuntu 24.04 en Debian 12 gebruiken systemd-timers:
sudo systemctl enable --now sysstat-collect.timer sysstat-summary.timer
# Op oudere Debian/Ubuntu: zet ENABLED="true" in /etc/default/sysstat

# Vanaf morgen kun je terugkijken:
sar -u          # CPU vandaag, per 10 min
sar -r          # geheugen
sar -d -p       # schijf-I/O per device
sar -n DEV      # netwerk per interface
sar -u -f /var/log/sysstat/sa12   # de 12e van deze maand

Wil je 90 dagen? Zet HISTORY=90 in /etc/sysstat/sysstat. Het kost een paar MB per maand.

Stap 3: de vier metingen die er toe doen

Je kunt honderd dingen meten. Dit zijn de vier waarvan de afwezigheid je een incident kost:

MetingWaaromDrempel die werkt
Schijfvulling en de richtingVolle schijf = database stopt, logs stoppen, updates falen> 85 % óf "vol binnen 7 dagen" op basis van groei
Failed units + reboot-requiredEen service die niet opkwam na een update merk je pas bij de klantsystemctl --failed ≠ 0, of /var/run/reboot-required bestaat > 3 dagen
OOM-killsHet geheugenlek van vandaag is de outage van volgende week≥ 1 OOM-kill in 24 u
HeartbeatDe server zelf is weg, dus meldt hij nietsGeen ping in 5 min

Let op wat er niet in staat: "CPU > 90 %". Een backup, een apt upgrade, een nachtelijke logrotate met compressie, een cron die een rapport bouwt — allemaal 100 % CPU, allemaal normaal. Die alert leert je binnen een week te negeren, en dan mis je de echte. Alert op symptomen (wachtrijen, I/O-wait boven 30 % gedurende 10 minuten, responstijd) of op afwijking van het normale patroon voor dat uur, niet op een absoluut getal.

Stap 4: een cron-script dat je telefoon aanspreekt

Dertig regels, geen dependencies buiten curl. Push gaat naar ntfy — self-hostbaar, gratis, EU-hostbaar. Vervang NTFY door je eigen topic.

sudo tee /usr/local/sbin/healthcheck.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
# Draait elke 10 min via cron. Meldt alleen wat afwijkt.
NTFY="https://ntfy.example.be/servers"
HOST=$(hostname -s)
ALERTS=()

# Schijf > 85 % (bytes of inodes), tmpfs uitgesloten
while read -r target pct; do
  ALERTS+=("disk $target ${pct}")
done < <(df -x tmpfs -x devtmpfs --output=target,pcent | awk 'NR>1 && $2+0>85')
while read -r target pct; do
  ALERTS+=("inodes $target ${pct}")
done < <(df -x tmpfs -x devtmpfs --output=target,ipcent | awk 'NR>1 && $2+0>85')

# Failed units
FAILED=$(systemctl --failed --no-legend | awk '{print $1}' | tr '\n' ' ')
[ -n "$FAILED" ] && ALERTS+=("failed: $FAILED")

# Reboot vereist sinds > 3 dagen
if [ -f /var/run/reboot-required ] && [ "$(find /var/run/reboot-required -mtime +3)" ]; then
  ALERTS+=("reboot-required > 3d ($(tr '\n' ' ' </var/run/reboot-required.pkgs))")
fi

# OOM-kills laatste 24 u
OOM=$(journalctl -k --since "24 hours ago" --no-pager | grep -ci 'out of memory')
[ "$OOM" -gt 0 ] && ALERTS+=("oom-kills: $OOM")

# Load > 2x cores, 15-min gemiddelde (dus geen korte piek)
CORES=$(nproc); LOAD15=$(awk '{print $3}' /proc/loadavg)
awk -v l="$LOAD15" -v c="$CORES" 'BEGIN{exit !(l > 2*c)}' && ALERTS+=("load15 $LOAD15 on $CORES cores")

if [ ${#ALERTS[@]} -gt 0 ]; then
  printf '%s\n' "${ALERTS[@]}" | curl -s -H "Title: $HOST" -H "Priority: high" --data-binary @- "$NTFY" >/dev/null
fi
EOF
sudo chmod 0755 /usr/local/sbin/healthcheck.sh
echo '*/10 * * * * root /usr/local/sbin/healthcheck.sh' | sudo tee /etc/cron.d/healthcheck

Test met een kunstmatige fout: sudo systemctl start nonexistent.service faalt niet zichtbaar, dus gebruik sudo systemctl mask cron && sudo systemctl restart cron — dat levert een failed unit op. Vergeet niet te unmask.

Heartbeat: de server die niets meer zegt

Bovenstaand script kan niet melden dat de server zelf weg is. Daarvoor heb je een tweede machine (of je laptop) die verwacht dat er iets binnenkomt. Simpelste vorm: het script doet elke 10 minuten een curl naar een ntfy-topic heartbeat-$HOST, en een cron op een andere host controleert of de laatste boodschap ouder is dan 15 minuten via curl "https://ntfy.example.be/heartbeat-$HOST/json?poll=1&since=15m". Het is knullig, en het werkt.

Stap 5: schijfgroei voorspellen in plaats van ontdekken

"85 %" op een schijf die 1 % per maand groeit is geen probleem. "60 %" op een schijf die 5 % per dag groeit is over acht dagen een outage. Met sar -F (Ubuntu 24.04+) of met je eigen logje bereken je de helling:

# Log elke dag de vulling
echo "0 6 * * * root df -B1 --output=target,used / /var | tail -n +2 | sed \"s/^/\$(date +\\%F) /\" >> /var/log/diskgrowth.log" | sudo tee /etc/cron.d/diskgrowth

# Na een week: bytes per dag en dagen tot vol
awk -v total="$(df -B1 --output=size / | tail -1)" '
  $2=="/" {n++; x[n]=n; y[n]=$3}
  END {
    for(i=1;i<=n;i++){sx+=x[i];sy+=y[i];sxy+=x[i]*y[i];sxx+=x[i]*x[i]}
    slope=(n*sxy-sx*sy)/(n*sxx-sx*sx)
    if (slope<=0) {print "krimpt of stabiel"; exit}
    printf "groei %.1f MB/dag, vol over %.0f dagen\n", slope/1e6, (total-y[n])/slope
  }' /var/log/diskgrowth.log

Dat is een lineaire regressie in awk. Niet elegant, wel voldoende om een aankoop of een cleanup twee weken vooruit te plannen.

Valkuilen

  • journald eet je schijf op. journalctl --disk-usage verrast mensen. Zet SystemMaxUse=500M in /etc/systemd/journald.conf en systemctl restart systemd-journald.
  • df ziet verwijderde-maar-open bestanden niet. Een logbestand van 20 GB dat is verwijderd terwijl nginx het nog open heeft, blijft ruimte innemen. sudo lsof +L1 toont ze; een reload van het proces geeft de ruimte vrij.
  • Snapshots en /boot. LVM-snapshots en oude kernels vullen /boot tot een apt upgrade faalt. Neem /boot op in de disk-check en draai apt autoremove --purge regelmatig.
  • Tijdzone in cron. cron draait in de systeemtijdzone; je ntfy-berichten en sar ook. Als de server in UTC staat en jij in Brussel kijkt, klopt "om 3 uur" niet. timedatectl vertelt het.
  • Alerts zonder eigenaar. Een script dat pusht naar een topic waar niemand meer op geabonneerd is, is geen monitoring. Zet in de kalender: elk kwartaal een testalert.

Wat je hiermee nog niet hebt

Dit werkt uitstekend voor één tot vijf servers. Daarna loop je tegen dezelfde vier muren:

  1. Geen historie over hosts heen. sar kijkt per machine. "Welke van mijn twintig servers groeit het snelst?" is een for-loop over ssh, elke keer weer.
  2. Geen deduplicatie. Een schijf op 86 % levert elke 10 minuten een push op tot iemand ingrijpt. Na een dag negeert iedereen het topic.
  3. Geen baseline. Het script weet niet dat deze host op dinsdagnacht altijd load 6 heeft door de backup. Jij wel, maar je vervanger niet.
  4. Geen bewijs. Een NIS2- of ISO 27001-auditor vraagt "hoe weet je dat je monitoring werkt?" en een cron-bestand is daarop een zwak antwoord.

Zo doet monsys het

De monsys-agent (één statisch Rust-binary, geen dependencies) meet dezelfde dingen — CPU, geheugen, schijf per mount, netwerk per NIC, failed units, OOM-kills, reboot-required — elke 15 seconden, en stuurt geaggregeerde signalen naar de hub. De hub bouwt per host een uur-van-dag baseline zodat je kunt alerteren op afwijking in plaats van op een absoluut getal, dedupliceert alerts tot één open rij per oorzaak, en houdt 13 maanden historie bij voor capaciteitsvragen. Heartbeat-stilte is een aparte detectie, met onderscheid tussen "even weg" en "al dagen stil".

De eerste vijf servers zijn gratis, voor altijd. Installeren is één regel: curl -fsSL https://get.monsys.ai/install.sh | sudo bash.

FAQ

Is 90 % CPU-gebruik een probleem?

Op zichzelf niet. Een server die zijn CPU gebruikt doet zijn werk. Het wordt een probleem als er tegelijk een wachtrij ontstaat (kolom r in vmstat structureel groter dan het aantal cores) of als de responstijd van je applicatie stijgt. Alert op die symptomen, niet op het percentage.

Heb ik Prometheus of Grafana nodig voor een paar servers?

Nee. Voor minder dan vijf servers geeft sysstat plus een cron-script met push-notificaties je 90 % van de waarde voor 5 % van het onderhoud. Prometheus wordt interessant wanneer je dashboards over meerdere hosts heen wilt of applicatie-metrics gaat scrapen.

Werkt dit ook op Debian 12?

Ja, alle commando's in dit artikel zijn getest op Debian 12 en Ubuntu 24.04. Het enige verschil is de naam van sommige units; sysstat-collect.timer bestaat op beide.

Geschreven door het monsys-team — sysadmins die dit dagelijks doen.

Zelf gedaan? Laat monsys het bijhouden.

Alles uit deze how-to draait in monsys als doorlopende check, met historie, alerts en audit-bewijs. 5 servers gratis, EU-gehost in België, geïnstalleerd in 60 seconden.