Un serviciu systemd robust trebuie să reziste la trei probleme diferite: procesul se închide neașteptat, aplicația rămâne pornită dar nu mai răspunde sau începe să consume excesiv memoria, procesorul ori numărul de procese. Aceste situații se controlează separat prin politici de restart, watchdog și limite cgroups.
Restart=on-failure este recomandat pentru numeroase servicii care rulează permanent, însă restarturile trebuie limitate pentru a evita o buclă rapidă atunci când aplicația are o configurație invalidă.
Pregătește utilizatorul și directoarele serviciului
Să presupunem că aplicația este instalată în /opt/myapp/bin/myapp și rulează cu utilizatorul myapp.
sudo useradd \
--system \
--home /var/lib/myapp \
--shell /usr/sbin/nologin \
myapp
sudo install -d \
-o myapp -g myapp -m 0750 \
/var/lib/myapp /var/log/myapp
Aplicația nu trebuie să ruleze ca root dacă nu are nevoie de privilegii administrative.
Creează unitatea systemd
Deschide:
sudo nano /etc/systemd/system/myapp.service
Adaugă:
[Unit]
Description=Aplicație web internă
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=5min
StartLimitBurst=5
[Service]
Type=notify
User=myapp
Group=myapp
WorkingDirectory=/var/lib/myapp
ExecStart=/opt/myapp/bin/myapp
Restart=on-failure
RestartSec=5s
TimeoutStartSec=30s
TimeoutStopSec=20s
NotifyAccess=main
WatchdogSec=30s
MemoryHigh=512M
MemoryMax=768M
CPUQuota=150%
TasksMax=256
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
StartLimitIntervalSec=5min și StartLimitBurst=5 permit cel mult cinci tentative de pornire în intervalul stabilit. Dacă serviciul continuă să eșueze, systemd îl marchează drept failed în loc să îl repornească permanent.
Înțelege politica de restart
Restart=on-failure repornește serviciul după un cod de ieșire nereușit, un semnal fatal, timeout sau eșec de watchdog. Este mai potrivit decât Restart=always atunci când aplicația trebuie să poată încheia legitim execuția fără să fie pornită din nou.
RestartSec=5s introduce o pauză între oprire și următoarea tentativă. Fără această întârziere, o eroare de configurare poate genera sute de porniri și mesaje în jurnal.
După ce ai corectat cauza unei limite de pornire:
sudo systemctl reset-failed myapp.service
sudo systemctl start myapp.service
Watchdog-ul trebuie implementat în aplicație
WatchdogSec=30s nu verifică automat o adresă HTTP și nici consumul procesului. Aplicația trebuie să comunice cu systemd prin sd_notify().
După inițializare, procesul principal trimite:
READY=1
Apoi trimite periodic:
WATCHDOG=1
Documentația recomandă transmiterea notificării înainte de expirarea intervalului, uzual la jumătatea acestuia. Pentru WatchdogSec=30s, un heartbeat la aproximativ 15 secunde oferă o marjă rezonabilă. Dacă notificările încetează, systemd consideră serviciul defect și aplică politica Restart=.
Dacă aplicația nu suportă protocolul systemd notify, folosește Type=simple și elimină WatchdogSec=. Simpla adăugare a directivei nu transformă un program obișnuit într-un serviciu monitorizat activ.
Limitează resursele prin cgroups
Systemd plasează procesele unității într-un cgroup și aplică limitele întregului serviciu, inclusiv proceselor copil. Cgroups organizează procesele ierarhic și permit controlarea resurselor alocate.
În exemplul nostru:
MemoryHigh=512M
MemoryMax=768M
CPUQuota=150%
TasksMax=256
MemoryHigh= este pragul principal de control: peste el, sistemul încearcă să reducă presiunea exercitată de serviciu. MemoryMax= este limita dură și trebuie tratată ca ultimă linie de apărare. Dacă memoria nu poate fi menținută sub acest plafon, poate fi declanșată terminarea proceselor din cgroup.
CPUQuota=150% permite consum echivalent cu un nucleu și jumătate, nu 150% din întreaga capacitate a unui server cu multe nuclee. TasksMax=256 limitează numărul total de procese și threaduri, reducând impactul unei bucle de creare a proceselor.
Validează și testează unitatea
Verifică sintaxa:
sudo systemd-analyze verify \
/etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
Inspectează rezultatul:
systemctl status myapp.service
journalctl -u myapp.service -f
systemctl show myapp.service \
-p Restart \
-p WatchdogUSec \
-p MemoryHigh \
-p MemoryMax \
-p CPUQuotaPerSecUSec \
-p TasksMax
Pentru un test controlat al restartului, într-un laborator:
sudo systemctl kill \
--signal=SIGKILL \
myapp.service
Serviciul trebuie să reapară ca activ după întârzierea configurată. Testează separat depășirea memoriei, răspunsul aplicației și oprirea heartbeat-ului. Nu experimenta cu limite agresive direct în producție.
Un serviciu robust nu este cel care repornește fără încetare, ci cel care detectează blocarea reală, revine controlat și nu poate epuiza resursele întregului server.
Surse folosite
systemd — configurarea unităților .service, watchdog și politicile de restart.
systemd — limitarea CPU, memoriei și proceselor prin cgroups.
Linux Kernel Documentation — arhitectura și controlerele cgroup v2.
systemd sd_notify — notificările READY=1 și WATCHDOG=1.

















































