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