1 use super::{BaseUnit, Unit}; 2 use crate::error::runtime_error::RuntimeError; 3 use crate::error::{parse_error::ParseError, parse_error::ParseErrorType}; 4 use crate::executor::service_executor::ServiceExecutor; 5 use crate::executor::ExitStatus; 6 7 use crate::parse::parse_service::ServiceParser; 8 use crate::parse::parse_util::UnitParseUtil; 9 use crate::parse::{Segment, SERVICE_UNIT_ATTR_TABLE}; 10 use crate::task::cmdtask::CmdTask; 11 12 #[derive(Clone, Debug)] 13 pub struct ServiceUnit { 14 unit_base: BaseUnit, 15 service_part: ServicePart, 16 } 17 18 impl Default for ServiceUnit { default() -> Self19 fn default() -> Self { 20 let mut sp = ServicePart::default(); 21 sp.working_directory = String::from("/"); 22 Self { 23 unit_base: BaseUnit::default(), 24 service_part: sp, 25 } 26 } 27 } 28 29 #[derive(Debug, Clone, Copy)] 30 pub enum ServiceType { 31 Simple, 32 Forking, 33 OneShot, 34 Dbus, 35 Notify, 36 Idle, 37 } 38 39 impl Default for ServiceType { default() -> Self40 fn default() -> Self { 41 ServiceType::Simple 42 } 43 } 44 45 #[derive(Debug, Clone, Copy, PartialEq)] 46 pub enum RestartOption { 47 //ServiceRestart 48 AlwaysRestart, //总是重启 49 OnSuccess, //在该服务正常退出时 50 OnFailure, //在该服务启动失败时 51 OnAbnormal, //在该服务以非0错误码退出时 52 OnAbort, //在该服务显示退出时(通过DragonReach手动退出) 53 OnWatchdog, //定时观测进程无响应时(当前未实现) 54 None, //不重启 55 } 56 57 impl Default for RestartOption { default() -> Self58 fn default() -> Self { 59 Self::None 60 } 61 } 62 63 impl RestartOption { is_restart(&self, exit_status: &ExitStatus) -> bool64 pub fn is_restart(&self, exit_status: &ExitStatus) -> bool { 65 if *self == Self::AlwaysRestart { 66 return true; 67 } 68 69 match (*self, *exit_status) { 70 (Self::OnSuccess, ExitStatus::Success) => { 71 return true; 72 } 73 (Self::OnAbnormal, ExitStatus::Abnormal) => { 74 return true; 75 } 76 (Self::OnAbort, ExitStatus::Abort) => { 77 return true; 78 } 79 (Self::OnFailure, ExitStatus::Failure) => { 80 return true; 81 } 82 (Self::OnWatchdog, ExitStatus::Watchdog) => { 83 return true; 84 } 85 _ => { 86 return false; 87 } 88 } 89 } 90 } 91 92 #[derive(Debug, Clone, Copy)] 93 pub enum MountFlag { 94 Shared, 95 Slave, 96 Private, 97 } 98 99 impl Default for MountFlag { default() -> Self100 fn default() -> Self { 101 Self::Private 102 } 103 } 104 105 #[allow(dead_code)] 106 #[derive(Default, Debug, Clone)] 107 pub struct ServicePart { 108 //生命周期相关 109 service_type: ServiceType, 110 /// 111 remain_after_exit: bool, 112 exec_start: CmdTask, 113 exec_start_pre: Vec<CmdTask>, 114 exec_start_pos: Vec<CmdTask>, 115 exec_reload: Vec<CmdTask>, 116 exec_stop: Vec<CmdTask>, 117 exec_stop_post: Vec<CmdTask>, 118 restart_sec: u64, 119 restart: RestartOption, 120 timeout_start_sec: u64, 121 timeout_stop_sec: u64, 122 //上下文配置相关 123 environment: Vec<(String, String)>, 124 nice: i8, 125 working_directory: String, 126 root_directory: String, 127 user: String, 128 group: String, 129 mount_flags: MountFlag, 130 //LimitCPU / LimitSTACK / LimitNOFILE / LimitNPROC 等,后续支持再添加 131 } 132 133 impl Unit for ServiceUnit { as_any(&self) -> &dyn core::any::Any134 fn as_any(&self) -> &dyn core::any::Any { 135 self 136 } 137 from_path(path: &str) -> Result<usize, ParseError> where Self: Sized,138 fn from_path(path: &str) -> Result<usize, ParseError> 139 where 140 Self: Sized, 141 { 142 return ServiceParser::parse(path); 143 } 144 set_attr(&mut self, segment: Segment, attr: &str, val: &str) -> Result<(), ParseError>145 fn set_attr(&mut self, segment: Segment, attr: &str, val: &str) -> Result<(), ParseError> { 146 if segment != Segment::Service { 147 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 148 } 149 if let Some(attr_type) = SERVICE_UNIT_ATTR_TABLE.get(attr) { 150 return self.service_part.set_attr(attr_type, val); 151 } 152 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 153 } 154 set_unit_base(&mut self, base: BaseUnit)155 fn set_unit_base(&mut self, base: BaseUnit) { 156 self.unit_base = base; 157 } 158 unit_type(&self) -> super::UnitType159 fn unit_type(&self) -> super::UnitType { 160 return self.unit_base.unit_type; 161 } 162 unit_base(&self) -> &BaseUnit163 fn unit_base(&self) -> &BaseUnit { 164 return &self.unit_base; 165 } 166 unit_id(&self) -> usize167 fn unit_id(&self) -> usize { 168 return self.unit_base.unit_id; 169 } 170 run(&mut self) -> Result<(), RuntimeError>171 fn run(&mut self) -> Result<(), RuntimeError> { 172 self.exec() 173 } 174 unit_base_mut(&mut self) -> &mut BaseUnit175 fn unit_base_mut(&mut self) -> &mut BaseUnit { 176 return &mut self.unit_base; 177 } 178 after_exit(&mut self, exit_status: ExitStatus)179 fn after_exit(&mut self, exit_status: ExitStatus) { 180 ServiceExecutor::after_exit(self, exit_status); 181 } 182 init(&mut self)183 fn init(&mut self) { 184 let part = &mut self.service_part; 185 for cmd in part.exec_reload.iter_mut() { 186 cmd.dir = part.working_directory.to_string(); 187 cmd.envs = part.environment.clone(); 188 } 189 part.exec_start.dir = part.working_directory.to_string(); 190 part.exec_start.envs = part.environment.clone(); 191 for cmd in part.exec_start_pos.iter_mut() { 192 cmd.dir = part.working_directory.to_string(); 193 cmd.envs = part.environment.clone(); 194 } 195 for cmd in part.exec_start_pre.iter_mut() { 196 cmd.dir = part.working_directory.to_string(); 197 cmd.envs = part.environment.clone(); 198 } 199 for cmd in part.exec_stop.iter_mut() { 200 cmd.dir = part.working_directory.to_string(); 201 cmd.envs = part.environment.clone(); 202 } 203 for cmd in part.exec_stop_post.iter_mut() { 204 cmd.dir = part.working_directory.to_string(); 205 cmd.envs = part.environment.clone(); 206 } 207 } 208 as_mut_any(&mut self) -> &mut dyn std::any::Any209 fn as_mut_any(&mut self) -> &mut dyn std::any::Any { 210 self 211 } 212 exit(&mut self)213 fn exit(&mut self) { 214 ServiceExecutor::exit(self); 215 //改变计时器内部状态 216 } 217 restart(&mut self) -> Result<(), RuntimeError>218 fn restart(&mut self) -> Result<(), RuntimeError> { 219 return ServiceExecutor::restart(self); 220 } 221 } 222 223 impl ServiceUnit { unit_base(&self) -> &BaseUnit224 pub fn unit_base(&self) -> &BaseUnit { 225 return &self.unit_base; 226 } 227 service_part(&self) -> &ServicePart228 pub fn service_part(&self) -> &ServicePart { 229 return &self.service_part; 230 } 231 mut_service_part(&mut self) -> &mut ServicePart232 pub fn mut_service_part(&mut self) -> &mut ServicePart { 233 return &mut self.service_part; 234 } 235 exec(&mut self) -> Result<(), RuntimeError>236 fn exec(&mut self) -> Result<(), RuntimeError> { 237 let _ = ServiceExecutor::exec(self); 238 Ok(()) 239 } 240 } 241 242 unsafe impl Sync for ServiceUnit {} 243 244 unsafe impl Send for ServiceUnit {} 245 246 pub enum ServiceUnitAttr { 247 //ServiceExecCommand+ 248 None, 249 //Service段 250 //定义启动时的进程行为 251 Type, 252 // 253 RemainAfterExit, 254 //启动命令 255 ExecStart, 256 //启动当前服务之前执行的命令 257 ExecStartPre, 258 //启动当前服务之后执行的命令 259 ExecStartPos, 260 //重启当前服务时执行的命令 261 ExecReload, 262 //停止当前服务时执行的命令 263 ExecStop, 264 //停止当其服务之后执行的命令 265 ExecStopPost, 266 //自动重启当前服务间隔的秒数 267 RestartSec, 268 //定义何种情况 Systemd 会自动重启当前服务 269 Restart, 270 //启动服务时等待的秒数 271 TimeoutStartSec, 272 //停止服务时的等待秒数,如果超过这个时间仍然没有停止,应该使用 SIGKILL 信号强行杀死服务的进程 273 TimeoutStopSec, 274 //为服务指定环境变量 275 Environment, 276 //指定加载一个包含服务所需的环境变量的列表的文件,文件中的每一行都是一个环境变量的定义 277 EnvironmentFile, 278 //服务的进程优先级,值越小优先级越高,默认为 0。其中 -20 为最高优先级,19 为最低优先级 279 Nice, 280 //指定服务的工作目录 281 WorkingDirectory, 282 //指定服务进程的根目录(/ 目录)。如果配置了这个参数,服务将无法访问指定目录以外的任何文件 283 RootDirectory, 284 //指定运行服务的用户 285 User, 286 //指定运行服务的用户组 287 Group, 288 //服务的 Mount Namespace 配置,会影响进程上下文中挂载点的信息 289 MountFlags, 290 } 291 292 #[allow(dead_code)] 293 impl ServicePart { set_attr(&'_ mut self, attr: &ServiceUnitAttr, val: &str) -> Result<(), ParseError>294 pub fn set_attr(&'_ mut self, attr: &ServiceUnitAttr, val: &str) -> Result<(), ParseError> { 295 match attr { 296 ServiceUnitAttr::Type => match val { 297 "simple" => self.service_type = ServiceType::Simple, 298 "forking" => self.service_type = ServiceType::Forking, 299 "oneshot" => self.service_type = ServiceType::OneShot, 300 "dbus" => self.service_type = ServiceType::Dbus, 301 "notify" => self.service_type = ServiceType::Notify, 302 "idle" => self.service_type = ServiceType::Idle, 303 _ => { 304 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 305 } 306 }, 307 ServiceUnitAttr::RemainAfterExit => { 308 self.remain_after_exit = UnitParseUtil::parse_boolean(val)? 309 } 310 ServiceUnitAttr::ExecStart => { 311 self.exec_start = UnitParseUtil::parse_cmd_task(val)?[0].clone(); 312 } 313 ServiceUnitAttr::ExecStartPre => { 314 self.exec_start_pre 315 .extend(UnitParseUtil::parse_cmd_task(val)?); 316 } 317 ServiceUnitAttr::ExecStartPos => { 318 self.exec_start_pos 319 .extend(UnitParseUtil::parse_cmd_task(val)?); 320 } 321 ServiceUnitAttr::ExecReload => { 322 self.exec_reload.extend(UnitParseUtil::parse_cmd_task(val)?); 323 } 324 ServiceUnitAttr::ExecStopPost => { 325 self.exec_stop_post 326 .extend(UnitParseUtil::parse_cmd_task(val)?); 327 } 328 ServiceUnitAttr::ExecStop => { 329 self.exec_stop.extend(UnitParseUtil::parse_cmd_task(val)?); 330 } 331 ServiceUnitAttr::RestartSec => self.restart_sec = UnitParseUtil::parse_sec(val)?, 332 ServiceUnitAttr::Restart => match val { 333 "always" => self.restart = RestartOption::AlwaysRestart, 334 "on-success" => self.restart = RestartOption::OnSuccess, 335 "on-failure" => self.restart = RestartOption::OnFailure, 336 "on-abnormal" => self.restart = RestartOption::OnAbnormal, 337 "on-abort" => self.restart = RestartOption::OnAbort, 338 "on-watchdog" => self.restart = RestartOption::OnWatchdog, 339 _ => { 340 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 341 } 342 }, 343 ServiceUnitAttr::TimeoutStartSec => { 344 self.timeout_start_sec = UnitParseUtil::parse_sec(val)? 345 } 346 ServiceUnitAttr::TimeoutStopSec => { 347 self.timeout_stop_sec = UnitParseUtil::parse_sec(val)? 348 } 349 ServiceUnitAttr::Environment => { 350 self.environment.push(UnitParseUtil::parse_env(val)?); 351 } 352 ServiceUnitAttr::EnvironmentFile => { 353 if !UnitParseUtil::is_valid_file(val) { 354 return Err(ParseError::new(ParseErrorType::EFILE, String::new(), 0)); 355 } 356 self.environment 357 .extend(UnitParseUtil::parse_environment_file(val)?); 358 } 359 ServiceUnitAttr::Nice => { 360 self.nice = UnitParseUtil::parse_nice(val)?; 361 } 362 ServiceUnitAttr::WorkingDirectory => { 363 if !UnitParseUtil::is_dir(val) { 364 return Err(ParseError::new(ParseErrorType::ENODIR, String::new(), 0)); 365 } 366 self.working_directory = String::from(val); 367 } 368 ServiceUnitAttr::User => { 369 //TODO: 检查系统是否存在这个用户 370 self.user = String::from(val); 371 } 372 ServiceUnitAttr::Group => { 373 //TODO: 检查系统是否存在该用户组 374 self.group = String::from(val); 375 } 376 ServiceUnitAttr::MountFlags => match val { 377 "shared" => self.mount_flags = MountFlag::Shared, 378 "slave" => self.mount_flags = MountFlag::Slave, 379 "private" => self.mount_flags = MountFlag::Private, 380 _ => { 381 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 382 } 383 }, 384 _ => { 385 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 386 } 387 } 388 return Ok(()); 389 } 390 391 // 生命周期相关 service_type(&self) -> &ServiceType392 pub fn service_type(&self) -> &ServiceType { 393 &self.service_type 394 } 395 remain_after_exit(&self) -> bool396 pub fn remain_after_exit(&self) -> bool { 397 self.remain_after_exit 398 } 399 exec_start(&self) -> &CmdTask400 pub fn exec_start(&self) -> &CmdTask { 401 &self.exec_start 402 } 403 exec_start_pre(&self) -> &Vec<CmdTask>404 pub fn exec_start_pre(&self) -> &Vec<CmdTask> { 405 &self.exec_start_pre 406 } 407 exec_start_pos(&self) -> &Vec<CmdTask>408 pub fn exec_start_pos(&self) -> &Vec<CmdTask> { 409 &self.exec_start_pos 410 } 411 exec_reload(&self) -> &Vec<CmdTask>412 pub fn exec_reload(&self) -> &Vec<CmdTask> { 413 &self.exec_reload 414 } 415 exec_stop(&self) -> &Vec<CmdTask>416 pub fn exec_stop(&self) -> &Vec<CmdTask> { 417 &self.exec_stop 418 } 419 exec_stop_post(&mut self) -> &mut Vec<CmdTask>420 pub fn exec_stop_post(&mut self) -> &mut Vec<CmdTask> { 421 &mut self.exec_stop_post 422 } 423 mut_exec_start_pre(&mut self) -> &mut Vec<CmdTask>424 pub fn mut_exec_start_pre(&mut self) -> &mut Vec<CmdTask> { 425 &mut self.exec_start_pre 426 } 427 mut_exec_start_pos(&mut self) -> &mut Vec<CmdTask>428 pub fn mut_exec_start_pos(&mut self) -> &mut Vec<CmdTask> { 429 &mut self.exec_start_pos 430 } 431 mut_exec_reload(&mut self) -> &mut Vec<CmdTask>432 pub fn mut_exec_reload(&mut self) -> &mut Vec<CmdTask> { 433 &mut self.exec_reload 434 } 435 mut_exec_stop(&mut self) -> &mut Vec<CmdTask>436 pub fn mut_exec_stop(&mut self) -> &mut Vec<CmdTask> { 437 &mut self.exec_stop 438 } 439 mut_exec_stop_post(&mut self) -> &mut Vec<CmdTask>440 pub fn mut_exec_stop_post(&mut self) -> &mut Vec<CmdTask> { 441 &mut self.exec_stop_post 442 } 443 restart_sec(&self) -> u64444 pub fn restart_sec(&self) -> u64 { 445 self.restart_sec 446 } 447 restart(&self) -> &RestartOption448 pub fn restart(&self) -> &RestartOption { 449 &self.restart 450 } 451 timeout_start_sec(&self) -> u64452 pub fn timeout_start_sec(&self) -> u64 { 453 self.timeout_start_sec 454 } 455 timeout_stop_sec(&self) -> u64456 pub fn timeout_stop_sec(&self) -> u64 { 457 self.timeout_stop_sec 458 } 459 460 // 上下文配置相关 environment(&self) -> &[(String, String)]461 pub fn environment(&self) -> &[(String, String)] { 462 &self.environment 463 } 464 nice(&self) -> i8465 pub fn nice(&self) -> i8 { 466 self.nice 467 } 468 working_directory(&self) -> &str469 pub fn working_directory(&self) -> &str { 470 &self.working_directory 471 } 472 root_directory(&self) -> &str473 pub fn root_directory(&self) -> &str { 474 &self.root_directory 475 } 476 user(&self) -> &str477 pub fn user(&self) -> &str { 478 &self.user 479 } 480 group(&self) -> &str481 pub fn group(&self) -> &str { 482 &self.group 483 } 484 mount_flags(&self) -> &MountFlag485 pub fn mount_flags(&self) -> &MountFlag { 486 &self.mount_flags 487 } 488 } 489