From 8d6017d799eb4389d1b3677f78c4879b47b7d5ad Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 11 Apr 2026 16:06:34 +0200 Subject: [PATCH] init: Make spawning for legacy scripts self-contained --- init/src/scheduler.rs | 20 +--------- init/src/script.rs | 89 +++++++++++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 44 deletions(-) diff --git a/init/src/scheduler.rs b/init/src/scheduler.rs index 670a552620..d42a4e5700 100644 --- a/init/src/scheduler.rs +++ b/init/src/scheduler.rs @@ -1,7 +1,6 @@ use std::collections::VecDeque; use crate::InitConfig; -use crate::script::Command; use crate::unit::{Unit, UnitId, UnitKind, UnitStore}; pub struct Scheduler { @@ -88,7 +87,7 @@ fn run(unit: &mut Unit, config: &mut InitConfig) { if config.log_debug { eprintln!("init: running: {cmd:?}"); } - run_command(cmd, config); + cmd.run(config); } } UnitKind::Service { service } => { @@ -115,20 +114,3 @@ fn run(unit: &mut Unit, config: &mut InitConfig) { } } } - -fn run_command(cmd: Command, config: &mut InitConfig) { - match cmd { - Command::Service(service) => { - if config.skip_cmd.contains(&service.cmd) { - eprintln!( - "init: skipping '{} {}'", - service.cmd, - service.args.join(" ") - ); - return; - } - - service.spawn(&config.envs); - } - } -} diff --git a/init/src/script.rs b/init/src/script.rs index 7db1f2ae38..d18e3a045b 100644 --- a/init/src/script.rs +++ b/init/src/script.rs @@ -1,7 +1,7 @@ -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use std::{env, io, iter}; -use crate::service::{Service, ServiceType}; +use crate::InitConfig; use crate::unit::UnitId; pub fn subst_env<'a>(arg: &str) -> String { @@ -39,8 +39,15 @@ impl Script { } #[derive(Clone, Debug)] -pub enum Command { - Service(Service), +pub struct Command { + process: Process, + kind: CommandKind, +} + +#[derive(Clone, Debug)] +enum CommandKind { + Oneshot, + OneshotAsync, } impl Command { @@ -59,35 +66,67 @@ impl Command { } "nowait" => { let process = Process::parse(args)?; - - Ok(Some(Command::Service(Service { - cmd: process.cmd, - args: process.args, - envs: process.envs, - inherit_envs: BTreeSet::new(), - type_: ServiceType::OneshotAsync, - }))) + Ok(Some(Command { + process, + kind: CommandKind::OneshotAsync, + })) } _ => { let process = Process::parse(iter::once(cmd).chain(args))?; - - Ok(Some(Command::Service(Service { - cmd: process.cmd, - args: process.args, - envs: process.envs, - inherit_envs: BTreeSet::new(), - type_: ServiceType::Oneshot, - }))) + Ok(Some(Command { + process, + kind: CommandKind::Oneshot, + })) } } } + + pub fn run(&self, config: &mut InitConfig) { + let Command { process, kind } = self; + + if config.skip_cmd.contains(&process.cmd) { + eprintln!( + "init: skipping '{} {}'", + process.cmd, + process.args.join(" ") + ); + return; + } + + let mut command = std::process::Command::new(&process.cmd); + command.args(process.args.iter().map(|arg| subst_env(arg))); + command.env_clear(); + command.envs(&config.envs).envs(&process.envs); + + let mut child = match command.spawn() { + Ok(child) => child, + Err(err) => { + eprintln!("init: failed to execute {:?}: {}", command, err); + return; + } + }; + + match kind { + CommandKind::Oneshot => match child.wait() { + Ok(exit_status) => { + if !exit_status.success() { + eprintln!("init: {command:?} failed with {exit_status}"); + } + } + Err(err) => { + eprintln!("init: failed to wait for {:?}: {}", command, err) + } + }, + CommandKind::OneshotAsync => {} + } + } } -#[derive(Debug)] -pub struct Process { - pub cmd: String, - pub args: Vec, - pub envs: BTreeMap, +#[derive(Clone, Debug)] +struct Process { + cmd: String, + args: Vec, + envs: BTreeMap, } impl Process {