-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support runit #1
Comments
If you don't mind following LFS-jr, the KISS Linux installation guide will take up an afternoon and leave you with a functioning system that uses runit. After that, the service management documentation will tell you how I'm not entirely sure how coupled Runit and |
It looks like Void Linux uses runit as the official system and it has a docker container, so maybe it could be plugged into a github action. https://docs.voidlinux.org/config/services/index.html
The checks today are fairly naive, not actually determining which system is being used, only that they're available. For my purposes, if there are multiple systems installed, I would require the user to specify which they want to use. |
This isn't in control of the developer so I think you should just improve your checks. Say hello to Bedrock Linux which makes multiple distros run on the same computer at the same time! You might have systemctl installed but be using Runit anyway. Hell, you might have |
I'm certainly sympathetic to the desire to avoid scope creep and retain the constraint that, if multiple service managers are installed, the user must specify which. I don't intend to add pressure here. However, should LoganDark's request be heeded, I think it worth noting that most Linux systems with multiple service managers installed (including Bedrock Linux) have one which is privileged as the "main" one for the given session. At least for most inits on most Linux systems,I don't think detecting this and defaulting to it would be terribly difficult. Tedious to implement and test for every supported service manager, maybe, but not difficult. Typically a Linux system is initialized by a service manager with PID 1. Information about this process can be queried via the The main exception is OpenRC, at least as I'm familiar with it on Gentoo systems. PID 1 is actually a SysV binary (just named With regards to Bedrock Linux's need for this functionality, I think there's a few things to note:
|
My main concern is the question of "who is the user here?". Certainly the developer using this library shouldn't choose which service manager to use, unless they know for sure. So this would be the user running the end application, all the way down, where actually specifying is difficult. How will the library get their input? Check for an environment variable and abort the process if it's not present? What will downstream crates think of that? Maybe shift the responsibility of asking for input onto the developer? That would be mildly inconvenient for everyone. I think an auto-detection mechanism is legitimately the easiest method that provides the greatest ROI, not just for this library, but for all its downstream consumers (users and developers alike). |
Thanks @paradigm and @LoganDark for all of the wonderful feedback and insight! I really value this kind of stuff, and it's already highlighted an area (
No pressure added! I have no qualms about supporting a more indepth attempt at determining the active manager :) I just lack the knowledge in many of these platforms to implement that myself. For the moment, this library does the minimum I need for my primary project of distant, but I can revisit this later or more than happy to accept a contribution for this.
Good to know! I'd seen in passing the PID 1 requirement for Linux service managers when I was setting up some of the CI testing, but didn't give it much thought. In the past, I've used the sysinfo crate to retrieve process information, so maybe I can use it to query for more information.
By default, you'll need elevated permissions to be able to write any of the files or execute commands. I've seen this when using my CLI to install services, start them, etc.
If you're using user-level installation and access, then you don't need an escalation. With systemd, this is I think it's out of scope to request elevated privileges through the library, but there are crates like deelevate on Windows and sudo on Unix systems.
For my usecase, the user I'm referring to is the user of my CLI. So from that perspective, it goes library -> cli -> end user where end user has the option to select an alternative service manager from the default by providing a CLI parameter or config file setting. I recognize that this isn't something that every Rust developer is going to do, so auto-detection would be a nice to have. Not ruling it out, but I don't have the depth of knowledge on the Linux/Unix side to do this over the span of a couple of days! 😄 Would love help here if you're interested in offer ❤️ |
You won't have access to this from a Rust library. You don't do argument or config file parsing. So this won't work. You'd need to get the developer to add integration manually, which is annoying for them :( |
Happy to help :)
While you could certainly use a specialized crate that provides the information if need be, you probably don't need one here if you're familiar with basic filesystem operations like reading files or the difference between a file name and a file path.
I'm swamped with other projects and won't have time to actually submit something polished, but hopefully this is enough to get you started: enum ServiceManager {
Systemd,
Runit,
OpenRC,
}
impl std::str::FromStr for ServiceManager {
type Err = std::io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"systemd" => Ok(ServiceManager::Systemd),
"runit" => Ok(ServiceManager::Runit),
"init" => Ok(ServiceManager::OpenRC), // or possibly SysV
_ => todo!(), // unrecognized init error
}
}
}
// Requires root
fn init_from_exe() -> ServiceManager {
// path to init binary, e.g. `/sbin/init`
let exe_path = std::fs::read_link("/proc/1/exe").unwrap();
// init binary filename, e.g. `init`
let exe_filename = exe_path.file_name().unwrap();
exe_filename.to_str().unwrap().parse().unwrap()
}
// Does not require, maybe less reliable than init_from_exe?
fn init_from_cmd() -> ServiceManager {
// Full command line with arguments, e.g. `/sbin/init foo bar baz`
let cmd_line = std::fs::read_to_string("/proc/1/cmd").unwrap();
// The command itself without args, e.g. `/sbin/init`
let cmd_path = cmd_line.split('\0').next().unwrap();
// The command's filename, e.g. `init`
let cmd_filename = cmd_path.rsplit('/').next().unwrap();
cmd_filename.parse().unwrap()
} |
In KISS Linux, |
I may need to walk back my initial assertion that reliably auto-detecting the main service manager would be trivial. I think my relatively simple proposal stands for many distros, including most systemd distros and some runit distros, but not all. |
I didn't think this was still used since wikipedia mentions the last stable release was in 2014, but was mentioned that it's used on busybox systems. Would need to see if we could get a test environment for this one.
The text was updated successfully, but these errors were encountered: