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