When you take over an unfamiliar Linux machine — a new server rack, a hand-me-down workstation, a cloud instance with a mystery instance type — the first thing you need is a clear picture of the hardware underneath the OS. Kernel logs tell part of the story, but four command-line tools give you the complete picture: lspci, dmidecode, lshw, and inxi. Each reads from different sources, covers different hardware layers, and serves a different use case. This article covers all four in enough depth to use them confidently in production.

Note

Most of these commands either require root or produce significantly richer output when run as root. Where sudo matters, it's noted explicitly. On systems with the wheel group configured for sudo access, substitute as appropriate for your environment.

lspci: Reading the PCI Bus

lspci is part of the pciutils package and queries the kernel's PCI subsystem — specifically /sys/bus/pci and /proc/bus/pci — to enumerate every device connected over PCI, PCIe, or a PCI bridge. That covers the vast majority of modern system components: GPUs, NVMe controllers, network adapters, USB host controllers, SATA controllers, and sound cards.

On Debian/Ubuntu systems, install it with apt install pciutils. On Fedora/RHEL it comes pre-installed; on Arch, pacman -S pciutils.

$ lspci

The default output is deliberately compact — one line per device showing the bus address, device class, and a short description. For production use you'll almost always want more:

lspci common flags
# Verbose output -- device capabilities, interrupt lines, memory regions
$ lspci -v

# Very verbose -- includes kernel driver in use and available kernel modules
$ lspci -k

# Show numeric vendor:device IDs alongside human-readable names
$ lspci -nn

# Machine-readable output -- useful for scripting
$ lspci -mm

# Show bus tree topology
$ lspci -t

# Combine: full verbose output with driver info and numeric IDs
$ lspci -nnkv

The -k flag is particularly useful when troubleshooting driver issues. It shows both the kernel driver currently bound to the device and any other kernel modules that could handle it. This is how you quickly confirm whether your 10GbE adapter is running ixgbe or mlx5_core, and whether the right one is actually loaded.

Filtering lspci Output

On dense server hardware with dozens of PCI devices, piping through grep is common. But lspci also has a built-in filter with -d for vendor and device ID, and -s for bus address. The -d flag accepts the format vendor:device using the numeric IDs shown by -nn:

filtering examples
# Show only NVIDIA devices (vendor ID 10de)
$ lspci -d 10de: -nnkv

# Show only network controllers
$ lspci | grep -i 'network\|ethernet\|wireless'

# Show only storage controllers
$ lspci | grep -i 'sata\|nvme\|raid\|storage'

# Examine a specific device by bus address (e.g., 03:00.0)
$ lspci -s 03:00.0 -vvv
Pro Tip

The PCI ID database lspci uses to translate numeric IDs to vendor names lives at /usr/share/misc/pci.ids or /usr/share/hwdata/pci.ids. If a device shows as Unknown device, run sudo update-pciids to pull a fresh copy from the pci-ids.ucw.cz database. This matters on new hardware where the distro's packaged database predates the device.

dmidecode: Reading BIOS and SMBIOS Tables

dmidecode reads the SMBIOS (System Management BIOS) table — a firmware-level data structure that the BIOS or UEFI populates with information about the hardware platform. This includes data that the OS kernel doesn't expose directly: the exact memory module part numbers, chassis serial numbers, BIOS version and release date, processor socket designations, and slot configurations.

It reads from /sys/firmware/dmi/tables on modern kernels (a privileged sysfs path) or directly from /dev/mem on older ones. Either way, sudo is required.

$ sudo dmidecode

Without flags, dmidecode dumps the entire SMBIOS table — hundreds of lines covering every hardware type. In practice you'll nearly always filter by type:

dmidecode by type
# BIOS version, release date, and firmware revision
$ sudo dmidecode -t bios

# System manufacturer, product name, serial number, UUID
$ sudo dmidecode -t system

# Baseboard (motherboard) manufacturer and product
$ sudo dmidecode -t baseboard

# Processor socket, speed, core/thread count
$ sudo dmidecode -t processor

# Memory slots: size, speed, part number, manufacturer per DIMM
$ sudo dmidecode -t memory

# Physical expansion slot types and status (occupied/available)
$ sudo dmidecode -t slot

# Chassis type, serial, lock status
$ sudo dmidecode -t chassis

The memory type output deserves special attention. Unlike /proc/meminfo which only tells you total and available RAM, dmidecode -t memory enumerates every physical memory slot on the board — including empty ones — and for populated slots shows the speed, size, ECC capability, manufacturer, part number, and serial number. This is how you verify that a server has the right DIMMs installed before a warranty claim, or confirm that a memory upgrade actually landed in the correct channels for interleaving.

example: dmidecode -t memory (truncated)
Memory Device
        Array Handle: 0x1000
        Error Information Handle: 0x1100
        Total Width: 72 bits
        Data Width: 64 bits
        Size: 32 GB
        Form Factor: DIMM
        Locator: DIMM_A1
        Bank Locator: NODE 1 CHANNEL A DIMM 0
        Type: DDR5
        Speed: 4800 MT/s
        Manufacturer: Samsung
        Serial Number: 3A45BE91
        Part Number: M321R4GA3BB6-CQKOL
        Configured Memory Speed: 4800 MT/s
        ECC: Yes

The numeric type codes are an alternative to keyword strings. Type 0 is BIOS, type 17 is memory device, type 4 is processor, and so on. The full table is in the dmidecode man page. You can also use sudo dmidecode -t 17 instead of sudo dmidecode -t memory — both work.

Warning

SMBIOS data is written by the firmware vendor and can be inaccurate, incomplete, or contain placeholder strings like "To Be Filled By O.E.M." on budget hardware. Always cross-reference critical values (especially memory speed) against what the kernel actually negotiated, visible in dmesg | grep -i ddr or the UEFI setup screen.

Extracting Specific Fields for Scripting

For automation — generating asset inventory reports, pre-flight checks before OS deployment, or populating a CMDB — you can combine dmidecode with string selection to extract clean values:

scripting with dmidecode
# Get just the system serial number
$ sudo dmidecode -s system-serial-number

# Get the BIOS version string
$ sudo dmidecode -s bios-version

# Get the system product name (model)
$ sudo dmidecode -s system-product-name

# List all available -s keywords
$ sudo dmidecode --string help

The -s flag outputs a single clean string with no surrounding text — ideal for shell variable assignment or piping into a configuration management tool. This pairs well with bash scripting for inventory automation across multiple hosts.

lshw: The Full Hardware Tree

lshw (list hardware) takes a broader approach than the previous two tools by aggregating data from multiple sources simultaneously: /proc, /sys, SMBIOS via DMI, the PCI bus, and udev events. The result is a structured hardware tree covering the entire system — firmware, CPU, memory, storage controllers and attached disks, network interfaces, PCI devices, USB buses, and more.

Install it with apt install lshw, dnf install lshw, or pacman -S lshw depending on your distribution. Running it as root gives the most complete output.

$ sudo lshw

The default text output is thorough but long. For most use cases, the short table or class-filtered output is more practical:

lshw common invocations
# Condensed table: class, description, product, vendor, logical name
$ sudo lshw -short

# Filter to a specific hardware class
$ sudo lshw -class network
$ sudo lshw -class storage
$ sudo lshw -class disk
$ sudo lshw -class processor
$ sudo lshw -class memory

# Export as HTML report (good for documentation)
$ sudo lshw -html > hardware-report.html

# Export as JSON for machine processing
$ sudo lshw -json > hardware.json

# Quiet mode -- suppress warnings about /proc access
$ sudo lshw -quiet

The -short output is often the fastest way to orient yourself on an unfamiliar system. It condenses everything into a readable table with hardware paths that reflect the physical bus hierarchy — you can see at a glance that your NVMe is on PCIe bus 1, your SATA controller is on bus 0, and your dual-port NIC is in slot 3.

example: sudo lshw -short (truncated)
H/W path        Device   Class       Description
========================================================
                          system      PowerEdge R750
/0                        bus         0XDYHM
/0/0                      memory      128GiB System Memory
/0/0/0                    memory      32GiB DIMM DDR5 4800 MHz
/0/0/1                    memory      32GiB DIMM DDR5 4800 MHz
/0/1                      processor   Intel Xeon Gold 6338
/0/100                    bridge      Sky Lake PCIe Controller
/0/100/1/0                storage     NVMe SSD Controller
/0/100/1/0/0    /dev/nvme0  disk        1.92TB Samsung PM9A3
/0/100/1c/0     eno1       network     Intel X550 10GbE

Using lshw for Network Interface Inventory

The network class filter is especially useful when documenting server NICs before configuration. It shows the interface name, MAC address, driver, firmware version, link speed capability, and whether auto-negotiation is enabled — all the information you need before writing an /etc/network/interfaces or configuring Ubuntu Server network management rules:

network interface detail
$ sudo lshw -class network

*-network
       description: Ethernet interface
       product: Ethernet Controller X550
       vendor: Intel Corporation
       logical name: eno1
       version: 01
       serial: a4:bf:01:23:45:67
       capacity: 10Gbit/s
       driver: ixgbe
       firmware: 0x800012c3
       link: yes
       autonegotiation: on
Pro Tip

The JSON output from sudo lshw -json is well-structured and easy to parse with jq. For fleet-wide hardware inventory, you can script this across hosts with SSH and aggregate the JSON into a central database. Pair it with port scanning tools to correlate network interface data with active services.

inxi: The System Summary Tool

inxi is a Perl script with a different goal from the three tools above. Where lspci, dmidecode, and lshw are diagnostic tools designed to give you raw hardware data, inxi is designed to produce readable, shareable system summaries. It pulls from lspci, dmidecode, /proc, /sys, and several other sources, then formats the output with human-readable labels and sensible defaults.

It's the tool you paste into a forum post or bug report when you need to describe your system quickly. It's also useful for sysadmins who need a fast overview without parsing walls of raw data.

Install it with apt install inxi, dnf install inxi, or pacman -S inxi.

$ inxi -Fxz

The three flags here are the standard starting point: -F for full output, -x for extra detail, and -z to anonymize private data like serial numbers and MAC addresses. On a system where you're sharing output publicly, -z is important.

inxi flags reference
# Full summary with extra details, private data anonymized
$ inxi -Fxz

# CPU info only
$ inxi -C

# Graphics/GPU only
$ inxi -G

# Memory info
$ inxi -m

# Network interfaces only
$ inxi -N

# Disk/storage summary
$ inxi -D

# RAID arrays if present
$ inxi -R

# Temperatures, fan speeds, voltages (requires lm-sensors)
$ inxi -s

# Running processes
$ inxi -t

# Repository and package info
$ inxi -r

The sensor output (-s) is particularly useful when you suspect thermal issues — it aggregates CPU, GPU, and motherboard temperatures into a single readable view without needing to install and configure additional monitoring tools.

example: inxi -Fxz output (abbreviated)
System:    Host: web01 Kernel: 6.8.0-55-generic x86_64 OS: Ubuntu 24.04.2 LTS
CPU:       Info: 32-core Intel Xeon Gold 6338 [MT MCP]
           Speed: 2100 MHz min/max: 800/3200 MHz
Graphics:  Device-1: ASPEED AST2600 driver: ast
Network:   Device-1: Intel Ethernet X550 driver: ixgbe
           IF: eno1 state: up speed: 10000 Mbps duplex: full
           Device-2: Intel Ethernet X550 driver: ixgbe
           IF: eno2 state: down
Drives:    Local Storage: total: 3.84 TiB
           ID-1: /dev/nvme0n1 vendor: Samsung model: MZQL21T9HCJR
           size: 1.92 TiB
           ID-2: /dev/nvme1n1 vendor: Samsung model: MZQL21T9HCJR
           size: 1.92 TiB
Partition: ID-1: / size: 1.82 TiB used: 214.3 GiB (11.5%) fs: ext4
Memory:    RAM: total: 125.72 GiB used: 22.14 GiB (17.6%)
Info:      Processes: 412 Uptime: 47 days Shell: bash

inxi on Minimal Server Installations

On minimal server installs, inxi may produce warnings about missing optional dependencies. These are informational — it will still output what it can. For full functionality including temperature readings, install lm-sensors and run sudo sensors-detect. For SMART disk health data alongside the drive listing, install smartmontools.

Note

On headless servers where terminal color codes cause problems in logs or monitoring systems, run inxi --no-color to strip ANSI escape sequences from the output. This also makes the output easier to diff across runs when tracking hardware changes over time.

Choosing the Right Tool

The four tools overlap in some areas but each has a clear primary use case. Understanding where each one draws its data from helps you choose the right one for the job:

The most productive habit is running sudo lshw -short and inxi -Fxz as part of any new-system checklist. Two commands, two minutes, complete hardware picture.

How to Inspect Linux Hardware From the Command Line

Step 1: Query PCI devices with lspci

Run lspci to list all PCI and PCIe devices. Add the -v flag for verbose output, -k to show kernel drivers in use, or -nn to include vendor and device ID codes alongside human-readable names. Use lspci -nnkv for the most complete single-pass view of PCI hardware and its driver bindings.

Step 2: Read BIOS and SMBIOS data with dmidecode

Run sudo dmidecode to dump the full SMBIOS table. Use the -t flag with a type keyword such as sudo dmidecode -t memory to filter output to a specific hardware category. Use the -s flag with a string keyword such as sudo dmidecode -s system-serial-number for clean single-value output suitable for scripting.

Step 3: Generate a full hardware tree with lshw

Run sudo lshw -short for a condensed hardware table showing bus hierarchy, or sudo lshw -class network to filter by a specific hardware class. Use sudo lshw -json to export machine-readable output for inventory automation, or sudo lshw -html to generate an HTML report for documentation.

Step 4: Get a system summary with inxi

Run inxi -Fxz for a full system summary with extra detail and private information anonymized. Use component-specific flags like inxi -G for graphics, inxi -N for network, or inxi -s for thermal sensor readings. Add --no-color when capturing output for logs or monitoring pipelines.

Frequently Asked Questions

What is the difference between lspci and lshw on Linux?

lspci shows only PCI and PCIe-connected devices by querying the kernel's PCI subsystem. lshw produces a full hardware tree covering CPU, memory, storage, firmware, and more by reading multiple sources including /proc, /sys, and DMI data. Use lspci for a fast PCI-only view and lshw when you need a comprehensive hardware inventory.

Why does dmidecode require sudo on Linux?

dmidecode reads the SMBIOS/DMI table directly from /dev/mem or /sys/firmware/dmi/tables, which is a privileged memory region. Reading from /dev/mem requires root access on most distributions because unrestricted memory reads could expose sensitive data or be abused to interact with hardware. On modern kernels the sysfs path is preferred, but it remains root-only.

Does inxi work on all Linux distributions?

inxi is a Perl script available in the package repositories of most major Linux distributions including Debian, Ubuntu, Fedora, Arch, and openSUSE. It can be installed via apt, dnf, pacman, or zypper. On minimal server installs it may not be present by default and requires manual installation. It will run with reduced output if optional dependencies like lm-sensors or smartmontools are missing.