objectif
Exécuter une commande dans une unité systemd transitoire, avec quotas CPU/mémoire, durée maximale, sandbox réseau/FS, utilisateur dédié, et logs consultables via journalctl. Idéal pour builds, scripts d’ETL, ou maintenance.
code minimal
# run éphémère (unit auto), 50% CPU, 512M RAM, durée max 10 min, logs dans journald
sudo systemd-run -p CPUQuota=50% -p MemoryMax=512M -p RuntimeMaxSec=600 \
--working-directory=/srv/data.pm \
--unit=data-pm-build \
/usr/bin/npm run build
utilisation
# 1) suivre les logs et l'état
journalctl -u data-pm-build -f -o short-iso
systemctl status data-pm-build
# 2) sandbox stricte en lecture seule + pas de réseau (build deterministe)
sudo systemd-run --unit=data-pm-build \
-p CPUQuota=75% -p MemoryMax=1G -p RuntimeMaxSec=900 \
-p ProtectSystem=strict -p ProtectHome=read-only -p PrivateTmp=yes \
-p IPAddressDeny=any \
--setenv=NODE_ENV=production \
--working-directory=/srv/data.pm \
/usr/bin/npm ci && /usr/bin/npm run build
# 3) exécuter sous un utilisateur dédié sans root, avec cwd et env
sudo systemd-run --unit=data-pm-etl \
-p User=data-pm -p Group=data-pm \
-p CPUWeight=50 -p IOWeight=50 -p MemoryHigh=768M -p RuntimeMaxSec=1200 \
--setenv=TZ=UTC --setenv=API_URL=https://api.data.pm \
--working-directory=/srv/jobs \
/usr/bin/python3 /srv/jobs/etl_data_pm.py
# 4) scope interactif côté utilisateur (pas besoin de sudo), hérite du TTY
systemd-run --user --scope -p CPUQuota=80% -p MemoryMax=1G \
bash -lc 'pytest -q'
# 5) arrêter/annuler une unité transitoire en cours
sudo systemctl stop data-pm-build
variante(s) utile(s)
# un service transitoire qui redémarre automatiquement en cas d'échec (Restart=on-failure)
sudo systemd-run --unit=data-pm-task \
-p Restart=on-failure -p RestartSec=5s \
-p CPUQuota=60% -p MemoryMax=512M -p RuntimeMaxSec=600 \
/usr/local/bin/task-data-pm.sh
# verrouillage fin des appels système (seccomp) et des capabilities
sudo systemd-run --unit=data-pm-safe \
-p NoNewPrivileges=yes \
-p CapabilityBoundingSet= \
-p SystemCallFilter='@system-service ~@mount @raw-io @reboot @debug' \
-p LockPersonality=yes -p PrivateDevices=yes \
/usr/local/bin/maintenance.sh
# réseau autorisé uniquement vers une IP (ex: cache interne) via sandbox IP
sudo systemd-run --unit=data-pm-net \
-p IPAddressDeny=any -p IPAddressAllow=10.0.0.5 \
curl -fsS http://10.0.0.5/cache/prefetch?site=data.pm
# limiter le nombre de fichiers ouverts (NOFILE) et processes (NPROC)
sudo systemd-run --unit=data-pm-limits \
-p LimitNOFILE=4096 -p TasksMax=256 \
/usr/bin/node /srv/data.pm/scripts/generate.js
# monter un répertoire en lecture seule dans le namespace du service
sudo systemd-run --unit=data-pm-ro \
-p ReadOnlyPaths=/srv/data.pm \
-p TemporaryFileSystem=/tmp:ro \
/usr/bin/true
notes
systemd-runcrée une unité transitoire (service ou scope) avec propriétés-p. Nommez-la avec--unitpour la suivre facilement.- Quotas et limites utiles:
CPUQuota,CPUWeight,MemoryMax/High,IOWeight,RuntimeMaxSec,TasksMax,LimitNOFILE. - Sandbox clés:
ProtectSystem=strict,ProtectHome=read-only,PrivateTmp=yes,NoNewPrivileges=yes,CapabilityBoundingSet=,IPAddressDeny/Allow,ReadOnlyPaths,TemporaryFileSystem. - Pour exécuter en user non privilégié, utilisez
-p User=et-p Group=(ou--usersi vous restez dans la session utilisateur). - Les logs sont dans journald:
journalctl -u <unit>. L’état et le code retour sont visibles viasystemctl status.