proc_cli/commands/
orphans.rs1use crate::core::Process;
11#[cfg(unix)]
12use crate::core::{apply_filters, apply_to_each, NameMatch};
13use crate::error::Result;
14#[cfg(unix)]
15use crate::ui::{must_confirm, plural, Printer};
16use clap::Args;
17#[cfg(unix)]
18use dialoguer::Confirm;
19
20#[derive(Args, Debug)]
22pub struct OrphansCommand {
23 #[arg(long, short = 'k')]
25 pub kill: bool,
26
27 #[arg(long)]
29 pub dry_run: bool,
30
31 #[arg(long, short = 'y')]
33 pub yes: bool,
34
35 #[arg(long, short = 'j')]
37 pub json: bool,
38
39 #[arg(long, short = 'v')]
41 pub verbose: bool,
42
43 #[arg(long, short = 'w')]
45 pub wide: bool,
46
47 #[arg(long = "in", short = 'i', num_args = 0..=1, default_missing_value = ".")]
50 pub in_dir: Option<String>,
51
52 #[arg(long = "by", short = 'b')]
54 pub by_name: Option<String>,
55
56 #[arg(long)]
58 pub cmd: bool,
59}
60
61impl OrphansCommand {
62 #[cfg(unix)]
64 pub fn execute(&self) -> Result<()> {
65 let printer = Printer::from_flags(self.json, self.verbose).wide(self.wide);
66
67 let mut processes = Process::find_orphans()?;
68
69 apply_filters(
71 &mut processes,
72 &self.in_dir,
73 &self.by_name,
74 NameMatch::from_flag(self.cmd),
75 );
76
77 if !(self.kill && self.json && self.yes && !self.dry_run) {
80 Process::measure_cpu(&mut processes);
81 }
82
83 if processes.is_empty() {
84 printer.print_empty_result("orphans", "No orphaned processes found");
85 return Ok(());
86 }
87
88 printer.warning(&format!(
89 "Found {} orphaned process{}",
90 processes.len(),
91 plural(processes.len())
92 ));
93
94 if !self.kill {
95 printer.print_processes_under_headline("orphans", &processes);
96 return Ok(());
97 }
98
99 if self.dry_run {
101 printer.print_dry_run_with(
102 "orphans",
103 &processes,
104 &format!(
105 "Dry run: would kill {} orphaned process{}",
106 processes.len(),
107 plural(processes.len())
108 ),
109 );
110 return Ok(());
111 }
112
113 if !self.json {
115 printer.print_processes_under_headline("orphans", &processes);
116 }
117
118 if must_confirm("orphans --kill", self.yes, self.json, &processes, None)? {
120 let confirmed = Confirm::new()
121 .with_prompt(format!(
122 "Kill {} orphaned process{}?",
123 processes.len(),
124 plural(processes.len())
125 ))
126 .default(false)
127 .interact()?;
128
129 if !confirmed {
130 printer.warning("Cancelled");
131 return Ok(());
132 }
133 }
134
135 let (killed, failed) = apply_to_each(&processes, |proc| proc.kill_and_wait());
136
137 printer.print_action_result_as("orphans", "kill", &killed, &failed)
138 }
139
140 #[cfg(not(unix))]
143 pub fn execute(&self) -> Result<()> {
144 Process::find_orphans().map(|_| ())
145 }
146}