| name | sysinfo |
| description | System and process information for Rust applications |
| version | 0.33 |
sysinfo
Cross-platform library for retrieving system information: processes, CPUs, memory, disks, and networks.
Key Types
Core Types
| Type | Purpose |
|---|
System | Main struct holding all system information |
Process | Information about a single process |
Pid | Process identifier (platform-specific wrapper) |
ProcessesToUpdate | Enum specifying which processes to refresh |
Refresh Kind Types (Performance Critical)
| Type | Purpose |
|---|
ProcessRefreshKind | Controls what process info to refresh |
RefreshKind | Controls what system info to refresh |
UpdateKind | Never, OnlyIfNotSet, or Always |
Usage in script-kit-gpui
Process Manager (process_manager.rs)
The crate is used for orphan process detection - checking if child bun processes are still running:
use sysinfo::{Pid, System};
pub fn is_process_running(&self, pid: u32) -> bool {
let mut system = System::new();
system.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
system.process(Pid::from_u32(pid)).is_some()
}
Key patterns used:
System::new() - Create minimal system instance
refresh_processes(ProcessesToUpdate::All, true) - Refresh all processes, remove dead ones
system.process(Pid::from_u32(pid)) - Look up specific process by PID
Pid::from_u32() - Convert platform u32 to sysinfo's Pid type
Process Information
Checking if Process Exists
use sysinfo::{Pid, ProcessesToUpdate, System};
let mut sys = System::new();
sys.refresh_processes(ProcessesToUpdate::All, true);
if let Some(process) = sys.process(Pid::from_u32(1234)) {
println!("Process {} is running", process.name().to_string_lossy());
}
let pids = [Pid::from_u32(1234), Pid::from_u32(5678)];
sys.refresh_processes(ProcessesToUpdate::Some(&pids), true);
Process Properties
process.pid()
process.name()
process.exe()
process.cmd()
process.cwd()
process.environ()
process.memory()
process.virtual_memory()
process.cpu_usage()
process.status()
process.parent()
process.start_time()
process.run_time()
Killing Processes
use sysinfo::Signal;
process.kill();
if let Some(success) = process.kill_with(Signal::Term) {
println!("Signal sent: {}", success);
}
process.wait();
Refresh Patterns
CRITICAL: Always Refresh Before Reading
sysinfo works on diffs - you must refresh to get current data:
let sys = System::new_all();
let mem = sys.used_memory();
let mut sys = System::new();
sys.refresh_memory();
let mem = sys.used_memory();
Performance: Refresh Only What You Need
use sysinfo::{ProcessRefreshKind, ProcessesToUpdate, System};
sys.refresh_all();
sys.refresh_processes_specifics(
ProcessesToUpdate::All,
true,
ProcessRefreshKind::nothing().with_memory(),
);
let pids = [Pid::from_u32(1234)];
sys.refresh_processes(ProcessesToUpdate::Some(&pids), true);
ProcessRefreshKind Builder
use sysinfo::{ProcessRefreshKind, UpdateKind};
ProcessRefreshKind::nothing()
ProcessRefreshKind::everything()
ProcessRefreshKind::nothing()
.with_memory()
.with_cpu()
.with_disk_usage()
.with_exe(UpdateKind::OnlyIfNotSet)
Reuse System Instance
fn check_process(pid: u32) -> bool {
let mut sys = System::new();
sys.refresh_processes(ProcessesToUpdate::All, true);
sys.process(Pid::from_u32(pid)).is_some()
}
struct ProcessMonitor {
sys: System,
}
impl ProcessMonitor {
fn check_process(&mut self, pid: u32) -> bool {
self.sys.refresh_processes(ProcessesToUpdate::All, true);
self.sys.process(Pid::from_u32(pid)).is_some()
}
}
CPU Usage Notes
CPU usage requires two measurements with time between them:
use sysinfo::{System, MINIMUM_CPU_UPDATE_INTERVAL};
use std::thread;
let mut sys = System::new_all();
sys.refresh_cpu_usage();
thread::sleep(MINIMUM_CPU_UPDATE_INTERVAL);
sys.refresh_cpu_usage();
for cpu in sys.cpus() {
println!("{}%", cpu.cpu_usage());
}
Platform Differences
Process Names on Linux
- Limited to 15 characters
- May not match executable name
- Use
process.exe() for full path when available
macOS Sandboxing
For App Store apps, use feature flags:
[dependencies]
sysinfo = { version = "0.33", features = ["apple-app-store"] }
Windows
- Admin privileges may be needed for some process info
- PID is
usize, not pid_t
Pid Conversions
use sysinfo::Pid;
let pid = Pid::from_u32(1234);
let n: u32 = pid.as_u32();
let pid = Pid::from(1234_usize);
let n: usize = pid.into();
let pid: Pid = "1234".parse().unwrap();
Anti-patterns
Creating System::new_all() Repeatedly
fn get_memory() -> u64 {
System::new_all().used_memory()
}
fn get_memory(sys: &mut System) -> u64 {
sys.refresh_memory();
sys.used_memory()
}
Not Refreshing Before Reading
let sys = System::new();
let procs = sys.processes();
let mut sys = System::new();
sys.refresh_processes(ProcessesToUpdate::All, true);
let procs = sys.processes();
Refreshing Everything When You Need One Thing
sys.refresh_all();
let mem = sys.used_memory();
sys.refresh_memory();
let mem = sys.used_memory();
Trusting process.name() on Linux
let name = process.name();
let name = process.exe()
.and_then(|p| p.file_name())
.map(|n| n.to_string_lossy().to_string())
.unwrap_or_else(|| process.name().to_string_lossy().to_string());
Reading CPU Usage Without History
let mut sys = System::new_all();
let cpu = sys.global_cpu_usage();
let mut sys = System::new_all();
std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
sys.refresh_cpu_usage();
let cpu = sys.global_cpu_usage();
Common Patterns
Find Process by Name
for process in sys.processes_by_exact_name("bun".as_ref()) {
println!("{}: {}", process.pid(), process.name().to_string_lossy());
}
for process in sys.processes_by_name("bun".as_ref()) {
println!("{}: {}", process.pid(), process.name().to_string_lossy());
}
Monitor Process Until Exit
use std::time::Duration;
fn wait_for_exit(pid: u32, timeout: Duration) -> bool {
let mut sys = System::new();
let deadline = std::time::Instant::now() + timeout;
let target_pid = Pid::from_u32(pid);
while std::time::Instant::now() < deadline {
sys.refresh_processes(
ProcessesToUpdate::Some(&[target_pid]),
true
);
if sys.process(target_pid).is_none() {
return true;
}
std::thread::sleep(Duration::from_millis(100));
}
false
}
Feature Flags
[dependencies]
sysinfo = { version = "0.33", default-features = false }
References