Skip to content

Latest commit

 

History

History
156 lines (114 loc) · 6.48 KB

File metadata and controls

156 lines (114 loc) · 6.48 KB

psutil

A cross-platform library for retrieving information about running processes, network connections, and system resource utilization (CPU, memory, disk, network).

Overview

psutil (process and system utilities) exposes a uniform API over OS internals on Linux, Windows, and macOS: enumerate processes, inspect open connections and listening ports, read CPU/RAM/disk usage, and list logged-in users. It is the Python equivalent of ps, netstat, top, and lsof combined. In security work it powers host inventory, live-response triage, and lightweight monitoring or detection scripts.

Installation

pip install psutil

Basic Usage

import psutil

print("cpu %:", psutil.cpu_percent(interval=1))
print("memory %:", psutil.virtual_memory().percent)

for conn in psutil.net_connections(kind="inet"):
    if conn.status == psutil.CONN_LISTEN:
        print(conn.laddr.ip, conn.laddr.port, conn.pid)

Listing sockets owned by other users requires root; without it those entries appear with pid=None.

Important APIs

API Purpose
psutil.process_iter(attrs=[...]) Iterate processes efficiently
psutil.Process(pid) A single process
proc.name(), .exe(), .cmdline(), .username() Process identity
proc.ppid(), .create_time(), .status() Lineage and state
proc.open_files(), .connections() Resources held
psutil.net_connections(kind="inet") System-wide sockets
psutil.net_if_addrs() / net_if_stats() Interfaces and link state
psutil.cpu_percent(), virtual_memory(), disk_usage(path) Resource metrics
psutil.users(), boot_time() Session and uptime data
psutil.AccessDenied, NoSuchProcess, ZombieProcess Exceptions you must handle

Process objects are live: a process can vanish between two attribute reads.

Example

Enumerate processes with their owner and command:

import psutil

for proc in psutil.process_iter(["pid", "name", "username"]):
    info = proc.info
    print(f"{info['pid']:>6}  {info['username'] or '-':<12} {info['name']}")

Output

     1  root         systemd
   842  root         sshd
  1337  tester       python3

List listening ports and the processes behind them (host triage):

import psutil

for conn in psutil.net_connections(kind="inet"):
    if conn.status == psutil.CONN_LISTEN:
        laddr = f"{conn.laddr.ip}:{conn.laddr.port}"
        name = psutil.Process(conn.pid).name() if conn.pid else "?"
        print(f"LISTEN {laddr:<22} pid={conn.pid} ({name})")

Output

LISTEN 0.0.0.0:22             pid=842 (sshd)
LISTEN 127.0.0.1:5432         pid=990 (postgres)
LISTEN 0.0.0.0:8080           pid=1337 (python3)

Snapshot system resource usage:

import psutil

print("CPU %:", psutil.cpu_percent(interval=1))
mem = psutil.virtual_memory()
print(f"RAM  : {mem.percent}% used ({mem.used // 1024**2} MB / {mem.total // 1024**2} MB)")
disk = psutil.disk_usage("/")
print(f"Disk : {disk.percent}% used")
print("Boot :", psutil.boot_time())

Output

CPU %: 12.5
RAM  : 43.2% used (3450 MB / 7987 MB)
Disk : 61.0% used
Boot : 1721160000.0

Security Use Cases

  • Host & process inventory — enumerate running processes, owners, and command lines for asset and baseline collection.
  • Live-response triage — during incident review of a system you administer, list open connections and listening ports to spot suspicious services.
  • Malware / anomaly hunting — flag processes with odd names, unexpected network listeners, or unusual resource spikes.
  • Detection scripting — build lightweight monitors that alert on new listeners, high CPU, or unexpected users.
  • Persistence checks — inspect startup processes and connections when validating a host's integrity.

Common Mistakes

  • Not catching NoSuchProcess — the process table changes while you iterate it.
  • Not catching AccessDenied — without root, many attributes are unreadable and raise.
  • Calling cpu_percent() without an interval — the first call always returns 0.0; pass interval=1 or call it twice.
  • Using process_iter() without attrs=, which is far slower because each attribute is fetched separately.
  • Assuming full visibility in a container — namespaces limit what is visible, by design.
  • Treating proc.name() as trustworthy — a process name is attacker-controllable; corroborate with exe() and cmdline().
  • Expecting identical fields across platforms — availability differs between Linux, macOS, and Windows.

Security Considerations

[!warning] Authorized use only Inspect only systems you own or are authorized to administer or monitor.

  • This is a local introspection tool, not a network scanner. It reads the host's own state and generates no traffic — which makes it safe to run, and useless for remote discovery.
  • The output is highly sensitive. A process and socket inventory reveals every running service, its command line (which may contain credentials passed as arguments), and the local topology.
  • Command lines leak secrets. proc.cmdline() frequently exposes passwords and tokens that other tools were careless enough to accept as arguments — a good demonstration of why your own tools must not.
  • Running as root reveals other users' processes. Do that only where you are authorized to see them.
  • Process names are attacker-controlled. Malware routinely masquerades as a legitimate process name; verify the executable path and hashes.
  • Sockets bound to 0.0.0.0 are the finding worth acting on — services exposed beyond loopback, often unintentionally.

Best Practices

  • Wrap per-process access in try/except (psutil.NoSuchProcess, psutil.AccessDenied) — processes vanish and permissions vary.
  • Run with sufficient privileges to see all processes/connections (root/admin for full visibility).
  • Prefer process_iter(attrs=[...]) to batch-fetch fields efficiently rather than querying attributes one by one.
  • Call cpu_percent(interval=...) with an interval, or the first reading returns 0.0.
  • Cache pid/create_time together to avoid PID-reuse confusion in long-running monitors.

References

Related Topics

  • [[Paramiko]] — gather psutil inventory across hosts over SSH
  • [[Rich]] — render process/connection tables cleanly
  • [[Readme|Python for Security Professionals]] — course home