Home / Alt manpages / proc_cgroups(5)

  • proc_cgroups(5)
  • File format
  • linux

Read /proc/cgroups Without Misreading a v2 Host

On a cgroup v2 host, /proc/cgroups showing hierarchy zero does not mean cgroups are off. This guide gives you a reliable read-only check: what /proc/cgroups actually reports, which cgroup filesystem is mounted, and where your current shell sits in it. The examples use Linux man-pages 6.7, package manpages 6.7-2, checked on Linux 6.8.0-139-generic; output on another kernel, container or service manager can differ. Budget ten minutes, and none of this needs sudo.

1. Read the installed manual page first

The installed proc_cgroups(5) page has a deliberately small scope. It identifies /proc/cgroups as the control-groups file, present since Linux 2.6.24, and points at cgroups(7) for the actual interpretation. It never promises to be a complete map of a modern cgroup hierarchy.

Confirm the local package and the file you are about to read:

$ dpkg-query -W -f='${Package} ${Version}\n' manpages
manpages 6.7-2
$ man 5 proc_cgroups

Checkpoint

Page missing? Stop here and use the documentation your distribution actually ships. Do not infer field meanings from an example copied off a different host.

2. Read the four columns

Treat the file as an inventory of controller names and counters:

$ cat /proc/cgroups
#subsys_name  hierarchy  num_cgroups  enabled
cpuset         0          503          1
cpu             0          503          1
memory         0          503          1
pids            0          503          1
  • Column one is the controller or subsystem name.
  • Column two is its legacy hierarchy identifier.
  • Column three is the number of cgroups counted for that subsystem.
  • Column four says whether the subsystem is enabled in the legacy interface.

Rows and numbers here are host-specific: treat the block above as a shape, not a value to paste into a report. The trap is seeing hierarchy at 0 and reading that as cgroups being disabled. On a cgroup v2 system, the unified hierarchy simply is not represented by the old v1 numbering scheme the way a lot of older examples assume. Cross-check the mounted filesystem and the current process before you decide what the file is telling you.

3. Identify which cgroup version is actually mounted

Ask findmnt which cgroup filesystem is live. Still an ordinary read-only command:

$ findmnt -t cgroup,cgroup2 -o TARGET,FSTYPE,OPTIONS
TARGET         FSTYPE  OPTIONS
/sys/fs/cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot

cgroup2 means this host runs the unified cgroup v2 filesystem at that mount point; a cgroup row means legacy v1. A system can expose both during a transition, so do not collapse a multi-row result into one label without checking the mount points individually.

Checkpoint

Confirm the controller interface exposed by the v2 mount.

$ cat /sys/fs/cgroup/cgroup.controllers
cpuset cpu io memory hugetlb pids rdma misc

That list is the controllers available at the v2 root, not a list of limits currently applied to every process, and it says nothing about which controllers a child cgroup has enabled in its own subtree.

Warning

Do not write to cgroup.subtree_control just to make a controller appear here. That changes resource-control policy and belongs in a planned, privileged configuration change, not an inspection exercise.

4. Locate the shell in the hierarchy

Read the current process's own membership record:

$ cat /proc/self/cgroup
0::/user.slice/user-1004.slice/[email protected]/session.scope

For v2 the format is 0::PATH. The empty middle field marks the unified hierarchy, and the final field is the cgroup path relative to its root; a path shown as 0::/ means the process sits at the v2 root. Your path will normally carry different systemd or container names than the example above.

For a quick sanity check, inspect the mounted tree without touching it:

$ stat -fc '%T %m' /sys/fs/cgroup
cgroup2 /sys/fs/cgroup
$ test -r /sys/fs/cgroup/cgroup.procs && echo cgroup-v2-root-readable
cgroup-v2-root-readable

The stat filesystem type and the /proc/self/cgroup record should agree. If they do not, check whether you are inside a container or a different mount namespace, since a container can show a restricted view of the host's real hierarchy.

5. Use the result for the right question

Reach for /proc/cgroups when you want a quick controller inventory or you are diagnosing older tooling. Reach for findmnt, /sys/fs/cgroup and /proc/self/cgroup to answer the operational questions: which cgroup API is mounted, which v2 controllers are visible, and where is this process actually attached.

Do not use hierarchy numbers from /proc/cgroups as paths under /sys/fs/cgroup, and do not assume a controller listed as enabled is active for your specific service. In v2, controllers are enabled per subtree through the hierarchy, and limits live in files inside the relevant cgroup directory. A service manager such as systemd may also be creating and moving cgroups on your behalf without asking.

If a script needs to consume any of this, keep the raw lines and record the mount type alongside them. That stops a v1-style hierarchy number being mistaken for a stable v2 identifier later. Re-run these checks after any container, service manager or boot configuration change, because the visible namespace and mounts can shift under you.

Done means

  • Checked the installed proc_cgroups(5) version and its limited scope.
  • Read the four columns without treating example counts as universal.
  • Confirmed the mounted filesystem with findmnt.
  • Checked available v2 controllers without writing to any cgroup control file.
  • Located the current shell with /proc/self/cgroup.
  • Know when a container or mount namespace might be hiding the host's real hierarchy.