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, print, println}; 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::Enabled { 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 println!("Service running..."); 73 //修改service状态 74 service.mut_unit_base().set_state(UnitState::Enabled); 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.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::kill_running(*bind); 174 } 175 176 //判断是否需要restart,需要则再次启动服务 177 if service.service_part().restart().is_restart(&exit_status) { 178 let ns = service.service_part().restart_sec(); 179 let binds = service.unit_base().unit_part().be_binded_by(); 180 let binds = Vec::from(binds); 181 let id = service.unit_id(); 182 if ns > 0 { 183 let cmds = service.service_part().exec_reload().clone(); 184 TimerManager::push_timer( 185 Duration::from_nanos(ns), 186 move || { 187 for cmd in &cmds { 188 cmd.no_spawn()?; 189 } 190 Executor::exec(id)?; 191 for bind in &binds { 192 Executor::exec(*bind)? 193 } 194 Ok(()) 195 }, 196 service.unit_id(), 197 ) 198 } else { 199 let _ = Self::exec_reload(service); 200 let _ = Executor::exec(id); 201 } 202 return; 203 } 204 205 //如果该进程标记了RemainAfterExit,则将其加入特殊标记表 206 if service.service_part().remain_after_exit() { 207 UnitManager::push_flag_running(service.unit_id()); 208 return; 209 } 210 211 //停止服务后设置Unit状态 212 service.mut_unit_base().set_state(UnitState::Disabled); 213 } 214 215 /// ## 显示退出Service 216 pub fn exit(service: &mut ServiceUnit) { 217 // TODO: 打印日志 218 let _ = Self::exec_stop(service); 219 220 let ns = service.service_part().timeout_stop_sec(); 221 let id = service.unit_id(); 222 if ns != 0 { 223 // 计时器触发后若服务还未停止,则kill掉进程 224 TimerManager::push_timer( 225 Duration::from_nanos(ns), 226 move || { 227 if UnitManager::is_running_unit(&id) { 228 UnitManager::kill_running(id); 229 } 230 Ok(()) 231 }, 232 service.unit_id(), 233 ) 234 } 235 } 236 } 237