Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

procutils is a suite of Linux command-line utilities — top, ps, free, vmstat, and friends — written from scratch in Rust as a clean-room, permissively-licensed reimplementation of the tools traditionally provided by procps-ng. Each tool reads from /proc (and a few other kernel interfaces) to report on processes, memory, and system state, and aims to be a drop-in replacement for its procps-ng counterpart while taking the opportunity to clean up rough edges where doing so does not break existing use-cases.

Source Code

The source is available on github and gitlab.

Installing

procutils is currently distributed as source. Deb and Rpm packages are planned but not yet available; a Nix flake is provided.

Building from source

You will need a recent Rust toolchain. The easiest way to install one is via rustup; the repository pins a specific toolchain via rust-toolchain.toml, which rustup will pick up automatically.

git clone https://github.com/rustutils/procutils
cd procutils
cargo build --release

The build produces one binary per tool in target/release/ (free, top, vmstat, etc.), plus a single multicall binary called procutils that behaves like any of the individual tools when invoked under the matching name (in the spirit of busybox). Symlinking procutils to top, ps, and so on is the simplest way to deploy the whole suite from a single binary.

With Nix

A flake.nix is provided at the repo root, using crane to drive the cargo build with the toolchain pinned by rust-toolchain.toml.

# Build the multicall binary plus all individual tools
nix build github:rustutils/procutils

# Run a tool ad-hoc without installing
nix run github:rustutils/procutils -- top

# Drop into a development shell with the right toolchain, just, and
# nightly rustfmt for `cargo +nightly fmt`
nix develop github:rustutils/procutils

The flake also exposes checks.<system>.{procutils,procutils-clippy,procutils-test} for CI integrations.

Static MUSL build

For deployment to systems without a matching glibc, the tools can be built against MUSL libc to produce fully static binaries. Install the MUSL target once:

rustup target add x86_64-unknown-linux-musl

Then build with:

cargo build --release --target x86_64-unknown-linux-musl

The resulting binaries land in target/x86_64-unknown-linux-musl/release/ and can be copied to any Linux host with no runtime dependencies.

Building a single tool

Each tool is its own crate inside the workspace. To build just one:

cargo build --release -p procutils-top

The crates are named procutils-<tool>; see the tools section for the full list.

free

Display amount of free and used memory in the system.

Description

Displays the total amount of free and used physical and swap memory in the system, as well as the buffers and caches used by the kernel. The information is gathered from /proc/meminfo.

Inputs

  • /proc/meminfo – memory statistics including MemTotal, MemFree, MemAvailable, Buffers, Cached, SReclaimable, Shmem, SwapTotal, SwapFree, LowTotal, LowFree, HighTotal, HighFree, CommitLimit, Committed_AS

Arguments

Unit selection

These flags are mutually exclusive. If none is specified, the default unit is kibibytes (1024 bytes).

FlagUnitBase
-b, --bytesbytes
--kilokilobytes1000
--megamegabytes1000^2
--gigagigabytes1000^3
--teraterabytes1000^4
--petapetabytes1000^5
-k, --kibikibibytes (default)1024
-m, --mebimebibytes1024^2
-g, --gibigibibytes1024^3
--tebitebibytes1024^4
--pebipebibytes1024^5

Display options

FlagDescription
-h, --humanHuman-readable output with auto-scaled units
--siUse powers of 1000 instead of 1024 (with -h)
-w, --wideWide output: show separate Buffers and Cache columns instead of combined buff/cache
-l, --lohiShow detailed low and high memory statistics
-L, --lineShow output on a single line
-t, --totalShow a Total row (RAM + swap combined)
-v, --committedShow committed memory and commit limit

Repeat options

FlagDescription
-s, --seconds SECSRepeat printing every SECS seconds (accepts fractional values)
-c, --count NRepeat N times then exit (if used without -s, prints N times with no delay)

When -s is used without -c, repeats indefinitely. When both are used, repeats N times at the given interval.

Behavior

Default table mode

Produces a table with the following columns and rows:

              TOTAL    USED    FREE  SHARED  BUFF/CACHE  AVAILABLE
Mem:       16306960 5765432 2341528  803712     8200000   10541528
Swap:       8388604  123456 8265148

Columns:

  • TOTAL – total installed memory (or swap)
  • USED – used memory, calculated as: TOTAL - FREE - BUFFERS - CACHE
  • FREE – unused memory
  • SHARED – memory used by tmpfs (Shmem from meminfo)
  • BUFF/CACHE – sum of buffers and cache (includes SReclaimable)
  • AVAILABLE – estimate of memory available for starting new applications

Wide mode (-w)

Replaces the combined BUFF/CACHE column with separate BUFFERS and CACHE columns:

              TOTAL    USED    FREE  SHARED  BUFFERS    CACHE  AVAILABLE

Line mode (-L)

Prints all values on a single line:

SwapUse 123456 CachUse 8200000  MemUse 5765432 MemFree 2341528

Additional rows

  • -l, --lohi adds Low and High memory rows (relevant on 32-bit systems)
  • -t, --total adds a Total row summing Mem and Swap
  • -v, --committed adds a Comm row showing CommitLimit, Committed_AS, and the difference

Memory calculations

  • cached = Cached + SReclaimable (from meminfo)
  • used = MemTotal - MemFree - Buffers - cached
  • buff/cache = Buffers + cached
  • swap used = SwapTotal - SwapFree

Human-readable mode (-h)

Automatically selects the most appropriate unit (B, Ki, Mi, Gi, Ti, Pi) for each value. Values below 10 of the selected unit are shown with one decimal place. With --si, uses powers of 1000 and suffixes B, K, M, G, T, P.

Exit codes

CodeMeaning
0Success
1Failure (cannot read /proc/meminfo)

Divergences from procps-ng

  • Column headers are UPPERCASE (TOTAL, USED, FREE, SHARED, BUFF/CACHE, AVAILABLE) rather than lowercase, matching the convention used by lsblk, lscpu, and other modern util-linux tools.
  • Error messages for invalid arguments use different wording.

hugetop

Display hugepage usage by process.

Description

A TUI tool that shows which processes are using hugepages, sorted by total hugepage usage. Displays both HugeTLB (explicit hugepages) and transparent hugepages (AnonHugePages) per process, along with a system-wide summary.

Only processes with non-zero hugepage usage are shown.

Press q to quit.

Inputs

System-wide

  • /proc/meminfo – hugepage statistics:
    • AnonHugePages – transparent hugepages in use (anonymous)
    • ShmemHugePages – transparent hugepages in use (shared memory)
    • HugePages_Total – total number of preallocated hugepages
    • HugePages_Free – number of unallocated hugepages
    • HugePages_Rsvd – reserved but not yet allocated hugepages
    • HugePages_Surp – surplus hugepages above the configured pool
    • Hugepagesize – default hugepage size (typically 2048 kB)
    • Hugetlb – total memory in HugeTLB pages

Per-process

  • /proc/[pid]/statusHugetlbPages field (explicit hugepage usage)
  • /proc/[pid]/smaps_rollupAnonHugePages field (transparent hugepage usage, aggregated across all mappings)
  • /proc/[pid]/stat – PID and command name
  • /etc/passwd – UID to username resolution (cached)

Arguments

FlagDescription
-d, --delay SECSRefresh interval in seconds (default: 2, minimum: 0.5)

Behavior

Display layout

The terminal is divided into two regions:

  1. System summary (top 4 lines):

    • HugeTLB pool status: total, free, reserved, surplus, page size
    • Transparent hugepage totals: anonymous and shared memory
    • Count of processes currently using hugepages
  2. Process table (remaining space):

    • Sorted by total hugepage usage (descending)
    • Columns: PID, USER, HUGETLB, ANON_HUGE, TOTAL, COMMAND

Columns

ColumnDescription
PIDProcess ID
USEREffective user name
HUGETLBExplicit HugeTLB usage (from /proc/[pid]/status)
ANON_HUGETransparent hugepage usage (from /proc/[pid]/smaps_rollup)
TOTALSum of HUGETLB + ANON_HUGE
COMMANDProcess name (comm)

Size formatting

Values are displayed in human-readable units: K (kibibytes), M (mebibytes), or G (gibibytes), automatically scaled.

Color

Row color indicates the magnitude of hugepage usage:

  • Default: total < 1 MiB
  • Yellow: total >= 1 MiB
  • Red: total >= 1 GiB

Terminal handling

Uses ratatui with crossterm as the terminal backend. Enters alternate screen and raw mode on startup, restores the terminal on exit.

Exit codes

CodeMeaning
0Normal exit (user pressed q)
1Failure (terminal initialization error or proc read failure)

kill

Send a signal to a process by PID.

Description

Sends a signal to one or more processes (or process groups) identified by PID. Without a signal flag, sends SIGTERM. Also exposes the canonical signal table via -l and -L, so it can be used to convert between signal names and numbers without sending anything.

Inputs

  • kill(2) syscall via libc::kill for delivery.
  • No /proc access; PIDs are passed straight through to the kernel.

Synopses

kill [options] <pid> [<pid> ...]
kill -l [<signal> ...]
kill -L

Arguments

FlagDescription
-s, --signal SIGSignal to send – name or number. Default: TERM
-<SIG> (e.g. -9, -KILL, -SIGKILL)Same as -s SIG. Equivalent forms; the leading - plus signal spec is consumed if -s was not given
-l, --list [SIG ...]List signal names. With no arguments, prints all signal names separated by spaces. With arguments, converts each from name to number or number to name (one per line)
-L, --tablePrint the signal table – number and name pairs, eight per line
--helpPrint help
-V, --versionPrint version
--End of options; subsequent arguments are PIDs even if they start with -
<pid>One or more PIDs to signal (see semantics below)

PID semantics

Following kill(2):

PIDEffect
> 0Signal the process with that PID
0Signal every process in the caller’s process group
-1Signal every process the caller is permitted to signal, except init
< -1Signal every process in the process group with PID |pid|

A negative PID that follows -- is parsed as a PID. Without --, a leading negative argument is consumed as the signal spec when -s was not given.

Behavior

Signal selection precedence

  1. -s SIG / --signal SIG
  2. A leading -N or -NAME argument (e.g. kill -9 1234, kill -KILL 1234)
  3. Default: TERM

Signal 0 is the null signal – delivery is checked but no signal is sent. kill -0 PID is the standard way to test whether a process exists and is signalable by the caller.

-l / --list

InvocationOutput
kill -lAll signal names (no SIG prefix), space-separated, one line
kill -l NName for signal number N
kill -l NAMENumber for signal name (with or without SIG prefix)
kill -l N1 N2 ...Each conversion on its own line

-L / --table

Prints the signal table eight pairs per line, formatted as:

 1 HUP   2 INT   3 QUIT   4 ILL   5 TRAP   6 ABRT   7 BUS   8 FPE
 9 KILL 10 USR1 11 SEGV 12 USR2 13 PIPE 14 ALRM 15 TERM 16 STKFLT
...

Supported signals

Standard signals 1–31 (HUP, INT, QUIT, ILL, TRAP, ABRT/IOT, BUS, FPE, KILL, USR1, SEGV, USR2, PIPE, ALRM, TERM, STKFLT, CHLD/CLD, CONT, STOP, TSTP, TTIN, TTOU, URG, XCPU, XFSZ, VTALRM, PROF, WINCH, IO/POLL, PWR, SYS). Real-time signals (SIGRTMIN..SIGRTMAX) are not yet listed by -l or -L but can still be sent by number.

Exit codes

CodeMeaning
0All signals delivered successfully (or a successful list/table operation)
1At least one signal delivery failed (no such process, permission denied, etc.)
2Usage error (unknown signal, no PIDs given, invalid PID)

pgrep

Look up processes based on name and other attributes.

Description

Searches the process table and reports process IDs of processes matching the given criteria. By default, matches the pattern against process names (the comm field). With -f, matches against the full command line.

Inputs

  • /proc/[pid]/stat – process name (comm), PID, PPID, process group, session, tty, start time
  • /proc/[pid]/status – real/effective UID, real GID
  • /proc/[pid]/cmdline – full command line
  • /proc/uptime – system uptime (for --older calculation)

Arguments

Positional

ArgumentDescription
pattern (optional)Extended regular expression to match process names (or full command lines with -f). Required unless at least one filter flag is specified.

Matching options

FlagDescription
-f, --fullMatch against the full command line instead of just the process name
-i, --ignore-caseCase-insensitive matching
-x, --exactRequire an exact match (anchors the pattern with ^...$)
-v, --inverseNegate the matching: select non-matching processes

Selection filters

FlagDescription
-n, --newestSelect only the most recently started matching process
-o, --oldestSelect only the least recently started matching process
-O, --older SECSSelect only processes older than SECS seconds
-P, --parent PPID,...Match only processes whose parent PID is in the list
-g, --pgroup PGRP,...Match only processes in the given process group IDs (0 means pgrep’s own process group)
-G, --group GID,...Match only processes whose real group ID is in the list
-s, --session SID,...Match only processes whose session ID is in the list (0 means pgrep’s own session)
-t, --terminal TERM,...Match only processes whose controlling terminal is in the list
-u, --euid UID,...Match only processes whose effective user ID is in the list (accepts names or numeric IDs)
-U, --uid UID,...Match only processes whose real user ID is in the list (accepts names or numeric IDs)
-r, --runstates STATE,...Match only processes in the given run states (R, S, D, Z, T, etc.)

Output options

FlagDescription
-c, --countPrint only a count of matching processes instead of PIDs
-d, --delimiter DELIMString to use between PIDs in output (default: newline)
-l, --list-namePrint PID and process name for each match
-a, --list-fullPrint PID and full command line for each match

Behavior

Iterates over all processes in /proc, applies the specified filters, and matches the pattern (if given) against the process name or full command line.

Key behaviors:

  • pgrep always excludes its own PID from results.
  • Results are sorted by PID.
  • Multiple filter flags are combined with AND logic: a process must satisfy all specified filters.
  • A pattern is optional when at least one filter flag is provided.
  • With --newest or --oldest, only a single process (the one with the most recent or earliest start time among all matches) is reported.
  • Process matching logic is shared with pkill via the procutils-common library crate.

Exit codes

CodeMeaning
0One or more processes matched
1No processes matched
2Syntax error (invalid arguments)
3Fatal error

Divergences from procps-ng

Behaviour matches procps-ng for the supported flag set; some procps-ng features are not yet implemented:

  • -F pidfile — read PIDs from a file. The mutual exclusion between -F and -p is therefore also absent.
  • --env VAR[=value] — match against a process’s environment.
  • -Q (shell-quoted output) — wrap names containing spaces in single quotes for safe shell consumption.
  • The warning emitted when the pattern is longer than 15 characters without -f (since comm is truncated to 15 characters by the kernel, a longer pattern can never match without -f).

Error messages for invalid arguments use different wording.

pkill

Signal processes based on name and other attributes.

Description

Looks up processes based on name and other attributes, then sends a signal to each matching process. Uses the same matching logic as pgrep. By default, sends SIGTERM.

Inputs

  • /proc/[pid]/stat – process status (PID, comm, state, PPID, pgrp, session, tty, starttime)
  • /proc/[pid]/status – effective and real UID/GID
  • /proc/[pid]/cmdline – full command line (for -f matching)
  • /proc/uptime – system uptime (for --older calculations)
  • kill() syscall via rustix – sends signals to matched processes

Arguments

Pattern

ArgumentDescription
pattern (positional, optional)Extended regex to match against process names

Signal selection

FlagDescription
--signal SIGNALSignal to send, by name or number (default: TERM)

Output options

FlagDescription
-c, --countPrint count of matched processes instead of signaling
-e, --echoDisplay name and PID of each signaled process

Matching options

FlagDescription
-f, --fullMatch pattern against full command line, not just process name
-i, --ignore-caseCase-insensitive pattern matching
-x, --exactRequire exact match of the process name (not a substring)

Selection filters

FlagDescription
-n, --newestSelect only the most recently started matching process
-o, --oldestSelect only the earliest started matching process
-O, --older SECSSelect processes older than SECS seconds
-P, --parent PPID,...Match only processes whose parent PID is listed
-g, --pgroup PGRP,...Match only processes in the listed process groups
-G, --group GID,...Match only processes with the listed real group IDs
-s, --session SID,...Match only processes in the listed sessions
-t, --terminal TERM,...Match only processes on the listed controlling terminals
-u, --euid UID,...Match only processes with the listed effective user IDs or names
-U, --uid UID,...Match only processes with the listed real user IDs or names
-r, --runstates STATE,...Match only processes in the listed run states (R, S, D, Z, T, etc.)

Note: -v (inverse matching) is intentionally not supported in pkill, matching procps-ng behavior.

Behavior

pkill iterates over all processes in /proc, applies the same filtering and pattern matching logic as pgrep, then sends a signal to each matched process.

Signal parsing

The --signal value is resolved in the following order:

  1. Named signal without prefix: TERM, HUP, KILL, etc.
  2. Named signal with SIG prefix: SIGTERM, SIGHUP, SIGKILL, etc.
  3. Numeric signal: 15, 1, 9, etc.

Supported signal names: HUP, INT, QUIT, ILL, TRAP, ABRT (IOT), BUS, FPE, KILL, USR1, SEGV, USR2, PIPE, ALRM, TERM, STKFLT, CHLD (CLD), CONT, STOP, TSTP, TTIN, TTOU, URG, XCPU, XFSZ, VTALRM, PROF, WINCH, IO (POLL), PWR, SYS.

Process matching

The matching algorithm is shared with pgrep:

  • The invoking process (pkill itself) is always excluded from matches.
  • Without -f, the pattern is matched against the process comm name.
  • With -f, the pattern is matched against the full command line.
  • With -x, the pattern must match the entire name (anchored match).
  • Selection filters (parent, group, terminal, etc.) are combined with AND logic.
  • -n and -o are applied after all other filtering.

Echo mode (-e)

When --echo is specified, pkill prints a line for each successfully signaled process:

name killed (pid N)

Count mode (-c)

When --count is specified, pkill prints the number of matching processes instead of sending signals.

Exit codes

CodeMeaning
0At least one process was matched and successfully signaled
1No processes matched, or signaling failed for all matches
2Syntax error in command line arguments
3Fatal error

pmap

Report memory map of a process.

Description

Displays the memory map of one or more processes, showing the address ranges, sizes, permissions, and mapped files or regions for each mapping.

Inputs

  • /proc/[pid]/maps – memory mappings (address range, permissions, offset, device, inode, pathname)
  • /proc/[pid]/smaps – extended per-mapping memory info including RSS, Private_Dirty, and Shared_Dirty (used with -x)
  • /proc/[pid]/cmdline – command line (displayed in the header)

Arguments

ArgumentDescription
pid... (required, positional)One or more process IDs to display

Format selection

These flags are mutually exclusive. If none is specified, the default format is used.

FlagDescription
-x, --extendedShow extended format with RSS and Dirty columns (reads smaps)
-d, --deviceShow device format with Offset and Device columns

Display options

FlagDescription
-q, --quietSuppress header and footer lines
-p, --show-pathShow full file paths instead of basenames

Behavior

For each requested PID, pmap prints a header line (unless -q), followed by one line per memory mapping, and a footer with totals (unless -q).

PID:   command_name

Default mode

Columns: Address, Kbytes, Mode, Mapping.

Address           Kbytes Mode  Mapping
000055a4c8200000     152 r-x-- bash
000055a4c8425000       4 r---- bash
...
 total            123456K

The footer shows the total virtual size in kB.

Extended mode (-x)

Columns: Address, Kbytes, RSS, Dirty, Mode, Mapping.

Reads /proc/[pid]/smaps to obtain RSS and dirty page counts for each mapping. The footer shows totals for Kbytes, RSS, and Dirty.

Address           Kbytes     RSS   Dirty Mode  Mapping
000055a4c8200000     152     148       0 r-x-- bash
...
----------------  ------  ------  ------
total             123456   45678    1234K

Device mode (-d)

Columns: Address, Kbytes, Mode, Offset, Device, Mapping.

The Offset is the file offset of the mapping. The Device is the major:minor device number. The footer shows the mapped total, writeable/private total, and shared total.

Address           Kbytes Mode  Offset           Device    Mapping
000055a4c8200000     152 r-x-- 0000000000000000 008:00001 bash
...
mapped: 123456K    writeable/private: 2345K    shared: 6789K

Permission string format

Permissions are displayed as a 5-character string: rwxs- where:

  • r = readable (or -)
  • w = writable (or -)
  • x = executable (or -)
  • s = shared, - = private
  • Trailing -

Examples: r-x-- (read-execute, private), rw-s- (read-write, shared).

Mapping names

  • File-backed mappings show the file basename, or the full path with -p.
  • Anonymous mappings show [ anon ].
  • Stack regions show [ stack ].
  • Special kernel regions show [ vdso ], [ vvar ], [ vsyscall ], etc.

All output uses the cols crate for column alignment.

Exit codes

CodeMeaning
0All requested PIDs were displayed successfully
42One or more requested PIDs could not be found

ps

Report a snapshot of current processes.

Description

Displays information about active processes. By default, shows only processes associated with the current user and terminal. Various options control which processes are selected and what information is displayed.

Inputs

  • /proc/[pid]/stat – PID, comm, state, PPID, pgrp, session, tty_nr, tpgid, utime, stime, nice, num_threads, starttime, vsize, rss
  • /proc/[pid]/status – effective UID, real UID
  • /proc/[pid]/cmdline – full command line arguments
  • /proc/stat – boot time (btime field, for calculating process start times)
  • /proc/meminfo – MemTotal (for %MEM calculation)
  • /proc/uptime – system uptime (for %CPU calculation)
  • /etc/passwd – UID to username mapping

Arguments

Process selection

FlagDescription
-A, --allSelect all processes
-eSelect all processes (identical to -A)
-aSelect all processes with a controlling terminal, except session leaders
-xInclude processes without a controlling terminal (typically combined with -a)
-p, --pid PID,...Select processes by process ID
-U, --user USER,...Select processes by effective user name or UID

Output format

FlagDescription
-uUser-oriented format (typically combined with -a -x for “aux” style)
-fFull-format listing

Behavior

Default mode (no arguments)

Shows processes owned by the current user on the current terminal.

Columns: PID, TTY, TIME, CMD.

  PID TTY          TIME CMD
 1234 pts/0    00:00:01 bash
 5678 pts/0    00:00:00 ps

BSD aux mode (-aux or -a -u -x)

Shows all processes in user-oriented format.

Columns: USER, PID, %CPU, %MEM, VSZ, RSS, TTY, STAT, START, TIME, COMMAND.

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1 169356 11892 ?        Ss   Jan15   0:05 /sbin/init

Full format (-ef or -e -f)

Shows all processes in full format.

Columns: UID, PID, PPID, C, STIME, TTY, TIME, COMMAND.

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Jan15 ?        00:00:05 /sbin/init

Computed fields

%CPU

Calculated as:

(utime + stime) / clock_ticks_per_second / elapsed_seconds * 100

Where elapsed_seconds is the time since the process started.

%MEM

Calculated as:

rss_pages * page_size / MemTotal * 100

STAT

A multi-character process state string:

CharacterPositionMeaning
R, S, D, Z, T, t, X, I1stProcess state (running, sleeping, disk sleep, zombie, stopped, tracing stop, dead, idle)
<modifierHigh priority (nice < 0)
NmodifierLow priority (nice > 0)
smodifierSession leader (PID == session ID)
lmodifierMulti-threaded (num_threads > 1)
+modifierIn foreground process group (tpgid == pgrp)

TIME

Cumulative CPU time (utime + stime), formatted as:

  • HH:MM:SS when one hour or more
  • M:SS when less than one hour

START / STIME

Process start time, formatted as:

  • HH:MM if the process started today
  • MonDD (e.g., Jan15) if the process started on a previous day

TTY

Decoded from the tty_nr field in /proc/[pid]/stat:

  • pts/N for pseudo-terminals
  • ttyN for virtual consoles
  • ttySN for serial terminals
  • ? for processes without a controlling terminal

All output uses the cols crate for column alignment.

Exit codes

CodeMeaning
0Success
1Failure

pwdx

Report current working directory of a process.

Description

For each given process ID, reads and displays the process’s current working directory.

Inputs

  • /proc/[pid]/cwd – symlink to the process’s current working directory

Arguments

ArgumentDescription
pid... (required, positional)One or more process IDs

Behavior

For each PID argument, reads the /proc/[pid]/cwd symlink and prints:

PID: /path/to/cwd

If a PID cannot be read (process does not exist, permission denied, or other error), an error message is printed to stderr and processing continues with the remaining PIDs.

Exit codes

CodeMeaning
0All PIDs were resolved successfully
1One or more PIDs could not be read

skill

Send a signal to processes selected by user, tty, pid, or command.

Description

skill is the obsolete predecessor of pkill; both tools are kept for compatibility, but new use cases should prefer pkill. The CLI follows procps-ng’s quirky convention where the signal is given as a leading -NAME or -N argument (e.g. skill -KILL -u alice), like kill(1).

The default signal is TERM. Selectors (-t, -u, -p, -c) are OR’d within their category and AND’d across categories.

Inputs

  • kill(2) syscall via libc::kill for delivery.
  • /proc/[pid]/{stat,status,cmdline} via the shared procmatch module for selection.

Synopsis

skill [signal] [options] <expression>

expression is a list of bare PIDs (interpreted in conjunction with -p). Selectors with explicit flags can be mixed with bare PIDs.

Arguments

FlagDescription
-<SIG> (e.g. -9, -KILL, -SIGKILL)Signal to send. Default: TERM
--signal SIGSame as the leading-flag form, but in long-flag style
-l, --listList all signal names
-L, --tableList all signal names in a numbered table
-n, --no-actionDon’t send signals; just print matching PIDs
-v, --verbosePrint the PID and comm of each signaled process
-t, --tty TTYMatch processes whose controlling tty is TTY (repeatable)
-u, --user USERMatch processes whose effective user is USER (name or numeric UID, repeatable)
-p, --pid PIDMatch processes by PID (repeatable)
-c, --command CMDMatch processes whose comm is exactly CMD (repeatable)
--help / -V, --versionHelp / version

The signal can appear anywhere on the command line; it is rewritten internally to --signal SIG before clap parses argv (see preprocess_argv). Bare positional integers are added to the PID list.

Behavior

Selection

procmatch::find_matching_processes is used to enumerate /proc and apply filters. -c values are turned into an anchored alternation regex over comm (^(cmd1|cmd2|...)$). -p values become an exact PID filter.

-l / -L

Identical output to kill -l / kill -L. Standard signals 1–31 only; real-time signals are omitted.

-n (no-action)

Prints matching PIDs, one per line, in ascending order. Useful as a dry-run before signaling.

-v (verbose)

For each successfully signaled process, prints pid: comm.

Notes

  • -i (interactive), -f (fast), -w (warnings) and --ns / --nslist (namespace selection) are listed in the upstream man page but not implemented here.
  • Real-time signals (SIGRTMIN..SIGRTMAX) cannot currently be expressed via name; they can be sent via --signal N for the corresponding number.

Exit codes

CodeMeaning
0At least one process matched and was signaled (or list/table requested)
1No processes matched, or all signal deliveries failed
2Usage error (unknown signal, no expression given, invalid argument)

slabtop

Display kernel slab cache information in real time.

Description

Displays detailed kernel slab cache information as a sorted table with a statistics summary header. Shows the top slab caches sorted by a user-selectable criterion. Requires read access to /proc/slabinfo (typically root).

Press q to quit. Press a sort key to change the sort order interactively. Press space to force a refresh.

Inputs

  • /proc/slabinfo – kernel slab allocator statistics (version 2.1 format). Each line contains: name, active objects, total objects, object size, objects per slab, pages per slab, tunables, and slab data (active slabs, total slabs).

Arguments

FlagDescription
-d, --delay SECSRefresh interval in seconds (default: 3, minimum: 0.5)
-s, --sort CHARSort criterion (default: o). See sort criteria below.
-o, --onceDisplay output once to stdout and exit (no TUI)

Sort criteria

The sort criterion can be set via -s at startup or changed interactively by pressing the corresponding key.

KeySort byColumn
aNumber of active objects (descending)ACTIVE
bObjects per slab (descending)OBJ/SLAB
cCache size (descending)CACHE SIZE
lNumber of slabs (descending)SLABS
nCache name (ascending, alphabetical)NAME
oNumber of objects (descending)OBJS
pPages per slab (descending)
sObject size (descending)OBJ SIZE
uCache utilization percentage (descending)USE%

Behavior

TUI mode (default)

The terminal is divided into two regions:

  1. Summary header (top 6 lines):

    • Active / Total Objects (% used)
    • Active / Total Slabs (% used)
    • Active / Total Caches (% used)
    • Active / Total Size (% used)
    • Minimum / Average / Maximum Object size
  2. Slab table (remaining space):

    • Columns: OBJS, ACTIVE, USE%, OBJ SIZE, SLABS, OBJ/SLAB, CACHE SIZE, NAME
    • Sorted by the selected criterion

Once mode (-o)

Prints the slab table to stdout in plain text format and exits. Does not enter the TUI. Useful for scripting.

Color

USE% column color indicates cache utilization:

  • Green: >= 90% utilization
  • Yellow: >= 50% utilization
  • Red: < 50% utilization (with objects allocated)

Computed fields

  • CACHE SIZE: num_slabs * pages_per_slab * 4096 bytes
  • USE%: active_objs / num_objs * 100

Interactive commands

KeyAction
q / QQuit
SpaceForce immediate refresh
a, b, c, l, n, o, p, s, uChange sort criterion
Up / kScroll up one row
Down / jScroll down one row
Page UpScroll up 20 rows
Page DownScroll down 20 rows
HomeScroll to top
EndScroll to bottom
Mouse wheelScroll up/down 3 rows

Terminal handling

Uses ratatui with crossterm as the terminal backend. Enters alternate screen and raw mode on startup, restores the terminal on exit.

Exit codes

CodeMeaning
0Normal exit
1Failure (cannot read /proc/slabinfo or terminal error)

Divergences from procps-ng

  • The use-percentage column header is USE% (with the percent sign baked into the column name) rather than procps-ng’s bare USE.
  • Error messages for invalid flag combinations and option-parse failures use different wording.

snice

Change the scheduling priority of processes selected by user, tty, pid, or command.

Description

snice is the obsolete predecessor of renice; both tools are kept for compatibility, but new use cases should prefer renice. The CLI follows procps-ng’s convention where the priority adjustment is given as a leading +N or -N argument (e.g. snice +7 -u alice).

The default priority is +4 (a small step toward “nicer” / lower priority).

Inputs

  • setpriority(2) via libc::setpriority (with PRIO_PROCESS).
  • /proc/[pid]/{stat,status,cmdline} via the shared procmatch module for selection.

Synopsis

snice [new priority] [options] <expression>

expression is a list of bare PIDs (interpreted in conjunction with -p). Selectors with explicit flags can be mixed with bare PIDs.

Arguments

FlagDescription
+N / -N (leading)New nice value. Range typically -20 (highest priority) to +20 (lowest). Default: +4
--priority NSame as the leading-flag form, but in long-flag style
-n, --no-actionDon’t change priority; just print matching PIDs
-v, --verbosePrint the PID, comm, and applied priority for each process
-t, --tty TTYMatch processes whose controlling tty is TTY (repeatable)
-u, --user USERMatch processes whose effective user is USER (repeatable)
-p, --pid PIDMatch processes by PID (repeatable)
-c, --command CMDMatch processes whose comm is exactly CMD (repeatable)
--help / -V, --versionHelp / version

The priority can appear anywhere on the command line; it is rewritten internally to --priority N before clap parses argv (see preprocess_argv). Bare positional integers are added to the PID list.

Behavior

Calls setpriority(PRIO_PROCESS, pid, N) for each matched process. Negative priority values require the appropriate capability (typically CAP_SYS_NICE or root); a process without that privilege will see EPERM for any negative N.

Notes

  • -i (interactive), -f (fast), -w (warnings) and --ns / --nslist are listed in the upstream man page but not implemented here.

Exit codes

CodeMeaning
0At least one process matched and had its priority adjusted
1No processes matched, or all setpriority calls failed
2Usage error (no expression given, invalid argument)

sysctl

Configure kernel parameters at runtime.

Description

Reads and writes kernel parameters exposed through the /proc/sys/ virtual filesystem. Parameters are identified by dotted key names (e.g., kernel.hostname), which map to files in the /proc/sys/ directory tree. Can also load settings in bulk from configuration files.

Inputs

  • /proc/sys/ – kernel parameter tree. Each parameter maps to a file: dots in key names become directory separators (e.g., kernel.hostname maps to /proc/sys/kernel/hostname). Slashes are also accepted as separators.
  • /etc/sysctl.conf – default configuration file (for -p)
  • /etc/sysctl.d/, /run/sysctl.d/, /usr/local/lib/sysctl.d/, /usr/lib/sysctl.d/, /lib/sysctl.d/ – system configuration directories (for --system)

Arguments

Positional

ArgumentDescription
variableKey to read (e.g., kernel.hostname). Prints the current value.
variable=valueKey=value pair to write. Sets the parameter to the given value.

Display options

FlagDescription
-n, --valuesPrint values only, without key names
-N, --namesPrint key names only, without values
-b, --binaryPrint value without a trailing newline

Read options

FlagDescription
-a, --allDisplay all available parameters (walks entire /proc/sys/ tree)
-r, --pattern REGEXOnly show keys matching the given extended regular expression

Write options

FlagDescription
-w, --writeForce all positional arguments to be treated as write operations
-q, --quietSuppress normal output when setting values

Load options

FlagDescription
-p, --load [FILE]Load settings from a file (default: /etc/sysctl.conf). Lines starting with # or ; are comments. Format: key = value.
--systemLoad settings from all system configuration directories and /etc/sysctl.conf

Error handling

FlagDescription
-e, --ignoreIgnore errors about unknown keys (silently skip them)

Behavior

Read mode

When given a variable argument without =, reads the corresponding file under /proc/sys/ and prints the result in key = value format. If the key path resolves to a directory rather than a file, recursively walks the directory showing all parameters beneath it.

Write mode

When given a variable=value argument (or any argument with -w), writes the value to the corresponding file under /proc/sys/. Requires appropriate permissions (usually root). Prints key = value confirming the change unless -q is specified.

List all (-a)

Recursively walks /proc/sys/ in sorted order, printing all readable parameters in key = value format. Parameters that are write-only or require elevated privileges to read are silently skipped.

Pattern filter (-r)

Filters output by matching the dotted key name against an extended regular expression. Can be combined with -a to filter the full parameter list or with individual reads to selectively display results.

Load mode (-p)

Reads a configuration file line by line and applies each setting:

  • Blank lines are skipped.
  • Lines starting with # or ; are treated as comments.
  • Each non-comment line should be in key = value format.
  • Whitespace around the = is trimmed.
  • Each setting is written to its corresponding /proc/sys/ path.

When invoked without a filename, defaults to /etc/sysctl.conf.

System load (--system)

Loads .conf files from the standard system configuration directories in the following order:

  1. /etc/sysctl.d/
  2. /run/sysctl.d/
  3. /usr/local/lib/sysctl.d/
  4. /usr/lib/sysctl.d/
  5. /lib/sysctl.d/

Within each directory, files are loaded in lexicographic order by filename. Finally, /etc/sysctl.conf is loaded. If the same key appears in multiple files, the last value wins.

Exit codes

CodeMeaning
0Success
1Failure (error reading or writing any parameter)

tload

Graphic representation of system load average.

Description

Displays a scrolling ASCII graph of the 1-minute system load average in the terminal. Each column represents one sample, and the height of the bar indicates the load value. The graph scrolls left as new samples are added. Color indicates load severity: green for low, yellow for moderate, red for high.

Press q to quit.

Inputs

  • /proc/loadavg – 1, 5, and 15 minute load averages

Arguments

FlagDescription
-s, --scale SCALEVertical scale in characters per unit of load (default: 4). A smaller value produces a larger visual scale.
-d, --delay SECSDelay between graph updates in seconds (default: 1, minimum: 0.1)

Behavior

Display

The terminal is divided into two regions:

  1. Header line: shows the current 1, 5, and 15 minute load averages.
  2. Graph area: fills the remaining terminal height. Each column is one sample of the 1-minute load average. The bar height is load * scale characters.

Graph characters

  • * – normal bar fill
  • = – tick mark at each scale interval (e.g., at load 1.0, 2.0, etc. when scale is 4)

Color

Bar color is determined by the load value of that sample:

  • Green: load <= 2.0
  • Yellow: load > 2.0 and <= 4.0
  • Red: load > 4.0

Terminal handling

Uses ratatui with crossterm as the terminal backend. Enters alternate screen and raw mode on startup, restores the terminal on exit. Responds to terminal resize by redrawing to fit the new dimensions.

Exit codes

CodeMeaning
0Normal exit (user pressed q)
1Failure (terminal initialization error)

top

Dynamic real-time view of running processes.

Description

Displays a continuously updating summary of system state and a sorted table of processes, similar to the top(1) provided by procps-ng. Defaults to an interactive TUI; can also run in batch mode for non-interactive output.

Press q to quit.

Inputs

System-wide

  • /proc/stat – aggregate and per-CPU jiffies (user, nice, system, idle, iowait, irq, softirq, steal). Used to compute CPU% deltas between samples.
  • /proc/meminfoMemTotal, MemFree, MemAvailable, Buffers, Cached, SReclaimable, SwapTotal, SwapFree.
  • /proc/loadavg – 1/5/15-minute load averages.
  • /proc/uptime – system uptime in seconds.
  • /var/run/utmp – count of USER_PROCESS (type 7) entries; reported as the user count in the header. Each entry is assumed to be 384 bytes (Linux x86_64 layout).
  • /etc/localtime (TZif v1/v2/v3) or the TZ environment variable – used to render the wall-clock time in the header without pulling in chrono or libc time facilities.

Per-process

  • /proc/[pid]/stat – pid, comm, state, priority, nice, vsize, rss, utime, stime.
  • /proc/[pid]/statuseuid, RssFile, RssShmem (used to derive SHR).
  • /proc/[pid]/cmdline – full command line (shown when c is toggled).
  • /etc/passwd – UID to username resolution, cached across refreshes.

Arguments

FlagDescription
-d, --delay SECSRefresh interval in seconds (default: 3.0, minimum: 0.1)
-n, --iterations NExit after N display updates
-b, --batchBatch mode – non-interactive plain-text output, suitable for piping
-p, --pid PIDSShow only the given PIDs (comma-separated)
-u, --user USERShow only processes for this user (name or numeric UID)
-1Start with per-CPU display enabled

Behavior

TUI mode (default)

The terminal is divided into two regions:

  1. Summary header – variable height (5 lines + per-CPU lines):

    • top - HH:MM:SS up ..., N users, load average: a, b, c
    • Tasks: T total, R running, S sleeping, T stopped, Z zombie
    • %Cpu(s): aggregate, or one line per CPU when per-CPU mode is on (us, sy, ni, id, wa, hi, si, st)
    • MiB Mem: total / free / used / buff+cache
    • MiB Swap: total / free / used / available
  2. Process table – remaining space:

    • Columns: PID, USER, PR, NI, VIRT, RES, SHR, S, %CPU, %MEM, TIME+, COMMAND
    • Sorted by the active sort field (default: %CPU descending)
    • Sort indicator (v descending / ^ ascending) shown next to the active column

Batch mode (-b)

Prints summary and process table to stdout each iteration in plain text (no TUI, no colors, no cursor control). Repeats every --delay seconds for --iterations rounds, or until interrupted.

CPU% computation

Per-process %CPU is computed as the process’s utime + stime delta divided by the total system CPU ticks delta between samples, scaled by the number of online CPUs so a single fully-busy core reports approximately 100%.

The first refresh has no previous sample, so per-process %CPU is reported as 0.0 and CPU summary lines show cumulative percentages since boot.

Columns

ColumnDescription
PIDProcess ID
USEREffective user name (truncated to 8 chars)
PRScheduling priority; rt if priority < -99
NINice value
VIRTVirtual memory size
RESResident set size
SHRShared resident memory (RssFile + RssShmem)
SState: R running, S sleeping, I idle, D disk-sleep, T/t stopped, Z zombie
%CPUPer-process CPU percentage (see above)
%MEMRES as a percentage of MemTotal
TIME+Cumulative CPU time, formatted M:SS.cc
COMMANDcomm by default; full cmdline when c is toggled

Size formatting

VIRT, RES and SHR are formatted with the shared format_kb helper, producing human-readable units (K / M / G / T) scaled automatically.

Color

State column color reflects process state:

  • Green: R (running)
  • Yellow: T or t (stopped / traced)
  • Red: Z (zombie)
  • Default: all others

The active sort column header is highlighted via the table header style.

Interactive commands

KeyAction
q / QQuit
SpaceForce immediate refresh
PSort by %CPU
MSort by %MEM
NSort by PID
TSort by TIME+
RReverse the current sort order
cToggle full command line vs. comm
1Toggle aggregate / per-CPU display
Up / kScroll up one row
Down / jScroll down one row
Page UpScroll up 20 rows
Page DownScroll down 20 rows
HomeScroll to top
EndScroll to bottom
Mouse wheelScroll up/down 3 rows

Sort changes and scroll actions trigger a redraw without a full /proc rescan; only the timer expiry or Space re-reads /proc.

Terminal handling

Uses ratatui with crossterm as the terminal backend. Enters alternate screen, raw mode, and mouse capture on startup; restores the terminal on exit. Pending mouse events are drained between redraws so a flurry of scroll events does not trigger repeated /proc scans.

Exit codes

CodeMeaning
0Normal exit
1Failure (terminal initialization error)

uptime

Display how long the system has been running.

Description

Prints the current time, how long the system has been running, and the system load averages for the past 1, 5, and 15 minutes.

Inputs

  • /proc/uptime – system uptime in seconds and idle time
  • /proc/loadavg – 1, 5, and 15 minute load averages
  • /var/run/utmp – counted for the N users field; parsed via the shared utmp module

Arguments

FlagDescription
-p, --prettyShow uptime in human-readable format
-s, --sinceShow the date/time when the system booted

Behavior

Default mode

Prints a single line with the current time, uptime duration, the number of USER_PROCESS entries in utmp, and load averages:

 14:30:00 up 3 days,  2:15,  3 users,  load average: 0.50, 0.30, 0.20

The uptime portion adapts its format based on duration:

  • 1+ days: N days, H:MM
  • Less than a day: H:MM
  • Less than an hour: M min

Pretty mode (-p)

Prints only the uptime in a human-readable format:

up 3 days, 2 hours, 15 minutes

Components with a value of zero are omitted. Singular/plural forms are used correctly (“1 day” vs “2 days”). If uptime is less than one minute, prints “up 0 minutes”.

Since mode (-s)

Prints the boot timestamp in YYYY-MM-DD HH:MM:SS format using the local timezone:

2024-01-15 08:30:00

Exit codes

CodeMeaning
0Success
1Failure (cannot read proc files)

vmstat

Report virtual memory statistics.

Description

Reports information about processes, memory, paging, block I/O, traps, disks, and CPU activity. The first report gives averages since the last reboot. Subsequent reports cover the sampling interval.

Inputs

  • /proc/stat – CPU times (user, nice, system, idle, iowait, irq, softirq, steal, guest), context switches, boot time, process forks, procs running, procs blocked, and total interrupt count from the “intr” line
  • /proc/meminfo – memory statistics (MemTotal, MemFree, Buffers, Cached, SwapTotal, SwapFree, Active, Inactive, SReclaimable)
  • /proc/vmstat – virtual memory counters (pswpin, pswpout, pgpgin, pgpgout)
  • /proc/uptime – system uptime in seconds (for per-second rate calculations on the first report)
  • /proc/diskstats – per-disk I/O statistics (for -d and -D modes)
  • /proc/slabinfo – slab allocator information (for -m mode)

Note: the total interrupt count is read directly from the “intr” line in /proc/stat because the procfs crate does not expose this field.

Arguments

Positional

ArgumentDescription
delaySeconds between updates (enables repeating mode)
countNumber of updates to print (default: infinite when delay is set)

Mode selection

These flags are mutually exclusive. If none is specified, the default VM statistics mode is used.

FlagDescription
-f, --forksDisplay the total number of forks since boot and exit
-m, --slabsDisplay slabinfo
-s, --statsDisplay a table of event counters and memory statistics
-d, --diskDisplay per-disk I/O statistics
-D, --disk-sumDisplay summary of disk I/O statistics across all disks

Display options

FlagDescription
-a, --activeShow active/inactive memory columns instead of buff/cache
-n, --one-headerPrint the column header only once, not periodically
-S, --unit CHARDisplay unit: k (1000), K (1024, default), m (1000000), M (1048576)
-t, --timestampAppend a timestamp column to each output line
-w, --wideWide output mode (wider columns to avoid truncation)
-y, --no-firstOmit the first report (which shows averages since boot)

Behavior

Default VM mode

Produces a table with the following column groups:

procs -----------memory---------- ---swap-- -----io---- -system-- --------cpu--------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs  us  sy  id  wa  st  gu

Columns:

  • procs: r (runnable processes), b (blocked processes)
  • memory: swpd (used swap), free (free memory), buff (buffer memory), cache (cache memory). With -a, buff and cache are replaced by inact (inactive memory) and active (active memory).
  • swap: si (swap in from disk per second), so (swap out to disk per second)
  • io: bi (blocks received from block devices per second), bo (blocks sent to block devices per second)
  • system: in (interrupts per second), cs (context switches per second)
  • cpu: us (user), sy (system), id (idle), wa (iowait), st (steal), gu (guest) – all as percentages of total CPU time

The first report shows averages since boot, calculated using system uptime as the elapsed interval. Subsequent reports show deltas over the sampling interval. With -y, the first report is omitted.

Stats mode (-s)

Displays a vertical list of memory statistics (in the selected unit), followed by CPU tick counts, paging and swap counts, interrupt and context switch totals, boot time, and fork count.

Disk mode (-d)

Displays a per-disk table:

DISK   TOTAL MERGED  SECTORS    MS  TOTAL MERGED  SECTORS     MS CUR SEC
vda   310603  34230 25314959 94573 392788 161615 28903938 850299   0  50

The first four data columns are reads (total, merged, sectors, ms); the next four are writes; the final two are current in-flight I/O and seconds spent on I/O.

Disk summary mode (-D)

Displays aggregate totals across all disks: total disks, partitions, total reads/writes, merged reads/writes, read/written sectors, and milliseconds spent reading/writing.

Forks mode (-f)

Prints a single line with the total number of forks (from the “processes” field in /proc/stat) since boot:

     12345678 forks

Slabs mode (-m)

Displays the raw contents of /proc/slabinfo.

Exit codes

CodeMeaning
0Success
1Failure (cannot read proc files or invalid arguments)

Divergences from procps-ng

  • Column headers are UPPERCASE (R, B, SWPD, FREE, SI, IN, …) rather than lowercase, matching the convention used by lsblk, lscpu, and other modern util-linux tools.
  • The section-grouping header line above the column names (procs / memory / swap / io / system / cpu for the default layout, disk / reads / writes / IO for -d) is not emitted. Column widths are sized to fit each report’s data, which would visually misalign with a fixed-width label row.

w

Show who is logged on and what they are doing.

Description

Reads the system utmp database to enumerate logged-in user sessions, then correlates each session against /proc to report login time, idle time, cumulative CPU time on the session’s tty (JCPU), CPU time of the foreground process (PCPU), and the command that process is running.

The header line matches uptime(1): current wall-clock time, system uptime, number of logged-in users, and the 1/5/15-minute load averages.

Inputs

  • /var/run/utmp – one record per login session. Each entry’s struct layout follows the system libc’s utmpx; entry stride is detected via std::mem::size_of::<libc::utmpx>() to stay correct across glibc architectures (384 bytes on x86_64, 400 bytes on aarch64).
  • /proc/[pid]/stattty_nr (controlling terminal device), tpgid (foreground process group), utime + stime (cumulative CPU ticks), comm.
  • /proc/[pid]/cmdline – shown in the WHAT column when non-empty.
  • /proc/uptime, /proc/loadavg – header line.
  • /dev/<tty>st_rdev (matched against tty_nr for session membership) and atime/mtime (used to derive idle time).

The session source is utmp only. Modern procps-ng builds compiled with systemd support read sessions from systemd-logind instead, which can yield a different session list on systemd hosts. Logind support is a planned follow-up.

Arguments

FlagDescription
[USER]Show information for the named user only
-h, --no-headerDon’t print the header line
-u, --no-currentDon’t try to identify the foreground process; report info for the utmp entry’s own pid
-s, --shortShort format – omit LOGIN@, JCPU, PCPU
-f, --fromShow the FROM (remote host or display) column
-i, --ip-addrIn FROM, show an IP address rather than hostname (best-effort DNS resolution)
-p, --pidsIn WHAT, prefix the command with loginpid/whatpid
-o, --old-styleBlank IDLE for sessions idle less than one minute

Behavior

Header line

 HH:MM:SS up <uptime>,  N user[s],  load average: A, B, C

<uptime> is D days, H:MM, H:MM, or M min depending on magnitude.

Columns

Default layout (no -f, no -s):

USER     TTY      LOGIN@   IDLE   JCPU  PCPU WHAT
ColumnSource / meaning
USERutmp ut_user (truncated to PROCPS_USERLEN, default 8)
TTYutmp ut_line (basename of the controlling tty, e.g. tty2, pts/0)
FROMutmp ut_host (only with -f; truncated to PROCPS_FROMLEN, default 16)
LOGIN@utmp ut_tv formatted by age (see below)
IDLEnow – max(atime, mtime) of /dev/<tty>; ? when the tty cannot be statted
JCPUsum of utime + stime over all processes with the same tty_nr as the session’s tty
PCPUutime + stime of the foreground process group leader on the tty
WHATcmdline of the foreground process; falls back to comm, then to -

When the session has no resolvable tty (empty ut_line or no matching device), JCPU/PCPU/WHAT fall back to the utmp entry’s own ut_pid.

LOGIN@ format

AgeFormatExample
Same calendar dayHH:MM14:32
Within 7 daysWeekdayHH (3-letter weekday + 2-digit hour)Sat01
OlderDDMmmYY25Apr26

Idle / CPU-time format

The IDLE column and the JCPU/PCPU columns share the same duration format:

MagnitudeFormatExample
< 60sS.SSs (seconds with two decimals)0.06s
< 60minMM:SS54:42
< 24hH:MMm (hours:minutes with m suffix)1:31m
>= 24hNdays3days

Environment

VariableDefaultEffect
PROCPS_USERLEN8Width of the USER column
PROCPS_FROMLEN16Width of the FROM column

Exit codes

CodeMeaning
0Success
1Failure (cannot read /var/run/utmp)

watch

Execute a program periodically, showing output fullscreen.

Description

Runs a command repeatedly at a configurable interval and displays its output in a fullscreen terminal view. Useful for monitoring changing system state. By default, the command is passed to sh -c for execution. The display is cleared and redrawn on each iteration, with an optional header showing the interval, command, and current time.

Inputs

  • External command execution via sh -c (default) or direct exec (with -x)
  • Terminal size via tcgetwinsize() syscall (rustix)

Arguments

Positional

ArgumentDescription
command... (required)Command and arguments to execute. Passed to sh -c as a single string unless -x is used.

Timing options

FlagDescription
-n, --interval SECSUpdate interval in seconds (default: 2.0, minimum: 0.1). Accepts fractional values.
-p, --preciseAttempt to run at precise intervals by compensating for command execution time

Display options

FlagDescription
-t, --no-titleHide the header line showing interval, command, and current time
-w, --no-wrapTruncate long lines at the terminal width instead of wrapping
-c, --colorInterpret and pass through ANSI color escape sequences
-C, --no-colorStrip ANSI color escape sequences from command output

Exit control options

FlagDescription
-b, --beepEmit a BEL character when the command exits with a non-zero status
-e, --errexitFreeze the display when the command exits with a non-zero status, wait for a keypress, then exit
-g, --chgexitExit when command output changes from the previous run
-q, --equexit CYCLESExit when command output remains unchanged for N consecutive cycles

Execution options

FlagDescription
-x, --execPass the command directly to exec() instead of sh -c. Arguments are not interpreted by a shell.

Behavior

Main loop

Each iteration performs the following steps:

  1. Query terminal dimensions.
  2. Execute the command (via sh -c or direct exec with -x).
  3. Clear the screen using ANSI escape sequences (ESC[2J ESC[H).
  4. Print the header line (unless -t is specified): Every N.Ns: command left-aligned with the current time right-aligned.
  5. Display the command output, truncated to the terminal height.
  6. If -w is specified, truncate each line at the terminal width.
  7. Sleep for the remaining interval time.

Precise mode (-p)

Without --precise, the interval is measured from the end of one execution to the start of the next. With --precise, the total cycle time (execution plus sleep) is kept as close to the requested interval as possible by subtracting the command’s execution time from the sleep duration. If the command takes longer than the interval, the next iteration starts immediately.

Exit conditions

  • Normal: runs indefinitely until interrupted (Ctrl-C).
  • --chgexit: exits with code 0 when the command output differs from the previous iteration.
  • --equexit N: exits with code 0 when the command output remains unchanged for N consecutive cycles.
  • --errexit: when the command exits non-zero, freezes the display with an error message, waits for a keypress, then exits with code 8.
  • --beep: sends a BEL character (\x07) when the command exits non-zero but continues running.

Exit codes

CodeMeaning
0Success, or exit triggered by --chgexit / --equexit
4Command could not be executed
8Command error with --errexit