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, prompt, Printer};
16use clap::Args;
17
18#[derive(Args, Debug)]
20pub struct OrphansCommand {
21 #[arg(long, short = 'k')]
23 pub kill: bool,
24
25 #[arg(long)]
27 pub dry_run: bool,
28
29 #[arg(long, short = 'y')]
31 pub yes: bool,
32
33 #[arg(long, short = 'j')]
35 pub json: bool,
36
37 #[arg(long, short = 'v')]
39 pub verbose: bool,
40
41 #[arg(long, short = 'w')]
43 pub wide: bool,
44
45 #[arg(long = "in", short = 'i', num_args = 0..=1, default_missing_value = ".")]
48 pub in_dir: Option<String>,
49
50 #[arg(long = "by", short = 'b')]
52 pub by_name: Option<String>,
53
54 #[arg(long)]
56 pub cmd: bool,
57}
58
59impl OrphansCommand {
60 #[cfg(unix)]
62 pub fn execute(&self) -> Result<()> {
63 let printer = Printer::from_flags(self.json, self.verbose).wide(self.wide);
64
65 let mut processes = Process::find_orphans()?;
66
67 apply_filters(
69 &mut processes,
70 &self.in_dir,
71 &self.by_name,
72 NameMatch::from_flag(self.cmd),
73 )?;
74
75 if !(self.kill && self.json && self.yes && !self.dry_run) {
78 Process::measure_cpu(&mut processes);
79 }
80
81 if processes.is_empty() {
82 printer.print_empty_result("orphans", "No orphaned processes found");
83 return Ok(());
84 }
85
86 printer.warning(&format!(
87 "Found {} orphaned process{}",
88 processes.len(),
89 plural(processes.len())
90 ));
91
92 if !self.kill {
93 printer.print_processes_under_headline("orphans", &processes);
94 return Ok(());
95 }
96
97 if self.dry_run {
99 printer.print_dry_run_with(
100 "orphans",
101 &processes,
102 &format!(
103 "Dry run: would kill {} orphaned process{}",
104 processes.len(),
105 plural(processes.len())
106 ),
107 );
108 return Ok(());
109 }
110
111 let asking = must_confirm("orphans --kill", self.yes, self.json, &processes, None);
113
114 if !self.json && !matches!(asking, Ok(true)) {
117 printer.print_processes_under_headline("orphans", &processes);
118 }
119
120 if asking? {
121 let question = format!(
122 "Kill {} orphaned process{}?",
123 processes.len(),
124 plural(processes.len())
125 );
126 let list = || printer.print_processes_under_headline("orphans", &processes);
127 let confirmed = prompt::ask("orphans --kill", &processes, None, &question, list)?;
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}