1 #[cfg(target_os = "dragonos")] 2 use drstd as std; 3 4 use crate::{ 5 error::runtime_error::{RuntimeError, RuntimeErrorType}, 6 manager::{timer_manager::TimerManager, UnitManager}, 7 parse::Segment, 8 unit::{ 9 service::{ServiceType, ServiceUnit}, 10 Unit, UnitState, 11 }, 12 }; 13 14 use std::process::Command; 15 use std::process::Stdio; 16 use std::time::Duration; 17 use std::vec::Vec; 18 use std::{eprint, eprintln, print, println}; 19 20 use super::{Executor, ExitStatus}; 21 22 pub struct ServiceExecutor; 23 24 impl ServiceExecutor { 25 /// ## Service执行器 26 pub fn exec(service: &mut ServiceUnit) -> Result<(), RuntimeError> { 27 // 通过服务启动类型分发 28 match *service.service_part().service_type() { 29 ServiceType::Simple => return Self::exec_simple(service), 30 ServiceType::Forking => return Self::exec_forking(service), 31 ServiceType::Dbus => return Self::exec_dbus(service), 32 ServiceType::Notify => return Self::exec_notify(service), 33 ServiceType::Idle => return Self::exec_idle(service), 34 ServiceType::OneShot => return Self::exec_one_shot(service), 35 }; 36 } 37 38 pub fn exec_simple(service: &mut ServiceUnit) -> Result<(), RuntimeError> { 39 //处理conflict 40 let conflicts = service.unit_base().unit_part().conflicts(); 41 for u in conflicts { 42 // 如果有冲突项enable的时候,该unit不能启动 43 let mutex = UnitManager::get_unit_with_id(u).unwrap(); 44 let unit = mutex.lock().unwrap(); 45 if *unit.unit_base().state() == UnitState::Enabled { 46 eprintln!( 47 "{}: Service startup failed: conflict unit", 48 unit.unit_base().unit_part().description() 49 ); 50 return Err(RuntimeError::new(RuntimeErrorType::ExecFailed)); 51 } 52 } 53 54 //获取启动命令 55 let exec_start = service.service_part().exec_start(); 56 57 //TODO:设置uid与gid 58 59 //处理ExecStartsPre,准备在服务启动前执行的命令 60 Self::exec_start_pre(service)?; 61 62 //创建服务进程 63 //服务配置环境变量,配置工作目录 64 let proc = Command::new(&exec_start.path) 65 .args(&exec_start.cmd) 66 .current_dir(service.service_part().working_directory()) 67 .envs(Vec::from(service.service_part().environment())) 68 .stderr(Stdio::inherit()) 69 .stdout(Stdio::inherit()) 70 .stdin(Stdio::inherit()) 71 .spawn(); 72 73 match proc { 74 Ok(p) => { 75 println!("Service running..."); 76 //修改service状态 77 service.mut_unit_base().set_state(UnitState::Enabled); 78 //启动成功后将Child加入全局管理的进程表 79 UnitManager::push_running(service.unit_id(), p); 80 //执行启动后命令 81 Self::exec_start_pos(service)?; 82 } 83 Err(err) => { 84 eprintln!("{}: Service startup failed: {}", exec_start.path, err); 85 return Err(RuntimeError::new(RuntimeErrorType::ExecFailed)); 86 } 87 } 88 Ok(()) 89 } 90 91 fn exec_dbus(_service: &ServiceUnit) -> Result<(), RuntimeError> { 92 Ok(()) 93 } 94 95 fn exec_forking(_service: &ServiceUnit) -> Result<(), RuntimeError> { 96 Ok(()) 97 } 98 99 // 此方法会改变service的启动模式为simple 100 fn exec_idle(service: &mut ServiceUnit) -> Result<(), RuntimeError> { 101 // 将该service加入等待运行队列 102 let _ = service.set_attr(Segment::Service, "Type", "simple"); 103 UnitManager::push_a_idle_service(service.unit_id()); 104 Ok(()) 105 } 106 107 fn exec_notify(_service: &ServiceUnit) -> Result<(), RuntimeError> { 108 Ok(()) 109 } 110 111 fn exec_one_shot(_service: &ServiceUnit) -> Result<(), RuntimeError> { 112 Ok(()) 113 } 114 115 fn exec_start_pos(service: &ServiceUnit) -> Result<(), RuntimeError> { 116 let cmds = service.service_part().exec_start_pos(); 117 for cmd in cmds { 118 cmd.spawn()?; 119 } 120 Ok(()) 121 } 122 123 fn exec_start_pre(service: &ServiceUnit) -> Result<(), RuntimeError> { 124 let cmds = service.service_part().exec_start_pre(); 125 for cmd in cmds { 126 cmd.spawn()?; 127 } 128 Ok(()) 129 } 130 131 //显式停止时执行的命令 132 fn exec_stop(service: &mut ServiceUnit) -> Result<(), RuntimeError> { 133 let cmds = service.service_part().exec_stop(); 134 for cmd in cmds { 135 cmd.no_spawn()?; 136 } 137 Ok(()) 138 } 139 140 //停止后执行的命令 141 fn exec_stop_post(service: &mut ServiceUnit) -> Result<(), RuntimeError> { 142 let cmds = service.mut_service_part().mut_exec_stop_post(); 143 for cmd in cmds { 144 cmd.no_spawn()?; 145 } 146 Ok(()) 147 } 148 149 fn exec_reload(service: &mut ServiceUnit) -> Result<(), RuntimeError> { 150 let cmds = service.service_part().exec_reload(); 151 for cmd in cmds { 152 cmd.no_spawn()?; 153 } 154 Ok(()) 155 } 156 157 /// ## 服务退出执行的逻辑(包括自然退出及显式退出) 158 pub fn after_exit(service: &mut ServiceUnit, exit_status: ExitStatus) { 159 //TODO: 需要考虑是否需要在此处执行退出后代码,还是只需要显式退出时才执行 160 let _ = Self::exec_stop_post(service); 161 162 // 停止被spawn的命令 163 let s_part = service.mut_service_part(); 164 for cmd in s_part.mut_exec_start_pos() { 165 cmd.stop() 166 } 167 for cmd in s_part.mut_exec_start_pre() { 168 cmd.stop() 169 } 170 171 // 取消未进行的定时器任务 172 TimerManager::cancel_timer(service.unit_id()); 173 174 // 关闭和此服务绑定的项目 175 for bind in service.unit_base().unit_part().be_binded_by() { 176 UnitManager::kill_running(*bind); 177 } 178 179 //判断是否需要restart,需要则再次启动服务 180 if service.service_part().restart().is_restart(&exit_status) { 181 let ns = service.service_part().restart_sec(); 182 let binds = service.unit_base().unit_part().be_binded_by(); 183 let binds = Vec::from(binds); 184 let id = service.unit_id(); 185 if ns > 0 { 186 let cmds = service.service_part().exec_reload().clone(); 187 TimerManager::push_timer( 188 Duration::from_nanos(ns), 189 move || { 190 for cmd in &cmds { 191 cmd.no_spawn()?; 192 } 193 Executor::exec(id)?; 194 for bind in &binds { 195 Executor::exec(*bind)? 196 } 197 Ok(()) 198 }, 199 service.unit_id(), 200 ) 201 } else { 202 let _ = Self::exec_reload(service); 203 let _ = Executor::exec(id); 204 } 205 return; 206 } 207 208 //如果该进程标记了RemainAfterExit,则将其加入特殊标记表 209 if service.service_part().remain_after_exit() { 210 UnitManager::push_flag_running(service.unit_id()); 211 return; 212 } 213 214 //停止服务后设置Unit状态 215 service.mut_unit_base().set_state(UnitState::Disabled); 216 } 217 218 /// ## 显示退出Service 219 pub fn exit(service: &mut ServiceUnit) { 220 // TODO: 打印日志 221 let _ = Self::exec_stop(service); 222 223 let ns = service.service_part().timeout_stop_sec(); 224 let id = service.unit_id(); 225 if ns != 0 { 226 // 计时器触发后若服务还未停止,则kill掉进程 227 TimerManager::push_timer( 228 Duration::from_nanos(ns), 229 move || { 230 if UnitManager::is_running_unit(&id) { 231 UnitManager::kill_running(id); 232 } 233 Ok(()) 234 }, 235 service.unit_id(), 236 ) 237 } 238 } 239 } 240