xref: /DragonReach/src/task/cmdtask/mod.rs (revision af4e087250481d24f7a6ee7057d648c56a4753e3)
1 use std::{eprint, eprintln, print, process::Command, string::String, vec::Vec};
2 
3 use crate::{
4     error::runtime_error::{RuntimeError, RuntimeErrorType},
5     manager::UnitManager,
6 };
7 
8 #[derive(Debug, Clone, Default)]
9 pub struct CmdTask {
10     pub path: String,
11     pub cmd: Vec<String>,
12     pub ignore: bool, //表示忽略这个命令的错误,即使它运行失败也不影响unit正常运作
13     pub dir: String,
14     pub envs: Vec<(String, String)>,
15     pub pid: u32,
16 }
17 
18 impl CmdTask {
19     /// ## 以新建进程的方式运行这个cmd
20     pub fn spawn(&self) -> Result<(), RuntimeError> {
21         let result = Command::new(&self.path)
22             .args(&self.cmd)
23             .current_dir(self.dir.clone())
24             .envs(self.envs.clone())
25             .spawn();
26         match result {
27             Ok(proc) => {
28                 UnitManager::push_cmd_proc(proc);
29             }
30             Err(err) => {
31                 if !self.ignore {
32                     eprintln!("{}: Command failed: {}", self.path, err);
33                     return Err(RuntimeError::new(RuntimeErrorType::ExecFailed));
34                 }
35             }
36         }
37         Ok(())
38     }
39 
40     /// ## 阻塞式运行
41     pub fn no_spawn(&self) -> Result<(), RuntimeError> {
42         let result = Command::new(&self.path)
43             .args(&self.cmd)
44             .current_dir(self.dir.clone())
45             .envs(self.envs.clone())
46             .spawn();
47 
48         match result {
49             Ok(mut child) => match child.wait() {
50                 Ok(status) => {
51                     if !status.success() && !self.ignore {
52                         return Err(RuntimeError::new(RuntimeErrorType::ExecFailed));
53                     }
54                 }
55                 Err(_) => {
56                     if !self.ignore {
57                         return Err(RuntimeError::new(RuntimeErrorType::ExecFailed));
58                     }
59                 }
60             },
61             Err(e) => {
62                 if !self.ignore {
63                     eprintln!("{}: Command failed: {}", self.path, e);
64                     return Err(RuntimeError::new(RuntimeErrorType::ExecFailed));
65                 }
66             }
67         }
68         Ok(())
69     }
70 
71     /// ## 若这个cmd任务spawn了,则kill这个cmd进程
72     pub fn stop(&mut self) {
73         if self.pid != 0 {
74             let res = UnitManager::pop_cmd_proc(self.pid).unwrap();
75 
76             let mut proc = res.lock().unwrap();
77 
78             match proc.try_wait() {
79                 //进程正常退出
80                 Ok(Some(_status)) => {}
81                 //进程错误退出(或启动失败)
82                 _ => {
83                     proc.kill().expect("Cannot kill cmd task");
84                 }
85             };
86         }
87     }
88 }
89