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 mut_unit_base(&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 222 impl ServiceUnit { 223 pub fn unit_base(&self) -> &BaseUnit { 224 return &self.unit_base; 225 } 226 227 pub fn service_part(&self) -> &ServicePart { 228 return &self.service_part; 229 } 230 231 pub fn mut_service_part(&mut self) -> &mut ServicePart { 232 return &mut self.service_part; 233 } 234 235 fn exec(&mut self) -> Result<(), RuntimeError> { 236 ServiceExecutor::exec(self) 237 } 238 } 239 240 unsafe impl Sync for ServiceUnit {} 241 242 unsafe impl Send for ServiceUnit {} 243 244 pub enum ServiceUnitAttr { 245 None, 246 //Service段 247 //定义启动时的进程行为 248 Type, 249 // 250 RemainAfterExit, 251 //启动命令 252 ExecStart, 253 //启动当前服务之前执行的命令 254 ExecStartPre, 255 //启动当前服务之后执行的命令 256 ExecStartPos, 257 //重启当前服务时执行的命令 258 ExecReload, 259 //停止当前服务时执行的命令 260 ExecStop, 261 //停止当其服务之后执行的命令 262 ExecStopPost, 263 //自动重启当前服务间隔的秒数 264 RestartSec, 265 //定义何种情况 Systemd 会自动重启当前服务 266 Restart, 267 //启动服务时等待的秒数 268 TimeoutStartSec, 269 //停止服务时的等待秒数,如果超过这个时间仍然没有停止,应该使用 SIGKILL 信号强行杀死服务的进程 270 TimeoutStopSec, 271 //为服务指定环境变量 272 Environment, 273 //指定加载一个包含服务所需的环境变量的列表的文件,文件中的每一行都是一个环境变量的定义 274 EnvironmentFile, 275 //服务的进程优先级,值越小优先级越高,默认为 0。其中 -20 为最高优先级,19 为最低优先级 276 Nice, 277 //指定服务的工作目录 278 WorkingDirectory, 279 //指定服务进程的根目录(/ 目录)。如果配置了这个参数,服务将无法访问指定目录以外的任何文件 280 RootDirectory, 281 //指定运行服务的用户 282 User, 283 //指定运行服务的用户组 284 Group, 285 //服务的 Mount Namespace 配置,会影响进程上下文中挂载点的信息 286 MountFlags, 287 } 288 289 #[allow(dead_code)] 290 impl ServicePart { 291 pub fn set_attr(&'_ mut self, attr: &ServiceUnitAttr, val: &str) -> Result<(), ParseError> { 292 match attr { 293 ServiceUnitAttr::Type => match val { 294 "simple" => self.service_type = ServiceType::Simple, 295 "forking" => self.service_type = ServiceType::Forking, 296 "oneshot" => self.service_type = ServiceType::OneShot, 297 "dbus" => self.service_type = ServiceType::Dbus, 298 "notify" => self.service_type = ServiceType::Notify, 299 "idle" => self.service_type = ServiceType::Idle, 300 _ => { 301 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 302 } 303 }, 304 ServiceUnitAttr::RemainAfterExit => { 305 self.remain_after_exit = UnitParseUtil::parse_boolean(val)? 306 } 307 ServiceUnitAttr::ExecStart => { 308 self.exec_start = UnitParseUtil::parse_cmd_task(val)?[0].clone(); 309 } 310 ServiceUnitAttr::ExecStartPre => { 311 self.exec_start_pre 312 .extend(UnitParseUtil::parse_cmd_task(val)?); 313 } 314 ServiceUnitAttr::ExecStartPos => { 315 self.exec_start_pos 316 .extend(UnitParseUtil::parse_cmd_task(val)?); 317 } 318 ServiceUnitAttr::ExecReload => { 319 self.exec_reload.extend(UnitParseUtil::parse_cmd_task(val)?); 320 } 321 ServiceUnitAttr::ExecStopPost => { 322 self.exec_stop_post 323 .extend(UnitParseUtil::parse_cmd_task(val)?); 324 } 325 ServiceUnitAttr::ExecStop => { 326 self.exec_stop.extend(UnitParseUtil::parse_cmd_task(val)?); 327 } 328 ServiceUnitAttr::RestartSec => self.restart_sec = UnitParseUtil::parse_sec(val)?, 329 ServiceUnitAttr::Restart => match val { 330 "always" => self.restart = RestartOption::AlwaysRestart, 331 "on-success" => self.restart = RestartOption::OnSuccess, 332 "on-failure" => self.restart = RestartOption::OnFailure, 333 "on-abnormal" => self.restart = RestartOption::OnAbnormal, 334 "on-abort" => self.restart = RestartOption::OnAbort, 335 "on-watchdog" => self.restart = RestartOption::OnWatchdog, 336 _ => { 337 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 338 } 339 }, 340 ServiceUnitAttr::TimeoutStartSec => { 341 self.timeout_start_sec = UnitParseUtil::parse_sec(val)? 342 } 343 ServiceUnitAttr::TimeoutStopSec => { 344 self.timeout_stop_sec = UnitParseUtil::parse_sec(val)? 345 } 346 ServiceUnitAttr::Environment => { 347 self.environment.push(UnitParseUtil::parse_env(val)?); 348 } 349 ServiceUnitAttr::EnvironmentFile => { 350 if !UnitParseUtil::is_valid_file(val) { 351 return Err(ParseError::new(ParseErrorType::EFILE, String::new(), 0)); 352 } 353 self.environment 354 .extend(UnitParseUtil::parse_environment_file(val)?); 355 } 356 ServiceUnitAttr::Nice => { 357 self.nice = UnitParseUtil::parse_nice(val)?; 358 } 359 ServiceUnitAttr::WorkingDirectory => { 360 if !UnitParseUtil::is_dir(val) { 361 return Err(ParseError::new(ParseErrorType::ENODIR, String::new(), 0)); 362 } 363 self.working_directory = String::from(val); 364 } 365 ServiceUnitAttr::User => { 366 //TODO: 检查系统是否存在这个用户 367 self.user = String::from(val); 368 } 369 ServiceUnitAttr::Group => { 370 //TODO: 检查系统是否存在该用户组 371 self.group = String::from(val); 372 } 373 ServiceUnitAttr::MountFlags => match val { 374 "shared" => self.mount_flags = MountFlag::Shared, 375 "slave" => self.mount_flags = MountFlag::Slave, 376 "private" => self.mount_flags = MountFlag::Private, 377 _ => { 378 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 379 } 380 }, 381 _ => { 382 return Err(ParseError::new(ParseErrorType::EINVAL, String::new(), 0)); 383 } 384 } 385 return Ok(()); 386 } 387 388 // 生命周期相关 389 pub fn service_type(&self) -> &ServiceType { 390 &self.service_type 391 } 392 393 pub fn remain_after_exit(&self) -> bool { 394 self.remain_after_exit 395 } 396 397 pub fn exec_start(&self) -> &CmdTask { 398 &self.exec_start 399 } 400 401 pub fn exec_start_pre(&self) -> &Vec<CmdTask> { 402 &self.exec_start_pre 403 } 404 405 pub fn exec_start_pos(&self) -> &Vec<CmdTask> { 406 &self.exec_start_pos 407 } 408 409 pub fn exec_reload(&self) -> &Vec<CmdTask> { 410 &self.exec_reload 411 } 412 413 pub fn exec_stop(&self) -> &Vec<CmdTask> { 414 &self.exec_stop 415 } 416 417 pub fn exec_stop_post(&mut self) -> &mut Vec<CmdTask> { 418 &mut self.exec_stop_post 419 } 420 421 pub fn mut_exec_start_pre(&mut self) -> &mut Vec<CmdTask> { 422 &mut self.exec_start_pre 423 } 424 425 pub fn mut_exec_start_pos(&mut self) -> &mut Vec<CmdTask> { 426 &mut self.exec_start_pos 427 } 428 429 pub fn mut_exec_reload(&mut self) -> &mut Vec<CmdTask> { 430 &mut self.exec_reload 431 } 432 433 pub fn mut_exec_stop(&mut self) -> &mut Vec<CmdTask> { 434 &mut self.exec_stop 435 } 436 437 pub fn mut_exec_stop_post(&mut self) -> &mut Vec<CmdTask> { 438 &mut self.exec_stop_post 439 } 440 441 pub fn restart_sec(&self) -> u64 { 442 self.restart_sec 443 } 444 445 pub fn restart(&self) -> &RestartOption { 446 &self.restart 447 } 448 449 pub fn timeout_start_sec(&self) -> u64 { 450 self.timeout_start_sec 451 } 452 453 pub fn timeout_stop_sec(&self) -> u64 { 454 self.timeout_stop_sec 455 } 456 457 // 上下文配置相关 458 pub fn environment(&self) -> &[(String, String)] { 459 &self.environment 460 } 461 462 pub fn nice(&self) -> i8 { 463 self.nice 464 } 465 466 pub fn working_directory(&self) -> &str { 467 &self.working_directory 468 } 469 470 pub fn root_directory(&self) -> &str { 471 &self.root_directory 472 } 473 474 pub fn user(&self) -> &str { 475 &self.user 476 } 477 478 pub fn group(&self) -> &str { 479 &self.group 480 } 481 482 pub fn mount_flags(&self) -> &MountFlag { 483 &self.mount_flags 484 } 485 } 486