Limiter la mémoire et le CPU avec systemd
Évitez qu’un processus bloque votre VPS : configurez MemoryHigh, MemoryMax, CPUQuota et TasksMax, puis vérifiez l’erreur OOM et le chargement du drop-in.
Limiter la mémoire et le CPU d’un processus avec un drop-in systemd
Vous limitez la mémoire et le CPU d’un processus sur un VPS Linux en ajoutant quelques lignes à l’unité qui exécute le processus. MemoryMax= définit la limite stricte de mémoire. CPUQuota= définit la limite de temps processeur. Ces deux limites sont appliquées par cgroup v2 (groupes de contrôle, version 2), la fonctionnalité du noyau que systemd utilise déjà pour comptabiliser chaque service du serveur.
sudo systemctl edit myapp.serviceCette commande ouvre un fichier drop-in contenant des instructions dans les commentaires. Ajoutez ceci au-dessus de ces instructions :
[Service]
MemoryHigh=512M
MemoryMax=768M
MemorySwapMax=0
CPUQuota=80%
TasksMax=128sudo systemctl daemon-reload
sudo systemctl restart myapp.service
systemctl show myapp.service -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec -p TasksMaxsystemctl show doit reprendre vos valeurs dans les unités propres au noyau : MemoryMax=805306368 et CPUQuotaPerSecUSec=800ms. S’il affiche MemoryMax=infinity, le drop-in n’a jamais été chargé. Vérifiez que le fichier se trouve bien à /etc/systemd/system/myapp.service.d/override.conf et qu’il commence par l’en-tête [Service], car une ligne de configuration sans section au-dessus amène systemd à journaliser Assignment outside of section. Ignoring. et à démarrer le service sans aucune limite.
La suite de ce guide explique comment choisir ces valeurs et quels problèmes peuvent encore survenir une fois qu’elles sont définies.
Pourquoi un processus qui s’emballe peut geler un VPS sans le remplir
Un processus qui atteint une limite stricte de mémoire est arrêté en environ une seconde, puis le service redémarre. C’est le bon cas. Le mauvais cas est celui où rien ne s’arrête : la machine répond au ping, SSH accepte la connexion, mais l’invite shell n’apparaît jamais. La machine est active et très sollicitée, mais aucun de ces traitements n’est utile.
Voici le mécanisme, car il n’est pas évident. Lorsque la mémoire libre devient insuffisante, le kernel récupère des pages au lieu d’en allouer de nouvelles. Les pages les moins coûteuses à récupérer sont celles qui sont adossées à des fichiers, et le page cache contient le code exécutable de tout ce qui s’exécute. Le kernel évince donc les pages de code de sshd, et l’instruction suivante exécutée par sshd provoque un page fault qui doit relire ces octets depuis le stockage. Chaque processus finit par attendre le disque au lieu de s’exécuter. Les mêmes pages sont évincées puis rechargées en boucle : c’est le thrashing.
Deux facteurs aggravent ce problème sur un VPS par rapport à un laptop. Le stockage est souvent connecté au réseau ou partagé, et chaque page fault coûte donc plus de millisecondes qu’avec un périphérique NVMe local. De plus, le kernel ne mesure pas le temps, mais les échecs : tant que la récupération de pages en restitue une, même très lentement, le kernel considère qu’il progresse et ne déclenche pas l’out of memory (OOM) killer. Une machine peut rester dans cet état pendant plusieurs minutes avant qu’un processus soit arrêté.
Vous pouvez observer le phénomène. Le kernel expose les pressure stall information (PSI) sous Linux 4.20 et versions ultérieures :
cat /proc/pressure/memory
cat /proc/pressure/iosome avg10=63.72 avg60=41.02 avg300=12.33 total=13729481
full avg10=48.15 avg60=30.44 avg300=8.90 total=9114233La ligne full est celle qui compte. full avg10=48.15 signifie que pendant 48% des dix dernières secondes, toutes les tâches non inactives de la machine étaient bloquées simultanément par un manque de mémoire. Aucun de vos traitements ne progressait donc. Sur un serveur sain, full reste proche de zéro. Au-dessus de 10, la lenteur devient perceptible pour un utilisateur. À partir de 40, la machine est généralement décrite comme gelée.
C’est aussi pourquoi une limite seule ne constitue pas une garantie. Une unité soumise à MemoryHigh= est ralentie au lieu d’être arrêtée. Elle reste donc active et lente, et rien ne la redémarre puisque, du point de vue de systemd, elle n’a jamais échoué. Une unité plafonnée qui peut toujours utiliser le swap génère des lectures et des écritures imputées à cette unité, mais exécutées par un périphérique partagé. Elle peut donc faire augmenter /proc/pressure/io pour tous les autres services de la machine. Les limites déterminent qui supporte le coût d’un manque de ressources, mais elles ne créent aucune capacité.
Vérifier que votre VPS utilise cgroup v2
stat -fc %T /sys/fs/cgroupcgroup2fs est la hiérarchie unifiée, dont les paramètres mémoire ci-dessous ont besoin. tmpfs signifie que la machine a démarré avec l’ancienne organisation v1, où MemoryHigh= et MemorySwapMax= ne sont pas pris en charge et où le comportement OOM par unité est différent, même si CPUQuota= fonctionne toujours via l’ancien fichier cpu.cfs_quota_us. Ubuntu 22.04 et les versions ultérieures, ainsi que Debian 11 et les versions ultérieures, utilisent v2 par défaut. Une ancienne image ne l’utilise pas. Avec systemd 257 ou une version antérieure, un kernel démarré avec systemd.unified_cgroup_hierarchy=0 ne l’utilise pas non plus. systemd 258 a supprimé la prise en charge de cgroup v1 et monte toujours la hiérarchie unifiée au démarrage. Sur les versions qui l’intègrent, cet argument ne permet donc plus de réactiver v1.
Avec cgroup v2, systemd active par défaut le suivi de la mémoire pour chaque unité. Les valeurs sont donc déjà disponibles :
systemd-cgtop -mCette commande liste les cgroups triés par utilisation mémoire. C’est le moyen le plus rapide de répondre à la question « qu’est-ce qui consomme les ressources de cette machine ? » tant qu’elle peut encore répondre. Si le serveur est nouveau, le compte et la configuration du firewall décrits dans les dix premières minutes sur un nouveau VPS passent avant cette étape.
MemoryHigh ralentit. MemoryMax tue.
La différence entre ces deux paramètres mémoire détermine la manière dont une panne se manifeste.
MemoryHigh=est une limite souple. Au-delà, le kernel récupère plus agressivement la mémoire de ce cgroup et ralentit volontairement ses allocations. L’utilisation peut dépasser cette valeur et aucun processus n’est tué.MemoryMax=est une limite stricte. Lorsqu’une allocation ne peut plus être satisfaite dans cette limite, l’OOM killer s’exécute dans ce cgroup et tue l’un des processus de cette unité.
C’est la vraie raison de définir MemoryMax= pour tout service auquel vous n’accordez pas une confiance totale. Sans limite, un manque de mémoire affecte tout le serveur, et l’OOM killer global choisit sa victime selon oom_score, ce qui désigne généralement le processus le plus volumineux. Il s’agit le plus souvent de votre base de données, et non du script qui a provoqué la fuite mémoire. Avec une limite, le processus tué appartient à l’unité qui a causé le problème.
Définissez les deux paramètres, avec MemoryHigh= environ 20 à 30 % en dessous de MemoryMax=. L’écart constitue une zone d’alerte : une fuite lente dépasse High et se manifeste par un service qui devient lent, tandis qu’un pic soudain dépasse directement Max et provoque l’arrêt du service.
Les valeurs en pourcentage sont calculées à partir de la mémoire physique installée. Ainsi, MemoryMax=25% sur une offre de 4 GB correspond à 1 GB et reste égal au quart du serveur après le redimensionnement de l’offre. MemorySwapMax=0 empêche complètement cette unité d’utiliser le swap. Lorsqu’elle atteint MemoryMax=, le processus est donc tué rapidement au lieu de ralentir longuement dans le swap. En dessous de cette valeur, MemoryHigh= peut toujours la ralentir. Le dépassement de la limite haute ne déclenche jamais l’OOM killer : une unité qui oscille entre les deux limites reste lente au lieu de s’arrêter.
Certains services permettent de définir leur consommation à l’avance au lieu de la mesurer. Une unité Ollama dimensionne son cache KV à partir de la fenêtre de contexte que vous lui attribuez. Consultez donc le coût en RAM de l’augmentation de num_ctx avant de choisir une limite.
Une limite doit être accompagnée d’une restart policy. Sinon, le processus tué laisse simplement le service à l’arrêt.
[Unit]
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Restart=on-failure
RestartSec=5sStartLimit* doit être placé dans [Unit] et Restart= dans [Service]. Si vous placez l’un des deux paramètres dans la mauvaise section, systemd l’ignore. Cinq redémarrages en cinq minutes indiquent une fuite plutôt qu’un incident ponctuel. Après cela, systemd abandonne et laisse l’unité en échec. C’est l’état que vous voulez pouvoir identifier plus tard, plutôt qu’une boucle de crash qui masque le problème.
Limiter le CPU avec CPUQuota ou le partager avec CPUWeight
CPUQuota= correspond à un pourcentage du temps disponible sur un CPU. CPUQuota=50% équivaut à la moitié d’un cœur. CPUQuota=200% correspond à deux cœurs, que l’unité peut répartir sur autant de threads qu’elle le souhaite. Sur une offre de 2 vCPU, CPUQuota=200% correspond à toute la machine.
CPUWeight= constitue le meilleur choix par défaut pour la plupart des services. Il s’agit d’une part relative comprise entre 1 et 10000, et la valeur par défaut du kernel est 100. Cette pondération ne s’applique que lorsqu’un autre processus est en concurrence : une tâche de sauvegarde à CPUWeight=20 cède la priorité à un serveur web à 100 lorsque la machine est chargée, tout en pouvant utiliser l’intégralité de la machine lorsqu’elle est inactive. Une limite stricte gaspille cette capacité disponible.
Soyez réaliste quant à l’intérêt d’une limite CPU. Un processus limité par le CPU bloque rarement Linux, car le scheduler continue d’attribuer du temps processeur à tous les processus. C’est la mémoire qui peut mettre une machine hors service. Utilisez CPUQuota= si vous voulez un plafond prévisible, par exemple pour un build ou un agent qui fonctionnerait sinon à pleine capacité pendant une heure. Le dimensionnement de ce type de charge est une question distincte, traitée dans la quantité de RAM et de CPU nécessaire à un VPS exécutant un agent de programmation.
Si le CPU semble saturé alors qu’aucun de vos processus ne consomme beaucoup de ressources, la cause peut se trouver de l’autre côté de l’hyperviseur. Il s’agit du temps CPU steal causé par un voisin bruyant, et aucune quota que vous définissez ne pourra le modifier.
TasksMax arrête une boucle de fork
TasksMax= correspond au nombre de processus et de threads qu’une unité peut contenir. Les threads sont comptabilisés. Un service Java ou Go a donc besoin de davantage de marge que ne le laisse penser la liste des processus. C’est la protection la moins coûteuse contre un script qui fork en boucle, car le fork échoue à l’intérieur de l’unité au lieu d’épuiser les PID disponibles sur le serveur.
TasksMax=128Lorsqu’une unité atteint la limite, le kernel journalise une ligne qui indique le cgroup :
cgroup: fork rejected by pids controller in /system.slice/myapp.serviceLe programme signale généralement fork: retry: Resource temporarily unavailable. Vérifiez la valeur appliquée par défaut par le manager avec systemctl show -p DefaultTasksMax.
Limiter une tâche ponctuelle avec systemd-run
Vous n’avez pas besoin d’un unit file pour utiliser tout cela. systemd-run en crée un de manière transitoire autour d’une seule commande.
sudo systemd-run --scope -p MemoryMax=1G -p MemorySwapMax=0 -p CPUQuota=50% -p TasksMax=64 ./import-data.sh--scope exécute la commande dans votre terminal après avoir affiché Running scope as unit: run-r7c1a....scope. La sortie reste à l’écran et les limites disparaissent lorsque la commande se termine. Toutes les propriétés de systemd.resource-control fonctionnent après -p.
Pour une tâche longue, supprimez --scope et donnez-lui un nom. Elle s’exécute alors en arrière-plan comme un service transitoire et écrit ses journaux dans le journal :
sudo systemd-run --unit=nightly-import -p MemoryMax=1G -p CPUWeight=20 ./import-data.sh
journalctl -u nightly-import -fLes mêmes options fonctionnent avec --user lorsque vous n’êtes pas root, mais votre user manager ne dispose que des contrôleurs qui lui ont été délégués ; une propriété peut donc y être refusée. Dans ce cas, exécutez-la avec sudo. Lorsqu’une tâche doit être conservée durablement, déplacez les paramètres tels quels dans une véritable unité : voir exécuter un script comme service et timer systemd.
La question du swap, avec une réponse honnête
Le swap modifie la forme de la panne, mais ne l’empêche pas.
Sans swap, une fuite atteint la limite et un processus s’arrête en quelques secondes. La panne est brutale, courte et facile à identifier ensuite dans le journal. Avec du swap, le kernel écrit sur le disque les pages anonymes peu utilisées et gagne du temps. Si le processus allait se stabiliser, le swap vous aide. S’il continue à consommer de la mémoire, le swap transforme une panne de cinq secondes en un blocage de vingt minutes. Ce blocage est pire, car un processus arrêté vous laisse toujours un shell fonctionnel, contrairement à une machine qui passe son temps à faire du thrashing.
swapon --show
free -hSur un petit VPS, un compromis viable consiste à conserver un fichier de swap modeste pour les pages allouées une seule fois et jamais réutilisées, puis à définir MemorySwapMax=0 sur les unités que vous acceptez de perdre. Les services importants conservent leur swap. Les services imprévisibles atteignent rapidement leur limite, et la stratégie de redémarrage définie à côté de cette limite les relance.
Réduire vm.swappiness est un levier peu efficace, et il est utile de comprendre pourquoi. Cela déplace uniquement l’équilibre entre l’éviction du page cache et le swap des pages anonymes. Dans les deux cas, une lecture sur disque sera nécessaire plus tard. Cela change les pages qui subissent le thrashing, mais pas le fait que la machine subisse du thrashing.
Un daemon OOM précoce tue les processus avant le blocage
Le noyau attend que la récupération de mémoire échoue complètement. Sur un petit VPS, cette attente correspond exactement à la période pendant laquelle la machine devient inaccessible. Deux daemons en espace utilisateur réduisent cette fenêtre en surveillant eux-mêmes la mémoire et en tuant les processus plus tôt.
earlyoom vérifie jusqu’à dix fois par seconde la mémoire disponible et le swap libre. Il tue le processus dont la valeur oom_score est la plus élevée uniquement lorsque les deux seuils sont franchis. Sur une machine sans swap, seul le seuil de mémoire est pris en compte.
sudo apt install earlyoom
systemctl status earlyoomLe paquet Debian et Ubuntu démarre le service lors de l’installation. Ses options se trouvent dans /etc/default/earlyoom :
EARLYOOM_ARGS="-m 5,2 -s 5,2 --avoid ^(sshd|systemd)$ --prefer ^(node|python3)$"-m PERCENT définit le minimum de mémoire disponible et -s PERCENT le minimum de swap libre. Les deux valeurs sont de 10 pour cent par défaut. Le second nombre de chaque paire correspond au seuil de SIGKILL : earlyoom envoie SIGTERM lorsque la mémoire et le swap passent tous deux sous leur première valeur, puis SIGKILL lorsqu’ils passent tous deux sous la seconde. Celle-ci correspond par défaut à la moitié de la première. Laissez les motifs --avoid et --prefer sans guillemets et sans espaces, car systemd transmet les caractères de guillemet tels quels et un motif entre guillemets ne correspond jamais. Appliquez une modification avec sudo systemctl restart earlyoom. Consultez journalctl -u earlyoom pour voir quel processus a été tué et quelle quantité de mémoire il occupait.
systemd-oomd est l’autre option. Sa page de manuel le décrit comme « un service système qui utilise cgroups-v2 et les informations PSI (Pressure Stall Information) pour surveiller le système et prendre des mesures correctives avant qu’un OOM ne se produise dans l’espace noyau ». Il agit sur des cgroups entiers plutôt que sur des processus individuels. Il tue donc une unité, et non un processus enfant isolé. Les unités l’activent avec ManagedOOMMemoryPressure=kill ou ManagedOOMSwap=kill. Les seuils se trouvent dans /etc/systemd/oomd.conf.
systemctl status systemd-oomd
oomctloomctl affiche ce qui est actuellement surveillé. Sur une image serveur, il ne s’agit souvent de rien, car le réglage doit être activé unité par unité. Choisissez un seul daemon. L’exécution des deux daemons crée une concurrence pour choisir la victime et complique l’identification de la cause de chaque kill.
Quelle unité était responsable ?
Commencez par le kernel, car il enregistre chaque kill qu’il effectue.
journalctl -k --grep "Killed process" --since "2 hours ago"Un kill du OOM killer global ressemble à ceci :
Out of memory: Killed process 4127 (node) total-vm:2731084kB, anon-rss:1874232kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:4212kB oom_score_adj:0anon-rss correspond à la mémoire anonyme, comme le heap, que le processus occupait en RAM au moment de sa mort, soit environ 1.8 GB ici. Les mappages de fichiers résidents et la mémoire partagée sont comptabilisés séparément, dans file-rss et shmem-rss. Lisez le nom entre crochets avec prudence. Il s’agit de la victime choisie par le kernel. Le kernel choisit le plus gros processus, qui n’est pas toujours celui à l’origine du manque de mémoire.
Un kill dû à une limite de cgroup porte un préfixe différent. Le rapport affiché au-dessus indique le cgroup qui a atteint son propre plafond :
Memory cgroup out of memory: Killed process 8811 (python3) total-vm:1044320kB, anon-rss:769112kB, file-rss:0kB, shmem-rss:0kB, UID:998 pgtables:1720kB oom_score_adj:0Ce préfixe fournit l’essentiel du diagnostic. Memory cgroup out of memory signifie qu’une unité a atteint le MemoryMax= que vous lui avez attribué, tandis que le reste du serveur fonctionnait normalement. Un simple Out of memory signifie que la machine entière a manqué de mémoire. Vos limites étaient donc absentes ou trop généreuses pour leur capacité cumulée.
Demandez ensuite à systemd ce qu’il a constaté :
systemctl status myapp.service
journalctl -u myapp.service -n 50myapp.service: A process of this unit has been killed by the OOM killer.
myapp.service: Main process exited, code=killed, status=9/KILL
myapp.service: Failed with result 'oom-kill'.systemctl status indique la même chose sur une seule ligne, dans Active: failed (Result: oom-kill).
Les compteurs du cgroup constituent la troisième source. C’est la seule qui enregistre la limitation de débit, laquelle ne produit jamais de ligne dans les journaux :
cat /sys/fs/cgroup/system.slice/myapp.service/memory.events
cat /sys/fs/cgroup/system.slice/myapp.service/memory.peaklow 0
high 4213
max 118
oom 12
oom_kill 12high compte le nombre de fois où l’unité a dépassé MemoryHigh= et a été limitée. max compte le nombre de fois où elle a atteint la limite stricte, et oom_kill compte les processus effectivement tués. Une valeur élevée de high avec oom_kill 0 correspond au cas silencieux décrit précédemment : depuis la création de son cgroup, l’unité a été limitée à plusieurs reprises sans qu’un seul processus soit tué, et systemd n’a donc enregistré aucun échec. Le compteur ne fait qu’augmenter. Lisez-le deux fois à une minute d’intervalle : un high qui continue d’augmenter signifie que la limitation est en cours. memory.peak (Linux 5.19 et versions ultérieures) contient l’utilisation maximale atteinte par le cgroup. C’est cette valeur qui sert à dimensionner MemoryMax=. Les deux fichiers sont réinitialisés au redémarrage de l’unité, car systemd recrée le cgroup.
Une condition préalable sous-tend tout cela. Si /var/log/journal n’existe pas, le journal est stocké en RAM et toutes les lignes disparaissent après le redémarrage nécessaire pour récupérer le serveur.
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
journalctl --list-bootsLe fait que journalctl --list-boots affiche plus que le boot courant signifie que l’historique est désormais conservé. journalctl -k -b -1 peut donc afficher les messages du kernel du boot qui a échoué.
Point de départ pour un petit VPS
Sur une offre de 2 GB, laissez 300 à 400 MB au noyau et au cache de pages. Ne faites pas en sorte que la somme des plafonds atteigne les 2 GB, car chaque unité peut atteindre son maximum au même moment. Accordez la plus grande part au service prioritaire. Limitez ensuite tous les services secondaires autour de celui-ci.
[Service]
MemoryHigh=256M
MemoryMax=384M
MemorySwapMax=0
CPUWeight=20
TasksMax=64
Restart=on-failure
RestartSec=5sConserver un accès au serveur justifie un réglage supplémentaire. OOMScoreAdjust=-500 dans un drop-in pour ssh.service réduit fortement le risque que le tueur OOM global choisisse votre démon SSH comme victime. Cela peut faire la différence entre réparer le serveur et le redémarrer depuis le panneau de contrôle. Ce réglage modifie uniquement le choix de la victime par le noyau. Il ne réduit pas la durée du blocage.
Les conteneurs s’exécutent dans leurs propres cgroups. Ceux-ci sont créés par le runtime de conteneurs et non par vos fichiers d’unité. Une limite sur docker.service ne devient donc pas une limite appliquée à un conteneur. Les équivalents par conteneur de MemoryMax= et CPUQuota= sont présentés dans définir des limites de mémoire et de processeur dans Docker Compose.
FAQ
Pourquoi mon VPS s’est-il figé au lieu de tuer le processus qui s’emballait ?
Parce que le kernel évalue la progression selon que la récupération libère des pages, et non selon le temps nécessaire. Lorsque la mémoire manque, il évacue le cache de pages, y compris les pages exécutables des programmes en cours, puis les relit à l’instruction suivante. Tout attend le stockage et aucune allocation n’a techniquement échoué : l’OOM killer n’est donc jamais appelé. Consultez /proc/pressure/memory pendant le problème : un full avg10 supérieur à 40 signifie que, pendant plus de 40% des dix dernières secondes, toutes les tâches non inactives étaient bloquées simultanément par la mémoire. Un daemon userspace tel que earlyoom tue le processus avant que la machine n’atteigne cet état.
Quelle est la différence entre MemoryHigh et MemoryMax ?
MemoryHigh= est une limite souple qui applique une régulation. Le kernel récupère de force la mémoire de l’unité et ralentit ses allocations, mais l’utilisation peut dépasser cette valeur et aucun processus n’est tué. MemoryMax= est une limite stricte : une allocation qui ne peut pas être satisfaite dans cette limite déclenche l’OOM killer dans le cgroup propre à cette unité. Le processus à l’origine du problème est donc tué, plutôt que le plus gros processus de la machine. Définissez MemoryHigh= en dessous de MemoryMax= et considérez l’écart entre les deux comme une zone d’avertissement.
Comment trouver le service touché par l’OOM killer ?
Exécutez journalctl -k --grep "Killed process" --since "2 hours ago". Une ligne commençant par Memory cgroup out of memory signifie qu’une unité a atteint son propre MemoryMax=, tandis qu’un simple Out of memory signifie que toute la machine est tombée à court de mémoire. Exécutez ensuite journalctl -u <unit> -n 50 et recherchez Failed with result 'oom-kill'. Si /var/log/journal n’existe pas sur votre serveur, le journal était conservé en RAM et les éléments de preuve ont disparu lors du redémarrage. Créez donc ce répertoire avant le prochain incident.
Dois-je ajouter du swap à un petit VPS ?
Un petit fichier swap aide pour les pages froides qui sont allouées une fois et ne sont plus jamais utilisées. Il n’aide pas avec un processus qui s’emballe : il retarde l’arrêt et remplace une courte interruption par un long blocage auquel vous ne pouvez pas vous connecter pour intervenir. Gardez une quantité de swap modeste et définissez MemorySwapMax=0 sur les unités que vous acceptez de perdre. Elles atteindront ainsi rapidement leur plafond et, avec Restart=on-failure défini, redémarreront automatiquement, tandis que les services importants conserveront leur swap.
Puis-je limiter une commande sans écrire de fichier d’unité ?
Oui. sudo systemd-run --scope -p MemoryMax=1G -p CPUQuota=50% ./script.sh exécute la commande dans votre terminal, au sein d’un scope temporaire avec ces limites. Les limites disparaissent lorsqu’elle se termine. Chaque propriété de systemd.resource-control est disponible après -p, donc MemorySwapMax=, TasksMax= et CPUWeight= fonctionnent également. Supprimez --scope et ajoutez --unit=name pour exécuter la tâche en arrière-plan et envoyer sa sortie dans le journal.