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