A nightly batch job had a habit of forgetting it shared the machine with anyone. It would spin up, eat every core and most of the memory, and drag everything else on the host into the mud until it finished. I could not fix the job itself, it was not mine to change, but I could put it on a leash.
On a modern distro cgroups v2 is already running under systemd, so the easiest handle is a transient scope. Instead of running the job directly, run it inside systemd-run with limits attached:
systemd-run --scope -p MemoryMax=2G -p CPUQuota=50% ./nightly-batch.sh
That caps it at two gigabytes and half a CPU's worth of time, enforced by the kernel, no cooperation from the job required. If it tries to climb past the memory cap the OOM killer takes it inside its own cgroup rather than picking a victim at random across the host, which is the behaviour I actually wanted.
You can watch it behave with systemd-cgtop, which shows live CPU and memory per slice and makes it obvious whether the limit is biting. For the permanent version I moved the job into its own slice with the same properties set in a unit file, so the limits survive a reboot and I never have to remember the flags again.
The lovely part is that the job has no idea. No code change, no config, no cooperation. The kernel simply refuses to let it have more than its share, and the rest of the box gets to breathe.