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).
| Flag | Unit | Base |
|---|---|---|
-b, --bytes | bytes | – |
--kilo | kilobytes | 1000 |
--mega | megabytes | 1000^2 |
--giga | gigabytes | 1000^3 |
--tera | terabytes | 1000^4 |
--peta | petabytes | 1000^5 |
-k, --kibi | kibibytes (default) | 1024 |
-m, --mebi | mebibytes | 1024^2 |
-g, --gibi | gibibytes | 1024^3 |
--tebi | tebibytes | 1024^4 |
--pebi | pebibytes | 1024^5 |
Display options
| Flag | Description |
|---|---|
-h, --human | Human-readable output with auto-scaled units |
--si | Use powers of 1000 instead of 1024 (with -h) |
-w, --wide | Wide output: show separate Buffers and Cache columns instead of combined buff/cache |
-l, --lohi | Show detailed low and high memory statistics |
-L, --line | Show output on a single line |
-t, --total | Show a Total row (RAM + swap combined) |
-v, --committed | Show committed memory and commit limit |
Repeat options
| Flag | Description |
|---|---|
-s, --seconds SECS | Repeat printing every SECS seconds (accepts fractional values) |
-c, --count N | Repeat 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, --lohiadds Low and High memory rows (relevant on 32-bit systems)-t, --totaladds a Total row summing Mem and Swap-v, --committedadds 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
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Failure (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 bylsblk,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 hugepagesHugePages_Free– number of unallocated hugepagesHugePages_Rsvd– reserved but not yet allocated hugepagesHugePages_Surp– surplus hugepages above the configured poolHugepagesize– default hugepage size (typically 2048 kB)Hugetlb– total memory in HugeTLB pages
Per-process
/proc/[pid]/status–HugetlbPagesfield (explicit hugepage usage)/proc/[pid]/smaps_rollup–AnonHugePagesfield (transparent hugepage usage, aggregated across all mappings)/proc/[pid]/stat– PID and command name/etc/passwd– UID to username resolution (cached)
Arguments
| Flag | Description |
|---|---|
-d, --delay SECS | Refresh interval in seconds (default: 2, minimum: 0.5) |
Behavior
Display layout
The terminal is divided into two regions:
-
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
-
Process table (remaining space):
- Sorted by total hugepage usage (descending)
- Columns: PID, USER, HUGETLB, ANON_HUGE, TOTAL, COMMAND
Columns
| Column | Description |
|---|---|
| PID | Process ID |
| USER | Effective user name |
| HUGETLB | Explicit HugeTLB usage (from /proc/[pid]/status) |
| ANON_HUGE | Transparent hugepage usage (from /proc/[pid]/smaps_rollup) |
| TOTAL | Sum of HUGETLB + ANON_HUGE |
| COMMAND | Process 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
| Code | Meaning |
|---|---|
| 0 | Normal exit (user pressed q) |
| 1 | Failure (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 vialibc::killfor delivery.- No
/procaccess; PIDs are passed straight through to the kernel.
Synopses
kill [options] <pid> [<pid> ...]
kill -l [<signal> ...]
kill -L
Arguments
| Flag | Description |
|---|---|
-s, --signal SIG | Signal 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, --table | Print the signal table – number and name pairs, eight per line |
--help | Print help |
-V, --version | Print 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):
| PID | Effect |
|---|---|
> 0 | Signal the process with that PID |
0 | Signal every process in the caller’s process group |
-1 | Signal every process the caller is permitted to signal, except init |
< -1 | Signal 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
-s SIG/--signal SIG- A leading
-Nor-NAMEargument (e.g.kill -9 1234,kill -KILL 1234) - 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
| Invocation | Output |
|---|---|
kill -l | All signal names (no SIG prefix), space-separated, one line |
kill -l N | Name for signal number N |
kill -l NAME | Number 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
| Code | Meaning |
|---|---|
| 0 | All signals delivered successfully (or a successful list/table operation) |
| 1 | At least one signal delivery failed (no such process, permission denied, etc.) |
| 2 | Usage 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--oldercalculation)
Arguments
Positional
| Argument | Description |
|---|---|
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
| Flag | Description |
|---|---|
-f, --full | Match against the full command line instead of just the process name |
-i, --ignore-case | Case-insensitive matching |
-x, --exact | Require an exact match (anchors the pattern with ^...$) |
-v, --inverse | Negate the matching: select non-matching processes |
Selection filters
| Flag | Description |
|---|---|
-n, --newest | Select only the most recently started matching process |
-o, --oldest | Select only the least recently started matching process |
-O, --older SECS | Select 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
| Flag | Description |
|---|---|
-c, --count | Print only a count of matching processes instead of PIDs |
-d, --delimiter DELIM | String to use between PIDs in output (default: newline) |
-l, --list-name | Print PID and process name for each match |
-a, --list-full | Print 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
--newestor--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-commonlibrary crate.
Exit codes
| Code | Meaning |
|---|---|
| 0 | One or more processes matched |
| 1 | No processes matched |
| 2 | Syntax error (invalid arguments) |
| 3 | Fatal 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-Fand-pis 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(sincecommis 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-fmatching)/proc/uptime– system uptime (for--oldercalculations)kill()syscall via rustix – sends signals to matched processes
Arguments
Pattern
| Argument | Description |
|---|---|
pattern (positional, optional) | Extended regex to match against process names |
Signal selection
| Flag | Description |
|---|---|
--signal SIGNAL | Signal to send, by name or number (default: TERM) |
Output options
| Flag | Description |
|---|---|
-c, --count | Print count of matched processes instead of signaling |
-e, --echo | Display name and PID of each signaled process |
Matching options
| Flag | Description |
|---|---|
-f, --full | Match pattern against full command line, not just process name |
-i, --ignore-case | Case-insensitive pattern matching |
-x, --exact | Require exact match of the process name (not a substring) |
Selection filters
| Flag | Description |
|---|---|
-n, --newest | Select only the most recently started matching process |
-o, --oldest | Select only the earliest started matching process |
-O, --older SECS | Select 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:
- Named signal without prefix:
TERM,HUP,KILL, etc. - Named signal with SIG prefix:
SIGTERM,SIGHUP,SIGKILL, etc. - 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.
-nand-oare 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
| Code | Meaning |
|---|---|
| 0 | At least one process was matched and successfully signaled |
| 1 | No processes matched, or signaling failed for all matches |
| 2 | Syntax error in command line arguments |
| 3 | Fatal 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
| Argument | Description |
|---|---|
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.
| Flag | Description |
|---|---|
-x, --extended | Show extended format with RSS and Dirty columns (reads smaps) |
-d, --device | Show device format with Offset and Device columns |
Display options
| Flag | Description |
|---|---|
-q, --quiet | Suppress header and footer lines |
-p, --show-path | Show 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).
Header
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
| Code | Meaning |
|---|---|
| 0 | All requested PIDs were displayed successfully |
| 42 | One 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
| Flag | Description |
|---|---|
-A, --all | Select all processes |
-e | Select all processes (identical to -A) |
-a | Select all processes with a controlling terminal, except session leaders |
-x | Include 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
| Flag | Description |
|---|---|
-u | User-oriented format (typically combined with -a -x for “aux” style) |
-f | Full-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:
| Character | Position | Meaning |
|---|---|---|
| R, S, D, Z, T, t, X, I | 1st | Process state (running, sleeping, disk sleep, zombie, stopped, tracing stop, dead, idle) |
< | modifier | High priority (nice < 0) |
N | modifier | Low priority (nice > 0) |
s | modifier | Session leader (PID == session ID) |
l | modifier | Multi-threaded (num_threads > 1) |
+ | modifier | In foreground process group (tpgid == pgrp) |
TIME
Cumulative CPU time (utime + stime), formatted as:
HH:MM:SSwhen one hour or moreM:SSwhen less than one hour
START / STIME
Process start time, formatted as:
HH:MMif the process started todayMonDD(e.g.,Jan15) if the process started on a previous day
TTY
Decoded from the tty_nr field in /proc/[pid]/stat:
pts/Nfor pseudo-terminalsttyNfor virtual consolesttySNfor serial terminals?for processes without a controlling terminal
All output uses the cols crate for column alignment.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Failure |
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
| Argument | Description |
|---|---|
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
| Code | Meaning |
|---|---|
| 0 | All PIDs were resolved successfully |
| 1 | One 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 vialibc::killfor delivery./proc/[pid]/{stat,status,cmdline}via the sharedprocmatchmodule 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
| Flag | Description |
|---|---|
-<SIG> (e.g. -9, -KILL, -SIGKILL) | Signal to send. Default: TERM |
--signal SIG | Same as the leading-flag form, but in long-flag style |
-l, --list | List all signal names |
-L, --table | List all signal names in a numbered table |
-n, --no-action | Don’t send signals; just print matching PIDs |
-v, --verbose | Print the PID and comm of each signaled process |
-t, --tty TTY | Match processes whose controlling tty is TTY (repeatable) |
-u, --user USER | Match processes whose effective user is USER (name or numeric UID, repeatable) |
-p, --pid PID | Match processes by PID (repeatable) |
-c, --command CMD | Match processes whose comm is exactly CMD (repeatable) |
--help / -V, --version | Help / 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 Nfor the corresponding number.
Exit codes
| Code | Meaning |
|---|---|
| 0 | At least one process matched and was signaled (or list/table requested) |
| 1 | No processes matched, or all signal deliveries failed |
| 2 | Usage 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
| Flag | Description |
|---|---|
-d, --delay SECS | Refresh interval in seconds (default: 3, minimum: 0.5) |
-s, --sort CHAR | Sort criterion (default: o). See sort criteria below. |
-o, --once | Display 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.
| Key | Sort by | Column |
|---|---|---|
a | Number of active objects (descending) | ACTIVE |
b | Objects per slab (descending) | OBJ/SLAB |
c | Cache size (descending) | CACHE SIZE |
l | Number of slabs (descending) | SLABS |
n | Cache name (ascending, alphabetical) | NAME |
o | Number of objects (descending) | OBJS |
p | Pages per slab (descending) | – |
s | Object size (descending) | OBJ SIZE |
u | Cache utilization percentage (descending) | USE% |
Behavior
TUI mode (default)
The terminal is divided into two regions:
-
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
-
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 * 4096bytes - USE%:
active_objs / num_objs * 100
Interactive commands
| Key | Action |
|---|---|
q / Q | Quit |
| Space | Force immediate refresh |
a, b, c, l, n, o, p, s, u | Change sort criterion |
Up / k | Scroll up one row |
Down / j | Scroll down one row |
| Page Up | Scroll up 20 rows |
| Page Down | Scroll down 20 rows |
| Home | Scroll to top |
| End | Scroll to bottom |
| Mouse wheel | Scroll 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
| Code | Meaning |
|---|---|
| 0 | Normal exit |
| 1 | Failure (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 bareUSE. - 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)vialibc::setpriority(withPRIO_PROCESS)./proc/[pid]/{stat,status,cmdline}via the sharedprocmatchmodule 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
| Flag | Description |
|---|---|
+N / -N (leading) | New nice value. Range typically -20 (highest priority) to +20 (lowest). Default: +4 |
--priority N | Same as the leading-flag form, but in long-flag style |
-n, --no-action | Don’t change priority; just print matching PIDs |
-v, --verbose | Print the PID, comm, and applied priority for each process |
-t, --tty TTY | Match processes whose controlling tty is TTY (repeatable) |
-u, --user USER | Match processes whose effective user is USER (repeatable) |
-p, --pid PID | Match processes by PID (repeatable) |
-c, --command CMD | Match processes whose comm is exactly CMD (repeatable) |
--help / -V, --version | Help / 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/--nslistare listed in the upstream man page but not implemented here.
Exit codes
| Code | Meaning |
|---|---|
| 0 | At least one process matched and had its priority adjusted |
| 1 | No processes matched, or all setpriority calls failed |
| 2 | Usage 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.hostnamemaps 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
| Argument | Description |
|---|---|
variable | Key to read (e.g., kernel.hostname). Prints the current value. |
variable=value | Key=value pair to write. Sets the parameter to the given value. |
Display options
| Flag | Description |
|---|---|
-n, --values | Print values only, without key names |
-N, --names | Print key names only, without values |
-b, --binary | Print value without a trailing newline |
Read options
| Flag | Description |
|---|---|
-a, --all | Display all available parameters (walks entire /proc/sys/ tree) |
-r, --pattern REGEX | Only show keys matching the given extended regular expression |
Write options
| Flag | Description |
|---|---|
-w, --write | Force all positional arguments to be treated as write operations |
-q, --quiet | Suppress normal output when setting values |
Load options
| Flag | Description |
|---|---|
-p, --load [FILE] | Load settings from a file (default: /etc/sysctl.conf). Lines starting with # or ; are comments. Format: key = value. |
--system | Load settings from all system configuration directories and /etc/sysctl.conf |
Error handling
| Flag | Description |
|---|---|
-e, --ignore | Ignore 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 = valueformat. - 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:
/etc/sysctl.d//run/sysctl.d//usr/local/lib/sysctl.d//usr/lib/sysctl.d//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
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Failure (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
| Flag | Description |
|---|---|
-s, --scale SCALE | Vertical scale in characters per unit of load (default: 4). A smaller value produces a larger visual scale. |
-d, --delay SECS | Delay between graph updates in seconds (default: 1, minimum: 0.1) |
Behavior
Display
The terminal is divided into two regions:
- Header line: shows the current 1, 5, and 15 minute load averages.
- Graph area: fills the remaining terminal height. Each column is one
sample of the 1-minute load average. The bar height is
load * scalecharacters.
Graph characters
*– normal bar fill=– tick mark at eachscaleinterval (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
| Code | Meaning |
|---|---|
| 0 | Normal exit (user pressed q) |
| 1 | Failure (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/meminfo–MemTotal,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 ofUSER_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 theTZenvironment variable – used to render the wall-clock time in the header without pulling inchronoor libc time facilities.
Per-process
/proc/[pid]/stat– pid, comm, state, priority, nice, vsize, rss, utime, stime./proc/[pid]/status–euid,RssFile,RssShmem(used to derive SHR)./proc/[pid]/cmdline– full command line (shown whencis toggled)./etc/passwd– UID to username resolution, cached across refreshes.
Arguments
| Flag | Description |
|---|---|
-d, --delay SECS | Refresh interval in seconds (default: 3.0, minimum: 0.1) |
-n, --iterations N | Exit after N display updates |
-b, --batch | Batch mode – non-interactive plain-text output, suitable for piping |
-p, --pid PIDS | Show only the given PIDs (comma-separated) |
-u, --user USER | Show only processes for this user (name or numeric UID) |
-1 | Start with per-CPU display enabled |
Behavior
TUI mode (default)
The terminal is divided into two regions:
-
Summary header – variable height (5 lines + per-CPU lines):
top - HH:MM:SS up ..., N users, load average: a, b, cTasks: 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+cacheMiB Swap:total / free / used / available
-
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 (
vdescending /^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
| Column | Description |
|---|---|
| PID | Process ID |
| USER | Effective user name (truncated to 8 chars) |
| PR | Scheduling priority; rt if priority < -99 |
| NI | Nice value |
| VIRT | Virtual memory size |
| RES | Resident set size |
| SHR | Shared resident memory (RssFile + RssShmem) |
| S | State: R running, S sleeping, I idle, D disk-sleep, T/t stopped, Z zombie |
| %CPU | Per-process CPU percentage (see above) |
| %MEM | RES as a percentage of MemTotal |
| TIME+ | Cumulative CPU time, formatted M:SS.cc |
| COMMAND | comm 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
| Key | Action |
|---|---|
q / Q | Quit |
| Space | Force immediate refresh |
P | Sort by %CPU |
M | Sort by %MEM |
N | Sort by PID |
T | Sort by TIME+ |
R | Reverse the current sort order |
c | Toggle full command line vs. comm |
1 | Toggle aggregate / per-CPU display |
Up / k | Scroll up one row |
Down / j | Scroll down one row |
| Page Up | Scroll up 20 rows |
| Page Down | Scroll down 20 rows |
| Home | Scroll to top |
| End | Scroll to bottom |
| Mouse wheel | Scroll 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
| Code | Meaning |
|---|---|
| 0 | Normal exit |
| 1 | Failure (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 theN usersfield; parsed via the sharedutmpmodule
Arguments
| Flag | Description |
|---|---|
-p, --pretty | Show uptime in human-readable format |
-s, --since | Show 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
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Failure (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-dand-Dmodes)/proc/slabinfo– slab allocator information (for-mmode)
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
| Argument | Description |
|---|---|
delay | Seconds between updates (enables repeating mode) |
count | Number 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.
| Flag | Description |
|---|---|
-f, --forks | Display the total number of forks since boot and exit |
-m, --slabs | Display slabinfo |
-s, --stats | Display a table of event counters and memory statistics |
-d, --disk | Display per-disk I/O statistics |
-D, --disk-sum | Display summary of disk I/O statistics across all disks |
Display options
| Flag | Description |
|---|---|
-a, --active | Show active/inactive memory columns instead of buff/cache |
-n, --one-header | Print the column header only once, not periodically |
-S, --unit CHAR | Display unit: k (1000), K (1024, default), m (1000000), M (1048576) |
-t, --timestamp | Append a timestamp column to each output line |
-w, --wide | Wide output mode (wider columns to avoid truncation) |
-y, --no-first | Omit 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
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Failure (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 bylsblk,lscpu, and other modern util-linux tools. - The section-grouping header line above the column names
(
procs / memory / swap / io / system / cpufor the default layout,disk / reads / writes / IOfor-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’sutmpx; entry stride is detected viastd::mem::size_of::<libc::utmpx>()to stay correct across glibc architectures (384 bytes on x86_64, 400 bytes on aarch64)./proc/[pid]/stat–tty_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 againsttty_nrfor session membership) andatime/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
| Flag | Description |
|---|---|
[USER] | Show information for the named user only |
-h, --no-header | Don’t print the header line |
-u, --no-current | Don’t try to identify the foreground process; report info for the utmp entry’s own pid |
-s, --short | Short format – omit LOGIN@, JCPU, PCPU |
-f, --from | Show the FROM (remote host or display) column |
-i, --ip-addr | In FROM, show an IP address rather than hostname (best-effort DNS resolution) |
-p, --pids | In WHAT, prefix the command with loginpid/whatpid |
-o, --old-style | Blank 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
| Column | Source / meaning |
|---|---|
| USER | utmp ut_user (truncated to PROCPS_USERLEN, default 8) |
| TTY | utmp ut_line (basename of the controlling tty, e.g. tty2, pts/0) |
| FROM | utmp ut_host (only with -f; truncated to PROCPS_FROMLEN, default 16) |
| LOGIN@ | utmp ut_tv formatted by age (see below) |
| IDLE | now – max(atime, mtime) of /dev/<tty>; ? when the tty cannot be statted |
| JCPU | sum of utime + stime over all processes with the same tty_nr as the session’s tty |
| PCPU | utime + stime of the foreground process group leader on the tty |
| WHAT | cmdline 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
| Age | Format | Example |
|---|---|---|
| Same calendar day | HH:MM | 14:32 |
| Within 7 days | WeekdayHH (3-letter weekday + 2-digit hour) | Sat01 |
| Older | DDMmmYY | 25Apr26 |
Idle / CPU-time format
The IDLE column and the JCPU/PCPU columns share the same duration format:
| Magnitude | Format | Example |
|---|---|---|
< 60s | S.SSs (seconds with two decimals) | 0.06s |
< 60min | MM:SS | 54:42 |
< 24h | H:MMm (hours:minutes with m suffix) | 1:31m |
>= 24h | Ndays | 3days |
Environment
| Variable | Default | Effect |
|---|---|---|
PROCPS_USERLEN | 8 | Width of the USER column |
PROCPS_FROMLEN | 16 | Width of the FROM column |
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Failure (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 directexec(with-x) - Terminal size via
tcgetwinsize()syscall (rustix)
Arguments
Positional
| Argument | Description |
|---|---|
command... (required) | Command and arguments to execute. Passed to sh -c as a single string unless -x is used. |
Timing options
| Flag | Description |
|---|---|
-n, --interval SECS | Update interval in seconds (default: 2.0, minimum: 0.1). Accepts fractional values. |
-p, --precise | Attempt to run at precise intervals by compensating for command execution time |
Display options
| Flag | Description |
|---|---|
-t, --no-title | Hide the header line showing interval, command, and current time |
-w, --no-wrap | Truncate long lines at the terminal width instead of wrapping |
-c, --color | Interpret and pass through ANSI color escape sequences |
-C, --no-color | Strip ANSI color escape sequences from command output |
Exit control options
| Flag | Description |
|---|---|
-b, --beep | Emit a BEL character when the command exits with a non-zero status |
-e, --errexit | Freeze the display when the command exits with a non-zero status, wait for a keypress, then exit |
-g, --chgexit | Exit when command output changes from the previous run |
-q, --equexit CYCLES | Exit when command output remains unchanged for N consecutive cycles |
Execution options
| Flag | Description |
|---|---|
-x, --exec | Pass 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:
- Query terminal dimensions.
- Execute the command (via
sh -cor directexecwith-x). - Clear the screen using ANSI escape sequences (
ESC[2J ESC[H). - Print the header line (unless
-tis specified):Every N.Ns: commandleft-aligned with the current time right-aligned. - Display the command output, truncated to the terminal height.
- If
-wis specified, truncate each line at the terminal width. - 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
| Code | Meaning |
|---|---|
| 0 | Success, or exit triggered by --chgexit / --equexit |
| 4 | Command could not be executed |
| 8 | Command error with --errexit |