]>
Commit | Line | Data |
---|---|---|
923072b8 FG |
1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | ||
3 | #![crate_type = "bin"] | |
4 | #![allow(unused_must_use, non_upper_case_globals)] | |
6522a427 | 5 | #![allow(clippy::manual_range_contains)] |
923072b8 FG |
6 | |
7 | extern crate sysinfo; | |
8 | ||
9 | use std::io::{self, BufRead, Write}; | |
10 | use std::str::FromStr; | |
11 | use sysinfo::Signal::*; | |
12 | use sysinfo::{ | |
13 | CpuExt, NetworkExt, NetworksExt, Pid, ProcessExt, Signal, System, SystemExt, UserExt, | |
14 | }; | |
15 | ||
16 | const signals: &[Signal] = &[ | |
17 | Hangup, | |
18 | Interrupt, | |
19 | Quit, | |
20 | Illegal, | |
21 | Trap, | |
22 | Abort, | |
23 | Bus, | |
24 | FloatingPointException, | |
25 | Kill, | |
26 | User1, | |
27 | Segv, | |
28 | User2, | |
29 | Pipe, | |
30 | Alarm, | |
31 | Term, | |
32 | Child, | |
33 | Continue, | |
34 | Stop, | |
35 | TSTP, | |
36 | TTIN, | |
37 | TTOU, | |
38 | Urgent, | |
39 | XCPU, | |
40 | XFSZ, | |
41 | VirtualAlarm, | |
42 | Profiling, | |
43 | Winch, | |
44 | IO, | |
45 | Power, | |
46 | Sys, | |
47 | ]; | |
48 | ||
49 | fn print_help() { | |
50 | writeln!(&mut io::stdout(), "== Help menu =="); | |
51 | writeln!(&mut io::stdout(), "help : show this menu"); | |
52 | writeln!( | |
53 | &mut io::stdout(), | |
54 | "signals : show the available signals" | |
55 | ); | |
56 | writeln!( | |
57 | &mut io::stdout(), | |
58 | "refresh : reloads all processes' information" | |
59 | ); | |
60 | writeln!( | |
61 | &mut io::stdout(), | |
62 | "refresh [pid] : reloads corresponding process' information" | |
63 | ); | |
64 | writeln!( | |
65 | &mut io::stdout(), | |
66 | "refresh_disks : reloads only disks' information" | |
67 | ); | |
68 | writeln!( | |
69 | &mut io::stdout(), | |
70 | "refresh_users : reloads only users' information" | |
71 | ); | |
72 | writeln!( | |
73 | &mut io::stdout(), | |
74 | "show [pid | name] : show information of the given process \ | |
75 | corresponding to [pid | name]" | |
76 | ); | |
77 | writeln!( | |
78 | &mut io::stdout(), | |
79 | "kill [pid] [signal]: send [signal] to the process with this \ | |
80 | [pid]. 0 < [signal] < 32" | |
81 | ); | |
82 | writeln!( | |
83 | &mut io::stdout(), | |
84 | "cpus : Displays CPUs state" | |
85 | ); | |
86 | writeln!( | |
87 | &mut io::stdout(), | |
88 | "memory : Displays memory state" | |
89 | ); | |
90 | writeln!( | |
91 | &mut io::stdout(), | |
92 | "temperature : Displays components' temperature" | |
93 | ); | |
94 | writeln!( | |
95 | &mut io::stdout(), | |
96 | "disks : Displays disks' information" | |
97 | ); | |
98 | writeln!( | |
99 | &mut io::stdout(), | |
100 | "network : Displays network' information" | |
101 | ); | |
102 | writeln!( | |
103 | &mut io::stdout(), | |
104 | "all : Displays all process name and pid" | |
105 | ); | |
106 | writeln!( | |
107 | &mut io::stdout(), | |
108 | "uptime : Displays system uptime" | |
109 | ); | |
110 | writeln!( | |
111 | &mut io::stdout(), | |
112 | "boot_time : Displays system boot time" | |
113 | ); | |
114 | writeln!( | |
115 | &mut io::stdout(), | |
116 | "vendor_id : Displays CPU vendor id" | |
117 | ); | |
118 | writeln!(&mut io::stdout(), "brand : Displays CPU brand"); | |
119 | writeln!( | |
120 | &mut io::stdout(), | |
121 | "load_avg : Displays system load average" | |
122 | ); | |
123 | writeln!( | |
124 | &mut io::stdout(), | |
125 | "frequency : Displays CPU frequency" | |
126 | ); | |
127 | writeln!(&mut io::stdout(), "users : Displays all users"); | |
128 | writeln!( | |
129 | &mut io::stdout(), | |
130 | "system : Displays system information (such as name, version and hostname)" | |
131 | ); | |
132 | writeln!( | |
133 | &mut io::stdout(), | |
134 | "pid : Display this example's PID" | |
135 | ); | |
136 | writeln!(&mut io::stdout(), "quit : Exit the program"); | |
137 | } | |
138 | ||
139 | fn interpret_input(input: &str, sys: &mut System) -> bool { | |
140 | match input.trim() { | |
141 | "help" => print_help(), | |
142 | "refresh_disks" => { | |
143 | writeln!(&mut io::stdout(), "Refreshing disk list..."); | |
144 | sys.refresh_disks_list(); | |
145 | writeln!(&mut io::stdout(), "Done."); | |
146 | } | |
147 | "refresh_users" => { | |
148 | writeln!(&mut io::stdout(), "Refreshing user list..."); | |
149 | sys.refresh_users_list(); | |
150 | writeln!(&mut io::stdout(), "Done."); | |
151 | } | |
152 | "signals" => { | |
153 | let mut nb = 1i32; | |
154 | ||
155 | for sig in signals { | |
6522a427 | 156 | writeln!(&mut io::stdout(), "{nb:2}:{sig:?}"); |
923072b8 FG |
157 | nb += 1; |
158 | } | |
159 | } | |
160 | "cpus" => { | |
161 | // Note: you should refresh a few times before using this, so that usage statistics | |
162 | // can be ascertained | |
163 | writeln!( | |
164 | &mut io::stdout(), | |
165 | "number of physical cores: {}", | |
166 | sys.physical_core_count() | |
167 | .map(|c| c.to_string()) | |
168 | .unwrap_or_else(|| "Unknown".to_owned()), | |
169 | ); | |
170 | writeln!( | |
171 | &mut io::stdout(), | |
172 | "total process usage: {}%", | |
173 | sys.global_cpu_info().cpu_usage() | |
174 | ); | |
175 | for proc_ in sys.cpus() { | |
6522a427 | 176 | writeln!(&mut io::stdout(), "{proc_:?}"); |
923072b8 FG |
177 | } |
178 | } | |
179 | "memory" => { | |
6522a427 EL |
180 | writeln!( |
181 | &mut io::stdout(), | |
182 | "total memory: {} KB", | |
183 | sys.total_memory() / 1_000 | |
184 | ); | |
185 | writeln!( | |
186 | &mut io::stdout(), | |
187 | "used memory : {} KB", | |
188 | sys.used_memory() / 1_000 | |
189 | ); | |
190 | writeln!( | |
191 | &mut io::stdout(), | |
192 | "total swap : {} KB", | |
193 | sys.total_swap() / 1_000 | |
194 | ); | |
195 | writeln!( | |
196 | &mut io::stdout(), | |
197 | "used swap : {} KB", | |
198 | sys.used_swap() / 1_000 | |
199 | ); | |
923072b8 FG |
200 | } |
201 | "quit" | "exit" => return true, | |
202 | "all" => { | |
203 | for (pid, proc_) in sys.processes() { | |
204 | writeln!( | |
205 | &mut io::stdout(), | |
206 | "{}:{} status={:?}", | |
207 | pid, | |
208 | proc_.name(), | |
209 | proc_.status() | |
210 | ); | |
211 | } | |
212 | } | |
213 | "frequency" => { | |
214 | writeln!( | |
215 | &mut io::stdout(), | |
216 | "{} MHz", | |
217 | sys.global_cpu_info().frequency() | |
218 | ); | |
219 | } | |
220 | "vendor_id" => { | |
221 | writeln!( | |
222 | &mut io::stdout(), | |
223 | "vendor ID: {}", | |
224 | sys.cpus()[0].vendor_id() | |
225 | ); | |
226 | } | |
227 | "brand" => { | |
228 | writeln!(&mut io::stdout(), "brand: {}", sys.cpus()[0].brand()); | |
229 | } | |
230 | "load_avg" => { | |
231 | let load_avg = sys.load_average(); | |
232 | writeln!(&mut io::stdout(), "one minute : {}%", load_avg.one); | |
233 | writeln!(&mut io::stdout(), "five minutes : {}%", load_avg.five); | |
234 | writeln!(&mut io::stdout(), "fifteen minutes: {}%", load_avg.fifteen); | |
235 | } | |
236 | e if e.starts_with("show ") => { | |
237 | let tmp: Vec<&str> = e.split(' ').collect(); | |
238 | ||
239 | if tmp.len() != 2 { | |
240 | writeln!( | |
241 | &mut io::stdout(), | |
242 | "show command takes a pid or a name in parameter!" | |
243 | ); | |
244 | writeln!(&mut io::stdout(), "example: show 1254"); | |
245 | } else if let Ok(pid) = Pid::from_str(tmp[1]) { | |
246 | match sys.process(pid) { | |
247 | Some(p) => writeln!(&mut io::stdout(), "{:?}", *p), | |
6522a427 | 248 | None => writeln!(&mut io::stdout(), "pid \"{pid:?}\" not found"), |
923072b8 FG |
249 | }; |
250 | } else { | |
251 | let proc_name = tmp[1]; | |
252 | for proc_ in sys.processes_by_name(proc_name) { | |
253 | writeln!(&mut io::stdout(), "==== {} ====", proc_.name()); | |
6522a427 | 254 | writeln!(&mut io::stdout(), "{proc_:?}"); |
923072b8 FG |
255 | } |
256 | } | |
257 | } | |
258 | "temperature" => { | |
259 | for component in sys.components() { | |
6522a427 | 260 | writeln!(&mut io::stdout(), "{component:?}"); |
923072b8 FG |
261 | } |
262 | } | |
263 | "network" => { | |
264 | for (interface_name, data) in sys.networks().iter() { | |
265 | writeln!( | |
266 | &mut io::stdout(), | |
267 | "{}:\n input data (new / total): {} / {} B\n output data (new / total): {} / {} B", | |
268 | interface_name, | |
269 | data.received(), | |
270 | data.total_received(), | |
271 | data.transmitted(), | |
272 | data.total_transmitted(), | |
273 | ); | |
274 | } | |
275 | } | |
276 | "show" => { | |
277 | writeln!( | |
278 | &mut io::stdout(), | |
279 | "'show' command expects a pid number or a process name" | |
280 | ); | |
281 | } | |
282 | e if e.starts_with("kill ") => { | |
283 | let tmp: Vec<&str> = e.split(' ').collect(); | |
284 | ||
285 | if tmp.len() != 3 { | |
286 | writeln!( | |
287 | &mut io::stdout(), | |
288 | "kill command takes the pid and a signal number in parameter!" | |
289 | ); | |
290 | writeln!(&mut io::stdout(), "example: kill 1254 9"); | |
291 | } else { | |
292 | let pid = Pid::from_str(tmp[1]).unwrap(); | |
293 | let signal = i32::from_str(tmp[2]).unwrap(); | |
294 | ||
295 | if signal < 1 || signal > 31 { | |
296 | writeln!( | |
297 | &mut io::stdout(), | |
298 | "Signal must be between 0 and 32 ! See the signals list with the \ | |
299 | signals command" | |
300 | ); | |
301 | } else { | |
302 | match sys.process(pid) { | |
303 | Some(p) => { | |
304 | if let Some(res) = | |
305 | p.kill_with(*signals.get(signal as usize - 1).unwrap()) | |
306 | { | |
6522a427 | 307 | writeln!(&mut io::stdout(), "kill: {res}"); |
923072b8 FG |
308 | } else { |
309 | writeln!( | |
310 | &mut io::stdout(), | |
311 | "kill: signal not supported on this platform" | |
312 | ); | |
313 | } | |
314 | } | |
315 | None => { | |
316 | writeln!(&mut io::stdout(), "pid not found"); | |
317 | } | |
318 | }; | |
319 | } | |
320 | } | |
321 | } | |
322 | "disks" => { | |
323 | for disk in sys.disks() { | |
6522a427 | 324 | writeln!(&mut io::stdout(), "{disk:?}"); |
923072b8 FG |
325 | } |
326 | } | |
327 | "users" => { | |
328 | for user in sys.users() { | |
329 | writeln!(&mut io::stdout(), "{:?}", user.name()); | |
330 | } | |
331 | } | |
332 | "boot_time" => { | |
333 | writeln!(&mut io::stdout(), "{} seconds", sys.boot_time()); | |
334 | } | |
335 | "uptime" => { | |
336 | let up = sys.uptime(); | |
337 | let mut uptime = sys.uptime(); | |
338 | let days = uptime / 86400; | |
339 | uptime -= days * 86400; | |
340 | let hours = uptime / 3600; | |
341 | uptime -= hours * 3600; | |
342 | let minutes = uptime / 60; | |
343 | writeln!( | |
344 | &mut io::stdout(), | |
345 | "{} days {} hours {} minutes ({} seconds in total)", | |
346 | days, | |
347 | hours, | |
348 | minutes, | |
349 | up, | |
350 | ); | |
351 | } | |
352 | x if x.starts_with("refresh") => { | |
353 | if x == "refresh" { | |
354 | writeln!(&mut io::stdout(), "Getting processes' information..."); | |
355 | sys.refresh_all(); | |
356 | writeln!(&mut io::stdout(), "Done."); | |
357 | } else if x.starts_with("refresh ") { | |
358 | writeln!(&mut io::stdout(), "Getting process' information..."); | |
359 | if let Some(pid) = x | |
360 | .split(' ') | |
361 | .filter_map(|pid| pid.parse().ok()) | |
362 | .take(1) | |
363 | .next() | |
364 | { | |
365 | if sys.refresh_process(pid) { | |
6522a427 | 366 | writeln!(&mut io::stdout(), "Process `{pid}` updated successfully"); |
923072b8 FG |
367 | } else { |
368 | writeln!( | |
369 | &mut io::stdout(), | |
370 | "Process `{}` couldn't be updated...", | |
371 | pid | |
372 | ); | |
373 | } | |
374 | } else { | |
375 | writeln!(&mut io::stdout(), "Invalid [pid] received..."); | |
376 | } | |
377 | } else { | |
378 | writeln!( | |
379 | &mut io::stdout(), | |
380 | "\"{}\": Unknown command. Enter 'help' if you want to get the commands' \ | |
381 | list.", | |
382 | x | |
383 | ); | |
384 | } | |
385 | } | |
386 | "pid" => { | |
387 | writeln!( | |
388 | &mut io::stdout(), | |
389 | "PID: {}", | |
390 | sysinfo::get_current_pid().expect("failed to get PID") | |
391 | ); | |
392 | } | |
393 | "system" => { | |
394 | writeln!( | |
395 | &mut io::stdout(), | |
396 | "System name: {}\n\ | |
397 | System kernel version: {}\n\ | |
398 | System OS version: {}\n\ | |
399 | System OS (long) version: {}\n\ | |
400 | System host name: {}", | |
401 | sys.name().unwrap_or_else(|| "<unknown>".to_owned()), | |
402 | sys.kernel_version() | |
403 | .unwrap_or_else(|| "<unknown>".to_owned()), | |
404 | sys.os_version().unwrap_or_else(|| "<unknown>".to_owned()), | |
405 | sys.long_os_version() | |
406 | .unwrap_or_else(|| "<unknown>".to_owned()), | |
407 | sys.host_name().unwrap_or_else(|| "<unknown>".to_owned()), | |
408 | ); | |
409 | } | |
410 | e => { | |
411 | writeln!( | |
412 | &mut io::stdout(), | |
413 | "\"{}\": Unknown command. Enter 'help' if you want to get the commands' \ | |
414 | list.", | |
415 | e | |
416 | ); | |
417 | } | |
418 | } | |
419 | false | |
420 | } | |
421 | ||
422 | fn main() { | |
423 | println!("Getting processes' information..."); | |
424 | let mut t = System::new_all(); | |
425 | println!("Done."); | |
426 | let t_stin = io::stdin(); | |
427 | let mut stin = t_stin.lock(); | |
428 | let mut done = false; | |
429 | ||
430 | println!("To get the commands' list, enter 'help'."); | |
431 | while !done { | |
432 | let mut input = String::new(); | |
433 | write!(&mut io::stdout(), "> "); | |
434 | io::stdout().flush(); | |
435 | ||
436 | stin.read_line(&mut input); | |
437 | if input.is_empty() { | |
438 | // The string is empty, meaning there is no '\n', meaning | |
439 | // that the user used CTRL+D so we can just quit! | |
440 | println!("\nLeaving, bye!"); | |
441 | break; | |
442 | } | |
443 | if (&input as &str).ends_with('\n') { | |
444 | input.pop(); | |
445 | } | |
446 | done = interpret_input(input.as_ref(), &mut t); | |
447 | } | |
448 | } |