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