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