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