MCPcopy Index your code
hub / github.com/chipsenkbeil/service-manager-rs

github.com/chipsenkbeil/service-manager-rs @v0.11.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.11.0 ↗ · + Follow
234 symbols 434 edges 14 files 46 documented · 20%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Service Manager

Crates.io Docs CI

Rust library that provides an interface towards working with the following service management platforms:

Requires Rust 1.58.1 or higher!

Installation

Add the following to your Cargo.toml:

[dependencies]
service-manager = "0.10"

Examples

Generic service management

This crate provides a mechanism to detect and use the default service management platform of the current operating system. Each ServiceManager instance provides four key methods:

  • install - will install the service specified by a given context
  • uninstall - will uninstall the service specified by a given context
  • start - will start an installed service specified by a given context
  • stop - will stop a running service specified by a given context

```rust,no_run use service_manager::*; use std::ffi::OsString; use std::path::PathBuf;

// Create a label for our service let label: ServiceLabel = "com.example.my-service".parse().unwrap();

// Get generic service by detecting what is available on the platform let manager = ::native() .expect("Failed to detect management platform");

// Install our service using the underlying service management platform manager.install(ServiceInstallCtx { label: label.clone(), program: PathBuf::from("path/to/my-service-executable"), args: vec![OsString::from("--some-arg")], contents: None, // Optional String for system-specific service content. username: None, // Optional String for alternative user to run service. working_directory: None, // Optional String for the working directory for the service process. environment: None, // Optional list of environment variables to supply the service process. autostart: true, // Specify whether the service should automatically start upon OS reboot. restart_policy: RestartPolicy::default(), // Restart on failure by default. }).expect("Failed to install");

// Start our service using the underlying service management platform manager.start(ServiceStartCtx { label: label.clone() }).expect("Failed to start");

// Stop our service using the underlying service management platform manager.stop(ServiceStopCtx { label: label.clone() }).expect("Failed to stop");

// Uninstall our service using the underlying service management platform manager.uninstall(ServiceUninstallCtx { label: label.clone() }).expect("Failed to stop");


### User-level service management

By default, service management platforms will interact with system-level
services; however, some service management platforms like `systemd` and
`launchd` support user-level services. To interact with services at the
user level, you configure your manager using the generic
`ServiceManager::set_level` function.

```rust,no_run
use service_manager::*;

// Create a label for our service
let label: ServiceLabel = "com.example.my-service".parse().unwrap();

// Get generic service by detecting what is available on the platform
let mut manager = <dyn ServiceManager>::native()
    .expect("Failed to detect management platform");

// Update our manager to work with user-level services
manager.set_level(ServiceLevel::User)
    .expect("Service manager does not support user-level services");

// Continue operating as usual via install/uninstall/start/stop
// ...

Specific service manager configurations

There are times where you need more control over the configuration of a service tied to a specific platform. To that end, you can create the service manager explicitly and set configuration properties appropriately.

```rust,no_run use service_manager::*; use std::ffi::OsString; use std::path::PathBuf;

// Create a label for our service let label: ServiceLabel = "com.example.my-service".parse().unwrap();

// Instantiate a specific service manager let mut manager = LaunchdServiceManager::system();

// Update an install configuration property where installing a service // will NOT add the KeepAlive flag manager.config.install.keep_alive = Some(false);

// Install our service using the explicit service manager manager.install(ServiceInstallCtx { label: label.clone(), program: PathBuf::from("path/to/my-service-executable"), args: vec![OsString::from("--some-arg")], contents: None, // Optional String for system-specific service content. username: None, // Optional String for alternative user to run service. working_directory: None, // Optional String for the working directory for the service process. environment: None, // Optional list of environment variables to supply the service process. autostart: true, // Specify whether the service should automatically start upon OS reboot. restart_policy: RestartPolicy::default(), // Restart on failure by default. }).expect("Failed to install");


### Configuring restart policies

The crate provides a cross-platform `RestartPolicy` enum that allows you to control
when and how services should be restarted. Different platforms support different levels
of granularity, and the implementation will use the closest approximation when an exact
match isn't available.

If you need options specific to any given service manager, you should use that specific
service manager rather than the generic `ServiceManager` crate.

```rust,no_run
use service_manager::*;
use std::ffi::OsString;
use std::path::PathBuf;

let label: ServiceLabel = "com.example.my-service".parse().unwrap();
let manager = <dyn ServiceManager>::native()
    .expect("Failed to detect management platform");

// Example 1: Never restart the service
manager.install(ServiceInstallCtx {
    label: label.clone(),
    program: PathBuf::from("path/to/my-service-executable"),
    args: vec![OsString::from("--some-arg")],
    contents: None,
    username: None,
    working_directory: None,
    environment: None,
    autostart: true,
    restart_policy: RestartPolicy::Never,
}).expect("Failed to install");

// Example 2: Always restart regardless of exit status
manager.install(ServiceInstallCtx {
    label: label.clone(),
    program: PathBuf::from("path/to/my-service-executable"),
    args: vec![OsString::from("--some-arg")],
    contents: None,
    username: None,
    working_directory: None,
    environment: None,
    autostart: true,
    restart_policy: RestartPolicy::Always { delay_secs: Some(10) },
}).expect("Failed to install");

// Example 3: Restart only on failure (non-zero exit)
manager.install(ServiceInstallCtx {
    label: label.clone(),
    program: PathBuf::from("path/to/my-service-executable"),
    args: vec![OsString::from("--some-arg")],
    contents: None,
    username: None,
    working_directory: None,
    environment: None,
    autostart: true,
    restart_policy: RestartPolicy::OnFailure {
        delay_secs: Some(5),
        max_retries: Some(3),
        reset_after_secs: Some(3600),
    },
}).expect("Failed to install");

Platform support: - systemd (Linux): Supports all restart policies natively - launchd (macOS): Only supports Never vs Always/OnFailure (uses KeepAlive boolean) - WinSW (Windows): Supports all restart policies - OpenRC/rc.d/sc.exe: Limited or no restart support; warnings logged for unsupported policies

Running tests

For testing purposes, we use a separate crate called system-tests and execute singular tests based on desired platform and level. From the root of the repository, execute the following to run a systemd user test:

cargo test -p system-tests systemd_for_user -- --nocapture

Separately, run a systemd system test using the following (notice using of sudo -E to maintain permissions needed for system-level installation):

sudo -E cargo test -p system-tests systemd_for_system -- --nocapture

License

This project is licensed under either of

Apache License, Version 2.0, (LICENSE-APACHE or apache-license) MIT license (LICENSE-MIT or mit-license) at your option.

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Method 117
Function 76
Class 27
Enum 13
Interface 1

Languages

Rust100%

Modules by API surface

src/winsw.rs41 symbols
src/lib.rs26 symbols
src/systemd.rs23 symbols
src/launchd.rs22 symbols
src/typed.rs20 symbols
src/sc.rs20 symbols
system-tests/src/main.rs17 symbols
src/rcd.rs16 symbols
src/openrc.rs16 symbols
system-tests/tests/lib.rs13 symbols
system-tests/tests/runner.rs8 symbols
src/sc/shell_escape.rs7 symbols

For agents

$ claude mcp add service-manager-rs \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page