proc_watch/proc_watch.rs
1//! Simple process event monitor.
2//!
3//! Prints all process events as they happen.
4//! Requires root or `CAP_NET_ADMIN` to run.
5//!
6//! Usage:
7//! ```sh
8//! cargo run --example proc_watch
9//! ```
10//!
11//! Example output:
12//! ```text
13//! [2026-05-11T21:30:00Z] EXEC pid=1234 tgid=1234
14//! [2026-05-11T21:30:01Z] FORK parent=(1000,1000) child=(1235,1235)
15//! [2026-05-11T21:30:05Z] EXIT pid=1235 tgid=1235 code=0 signal=17
16//! ```
17
18use proc_connector::ProcConnector;
19use std::time::Instant;
20
21fn main() {
22 // Create connector (requires root / CAP_NET_ADMIN)
23 let conn = ProcConnector::new().expect("failed to create proc connector (try as root)");
24 let mut buf = vec![0u8; 4096];
25
26 println!("listening for process events... (Ctrl+C to stop)");
27
28 // Example 1: blocking recv loop
29 loop {
30 match conn.recv(&mut buf) {
31 Ok(event) => {
32 let now = humantime_or_iso(Instant::now());
33 println!("[{now}] {event}");
34 }
35 Err(e) => {
36 eprintln!("recv error: {e}");
37 break;
38 }
39 }
40 }
41}
42
43/// Format an Instant as a human-readable timestamp.
44fn humantime_or_iso(instant: Instant) -> String {
45 // Simple ISO-like timestamp since process start
46 let secs = instant.elapsed().as_secs();
47 let hours = secs / 3600;
48 let mins = (secs % 3600) / 60;
49 let secs = secs % 60;
50 format!("{:02}:{:02}:{:02}", hours, mins, secs)
51}