1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use crate::{ |
4 | common::{Gid, MacAddr, Uid}, |
5 | sys::{Component, Cpu, Disk, Networks, Process}, |
6 | }; |
7 | use crate::{ |
8 | CpuRefreshKind, DiskKind, DiskUsage, LoadAvg, NetworksIter, Pid, ProcessRefreshKind, |
9 | ProcessStatus, RefreshKind, Signal, User, |
10 | }; |
11 | |
12 | use std::collections::HashMap; |
13 | use std::ffi::OsStr; |
14 | use std::fmt::Debug; |
15 | use std::path::Path; |
16 | use std::time::Duration; |
17 | |
18 | /// Contains all the methods of the [`Disk`][crate::Disk] struct. |
19 | /// |
20 | /// ```no_run |
21 | /// use sysinfo::{DiskExt, System, SystemExt}; |
22 | /// |
23 | /// let mut s = System::new(); |
24 | /// s.refresh_disks_list(); |
25 | /// for disk in s.disks() { |
26 | /// println!("{:?}: {:?}" , disk.name(), disk.kind()); |
27 | /// } |
28 | /// ``` |
29 | pub trait DiskExt: Debug { |
30 | /// Returns the kind of disk. |
31 | /// |
32 | /// ```no_run |
33 | /// use sysinfo::{DiskExt, System, SystemExt}; |
34 | /// |
35 | /// let mut s = System::new(); |
36 | /// s.refresh_disks_list(); |
37 | /// for disk in s.disks() { |
38 | /// println!("{:?}" , disk.kind()); |
39 | /// } |
40 | /// ``` |
41 | fn kind(&self) -> DiskKind; |
42 | |
43 | /// Returns the disk name. |
44 | /// |
45 | /// ```no_run |
46 | /// use sysinfo::{DiskExt, System, SystemExt}; |
47 | /// |
48 | /// let mut s = System::new(); |
49 | /// s.refresh_disks_list(); |
50 | /// for disk in s.disks() { |
51 | /// println!("{:?}" , disk.name()); |
52 | /// } |
53 | /// ``` |
54 | fn name(&self) -> &OsStr; |
55 | |
56 | /// Returns the file system used on this disk (so for example: `EXT4`, `NTFS`, etc...). |
57 | /// |
58 | /// ```no_run |
59 | /// use sysinfo::{DiskExt, System, SystemExt}; |
60 | /// |
61 | /// let mut s = System::new(); |
62 | /// s.refresh_disks_list(); |
63 | /// for disk in s.disks() { |
64 | /// println!("{:?}" , disk.file_system()); |
65 | /// } |
66 | /// ``` |
67 | fn file_system(&self) -> &[u8]; |
68 | |
69 | /// Returns the mount point of the disk (`/` for example). |
70 | /// |
71 | /// ```no_run |
72 | /// use sysinfo::{DiskExt, System, SystemExt}; |
73 | /// |
74 | /// let mut s = System::new(); |
75 | /// s.refresh_disks_list(); |
76 | /// for disk in s.disks() { |
77 | /// println!("{:?}" , disk.mount_point()); |
78 | /// } |
79 | /// ``` |
80 | fn mount_point(&self) -> &Path; |
81 | |
82 | /// Returns the total disk size, in bytes. |
83 | /// |
84 | /// ```no_run |
85 | /// use sysinfo::{DiskExt, System, SystemExt}; |
86 | /// |
87 | /// let mut s = System::new(); |
88 | /// s.refresh_disks_list(); |
89 | /// for disk in s.disks() { |
90 | /// println!("{}" , disk.total_space()); |
91 | /// } |
92 | /// ``` |
93 | fn total_space(&self) -> u64; |
94 | |
95 | /// Returns the available disk size, in bytes. |
96 | /// |
97 | /// ```no_run |
98 | /// use sysinfo::{DiskExt, System, SystemExt}; |
99 | /// |
100 | /// let mut s = System::new(); |
101 | /// s.refresh_disks_list(); |
102 | /// for disk in s.disks() { |
103 | /// println!("{}" , disk.available_space()); |
104 | /// } |
105 | /// ``` |
106 | fn available_space(&self) -> u64; |
107 | |
108 | /// Returns `true` if the disk is removable. |
109 | /// |
110 | /// ```no_run |
111 | /// use sysinfo::{DiskExt, System, SystemExt}; |
112 | /// |
113 | /// let mut s = System::new(); |
114 | /// s.refresh_disks_list(); |
115 | /// for disk in s.disks() { |
116 | /// println!("{}" , disk.is_removable()); |
117 | /// } |
118 | /// ``` |
119 | fn is_removable(&self) -> bool; |
120 | |
121 | /// Updates the disk' information. |
122 | /// |
123 | /// ```no_run |
124 | /// use sysinfo::{DiskExt, System, SystemExt}; |
125 | /// |
126 | /// let mut s = System::new(); |
127 | /// s.refresh_disks_list(); |
128 | /// for disk in s.disks_mut() { |
129 | /// disk.refresh(); |
130 | /// } |
131 | /// ``` |
132 | fn refresh(&mut self) -> bool; |
133 | } |
134 | |
135 | /// Contains all the methods of the [`Process`][crate::Process] struct. |
136 | pub trait ProcessExt: Debug { |
137 | /// Sends [`Signal::Kill`] to the process (which is the only signal supported on all supported |
138 | /// platforms by this crate). |
139 | /// |
140 | /// If you want to send another signal, take a look at [`ProcessExt::kill_with`]. |
141 | /// |
142 | /// To get the list of the supported signals on this system, use |
143 | /// [`SystemExt::SUPPORTED_SIGNALS`]. |
144 | /// |
145 | /// ```no_run |
146 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
147 | /// |
148 | /// let s = System::new_all(); |
149 | /// if let Some(process) = s.process(Pid::from(1337)) { |
150 | /// process.kill(); |
151 | /// } |
152 | /// ``` |
153 | fn kill(&self) -> bool { |
154 | self.kill_with(Signal::Kill).unwrap_or(false) |
155 | } |
156 | |
157 | /// Sends the given `signal` to the process. If the signal doesn't exist on this platform, |
158 | /// it'll do nothing and will return `None`. Otherwise it'll return if the signal was sent |
159 | /// successfully. |
160 | /// |
161 | /// If you just want to kill the process, use [`ProcessExt::kill`] directly. |
162 | /// |
163 | /// To get the list of the supported signals on this system, use |
164 | /// [`SystemExt::SUPPORTED_SIGNALS`]. |
165 | /// |
166 | /// ```no_run |
167 | /// use sysinfo::{Pid, ProcessExt, Signal, System, SystemExt}; |
168 | /// |
169 | /// let s = System::new_all(); |
170 | /// if let Some(process) = s.process(Pid::from(1337)) { |
171 | /// if process.kill_with(Signal::Kill).is_none() { |
172 | /// eprintln!("This signal isn't supported on this platform" ); |
173 | /// } |
174 | /// } |
175 | /// ``` |
176 | fn kill_with(&self, signal: Signal) -> Option<bool>; |
177 | |
178 | /// Returns the name of the process. |
179 | /// |
180 | /// **⚠️ Important ⚠️** |
181 | /// |
182 | /// On **Linux**, there are two things to know about processes' name: |
183 | /// 1. It is limited to 15 characters. |
184 | /// 2. It is not always the exe name. |
185 | /// |
186 | /// If you are looking for a specific process, unless you know what you are doing, in most |
187 | /// cases it's better to use [`ProcessExt::exe`] instead (which can be empty sometimes!). |
188 | /// |
189 | /// ```no_run |
190 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
191 | /// |
192 | /// let s = System::new_all(); |
193 | /// if let Some(process) = s.process(Pid::from(1337)) { |
194 | /// println!("{}" , process.name()); |
195 | /// } |
196 | /// ``` |
197 | fn name(&self) -> &str; |
198 | |
199 | /// Returns the command line. |
200 | /// |
201 | /// ```no_run |
202 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
203 | /// |
204 | /// let s = System::new_all(); |
205 | /// if let Some(process) = s.process(Pid::from(1337)) { |
206 | /// println!("{:?}" , process.cmd()); |
207 | /// } |
208 | /// ``` |
209 | fn cmd(&self) -> &[String]; |
210 | |
211 | /// Returns the path to the process. |
212 | /// |
213 | /// ```no_run |
214 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
215 | /// |
216 | /// let s = System::new_all(); |
217 | /// if let Some(process) = s.process(Pid::from(1337)) { |
218 | /// println!("{}" , process.exe().display()); |
219 | /// } |
220 | /// ``` |
221 | /// |
222 | /// ### Implementation notes |
223 | /// |
224 | /// On Linux, this method will return an empty path if there |
225 | /// was an error trying to read `/proc/<pid>/exe`. This can |
226 | /// happen, for example, if the permission levels or UID namespaces |
227 | /// between the caller and target processes are different. |
228 | /// |
229 | /// It is also the case that `cmd[0]` is _not_ usually a correct |
230 | /// replacement for this. |
231 | /// A process [may change its `cmd[0]` value](https://man7.org/linux/man-pages/man5/proc.5.html) |
232 | /// freely, making this an untrustworthy source of information. |
233 | fn exe(&self) -> &Path; |
234 | |
235 | /// Returns the PID of the process. |
236 | /// |
237 | /// ```no_run |
238 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
239 | /// |
240 | /// let s = System::new_all(); |
241 | /// if let Some(process) = s.process(Pid::from(1337)) { |
242 | /// println!("{}" , process.pid()); |
243 | /// } |
244 | /// ``` |
245 | fn pid(&self) -> Pid; |
246 | |
247 | /// Returns the environment variables of the process. |
248 | /// |
249 | /// ```no_run |
250 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
251 | /// |
252 | /// let s = System::new_all(); |
253 | /// if let Some(process) = s.process(Pid::from(1337)) { |
254 | /// println!("{:?}" , process.environ()); |
255 | /// } |
256 | /// ``` |
257 | fn environ(&self) -> &[String]; |
258 | |
259 | /// Returns the current working directory. |
260 | /// |
261 | /// ```no_run |
262 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
263 | /// |
264 | /// let s = System::new_all(); |
265 | /// if let Some(process) = s.process(Pid::from(1337)) { |
266 | /// println!("{}" , process.cwd().display()); |
267 | /// } |
268 | /// ``` |
269 | fn cwd(&self) -> &Path; |
270 | |
271 | /// Returns the path of the root directory. |
272 | /// |
273 | /// ```no_run |
274 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
275 | /// |
276 | /// let s = System::new_all(); |
277 | /// if let Some(process) = s.process(Pid::from(1337)) { |
278 | /// println!("{}" , process.root().display()); |
279 | /// } |
280 | /// ``` |
281 | fn root(&self) -> &Path; |
282 | |
283 | /// Returns the memory usage (in bytes). |
284 | /// |
285 | /// ```no_run |
286 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
287 | /// |
288 | /// let s = System::new_all(); |
289 | /// if let Some(process) = s.process(Pid::from(1337)) { |
290 | /// println!("{} bytes" , process.memory()); |
291 | /// } |
292 | /// ``` |
293 | fn memory(&self) -> u64; |
294 | |
295 | /// Returns the virtual memory usage (in bytes). |
296 | /// |
297 | /// ```no_run |
298 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
299 | /// |
300 | /// let s = System::new_all(); |
301 | /// if let Some(process) = s.process(Pid::from(1337)) { |
302 | /// println!("{} bytes" , process.virtual_memory()); |
303 | /// } |
304 | /// ``` |
305 | fn virtual_memory(&self) -> u64; |
306 | |
307 | /// Returns the parent PID. |
308 | /// |
309 | /// ```no_run |
310 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
311 | /// |
312 | /// let s = System::new_all(); |
313 | /// if let Some(process) = s.process(Pid::from(1337)) { |
314 | /// println!("{:?}" , process.parent()); |
315 | /// } |
316 | /// ``` |
317 | fn parent(&self) -> Option<Pid>; |
318 | |
319 | /// Returns the status of the process. |
320 | /// |
321 | /// ```no_run |
322 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
323 | /// |
324 | /// let s = System::new_all(); |
325 | /// if let Some(process) = s.process(Pid::from(1337)) { |
326 | /// println!("{:?}" , process.status()); |
327 | /// } |
328 | /// ``` |
329 | fn status(&self) -> ProcessStatus; |
330 | |
331 | /// Returns the time where the process was started (in seconds) from epoch. |
332 | /// |
333 | /// ```no_run |
334 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
335 | /// |
336 | /// let s = System::new_all(); |
337 | /// if let Some(process) = s.process(Pid::from(1337)) { |
338 | /// println!("Started at {} seconds" , process.start_time()); |
339 | /// } |
340 | /// ``` |
341 | fn start_time(&self) -> u64; |
342 | |
343 | /// Returns for how much time the process has been running (in seconds). |
344 | /// |
345 | /// ```no_run |
346 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
347 | /// |
348 | /// let s = System::new_all(); |
349 | /// if let Some(process) = s.process(Pid::from(1337)) { |
350 | /// println!("Running since {} seconds" , process.run_time()); |
351 | /// } |
352 | /// ``` |
353 | fn run_time(&self) -> u64; |
354 | |
355 | /// Returns the total CPU usage (in %). Notice that it might be bigger than 100 if run on a |
356 | /// multi-core machine. |
357 | /// |
358 | /// If you want a value between 0% and 100%, divide the returned value by the number of CPUs. |
359 | /// |
360 | /// ⚠️ To start to have accurate CPU usage, a process needs to be refreshed **twice** because |
361 | /// CPU usage computation is based on time diff (process time on a given time period divided by |
362 | /// total system time on the same time period). |
363 | /// |
364 | /// ⚠️ If you want accurate CPU usage number, better leave a bit of time |
365 | /// between two calls of this method (take a look at |
366 | /// [`SystemExt::MINIMUM_CPU_UPDATE_INTERVAL`] for more information). |
367 | /// |
368 | /// ```no_run |
369 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
370 | /// |
371 | /// let s = System::new_all(); |
372 | /// if let Some(process) = s.process(Pid::from(1337)) { |
373 | /// println!("{}%" , process.cpu_usage()); |
374 | /// } |
375 | /// ``` |
376 | fn cpu_usage(&self) -> f32; |
377 | |
378 | /// Returns number of bytes read and written to disk. |
379 | /// |
380 | /// ⚠️ On Windows and FreeBSD, this method actually returns **ALL** I/O read and written bytes. |
381 | /// |
382 | /// ```no_run |
383 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
384 | /// |
385 | /// let s = System::new_all(); |
386 | /// if let Some(process) = s.process(Pid::from(1337)) { |
387 | /// let disk_usage = process.disk_usage(); |
388 | /// println!("read bytes : new/total => {}/{}" , |
389 | /// disk_usage.read_bytes, |
390 | /// disk_usage.total_read_bytes, |
391 | /// ); |
392 | /// println!("written bytes: new/total => {}/{}" , |
393 | /// disk_usage.written_bytes, |
394 | /// disk_usage.total_written_bytes, |
395 | /// ); |
396 | /// } |
397 | /// ``` |
398 | fn disk_usage(&self) -> DiskUsage; |
399 | |
400 | /// Returns the ID of the owner user of this process or `None` if this information couldn't |
401 | /// be retrieved. If you want to get the [`User`] from it, take a look at |
402 | /// [`SystemExt::get_user_by_id`]. |
403 | /// |
404 | /// ```no_run |
405 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
406 | /// |
407 | /// let mut s = System::new_all(); |
408 | /// |
409 | /// if let Some(process) = s.process(Pid::from(1337)) { |
410 | /// eprintln!("User id for process 1337: {:?}" , process.user_id()); |
411 | /// } |
412 | /// ``` |
413 | fn user_id(&self) -> Option<&Uid>; |
414 | |
415 | /// Returns the user ID of the effective owner of this process or `None` if this information |
416 | /// couldn't be retrieved. If you want to get the [`User`] from it, take a look at |
417 | /// [`SystemExt::get_user_by_id`]. |
418 | /// |
419 | /// If you run something with `sudo`, the real user ID of the launched process will be the ID of |
420 | /// the user you are logged in as but effective user ID will be `0` (i-e root). |
421 | /// |
422 | /// ⚠️ It always returns `None` on Windows. |
423 | /// |
424 | /// ```no_run |
425 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
426 | /// |
427 | /// let mut s = System::new_all(); |
428 | /// |
429 | /// if let Some(process) = s.process(Pid::from(1337)) { |
430 | /// eprintln!("User id for process 1337: {:?}" , process.effective_user_id()); |
431 | /// } |
432 | /// ``` |
433 | fn effective_user_id(&self) -> Option<&Uid>; |
434 | |
435 | /// Returns the process group ID of the process. |
436 | /// |
437 | /// ⚠️ It always returns `None` on Windows. |
438 | /// |
439 | /// ```no_run |
440 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
441 | /// |
442 | /// let mut s = System::new_all(); |
443 | /// |
444 | /// if let Some(process) = s.process(Pid::from(1337)) { |
445 | /// eprintln!("Group ID for process 1337: {:?}" , process.group_id()); |
446 | /// } |
447 | /// ``` |
448 | fn group_id(&self) -> Option<Gid>; |
449 | |
450 | /// Returns the effective group ID of the process. |
451 | /// |
452 | /// If you run something with `sudo`, the real group ID of the launched process will be the |
453 | /// primary group ID you are logged in as but effective group ID will be `0` (i-e root). |
454 | /// |
455 | /// ⚠️ It always returns `None` on Windows. |
456 | /// |
457 | /// ```no_run |
458 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
459 | /// |
460 | /// let mut s = System::new_all(); |
461 | /// |
462 | /// if let Some(process) = s.process(Pid::from(1337)) { |
463 | /// eprintln!("User id for process 1337: {:?}" , process.effective_group_id()); |
464 | /// } |
465 | /// ``` |
466 | fn effective_group_id(&self) -> Option<Gid>; |
467 | |
468 | /// Wait for process termination. |
469 | /// |
470 | /// ```no_run |
471 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
472 | /// |
473 | /// let mut s = System::new_all(); |
474 | /// |
475 | /// if let Some(process) = s.process(Pid::from(1337)) { |
476 | /// eprintln!("Waiting for pid 1337" ); |
477 | /// process.wait(); |
478 | /// eprintln!("Pid 1337 exited" ); |
479 | /// } |
480 | /// ``` |
481 | fn wait(&self); |
482 | |
483 | /// Returns the session ID for the current process or `None` if it couldn't be retrieved. |
484 | /// |
485 | /// ⚠️ This information is computed every time this method is called. |
486 | /// |
487 | /// ```no_run |
488 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
489 | /// |
490 | /// let mut s = System::new_all(); |
491 | /// |
492 | /// if let Some(process) = s.process(Pid::from(1337)) { |
493 | /// eprintln!("Session ID for process 1337: {:?}" , process.session_id()); |
494 | /// } |
495 | /// ``` |
496 | fn session_id(&self) -> Option<Pid>; |
497 | } |
498 | |
499 | /// Contains all the methods of the [`Cpu`][crate::Cpu] struct. |
500 | pub trait CpuExt: Debug { |
501 | /// Returns this CPU's usage. |
502 | /// |
503 | /// Note: You'll need to refresh it at least twice (diff between the first and the second is |
504 | /// how CPU usage is computed) at first if you want to have a non-zero value. |
505 | /// |
506 | /// ```no_run |
507 | /// use sysinfo::{CpuExt, System, SystemExt, RefreshKind, CpuRefreshKind}; |
508 | /// |
509 | /// let s = System::new_with_specifics( |
510 | /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()), |
511 | /// ); |
512 | /// for cpu in s.cpus() { |
513 | /// println!("{}%" , cpu.cpu_usage()); |
514 | /// } |
515 | /// ``` |
516 | fn cpu_usage(&self) -> f32; |
517 | |
518 | /// Returns this CPU's name. |
519 | /// |
520 | /// ```no_run |
521 | /// use sysinfo::{CpuExt, System, SystemExt, RefreshKind, CpuRefreshKind}; |
522 | /// |
523 | /// let s = System::new_with_specifics( |
524 | /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()), |
525 | /// ); |
526 | /// for cpu in s.cpus() { |
527 | /// println!("{}" , cpu.name()); |
528 | /// } |
529 | /// ``` |
530 | fn name(&self) -> &str; |
531 | |
532 | /// Returns the CPU's vendor id. |
533 | /// |
534 | /// ```no_run |
535 | /// use sysinfo::{CpuExt, System, SystemExt, RefreshKind, CpuRefreshKind}; |
536 | /// |
537 | /// let s = System::new_with_specifics( |
538 | /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()), |
539 | /// ); |
540 | /// for cpu in s.cpus() { |
541 | /// println!("{}" , cpu.vendor_id()); |
542 | /// } |
543 | /// ``` |
544 | fn vendor_id(&self) -> &str; |
545 | |
546 | /// Returns the CPU's brand. |
547 | /// |
548 | /// ```no_run |
549 | /// use sysinfo::{CpuExt, System, SystemExt, RefreshKind, CpuRefreshKind}; |
550 | /// |
551 | /// let s = System::new_with_specifics( |
552 | /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()), |
553 | /// ); |
554 | /// for cpu in s.cpus() { |
555 | /// println!("{}" , cpu.brand()); |
556 | /// } |
557 | /// ``` |
558 | fn brand(&self) -> &str; |
559 | |
560 | /// Returns the CPU's frequency. |
561 | /// |
562 | /// ```no_run |
563 | /// use sysinfo::{CpuExt, System, SystemExt, RefreshKind, CpuRefreshKind}; |
564 | /// |
565 | /// let s = System::new_with_specifics( |
566 | /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()), |
567 | /// ); |
568 | /// for cpu in s.cpus() { |
569 | /// println!("{}" , cpu.frequency()); |
570 | /// } |
571 | /// ``` |
572 | fn frequency(&self) -> u64; |
573 | } |
574 | |
575 | /// Contains all the methods of the [`System`][crate::System] type. |
576 | pub trait SystemExt: Sized + Debug + Default + Send + Sync { |
577 | /// Returns `true` if this OS is supported. Please refer to the |
578 | /// [crate-level documentation](index.html) to get the list of supported OSes. |
579 | /// |
580 | /// ``` |
581 | /// use sysinfo::{System, SystemExt}; |
582 | /// |
583 | /// if System::IS_SUPPORTED { |
584 | /// println!("This OS is supported!" ); |
585 | /// } else { |
586 | /// println!("This OS isn't supported (yet?)." ); |
587 | /// } |
588 | /// ``` |
589 | const IS_SUPPORTED: bool; |
590 | |
591 | /// Returns the list of the supported signals on this system (used by |
592 | /// [`ProcessExt::kill_with`]). |
593 | /// |
594 | /// ``` |
595 | /// use sysinfo::{System, SystemExt}; |
596 | /// |
597 | /// println!("supported signals: {:?}" , System::SUPPORTED_SIGNALS); |
598 | /// ``` |
599 | const SUPPORTED_SIGNALS: &'static [Signal]; |
600 | |
601 | /// This is the minimum interval time used internally by `sysinfo` to refresh the CPU time. |
602 | /// |
603 | /// ⚠️ This value differs from one OS to another. |
604 | /// |
605 | /// Why is this constant even needed? |
606 | /// |
607 | /// If refreshed too often, the CPU usage of processes will be `0` whereas on Linux it'll |
608 | /// always be the maximum value (`number of CPUs * 100`). |
609 | const MINIMUM_CPU_UPDATE_INTERVAL: Duration; |
610 | |
611 | /// Creates a new [`System`] instance with nothing loaded. If you want to |
612 | /// load components, network interfaces or the disks, you'll have to use the |
613 | /// `refresh_*_list` methods. [`SystemExt::refresh_networks_list`] for |
614 | /// example. |
615 | /// |
616 | /// Use the [`refresh_all`] method to update its internal information (or any of the `refresh_` |
617 | /// method). |
618 | /// |
619 | /// [`System`]: crate::System |
620 | /// [`refresh_all`]: #method.refresh_all |
621 | /// |
622 | /// ```no_run |
623 | /// use sysinfo::{System, SystemExt}; |
624 | /// |
625 | /// let s = System::new(); |
626 | /// ``` |
627 | fn new() -> Self { |
628 | Self::new_with_specifics(RefreshKind::new()) |
629 | } |
630 | |
631 | /// Creates a new [`System`] instance with everything loaded. |
632 | /// |
633 | /// It is an equivalent of [`SystemExt::new_with_specifics`]`(`[`RefreshKind::everything`]`())`. |
634 | /// |
635 | /// [`System`]: crate::System |
636 | /// |
637 | /// ```no_run |
638 | /// use sysinfo::{System, SystemExt}; |
639 | /// |
640 | /// let s = System::new_all(); |
641 | /// ``` |
642 | fn new_all() -> Self { |
643 | Self::new_with_specifics(RefreshKind::everything()) |
644 | } |
645 | |
646 | /// Creates a new [`System`] instance and refresh the data corresponding to the |
647 | /// given [`RefreshKind`]. |
648 | /// |
649 | /// [`System`]: crate::System |
650 | /// |
651 | /// ``` |
652 | /// use sysinfo::{RefreshKind, System, SystemExt}; |
653 | /// |
654 | /// // We want everything except disks. |
655 | /// let mut system = System::new_with_specifics( |
656 | /// RefreshKind::everything().without_disks_list(), |
657 | /// ); |
658 | /// |
659 | /// assert!(system.disks().is_empty()); |
660 | /// # if System::IS_SUPPORTED && !cfg!(feature = "apple-sandbox" ) { |
661 | /// assert!(!system.processes().is_empty()); |
662 | /// # } |
663 | /// |
664 | /// // If you want the disks list afterwards, just call the corresponding |
665 | /// // "refresh_disks_list": |
666 | /// system.refresh_disks_list(); |
667 | /// let disks = system.disks(); |
668 | /// ``` |
669 | fn new_with_specifics(refreshes: RefreshKind) -> Self; |
670 | |
671 | /// Refreshes according to the given [`RefreshKind`]. It calls the corresponding |
672 | /// "refresh_" methods. |
673 | /// |
674 | /// ``` |
675 | /// use sysinfo::{ProcessRefreshKind, RefreshKind, System, SystemExt}; |
676 | /// |
677 | /// let mut s = System::new_all(); |
678 | /// |
679 | /// // Let's just update networks and processes: |
680 | /// s.refresh_specifics( |
681 | /// RefreshKind::new().with_networks().with_processes(ProcessRefreshKind::everything()), |
682 | /// ); |
683 | /// ``` |
684 | fn refresh_specifics(&mut self, refreshes: RefreshKind) { |
685 | if refreshes.memory() { |
686 | self.refresh_memory(); |
687 | } |
688 | if let Some(kind) = refreshes.cpu() { |
689 | self.refresh_cpu_specifics(kind); |
690 | } |
691 | if refreshes.components_list() { |
692 | self.refresh_components_list(); |
693 | } else if refreshes.components() { |
694 | self.refresh_components(); |
695 | } |
696 | if refreshes.networks_list() { |
697 | self.refresh_networks_list(); |
698 | } else if refreshes.networks() { |
699 | self.refresh_networks(); |
700 | } |
701 | if let Some(kind) = refreshes.processes() { |
702 | self.refresh_processes_specifics(kind); |
703 | } |
704 | if refreshes.disks_list() { |
705 | self.refresh_disks_list(); |
706 | } else if refreshes.disks() { |
707 | self.refresh_disks(); |
708 | } |
709 | if refreshes.users_list() { |
710 | self.refresh_users_list(); |
711 | } |
712 | } |
713 | |
714 | /// Refreshes all system, processes, disks and network interfaces information. |
715 | /// |
716 | /// Please note that it doesn't recompute disks list, components list, network interfaces |
717 | /// list nor users list. |
718 | /// |
719 | /// ```no_run |
720 | /// use sysinfo::{System, SystemExt}; |
721 | /// |
722 | /// let mut s = System::new_all(); |
723 | /// s.refresh_all(); |
724 | /// ``` |
725 | fn refresh_all(&mut self) { |
726 | self.refresh_system(); |
727 | self.refresh_processes(); |
728 | self.refresh_disks(); |
729 | self.refresh_networks(); |
730 | } |
731 | |
732 | /// Refreshes system information (RAM, swap, CPU usage and components' temperature). |
733 | /// |
734 | /// If you want some more specific refreshes, you might be interested into looking at |
735 | /// [`refresh_memory`], [`refresh_cpu`] and [`refresh_components`]. |
736 | /// |
737 | /// [`refresh_memory`]: SystemExt::refresh_memory |
738 | /// [`refresh_cpu`]: SystemExt::refresh_memory |
739 | /// [`refresh_components`]: SystemExt::refresh_components |
740 | /// |
741 | /// ```no_run |
742 | /// use sysinfo::{System, SystemExt}; |
743 | /// |
744 | /// let mut s = System::new_all(); |
745 | /// s.refresh_system(); |
746 | /// ``` |
747 | fn refresh_system(&mut self) { |
748 | self.refresh_memory(); |
749 | self.refresh_cpu(); |
750 | self.refresh_components(); |
751 | } |
752 | |
753 | /// Refreshes RAM and SWAP usage. |
754 | /// |
755 | /// ```no_run |
756 | /// use sysinfo::{System, SystemExt}; |
757 | /// |
758 | /// let mut s = System::new_all(); |
759 | /// s.refresh_memory(); |
760 | /// ``` |
761 | fn refresh_memory(&mut self); |
762 | |
763 | /// Refreshes CPUs information. |
764 | /// |
765 | /// ⚠️ Please note that the result will very likely be inaccurate at the first call. |
766 | /// You need to call this method at least twice (with a bit of time between each call, like |
767 | /// 200 ms, take a look at [`SystemExt::MINIMUM_CPU_UPDATE_INTERVAL`] for more information) |
768 | /// to get accurate value as it uses previous results to compute the next value. |
769 | /// |
770 | /// Calling this method is the same as calling |
771 | /// `refresh_cpu_specifics(CpuRefreshKind::new().with_cpu_usage())`. |
772 | /// |
773 | /// ```no_run |
774 | /// use sysinfo::{System, SystemExt}; |
775 | /// |
776 | /// let mut s = System::new_all(); |
777 | /// s.refresh_cpu(); |
778 | /// ``` |
779 | fn refresh_cpu(&mut self) { |
780 | self.refresh_cpu_specifics(CpuRefreshKind::new().with_cpu_usage()) |
781 | } |
782 | |
783 | /// Refreshes CPUs specific information. |
784 | /// |
785 | /// Please note that it doesn't recompute disks list, components list, network interfaces |
786 | /// list nor users list. |
787 | /// |
788 | /// ```no_run |
789 | /// use sysinfo::{System, SystemExt, CpuRefreshKind}; |
790 | /// |
791 | /// let mut s = System::new_all(); |
792 | /// s.refresh_cpu_specifics(CpuRefreshKind::everything()); |
793 | /// ``` |
794 | fn refresh_cpu_specifics(&mut self, refresh_kind: CpuRefreshKind); |
795 | |
796 | /// Refreshes components' temperature. |
797 | /// |
798 | /// ```no_run |
799 | /// use sysinfo::{System, SystemExt}; |
800 | /// |
801 | /// let mut s = System::new_all(); |
802 | /// s.refresh_components(); |
803 | /// ``` |
804 | fn refresh_components(&mut self) { |
805 | for component in self.components_mut() { |
806 | component.refresh(); |
807 | } |
808 | } |
809 | |
810 | /// Refreshes components list. |
811 | /// |
812 | /// ```no_run |
813 | /// use sysinfo::{System, SystemExt}; |
814 | /// |
815 | /// let mut s = System::new(); |
816 | /// assert!(s.components().is_empty()); |
817 | /// |
818 | /// s.refresh_components_list(); |
819 | /// assert!(!s.components().is_empty()); |
820 | /// ``` |
821 | fn refresh_components_list(&mut self); |
822 | |
823 | /// Gets all processes and updates their information. |
824 | /// |
825 | /// It does the same as `system.refresh_processes_specifics(ProcessRefreshKind::everything())`. |
826 | /// |
827 | /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour |
828 | /// by using [`set_open_files_limit`][crate::set_open_files_limit]. |
829 | /// |
830 | /// ```no_run |
831 | /// use sysinfo::{System, SystemExt}; |
832 | /// |
833 | /// let mut s = System::new_all(); |
834 | /// s.refresh_processes(); |
835 | /// ``` |
836 | fn refresh_processes(&mut self) { |
837 | self.refresh_processes_specifics(ProcessRefreshKind::everything()); |
838 | } |
839 | |
840 | /// Gets all processes and updates the specified information. |
841 | /// |
842 | /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour |
843 | /// by using [`set_open_files_limit`][crate::set_open_files_limit]. |
844 | /// |
845 | /// ```no_run |
846 | /// use sysinfo::{ProcessRefreshKind, System, SystemExt}; |
847 | /// |
848 | /// let mut s = System::new_all(); |
849 | /// s.refresh_processes_specifics(ProcessRefreshKind::new()); |
850 | /// ``` |
851 | fn refresh_processes_specifics(&mut self, refresh_kind: ProcessRefreshKind); |
852 | |
853 | /// Refreshes *only* the process corresponding to `pid`. Returns `false` if the process doesn't |
854 | /// exist (it will **NOT** be removed from the processes if it doesn't exist anymore). If it |
855 | /// isn't listed yet, it'll be added. |
856 | /// |
857 | /// It is the same as calling |
858 | /// `sys.refresh_process_specifics(pid, ProcessRefreshKind::everything())`. |
859 | /// |
860 | /// ```no_run |
861 | /// use sysinfo::{Pid, System, SystemExt}; |
862 | /// |
863 | /// let mut s = System::new_all(); |
864 | /// s.refresh_process(Pid::from(1337)); |
865 | /// ``` |
866 | fn refresh_process(&mut self, pid: Pid) -> bool { |
867 | self.refresh_process_specifics(pid, ProcessRefreshKind::everything()) |
868 | } |
869 | |
870 | /// Refreshes *only* the process corresponding to `pid`. Returns `false` if the process doesn't |
871 | /// exist (it will **NOT** be removed from the processes if it doesn't exist anymore). If it |
872 | /// isn't listed yet, it'll be added. |
873 | /// |
874 | /// ```no_run |
875 | /// use sysinfo::{Pid, ProcessRefreshKind, System, SystemExt}; |
876 | /// |
877 | /// let mut s = System::new_all(); |
878 | /// s.refresh_process_specifics(Pid::from(1337), ProcessRefreshKind::new()); |
879 | /// ``` |
880 | fn refresh_process_specifics(&mut self, pid: Pid, refresh_kind: ProcessRefreshKind) -> bool; |
881 | |
882 | /// Refreshes the listed disks' information. |
883 | /// |
884 | /// ```no_run |
885 | /// use sysinfo::{System, SystemExt}; |
886 | /// |
887 | /// let mut s = System::new_all(); |
888 | /// s.refresh_disks(); |
889 | /// ``` |
890 | fn refresh_disks(&mut self) { |
891 | for disk in self.disks_mut() { |
892 | disk.refresh(); |
893 | } |
894 | } |
895 | |
896 | /// The disk list will be emptied then completely recomputed. |
897 | /// |
898 | /// ## Linux |
899 | /// |
900 | /// ⚠️ On Linux, the [NFS](https://en.wikipedia.org/wiki/Network_File_System) file |
901 | /// systems are ignored and the information of a mounted NFS **cannot** be obtained |
902 | /// via [`SystemExt::refresh_disks_list`]. This is due to the fact that I/O function |
903 | /// `statvfs` used by [`SystemExt::refresh_disks_list`] is blocking and |
904 | /// [may hang](https://github.com/GuillaumeGomez/sysinfo/pull/876) in some cases, |
905 | /// requiring to call `systemctl stop` to terminate the NFS service from the remote |
906 | /// server in some cases. |
907 | /// |
908 | /// ```no_run |
909 | /// use sysinfo::{System, SystemExt}; |
910 | /// |
911 | /// let mut s = System::new_all(); |
912 | /// s.refresh_disks_list(); |
913 | /// ``` |
914 | fn refresh_disks_list(&mut self); |
915 | |
916 | /// Refreshes users list. |
917 | /// |
918 | /// ```no_run |
919 | /// use sysinfo::{System, SystemExt}; |
920 | /// |
921 | /// let mut s = System::new_all(); |
922 | /// s.refresh_users_list(); |
923 | /// ``` |
924 | fn refresh_users_list(&mut self); |
925 | |
926 | /// Refreshes networks data. |
927 | /// |
928 | /// ```no_run |
929 | /// use sysinfo::{System, SystemExt}; |
930 | /// |
931 | /// let mut s = System::new_all(); |
932 | /// s.refresh_networks(); |
933 | /// ``` |
934 | /// |
935 | /// It is a shortcut for: |
936 | /// |
937 | /// ```no_run |
938 | /// use sysinfo::{NetworksExt, System, SystemExt}; |
939 | /// |
940 | /// let mut s = System::new_all(); |
941 | /// let networks = s.networks_mut(); |
942 | /// networks.refresh(); |
943 | /// ``` |
944 | fn refresh_networks(&mut self) { |
945 | self.networks_mut().refresh(); |
946 | } |
947 | |
948 | /// The network list will be updated: removing not existing anymore interfaces and adding new |
949 | /// ones. |
950 | /// |
951 | /// ```no_run |
952 | /// use sysinfo::{System, SystemExt}; |
953 | /// |
954 | /// let mut s = System::new_all(); |
955 | /// s.refresh_networks_list(); |
956 | /// ``` |
957 | /// |
958 | /// This is a shortcut for: |
959 | /// |
960 | /// ```no_run |
961 | /// use sysinfo::{NetworksExt, System, SystemExt}; |
962 | /// |
963 | /// let mut s = System::new_all(); |
964 | /// let networks = s.networks_mut(); |
965 | /// networks.refresh_networks_list(); |
966 | /// ``` |
967 | fn refresh_networks_list(&mut self) { |
968 | self.networks_mut().refresh_networks_list(); |
969 | } |
970 | |
971 | /// Returns the process list. |
972 | /// |
973 | /// ```no_run |
974 | /// use sysinfo::{ProcessExt, System, SystemExt}; |
975 | /// |
976 | /// let s = System::new_all(); |
977 | /// for (pid, process) in s.processes() { |
978 | /// println!("{} {}" , pid, process.name()); |
979 | /// } |
980 | /// ``` |
981 | fn processes(&self) -> &HashMap<Pid, Process>; |
982 | |
983 | /// Returns the process corresponding to the given `pid` or `None` if no such process exists. |
984 | /// |
985 | /// ```no_run |
986 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
987 | /// |
988 | /// let s = System::new_all(); |
989 | /// if let Some(process) = s.process(Pid::from(1337)) { |
990 | /// println!("{}" , process.name()); |
991 | /// } |
992 | /// ``` |
993 | fn process(&self, pid: Pid) -> Option<&Process>; |
994 | |
995 | /// Returns an iterator of process containing the given `name`. |
996 | /// |
997 | /// If you want only the processes with exactly the given `name`, take a look at |
998 | /// [`SystemExt::processes_by_exact_name`]. |
999 | /// |
1000 | /// **⚠️ Important ⚠️** |
1001 | /// |
1002 | /// On **Linux**, there are two things to know about processes' name: |
1003 | /// 1. It is limited to 15 characters. |
1004 | /// 2. It is not always the exe name. |
1005 | /// |
1006 | /// ```no_run |
1007 | /// use sysinfo::{ProcessExt, System, SystemExt}; |
1008 | /// |
1009 | /// let s = System::new_all(); |
1010 | /// for process in s.processes_by_name("htop" ) { |
1011 | /// println!("{} {}" , process.pid(), process.name()); |
1012 | /// } |
1013 | /// ``` |
1014 | // FIXME: replace the returned type with `impl Iterator<Item = &Process>` when it's supported! |
1015 | fn processes_by_name<'a: 'b, 'b>( |
1016 | &'a self, |
1017 | name: &'b str, |
1018 | ) -> Box<dyn Iterator<Item = &'a Process> + 'b> { |
1019 | Box::new( |
1020 | self.processes() |
1021 | .values() |
1022 | .filter(move |val: &&Process| val.name().contains(name)), |
1023 | ) |
1024 | } |
1025 | |
1026 | /// Returns an iterator of processes with exactly the given `name`. |
1027 | /// |
1028 | /// If you instead want the processes containing `name`, take a look at |
1029 | /// [`SystemExt::processes_by_name`]. |
1030 | /// |
1031 | /// **⚠️ Important ⚠️** |
1032 | /// |
1033 | /// On **Linux**, there are two things to know about processes' name: |
1034 | /// 1. It is limited to 15 characters. |
1035 | /// 2. It is not always the exe name. |
1036 | /// |
1037 | /// ```no_run |
1038 | /// use sysinfo::{ProcessExt, System, SystemExt}; |
1039 | /// |
1040 | /// let s = System::new_all(); |
1041 | /// for process in s.processes_by_exact_name("htop" ) { |
1042 | /// println!("{} {}" , process.pid(), process.name()); |
1043 | /// } |
1044 | /// ``` |
1045 | // FIXME: replace the returned type with `impl Iterator<Item = &Process>` when it's supported! |
1046 | fn processes_by_exact_name<'a: 'b, 'b>( |
1047 | &'a self, |
1048 | name: &'b str, |
1049 | ) -> Box<dyn Iterator<Item = &'a Process> + 'b> { |
1050 | Box::new( |
1051 | self.processes() |
1052 | .values() |
1053 | .filter(move |val: &&Process| val.name() == name), |
1054 | ) |
1055 | } |
1056 | |
1057 | /// Returns "global" CPUs information (aka the addition of all the CPUs). |
1058 | /// |
1059 | /// To have up-to-date information, you need to call [`SystemExt::refresh_cpu`] or |
1060 | /// [`SystemExt::refresh_specifics`] with `cpu` enabled. |
1061 | /// |
1062 | /// ```no_run |
1063 | /// use sysinfo::{CpuRefreshKind, CpuExt, RefreshKind, System, SystemExt}; |
1064 | /// |
1065 | /// let s = System::new_with_specifics( |
1066 | /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()), |
1067 | /// ); |
1068 | /// println!("{}%" , s.global_cpu_info().cpu_usage()); |
1069 | /// ``` |
1070 | fn global_cpu_info(&self) -> &Cpu; |
1071 | |
1072 | /// Returns the list of the CPUs. |
1073 | /// |
1074 | /// By default, the list of CPUs is empty until you call [`SystemExt::refresh_cpu`] or |
1075 | /// [`SystemExt::refresh_specifics`] with `cpu` enabled. |
1076 | /// |
1077 | /// ```no_run |
1078 | /// use sysinfo::{CpuRefreshKind, CpuExt, RefreshKind, System, SystemExt}; |
1079 | /// |
1080 | /// let s = System::new_with_specifics( |
1081 | /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()), |
1082 | /// ); |
1083 | /// for cpu in s.cpus() { |
1084 | /// println!("{}%" , cpu.cpu_usage()); |
1085 | /// } |
1086 | /// ``` |
1087 | fn cpus(&self) -> &[Cpu]; |
1088 | |
1089 | /// Returns the number of physical cores on the CPU or `None` if it couldn't get it. |
1090 | /// |
1091 | /// In case there are multiple CPUs, it will combine the physical core count of all the CPUs. |
1092 | /// |
1093 | /// **Important**: this information is computed every time this function is called. |
1094 | /// |
1095 | /// ```no_run |
1096 | /// use sysinfo::{CpuExt, System, SystemExt}; |
1097 | /// |
1098 | /// let s = System::new(); |
1099 | /// println!("{:?}" , s.physical_core_count()); |
1100 | /// ``` |
1101 | fn physical_core_count(&self) -> Option<usize>; |
1102 | |
1103 | /// Returns the RAM size in bytes. |
1104 | /// |
1105 | /// ```no_run |
1106 | /// use sysinfo::{System, SystemExt}; |
1107 | /// |
1108 | /// let s = System::new_all(); |
1109 | /// println!("{} bytes" , s.total_memory()); |
1110 | /// ``` |
1111 | fn total_memory(&self) -> u64; |
1112 | |
1113 | /// Returns the amount of free RAM in bytes. |
1114 | /// |
1115 | /// Generally, "free" memory refers to unallocated memory whereas "available" memory refers to |
1116 | /// memory that is available for (re)use. |
1117 | /// |
1118 | /// Side note: Windows doesn't report "free" memory so this method returns the same value |
1119 | /// as [`get_available_memory`](#tymethod.available_memory). |
1120 | /// |
1121 | /// ```no_run |
1122 | /// use sysinfo::{System, SystemExt}; |
1123 | /// |
1124 | /// let s = System::new_all(); |
1125 | /// println!("{} bytes" , s.free_memory()); |
1126 | /// ``` |
1127 | fn free_memory(&self) -> u64; |
1128 | |
1129 | /// Returns the amount of available RAM in bytes. |
1130 | /// |
1131 | /// Generally, "free" memory refers to unallocated memory whereas "available" memory refers to |
1132 | /// memory that is available for (re)use. |
1133 | /// |
1134 | /// ⚠️ Windows and FreeBSD don't report "available" memory so [`SystemExt::free_memory`] |
1135 | /// returns the same value as this method. |
1136 | /// |
1137 | /// ```no_run |
1138 | /// use sysinfo::{System, SystemExt}; |
1139 | /// |
1140 | /// let s = System::new_all(); |
1141 | /// println!("{} bytes" , s.available_memory()); |
1142 | /// ``` |
1143 | fn available_memory(&self) -> u64; |
1144 | |
1145 | /// Returns the amount of used RAM in bytes. |
1146 | /// |
1147 | /// ```no_run |
1148 | /// use sysinfo::{System, SystemExt}; |
1149 | /// |
1150 | /// let s = System::new_all(); |
1151 | /// println!("{} bytes" , s.used_memory()); |
1152 | /// ``` |
1153 | fn used_memory(&self) -> u64; |
1154 | |
1155 | /// Returns the SWAP size in bytes. |
1156 | /// |
1157 | /// ```no_run |
1158 | /// use sysinfo::{System, SystemExt}; |
1159 | /// |
1160 | /// let s = System::new_all(); |
1161 | /// println!("{} bytes" , s.total_swap()); |
1162 | /// ``` |
1163 | fn total_swap(&self) -> u64; |
1164 | |
1165 | /// Returns the amount of free SWAP in bytes. |
1166 | /// |
1167 | /// ```no_run |
1168 | /// use sysinfo::{System, SystemExt}; |
1169 | /// |
1170 | /// let s = System::new_all(); |
1171 | /// println!("{} bytes" , s.free_swap()); |
1172 | /// ``` |
1173 | fn free_swap(&self) -> u64; |
1174 | |
1175 | /// Returns the amount of used SWAP in bytes. |
1176 | /// |
1177 | /// ```no_run |
1178 | /// use sysinfo::{System, SystemExt}; |
1179 | /// |
1180 | /// let s = System::new_all(); |
1181 | /// println!("{} bytes" , s.used_swap()); |
1182 | /// ``` |
1183 | fn used_swap(&self) -> u64; |
1184 | |
1185 | /// Returns the components list. |
1186 | /// |
1187 | /// ```no_run |
1188 | /// use sysinfo::{ComponentExt, System, SystemExt}; |
1189 | /// |
1190 | /// let s = System::new_all(); |
1191 | /// for component in s.components() { |
1192 | /// println!("{}: {}°C" , component.label(), component.temperature()); |
1193 | /// } |
1194 | /// ``` |
1195 | fn components(&self) -> &[Component]; |
1196 | |
1197 | /// Returns a mutable components list. |
1198 | /// |
1199 | /// ```no_run |
1200 | /// use sysinfo::{ComponentExt, System, SystemExt}; |
1201 | /// |
1202 | /// let mut s = System::new_all(); |
1203 | /// for component in s.components_mut() { |
1204 | /// component.refresh(); |
1205 | /// } |
1206 | /// ``` |
1207 | fn components_mut(&mut self) -> &mut [Component]; |
1208 | |
1209 | /// Returns the users list. |
1210 | /// |
1211 | /// ```no_run |
1212 | /// use sysinfo::{System, SystemExt, UserExt}; |
1213 | /// |
1214 | /// let mut s = System::new_all(); |
1215 | /// for user in s.users() { |
1216 | /// println!("{} is in {} groups" , user.name(), user.groups().len()); |
1217 | /// } |
1218 | /// ``` |
1219 | fn users(&self) -> &[User]; |
1220 | |
1221 | /// Returns the disks list. |
1222 | /// |
1223 | /// ```no_run |
1224 | /// use sysinfo::{DiskExt, System, SystemExt}; |
1225 | /// |
1226 | /// let mut s = System::new(); |
1227 | /// s.refresh_disks_list(); |
1228 | /// for disk in s.disks() { |
1229 | /// println!("{:?}" , disk.name()); |
1230 | /// } |
1231 | /// ``` |
1232 | fn disks(&self) -> &[Disk]; |
1233 | |
1234 | /// Returns the disks list. |
1235 | /// |
1236 | /// ```no_run |
1237 | /// use sysinfo::{DiskExt, System, SystemExt}; |
1238 | /// |
1239 | /// let mut s = System::new_all(); |
1240 | /// for disk in s.disks_mut() { |
1241 | /// disk.refresh(); |
1242 | /// } |
1243 | /// ``` |
1244 | fn disks_mut(&mut self) -> &mut [Disk]; |
1245 | |
1246 | /// Sort the disk list with the provided callback. |
1247 | /// |
1248 | /// Internally, it is using the [`slice::sort_unstable_by`] function, so please refer to it |
1249 | /// for implementation details. |
1250 | /// |
1251 | /// ⚠️ If you use [`SystemExt::refresh_disks_list`], you need to use this method before using |
1252 | /// [`SystemExt::disks`] or [`SystemExt::disks_mut`] if you want them to be sorted. |
1253 | fn sort_disks_by<F>(&mut self, compare: F) |
1254 | where |
1255 | F: FnMut(&Disk, &Disk) -> std::cmp::Ordering; |
1256 | |
1257 | /// Returns the network interfaces object. |
1258 | /// |
1259 | /// ```no_run |
1260 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1261 | /// |
1262 | /// let s = System::new_all(); |
1263 | /// let networks = s.networks(); |
1264 | /// for (interface_name, data) in networks { |
1265 | /// println!( |
1266 | /// "[{}] in: {}, out: {}" , |
1267 | /// interface_name, |
1268 | /// data.received(), |
1269 | /// data.transmitted(), |
1270 | /// ); |
1271 | /// } |
1272 | /// ``` |
1273 | fn networks(&self) -> &Networks; |
1274 | |
1275 | /// Returns a mutable access to network interfaces. |
1276 | /// |
1277 | /// ```no_run |
1278 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1279 | /// |
1280 | /// let mut s = System::new_all(); |
1281 | /// let networks = s.networks_mut(); |
1282 | /// networks.refresh_networks_list(); |
1283 | /// ``` |
1284 | fn networks_mut(&mut self) -> &mut Networks; |
1285 | |
1286 | /// Returns system uptime (in seconds). |
1287 | /// |
1288 | /// ```no_run |
1289 | /// use sysinfo::{System, SystemExt}; |
1290 | /// |
1291 | /// let s = System::new_all(); |
1292 | /// println!("System running since {} seconds" , s.uptime()); |
1293 | /// ``` |
1294 | fn uptime(&self) -> u64; |
1295 | |
1296 | /// Returns the time (in seconds) when the system booted since UNIX epoch. |
1297 | /// |
1298 | /// ```no_run |
1299 | /// use sysinfo::{System, SystemExt}; |
1300 | /// |
1301 | /// let s = System::new(); |
1302 | /// println!("System booted at {} seconds" , s.boot_time()); |
1303 | /// ``` |
1304 | fn boot_time(&self) -> u64; |
1305 | |
1306 | /// Returns the system load average value. |
1307 | /// |
1308 | /// ```no_run |
1309 | /// use sysinfo::{System, SystemExt}; |
1310 | /// |
1311 | /// let s = System::new_all(); |
1312 | /// let load_avg = s.load_average(); |
1313 | /// println!( |
1314 | /// "one minute: {}%, five minutes: {}%, fifteen minutes: {}%" , |
1315 | /// load_avg.one, |
1316 | /// load_avg.five, |
1317 | /// load_avg.fifteen, |
1318 | /// ); |
1319 | /// ``` |
1320 | fn load_average(&self) -> LoadAvg; |
1321 | |
1322 | /// Returns the system name. |
1323 | /// |
1324 | /// **Important**: this information is computed every time this function is called. |
1325 | /// |
1326 | /// ```no_run |
1327 | /// use sysinfo::{System, SystemExt}; |
1328 | /// |
1329 | /// let s = System::new(); |
1330 | /// println!("OS: {:?}" , s.name()); |
1331 | /// ``` |
1332 | fn name(&self) -> Option<String>; |
1333 | |
1334 | /// Returns the system's kernel version. |
1335 | /// |
1336 | /// **Important**: this information is computed every time this function is called. |
1337 | /// |
1338 | /// ```no_run |
1339 | /// use sysinfo::{System, SystemExt}; |
1340 | /// |
1341 | /// let s = System::new(); |
1342 | /// println!("kernel version: {:?}" , s.kernel_version()); |
1343 | /// ``` |
1344 | fn kernel_version(&self) -> Option<String>; |
1345 | |
1346 | /// Returns the system version (e.g. for MacOS this will return 11.1 rather than the kernel version). |
1347 | /// |
1348 | /// **Important**: this information is computed every time this function is called. |
1349 | /// |
1350 | /// ```no_run |
1351 | /// use sysinfo::{System, SystemExt}; |
1352 | /// |
1353 | /// let s = System::new(); |
1354 | /// println!("OS version: {:?}" , s.os_version()); |
1355 | /// ``` |
1356 | fn os_version(&self) -> Option<String>; |
1357 | |
1358 | /// Returns the system long os version (e.g "MacOS 11.2 BigSur"). |
1359 | /// |
1360 | /// **Important**: this information is computed every time this function is called. |
1361 | /// |
1362 | /// ```no_run |
1363 | /// use sysinfo::{System, SystemExt}; |
1364 | /// |
1365 | /// let s = System::new(); |
1366 | /// println!("Long OS Version: {:?}" , s.long_os_version()); |
1367 | /// ``` |
1368 | fn long_os_version(&self) -> Option<String>; |
1369 | |
1370 | /// Returns the distribution id as defined by os-release, |
1371 | /// or [`std::env::consts::OS`]. |
1372 | /// |
1373 | /// See also |
1374 | /// - <https://www.freedesktop.org/software/systemd/man/os-release.html#ID=> |
1375 | /// - <https://doc.rust-lang.org/std/env/consts/constant.OS.html> |
1376 | /// |
1377 | /// **Important**: this information is computed every time this function is called. |
1378 | /// |
1379 | /// ```no_run |
1380 | /// use sysinfo::{System, SystemExt}; |
1381 | /// |
1382 | /// let s = System::new(); |
1383 | /// println!("Distribution ID: {:?}" , s.distribution_id()); |
1384 | /// ``` |
1385 | fn distribution_id(&self) -> String; |
1386 | |
1387 | /// Returns the system hostname based off DNS |
1388 | /// |
1389 | /// **Important**: this information is computed every time this function is called. |
1390 | /// |
1391 | /// ```no_run |
1392 | /// use sysinfo::{System, SystemExt}; |
1393 | /// |
1394 | /// let s = System::new(); |
1395 | /// println!("Hostname: {:?}" , s.host_name()); |
1396 | /// ``` |
1397 | fn host_name(&self) -> Option<String>; |
1398 | |
1399 | /// Returns the [`User`] matching the given `user_id`. |
1400 | /// |
1401 | /// **Important**: The user list must be filled before using this method, otherwise it will |
1402 | /// always return `None` (through the `refresh_*` methods). |
1403 | /// |
1404 | /// It is a shorthand for: |
1405 | /// |
1406 | /// ```ignore |
1407 | /// let s = System::new_all(); |
1408 | /// s.users().find(|user| user.id() == user_id); |
1409 | /// ``` |
1410 | /// |
1411 | /// Full example: |
1412 | /// |
1413 | /// ```no_run |
1414 | /// use sysinfo::{Pid, ProcessExt, System, SystemExt}; |
1415 | /// |
1416 | /// let mut s = System::new_all(); |
1417 | /// |
1418 | /// if let Some(process) = s.process(Pid::from(1337)) { |
1419 | /// if let Some(user_id) = process.user_id() { |
1420 | /// eprintln!("User for process 1337: {:?}" , s.get_user_by_id(user_id)); |
1421 | /// } |
1422 | /// } |
1423 | /// ``` |
1424 | fn get_user_by_id(&self, user_id: &Uid) -> Option<&User> { |
1425 | self.users().iter().find(|user| user.id() == user_id) |
1426 | } |
1427 | } |
1428 | |
1429 | /// Getting volume of received and transmitted data. |
1430 | pub trait NetworkExt: Debug { |
1431 | /// Returns the number of received bytes since the last refresh. |
1432 | /// |
1433 | /// ```no_run |
1434 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1435 | /// |
1436 | /// let s = System::new_all(); |
1437 | /// let networks = s.networks(); |
1438 | /// for (interface_name, network) in networks { |
1439 | /// println!("in: {} B" , network.received()); |
1440 | /// } |
1441 | /// ``` |
1442 | fn received(&self) -> u64; |
1443 | |
1444 | /// Returns the total number of received bytes. |
1445 | /// |
1446 | /// ```no_run |
1447 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1448 | /// |
1449 | /// let s = System::new_all(); |
1450 | /// let networks = s.networks(); |
1451 | /// for (interface_name, network) in networks { |
1452 | /// println!("in: {} B" , network.total_received()); |
1453 | /// } |
1454 | /// ``` |
1455 | fn total_received(&self) -> u64; |
1456 | |
1457 | /// Returns the number of transmitted bytes since the last refresh. |
1458 | /// |
1459 | /// ```no_run |
1460 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1461 | /// |
1462 | /// let s = System::new_all(); |
1463 | /// let networks = s.networks(); |
1464 | /// for (interface_name, network) in networks { |
1465 | /// println!("out: {} B" , network.transmitted()); |
1466 | /// } |
1467 | /// ``` |
1468 | fn transmitted(&self) -> u64; |
1469 | |
1470 | /// Returns the total number of transmitted bytes. |
1471 | /// |
1472 | /// ```no_run |
1473 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1474 | /// |
1475 | /// let s = System::new_all(); |
1476 | /// let networks = s.networks(); |
1477 | /// for (interface_name, network) in networks { |
1478 | /// println!("out: {} B" , network.total_transmitted()); |
1479 | /// } |
1480 | /// ``` |
1481 | fn total_transmitted(&self) -> u64; |
1482 | |
1483 | /// Returns the number of incoming packets since the last refresh. |
1484 | /// |
1485 | /// ```no_run |
1486 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1487 | /// |
1488 | /// let s = System::new_all(); |
1489 | /// let networks = s.networks(); |
1490 | /// for (interface_name, network) in networks { |
1491 | /// println!("in: {}" , network.packets_received()); |
1492 | /// } |
1493 | /// ``` |
1494 | fn packets_received(&self) -> u64; |
1495 | |
1496 | /// Returns the total number of incoming packets. |
1497 | /// |
1498 | /// ```no_run |
1499 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1500 | /// |
1501 | /// let s = System::new_all(); |
1502 | /// let networks = s.networks(); |
1503 | /// for (interface_name, network) in networks { |
1504 | /// println!("in: {}" , network.total_packets_received()); |
1505 | /// } |
1506 | /// ``` |
1507 | fn total_packets_received(&self) -> u64; |
1508 | |
1509 | /// Returns the number of outcoming packets since the last refresh. |
1510 | /// |
1511 | /// ```no_run |
1512 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1513 | /// |
1514 | /// let s = System::new_all(); |
1515 | /// let networks = s.networks(); |
1516 | /// for (interface_name, network) in networks { |
1517 | /// println!("out: {}" , network.packets_transmitted()); |
1518 | /// } |
1519 | /// ``` |
1520 | fn packets_transmitted(&self) -> u64; |
1521 | |
1522 | /// Returns the total number of outcoming packets. |
1523 | /// |
1524 | /// ```no_run |
1525 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1526 | /// |
1527 | /// let s = System::new_all(); |
1528 | /// let networks = s.networks(); |
1529 | /// for (interface_name, network) in networks { |
1530 | /// println!("out: {}" , network.total_packets_transmitted()); |
1531 | /// } |
1532 | /// ``` |
1533 | fn total_packets_transmitted(&self) -> u64; |
1534 | |
1535 | /// Returns the number of incoming errors since the last refresh. |
1536 | /// |
1537 | /// ```no_run |
1538 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1539 | /// |
1540 | /// let s = System::new_all(); |
1541 | /// let networks = s.networks(); |
1542 | /// for (interface_name, network) in networks { |
1543 | /// println!("in: {}" , network.errors_on_received()); |
1544 | /// } |
1545 | /// ``` |
1546 | fn errors_on_received(&self) -> u64; |
1547 | |
1548 | /// Returns the total number of incoming errors. |
1549 | /// |
1550 | /// ```no_run |
1551 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1552 | /// |
1553 | /// let s = System::new_all(); |
1554 | /// let networks = s.networks(); |
1555 | /// for (interface_name, network) in networks { |
1556 | /// println!("in: {}" , network.total_errors_on_received()); |
1557 | /// } |
1558 | /// ``` |
1559 | fn total_errors_on_received(&self) -> u64; |
1560 | |
1561 | /// Returns the number of outcoming errors since the last refresh. |
1562 | /// |
1563 | /// ```no_run |
1564 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1565 | /// |
1566 | /// let s = System::new_all(); |
1567 | /// let networks = s.networks(); |
1568 | /// for (interface_name, network) in networks { |
1569 | /// println!("out: {}" , network.errors_on_transmitted()); |
1570 | /// } |
1571 | /// ``` |
1572 | fn errors_on_transmitted(&self) -> u64; |
1573 | |
1574 | /// Returns the total number of outcoming errors. |
1575 | /// |
1576 | /// ```no_run |
1577 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1578 | /// |
1579 | /// let s = System::new_all(); |
1580 | /// let networks = s.networks(); |
1581 | /// for (interface_name, network) in networks { |
1582 | /// println!("out: {}" , network.total_errors_on_transmitted()); |
1583 | /// } |
1584 | /// ``` |
1585 | fn total_errors_on_transmitted(&self) -> u64; |
1586 | |
1587 | /// Returns the MAC address associated to current interface. |
1588 | /// |
1589 | /// ```no_run |
1590 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1591 | /// |
1592 | /// let s = System::new_all(); |
1593 | /// let networks = s.networks(); |
1594 | /// for (interface_name, network) in networks { |
1595 | /// println!("MAC address: {}" , network.mac_address()); |
1596 | /// } |
1597 | /// ``` |
1598 | fn mac_address(&self) -> MacAddr; |
1599 | } |
1600 | |
1601 | /// Interacting with network interfaces. |
1602 | pub trait NetworksExt: Debug { |
1603 | /// Returns an iterator over the network interfaces. |
1604 | /// |
1605 | /// ```no_run |
1606 | /// use sysinfo::{NetworkExt, NetworksExt, System, SystemExt}; |
1607 | /// |
1608 | /// let s = System::new_all(); |
1609 | /// let networks = s.networks(); |
1610 | /// for (interface_name, network) in networks { |
1611 | /// println!("in: {} B" , network.received()); |
1612 | /// } |
1613 | /// ``` |
1614 | fn iter(&self) -> NetworksIter; |
1615 | |
1616 | /// Refreshes the network interfaces list. |
1617 | /// |
1618 | /// ```no_run |
1619 | /// use sysinfo::{NetworksExt, System, SystemExt}; |
1620 | /// |
1621 | /// let mut s = System::new_all(); |
1622 | /// let networks = s.networks_mut(); |
1623 | /// networks.refresh_networks_list(); |
1624 | /// ``` |
1625 | fn refresh_networks_list(&mut self); |
1626 | |
1627 | /// Refreshes the network interfaces' content. |
1628 | /// |
1629 | /// ```no_run |
1630 | /// use sysinfo::{NetworksExt, System, SystemExt}; |
1631 | /// |
1632 | /// let mut s = System::new_all(); |
1633 | /// let networks = s.networks_mut(); |
1634 | /// networks.refresh(); |
1635 | /// ``` |
1636 | fn refresh(&mut self); |
1637 | } |
1638 | |
1639 | /// Getting a component temperature information. |
1640 | pub trait ComponentExt: Debug { |
1641 | /// Returns the temperature of the component (in celsius degree). |
1642 | /// |
1643 | /// ```no_run |
1644 | /// use sysinfo::{ComponentExt, System, SystemExt}; |
1645 | /// |
1646 | /// let s = System::new_all(); |
1647 | /// for component in s.components() { |
1648 | /// println!("{}°C" , component.temperature()); |
1649 | /// } |
1650 | /// ``` |
1651 | /// |
1652 | /// ## Linux |
1653 | /// |
1654 | /// Returns `f32::NAN` if it failed to retrieve it. |
1655 | fn temperature(&self) -> f32; |
1656 | |
1657 | /// Returns the maximum temperature of the component (in celsius degree). |
1658 | /// |
1659 | /// Note: if `temperature` is higher than the current `max`, |
1660 | /// `max` value will be updated on refresh. |
1661 | /// |
1662 | /// ```no_run |
1663 | /// use sysinfo::{ComponentExt, System, SystemExt}; |
1664 | /// |
1665 | /// let s = System::new_all(); |
1666 | /// for component in s.components() { |
1667 | /// println!("{}°C" , component.max()); |
1668 | /// } |
1669 | /// ``` |
1670 | /// |
1671 | /// ## Linux |
1672 | /// |
1673 | /// May be computed by `sysinfo` from kernel. |
1674 | /// Returns `f32::NAN` if it failed to retrieve it. |
1675 | fn max(&self) -> f32; |
1676 | |
1677 | /// Returns the highest temperature before the component halts (in celsius degree). |
1678 | /// |
1679 | /// ```no_run |
1680 | /// use sysinfo::{ComponentExt, System, SystemExt}; |
1681 | /// |
1682 | /// let s = System::new_all(); |
1683 | /// for component in s.components() { |
1684 | /// println!("{:?}°C" , component.critical()); |
1685 | /// } |
1686 | /// ``` |
1687 | /// |
1688 | /// ## Linux |
1689 | /// |
1690 | /// Critical threshold defined by chip or kernel. |
1691 | fn critical(&self) -> Option<f32>; |
1692 | |
1693 | /// Returns the label of the component. |
1694 | /// |
1695 | /// ```no_run |
1696 | /// use sysinfo::{ComponentExt, System, SystemExt}; |
1697 | /// |
1698 | /// let s = System::new_all(); |
1699 | /// for component in s.components() { |
1700 | /// println!("{}" , component.label()); |
1701 | /// } |
1702 | /// ``` |
1703 | /// |
1704 | /// ## Linux |
1705 | /// |
1706 | /// Since components information is retrieved thanks to `hwmon`, |
1707 | /// the labels are generated as follows. |
1708 | /// Note: it may change and it was inspired by `sensors` own formatting. |
1709 | /// |
1710 | /// | name | label | device_model | id_sensor | Computed label by `sysinfo` | |
1711 | /// |---------|--------|------------|----------|----------------------| |
1712 | /// | ✓ | ✓ | ✓ | ✓ | `"{name} {label} {device_model} temp{id}"` | |
1713 | /// | ✓ | ✓ | ✗ | ✓ | `"{name} {label} {id}"` | |
1714 | /// | ✓ | ✗ | ✓ | ✓ | `"{name} {device_model}"` | |
1715 | /// | ✓ | ✗ | ✗ | ✓ | `"{name} temp{id}"` | |
1716 | fn label(&self) -> &str; |
1717 | |
1718 | /// Refreshes component. |
1719 | /// |
1720 | /// ```no_run |
1721 | /// use sysinfo::{ComponentExt, System, SystemExt}; |
1722 | /// |
1723 | /// let mut s = System::new_all(); |
1724 | /// for component in s.components_mut() { |
1725 | /// component.refresh(); |
1726 | /// } |
1727 | /// ``` |
1728 | fn refresh(&mut self); |
1729 | } |
1730 | |
1731 | /// Getting information for a user. |
1732 | /// |
1733 | /// It is returned from [`SystemExt::users`]. |
1734 | /// |
1735 | /// ```no_run |
1736 | /// use sysinfo::{System, SystemExt, UserExt}; |
1737 | /// |
1738 | /// let mut s = System::new_all(); |
1739 | /// for user in s.users() { |
1740 | /// println!("{} is in {} groups" , user.name(), user.groups().len()); |
1741 | /// } |
1742 | /// ``` |
1743 | pub trait UserExt: Debug { |
1744 | /// Return the user id of the user. |
1745 | /// |
1746 | /// ```no_run |
1747 | /// use sysinfo::{System, SystemExt, UserExt}; |
1748 | /// |
1749 | /// let mut s = System::new_all(); |
1750 | /// for user in s.users() { |
1751 | /// println!("{:?}" , *user.id()); |
1752 | /// } |
1753 | /// ``` |
1754 | fn id(&self) -> &Uid; |
1755 | |
1756 | /// Return the group id of the user. |
1757 | /// |
1758 | /// *NOTE* - On Windows, this value defaults to 0. Windows doesn't have a `username` specific group assigned to the user. |
1759 | /// They do however have unique [Security Identifiers](https://docs.microsoft.com/en-us/windows/win32/secauthz/security-identifiers) |
1760 | /// made up of various [Components](https://docs.microsoft.com/en-us/windows/win32/secauthz/sid-components). |
1761 | /// Pieces of the SID may be a candidate for this field, but it doesn't map well to a single group id. |
1762 | /// |
1763 | /// ```no_run |
1764 | /// use sysinfo::{System, SystemExt, UserExt}; |
1765 | /// |
1766 | /// let mut s = System::new_all(); |
1767 | /// for user in s.users() { |
1768 | /// println!("{}" , *user.group_id()); |
1769 | /// } |
1770 | /// ``` |
1771 | fn group_id(&self) -> Gid; |
1772 | |
1773 | /// Returns the name of the user. |
1774 | /// |
1775 | /// ```no_run |
1776 | /// use sysinfo::{System, SystemExt, UserExt}; |
1777 | /// |
1778 | /// let mut s = System::new_all(); |
1779 | /// for user in s.users() { |
1780 | /// println!("{}" , user.name()); |
1781 | /// } |
1782 | /// ``` |
1783 | fn name(&self) -> &str; |
1784 | |
1785 | /// Returns the groups of the user. |
1786 | /// |
1787 | /// ```no_run |
1788 | /// use sysinfo::{System, SystemExt, UserExt}; |
1789 | /// |
1790 | /// let mut s = System::new_all(); |
1791 | /// for user in s.users() { |
1792 | /// println!("{} is in {:?}" , user.name(), user.groups()); |
1793 | /// } |
1794 | /// ``` |
1795 | fn groups(&self) -> &[String]; |
1796 | } |
1797 | |