PLGRP(1)

πŸ“¦
version 0.2.23 Β· 2 versions
, in fedora 44

πŸ’– PLGRP(1) β€” the manual, but make it make sense πŸ’–

okay bestie, gather round β€” this is plgrp, a lil tool from the General Commands Manual fam that shows you current NUMA node and thread CPU affinities. It's giving "who is my thread actually hanging out with" energy and honestly? Iconic. 🧚


✨ NAME ✨

plgrp β€” display current NUMA node and thread CPU affinities 🌸


πŸŽ€ SYNOPSIS πŸŽ€

plgrp [-a node_list] [pid[/tid] | core] ...

πŸ¦‹ DESCRIPTION πŸ¦‹

So basically, plgrp shows you the current NUMA node for every thread in the processes (or process core files) you point it at. And what even is "the node"? It's the NUMA node of the CPU that the thread is currently running on β€” or, if it's not running right now, the last CPU it was on. Lowkey a detective story for your scheduler. πŸ”

Add the -a option and it also tells you whether each thread's CPU affinity mask covers all, some, or none of the CPUs on the nodes you asked about. Vibe check: passed or not, no cap. βœ…

For core files tho, the NODE column just shows ? β€” because the running CPU isn't captured by systemd-coredump(8) 😭. Meanwhile CPU affinity is derived from Cpus_allowed_list in the saved process status. So you get some tea, just not all of it. πŸ’…


πŸ’… OPTIONS πŸ’…

  • -a node_list β€” show affinity info for the NUMA nodes you name. The node_list is a comma-separated list of node IDs, ranges (like 0-3), or the keywords all or leaves (which means all online nodes, bestie). Nodes get grouped by affinity:
    • all means the thread's CPU affinity mask includes every CPU on that node πŸ‘‘
    • some means it includes some but not all of them πŸ™ˆ
    • none means it includes no CPUs on that node πŸ’€

🌈 OPERANDS 🌈

  • pid[/tid] β€” a Process ID, optionally followed by a slash and a thread ID if you only want to see one single thread. You can also pass a /proc/pid path, which means shell expansions like /proc/* work and will target every process on the system. Go off, wildcard. ⭐
  • core β€” a process core file, as produced by systemd-coredump(8). Fun fact: the core file doesn't actually need to exist on disk! If it's been deleted, the corresponding systemd journal entry gets used instead. (See NOTES below, bestie, there's lore.) 🫢

πŸ”₯ EXAMPLES πŸ”₯

Example 1 β€” Display current nodes. Show the current NUMA node for each thread of the shell:

$ plgrp $$
       PID/TID  NODE
     3401/3401     1

Example 2 β€” Display affinities. Show current node and affinity for nodes 0 through 2:

$ plgrp -a 0-2 101398
       PID/TID  NODE  AFFINITY
 101398/101398     1  0,2/all,1/none
 101398/101412     0  0,2/all,1/none

⭐ EXIT STATUS ⭐

0 on success. Non-zero if an error occurs β€” like no such process, permission denied, or an invalid option. Sad girl hours, but at least the exit code is honest. 😭


🌸 FILES 🌸

  • /proc/pid/task/tid/stat β€” thread scheduling information. The receipts. 🧾
  • /sys/devices/system/node/ β€” NUMA topology information. The map of the whole kingdom. πŸ‘‘

πŸ’œ NOTES πŸ’œ

When a core file has been removed by systemd-tmpfiles(8) or by storage limits configured in coredump.conf(5), the systemd-coredump(8) journal entry for that crash may still be available. In that case, you can pass the path to the deleted core file as the core operand even though the file no longer exists on disk β€” and the process metadata gets retrieved from the journal entry instead. Not all hope is lost, bestie. ✨

Use coredumpctl(1) to obtain the path of a missing core file, e.g.:

coredumpctl list <name> -F COREDUMP_FILENAME

Ubuntu/Debian apport .crash files are also supported, and yes, that's a whole thing. These files use Debian control syntax with base64-encoded gzip core dumps. Text fields (such as ProcCmdline, ProcEnviron, and ExecutablePath) are mapped to COREDUMP_* fields, and the core dump is extracted on first access. 🎁


🚨 WARNINGS 🚨

For core files, the NODE column always shows ? β€” because systemd-coredump(8) does not capture which CPU each thread was running on at the time of the crash. It's simply not in the data, no cap. πŸ’€

Also: only the main thread is available from core files. Information for other threads is not displayed. So don't come for plgrp about the missing threads, it literally cannot see them. 😭


πŸ‘‘ SEE ALSO πŸ‘‘

taskset(1), numactl(8), coredumpctl(1), sched_getaffinity(2), proc(5)


That's the whole page, bestie β€” you're officially NUMA-pilled. πŸ¦‹

This was plgrp version 0.2.23, dated September 2026 β€” mwah, xoxo, go check your affinities. πŸ’–βœ¨

πŸ“¦ where this page comes from