fix: detect systemd unit directory at runtime for cross-distro compatibility#35
fix: detect systemd unit directory at runtime for cross-distro compatibility#35Benoît Cortier (CBenoit) merged 2 commits intomasterfrom
Conversation
…ibility
Fixes installation failure on Rocky Linux 8.4 and other RHEL-based
distributions where systemd units are located in /usr/lib/systemd/system
instead of /lib/systemd/system.
- Add detect_systemd_unit_dir() with three-tier detection:
1. CEVICHE_SYSTEMD_UNITDIR environment variable (takes precedence)
2. pkg-config --variable=systemdsystemunitdir systemd
3. Fallback probing: /lib/systemd/system, then /usr/lib/systemd/system
- Update get_service_unit_path() and get_service_dropin_dir() to use detection
- Add comprehensive documentation in README explaining the approach and caveats
- Include rationale comments about when to use distro-specific tooling
This pragmatic runtime detection works across distributions while still
recommending proper packaging tools (dh_installsystemd, %{_unitdir}) for
production packages.
There was a problem hiding this comment.
Pull Request Overview
This PR adds runtime detection of systemd unit directories to make the library more portable across different Linux distributions, replacing the hardcoded /lib/systemd/system/ path. The version is bumped from 0.6.1 to 0.7.0.
- Implements a three-tier detection strategy: environment variable override, pkg-config query, and fallback probing
- Updates all methods that reference systemd paths to use the new detection function
- Adds comprehensive documentation explaining the approach and its caveats
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/controller/linux.rs | Adds detect_systemd_unit_dir() function with runtime detection logic, updates get_service_unit_path() and get_service_dropin_dir() to return Result<PathBuf, Error>, adjusts callers to handle new error cases |
| README.md | Documents the systemd unit detection strategy, caveats for packagers, and usage instructions for the CEVICHE_SYSTEMD_UNITDIR environment variable |
| Cargo.toml | Bumps version from 0.6.1 to 0.7.0 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fn get_service_dropin_dir(&self) -> Result<PathBuf, Error> { | ||
| let unit_dir = detect_systemd_unit_dir()?; | ||
| Ok(unit_dir.join(format!("{}.d", self.get_service_file_name()))) | ||
| } |
There was a problem hiding this comment.
The detect_systemd_unit_dir() function is called separately in both get_service_unit_path() and get_service_dropin_dir(). When both methods are called (e.g., in write_service_config() and delete()), this results in redundant detection work including potential Command execution and filesystem probing. Consider caching the detected directory in the LinuxController struct or calling the detection once at a higher level.
| Error::new(&format!("Failed to create {}: {}", path.display(), e)) | ||
| })?; | ||
| fs::create_dir(&dropin_dir) | ||
| .map_err(|e| Error::new(&format!("Failed to create {}: {}", path.display(), e)))?; |
There was a problem hiding this comment.
The error message references path.display() but the variable being created is dropin_dir. This will show the wrong path (the config file path instead of the directory path) if directory creation fails. Change to dropin_dir.display().
| .map_err(|e| Error::new(&format!("Failed to create {}: {}", path.display(), e)))?; | |
| .map_err(|e| Error::new(&format!("Failed to create {}: {}", dropin_dir.display(), e)))?; |
Fixes installation failure on Rocky Linux 8.4 and other RHEL-based distributions where systemd units are located in /usr/lib/systemd/system instead of /lib/systemd/system.
This pragmatic runtime detection works across distributions while still recommending proper packaging tools (dh_installsystemd, %{_unitdir}) for production packages.
Prompt
I used Claude Code to generate this fix, and audited it.
Here is the prompt I used: