4.6 KiB
4.6 KiB
shepherd-host-linux
Linux host adapter for Shepherd.
Overview
This crate implements the HostAdapter trait for Linux systems, providing:
- Process spawning with process group isolation
- Process termination via graceful (SIGTERM) and forceful (SIGKILL) signals
- Exit observation through async process monitoring
- Snap application support via systemd scope-based management
- stdout/stderr capture to log files
- Volume control with auto-detection of sound systems (PipeWire, PulseAudio, ALSA)
Capabilities
The Linux adapter reports these capabilities:
HostCapabilities {
// Supported entry kinds
spawn_kind_supported: [Process, Snap],
// Enforcement capabilities
can_kill_forcefully: true, // SIGKILL
can_graceful_stop: true, // SIGTERM
can_group_process_tree: true, // Process groups (pgid)
can_observe_exit: true, // async wait
// Optional features (not yet implemented)
can_observe_window_ready: false,
can_force_foreground: false,
can_force_fullscreen: false,
can_lock_to_single_app: false,
}
Usage
Creating the Adapter
use shepherd_host_linux::LinuxHost;
let host = LinuxHost::new();
// Check capabilities
let caps = host.capabilities();
assert!(caps.can_kill_forcefully);
Spawning Processes
use shepherd_host_api::{SpawnOptions, EntryKind};
let entry_kind = EntryKind::Process {
command: "/usr/bin/game".to_string(),
args: vec!["--fullscreen".to_string()],
env: Default::default(),
cwd: None,
};
let options = SpawnOptions {
capture_stdout: true,
capture_stderr: true,
log_path: Some("/var/log/shepherdd/sessions".into()),
fullscreen: false,
foreground: false,
};
let handle = host.spawn(session_id, &entry_kind, options).await?;
Spawning Snap Applications
Snap applications are managed using systemd scopes for proper process tracking:
let entry_kind = EntryKind::Snap {
snap_name: "mc-installer".to_string(),
command: None, // Defaults to snap_name
args: vec![],
env: Default::default(),
};
// Spawns via: snap run mc-installer
// Process group is isolated within a systemd scope
let handle = host.spawn(session_id, &entry_kind, options).await?;
Stopping Sessions
use shepherd_host_api::StopMode;
use std::time::Duration;
// Graceful: SIGTERM, wait 5s, then SIGKILL
host.stop(&handle, StopMode::Graceful {
timeout: Duration::from_secs(5),
}).await?;
// Force: immediate SIGKILL
host.stop(&handle, StopMode::Force).await?;
Monitoring Exits
let mut events = host.subscribe();
tokio::spawn(async move {
while let Some(event) = events.recv().await {
match event {
HostEvent::Exited { handle, status } => {
println!("Session {} exited: {:?}", handle.session_id(), status);
}
_ => {}
}
}
});
Volume Control
The crate includes LinuxVolumeController which auto-detects the available sound system:
use shepherd_host_linux::LinuxVolumeController;
let controller = LinuxVolumeController::new().await?;
// Get current volume (0-100)
let volume = controller.get_volume().await?;
// Set volume with enforcement of configured maximum
controller.set_volume(75).await?;
// Mute/unmute
controller.set_muted(true).await?;
Sound System Detection Order
- PipeWire (
wpctlorpw-cli) - Modern default on Ubuntu 22.04+, Fedora - PulseAudio (
pactl) - Legacy but widely available - ALSA (
amixer) - Fallback for systems without a sound server
Process Group Handling
All spawned processes are placed in their own process group:
// Internally uses setsid() or setpgid()
// This allows killing the entire process tree
When stopping a session:
- SIGTERM is sent to the process group (
-pgid) - After timeout, SIGKILL is sent to the process group
- Orphaned children are cleaned up
Log Capture
stdout and stderr can be captured to session log files:
/var/log/shepherdd/sessions/
├── 2025-01-15-abc123-minecraft.log
├── 2025-01-15-def456-gcompris.log
└── ...
Future Enhancements
Planned features (hooks are designed in):
- cgroups v2 - CPU/memory/IO limits per session
- Namespace isolation - Optional sandboxing
- Sway/Wayland integration - Focus and fullscreen control
- D-Bus monitoring - Window readiness detection
Dependencies
nix- Unix system callstokio- Async runtimetracing- Loggingserde- Serializationshepherd-host-api- Trait definitionsshepherd-api- Entry types