== Using _systemd-run_ to limit something's RAM consumption on the fly A year ago I wrote about [[using cgroups to limit something's RAM consumption CgroupsForMemoryLimiting]], for limiting the resources that _make_'ing Firefox could use when I did it. At the time my approach with an explicitly configured [[cgroup https://en.wikipedia.org/wiki/Cgroups]] and the direct use of _cgexec_ was the only way to do it on my machines; although [[systemd http://www.freedesktop.org/wiki/Software/systemd/]] has facilities to do this in general, my version could not do this for ad hoc user-run programs. Well, I've upgraded to Fedora 21 and that's now changed, so here's a quick guide to doing it the systemd way. The core command is [[_systemd-run_ http://www.freedesktop.org/software/systemd/man/systemd-run.html]], which we use to start a command with various limits set. The basic command is: .pn prewrap on > systemd-run --user --scope -p LIM1=VAL1 -p LIM2=VAL2 [...] CMD ARG [...] The _--user_ makes things run as ourselves with no special privileges, and is necessary to get things to run. The _--scope_ basically means 'run this as a subcommand', although systemd considers it a named object while it's running. Systemd-run will make up a name for it (and report the name when it starts your command), or you can use _--unit NAME_ to give it your own name. The limits you can set are covered in [[systemd.resource-control http://www.freedesktop.org/software/systemd/man/systemd.resource-control.html]]. Since systemd is just using cgroups, the limits you can set up are just the cgroup limits (and the documentation will tell you exactly what the mapping is, if you need it). Conveniently, systemd-run allows you to specify memory limits in Gb (or Mb), not just bytes. The specific limits I set up in [[the original entry CgroupsForMemoryLimiting]] give us a final command of: > systemd-run --user --scope -p MemoryLimit=3G -p CPUShares=512 -p BlockIOWeight=500 make (Here I'm once again running _make_ as my example command.) You can inspect the parameters of your new scope with '_systemctl show --user _', and change them on the fly with '_systemctl set-property --user LIM=VAL_'. I'll leave potential uses of this up to your imagination. _systemd-cgls_ can be used to show all of the scopes and find any particular one that's running this way (and show its processes). (It would be nice if _systemd-cgtop_ gave you a nice rundown of what resources were getting used by your confined scope, but as far as I can tell it doesn't. Maybe I'm missing a magic trick here.) Now, there's a subtle semantic difference between what we're doing here and what I did in [[the original entry]]. With _cgexec_, everything that ran in our _confine_ cgroup shared the same limit even if they were started completely separately. With _systemd-run_, separately started commands have separate limits; if you start two _make_s in parallel, each of them can use 3 GB of RAM. I'm not sure yet how you fix this in the official systemd way, but I think it involves defining [[a slice http://www.freedesktop.org/software/systemd/man/systemd.slice.html]] and then attaching our scopes to it. (On the other hand, this separation of limits for separate commands may be something you consider a feature.) === Sidebar: _systemd-run_ versus _cgexec_ et al In Fedora 20 and Fedora 21, _cgexec_ works okay for me but I found that systemd would periodically clear out my custom _confine_ cgroup and I'd have to do '_systemctl restart cgconfig_' to recreate it (generally anything that caused systemd to reload itself would do this, including _yum_ package updates that poked systemd). Now that the Fedora 21 version of _systemd-run_ supports _-p_, using it and doing things the systemd way is just easier. (I wrap the entire invocation up in a script, of course.)