Home / Alt manpages / lsmem(1)

  • lsmem(1)
  • User command
  • linux

Read Linux Memory Ranges with lsmem Without Guessing

You will finish with a repeatable way to inspect the kernel's memory blocks, see which ranges are online, and produce output that is safe to consume in a script. The examples use the lsmem from util-linux 2.41.3 available on this machine. Its installed manual page describes util-linux 2.39.3, so check both the command and the package on systems where exact version behaviour matters.

Allow about ten minutes. You need a shell and the util-linux package. The commands below only read memory information. They do not online or offline memory, change NUMA placement, or alter a service. No elevated privileges are normally required.

1. Check the command and its version

Start by finding the binary and asking it for its version. This catches a common distraction: a shell can find a different util-linux installation before the distribution package in your path.

$ command -v lsmem
/home/linuxbrew/.linuxbrew/bin/lsmem
$ lsmem --version
lsmem from util-linux 2.41.3

The manual page installed here is labelled util-linux 2.39.3, while the binary reports 2.41.3. That mismatch is a reason to test the command you will actually run, rather than assuming that a distribution manual describes every detail of another installation. On a Debian or Ubuntu host, this also shows the package metadata:

$ dpkg-query -W -f='${Package} ${Version}\n' util-linux
util-linux 2.39.3-9ubuntu6.6

Your path and version will differ. If lsmem --version fails, stop and install or repair the package through your normal system-management process. Do not work around a missing command by reading arbitrary files under /sys and treating them as an equivalent interface.

2. Read the default human-oriented view

Run lsmem with no options:

$ lsmem
RANGE                                  SIZE  STATE REMOVABLE  BLOCK
0x0000000000000000-0x00000000cfffffff  3.3G online       yes   0-25
0x0000000100000000-0x000000082fffffff 28.8G online       yes 32-261

Memory block size:                128M
Total online memory:               32G
Total offline memory:               0B

The exact ranges depend on the host. A row is a range of memory blocks with matching values under the current split rules. The BLOCK column identifies the block numbers, while RANGE shows the physical address interval. The summary reports the block size and online and offline totals.

Do not parse this default layout in a long-lived script. Human-readable sizes are convenient at a terminal, but headings, spacing, grouping and displayed units are presentation choices. Treat this command as a quick inspection only.

3. Ask for the columns you need

For a report that is easier to compare, select columns explicitly and request bytes:

$ lsmem --bytes --output=RANGE,SIZE,STATE,NODE,ZONES,REMOVABLE --summary=always
RANGE                                        SIZE  STATE NODE  ZONES REMOVABLE
0x0000000000000000-0x0000000007ffffff   134217728 online    0   None       yes
0x0000000008000000-0x00000000cfffffff  3355443200 online    0 DMA32       yes
0x0000000100000000-0x000000082fffffff 30870077440 online    0 Normal       yes

Memory block size:                     134217728
Total online memory:                 34359738368
Total offline memory:                          0

Column names are case-insensitive in normal use, but spelling them as shown makes scripts and reviews clearer. The available names on this installation include RANGE, SIZE, STATE, REMOVABLE, BLOCK, NODE and ZONES. Ask the installed command for its authoritative list with lsmem --help.

Some columns are not supported on every system. In that case, lsmem can print the requested column without providing data. An empty or placeholder value is not proof that the property is false. It can mean that the kernel or the inspected system does not expose it.

4. Choose how ranges are grouped

By default, lsmem starts a new range when a relevant attribute differs from the previous memory block. Use --all when you need one row per block:

$ lsmem --all --bytes --output=BLOCK,RANGE,SIZE,STATE
BLOCK RANGE                                      SIZE  STATE
0     0x0000000000000000-0x0000000007ffffff 134217728 online
1     0x0000000008000000-0x000000000fffffff 134217728 online

The block numbers and number of rows are host-specific. The useful check is that adjacent blocks are no longer combined merely because their selected attributes match.

To control which attributes cause a split, pass a list to --split. The manual documents STATE, REMOVABLE, NODE, ZONES and the special value none:

$ lsmem --split=ZONES --output=RANGE,SIZE,ZONES,STATE
RANGE                                  SIZE ZONES  STATE
# ranges on this host depend on its memory layout

With --split=none, lsmem tries to make ranges as large as possible. That can merge blocks whose attributes differ. If you force a merge, some displayed columns can become misleading because the command has deliberately ignored those differences. Use --all when the individual block records matter.

5. Produce data for a script

JSON is usually the clearest machine-readable format:

$ lsmem --json --bytes --output=RANGE,SIZE,STATE,NODE,ZONES,REMOVABLE --summary=never
{
   "memory": [
      {
         "range": "0x0000000000000000-0x0000000007ffffff",
         "size": 134217728,
         "state": "online",
         "node": 0,
         "zones": "None",
         "removable": true
      }
   ]
}

The example is shortened to one object; a real host can return many. --summary=never avoids mixing human summary lines into a data stream, although JSON already suppresses summary output. Keep --bytes when a consumer compares sizes numerically, and select only the fields the consumer needs.

Pairs and raw output are alternatives when another tool already expects those formats:

$ lsmem --pairs --bytes --summary=never --output=BLOCK,SIZE,STATE
BLOCK="0" SIZE="134217728" STATE="online"

Values in pairs and raw output can be escaped. Do not parse either format by splitting blindly on spaces. For JSON, use a JSON parser rather than regular expressions. If the command exits non-zero, preserve its diagnostic and status instead of treating an empty result as zero memory.

6. Inspect another Linux root carefully

--sysroot makes lsmem gather memory data from a different Linux system root. This is useful for an image or mounted system, but the directory must be a suitable root containing the expected sysfs view:

$ TARGET_ROOT='/path/to/mounted-system'
$ lsmem --sysroot "$TARGET_ROOT" --bytes --output=RANGE,SIZE,STATE
# output depends on the mounted system

Replace /path/to/mounted-system with a real, trusted mount point. This command does not make an ordinary disk image expose live kernel memory data. If the output is empty or the command reports a missing sysfs path, inspect the mount arrangement rather than adding sudo at random. Use elevated privileges only when your normal mount permissions require them, and review the target path before running any command against it.

7. Separate inspection from memory changes

lsmem is a reporting command. It has no option to online or offline memory. Do not confuse it with chmem, which is the separate command named in the manual page's see-also section. Online and offline operations can affect applications and available capacity, so they need a maintenance plan, a rollback decision and an explicit check of the target range.

For this guide there is nothing to undo: every example only reads data and writes output to the terminal. If you redirected output to a file, remove or replace that file only after checking its path. A command such as lsmem ... > report.txt truncates an existing report before the command runs, so use a new filename when the old report matters.

Common traps

  • A range is not necessarily one memory block. Use --all if you need per-block rows.
  • Human-readable sizes use power-of-1024 units and abbreviated suffixes such as M. Use --bytes for unambiguous numeric comparisons.
  • Online memory is not the same as memory available to a particular process. A range can be online while workloads still face cgroup, NUMA or allocator limits.
  • An unsupported column can be printed without useful data. Check kernel and sysfs support before alerting on that field.
  • Do not infer state from a column position in default output. Set --output explicitly and disable summaries for a parser.

Done means

  • You confirmed which lsmem binary and util-linux version you are running.
  • You can read the default ranges without mistaking grouping for individual blocks.
  • You can select columns and use bytes when results need comparison or storage.
  • Your script uses JSON, pairs or raw output deliberately and does not scrape the default display.
  • You know that lsmem does not change memory state, and you have not used it as a substitute for a memory-management operation.