Read CPU Topology Clearly with lscpu
lscpu answers the questions that matter during diagnosis: how many logical CPUs Linux sees, and how they map to cores, sockets and NUMA nodes. In about five minutes you will have stable commands for scripts, plus a clear boundary around what the output does not prove.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
You need a Linux shell with the util-linux package installed. This guide uses the local command version 2.41.3. The installed manpage identifies util-linux 2.39.3, so check both when behaviour must match a particular host image. The commands are read-only and normally need no elevated privileges. Allow five to ten minutes, plus time to compare the result with your workload if you are investigating performance.
Checkpoint
Confirm which executable and version you are about to inspect.
command -v lscpu
lscpu --version
Expected output includes a path such as /usr/bin/lscpu and a line similar to:
lscpu from util-linux 2.41.3
1. Read the summary without over-interpreting it
Run the default command first:
lscpu
The summary reports architecture, CPU modes, logical CPU count, online CPU range, model, threads per core, cores per socket, sockets, NUMA nodes, caches and kernel-reported vulnerability status where available. The exact fields vary with architecture, kernel and util-linux version.
When output goes to a terminal, the presentation may use subsections for readability. When it is piped, the default is a flat Field: data form. That is useful for a quick capture, but it is not a promise that a field will exist on every machine.
lscpu | less
Do not treat CPU(s) as a count of physical processors: it normally means logical CPUs. A useful first check is the relationship between threads, cores and sockets, but firmware, hotplug state and virtualisation can make the picture less tidy than the labels suggest.
2. Inspect the topology as a table
Use extended output when you need one row per CPU. Select columns explicitly so a later util-linux update does not silently rearrange a report.
lscpu -e=cpu,node,core,socket,online
On an eight-thread, one-socket example, the shape is:
CPU NODE CORE SOCKET ONLINE
0 0 0 0 yes
1 0 1 0 yes
2 0 2 0 yes
3 0 3 0 yes
Your rows and values will differ. CPU, CORE, SOCKET and NODE are logical identifiers unless you request physical IDs. Add -y when physical topology identifiers are what you need:
lscpu -y -e=cpu,node,core,socket,online
Physical IDs come from the kernel and may be non-unique or non-sequential. The option does not renumber logical CPUs. A dash means the kernel could not provide that physical ID.
3. Check cache sharing separately
The summary gives aggregate cache sizes. For cache levels and per-cache details, use the cache table.
lscpu -C=NAME,LEVEL,ONE-SIZE,ALL-SIZE
A typical result looks like:
NAME LEVEL ONE-SIZE ALL-SIZE
L1d 1 32K 128K
L1i 1 32K 128K
L2 2 256K 1M
L3 3 8M 8M
ONE-SIZE describes one cache instance and ALL-SIZE the total for that cache type. The meaning is easier to trust when you also inspect the topology, because cache sharing is not necessarily one-to-one with cores. Cache IDs follow the identifiers supplied by the Linux kernel and do not have to start at zero.
4. Produce data for a script
For a human-maintained report, extended output is usually enough. For a parser, choose one of the formats designed for that job.
lscpu -p=cpu,node,core,socket
The parse format begins with explanatory comment lines, then emits comma-separated rows. If you specify a list, cache columns use a colon as their separator. With no list, the command retains an older compatible format, including its cache-column rules.
For a summary or extended result that a JSON-aware program can consume, use:
lscpu -Jlscpu -J -e=cpu,node,core,socket,online
- Do not scrape the aligned default display with whitespace splitting: column order and the default set of fields can change.
- Do not assume every requested column has data: unsupported columns may be printed with no value on a particular architecture.
5. Inspect another Linux root
If a mounted system is rooted at /mnt/target, ask lscpu to read that instance:
lscpu --sysroot=/mnt/target
The directory must be the target system root, not its /proc or /sys subdirectory, and the target must contain the interfaces that lscpu needs. A missing or incomplete tree produces an error such as:
lscpu: failed to determine number of CPUs: /sys/devices/system/cpu/possible: No such file or directory
This option reads data; it does not configure the target system. You may need permission to read the mounted tree, but do not use sudo merely because the command has a system-oriented name. If you mounted the tree yourself and are finished, unmount it using the procedure that created the mount. Do not unmount a path you did not verify.
Common traps
- Guest versus host: in a virtual machine, the summary normally describes the guest configuration. It is not a reliable inventory of the physical host.
- Online versus present:
-edefaults to online CPUs, while-palso defaults to online CPUs. Use-awith either when offline CPUs must be included. - Frequency snapshots: MHz and scaling values are observations, not fixed hardware guarantees. They can change while the command runs.
- Topology is not performance: a correct topology report does not explain scheduler pressure, throttling, memory bandwidth or workload behaviour by itself.
- Version drift: the default display is explicitly subject to change. Pin column lists and record
lscpu --versionwith collected data.
Done means
- You recorded the executable path and util-linux version.
- You can distinguish logical CPUs from cores, sockets and NUMA nodes.
- You checked cache sharing with
lscpu -Cwhen it mattered. - Your script uses
-e,-por-Jwith explicit fields rather than scraping the default display. - You know whether the result describes a guest, the current root, or a verified alternate sysroot.