Skip to main content

crabtalk_command/service/
linux.rs

1//! Linux systemd service management.
2
3use anyhow::Result;
4use wcore::paths::LOGS_DIR;
5
6/// Embedded systemd service template.
7pub const TEMPLATE: &str = include_str!("systemd.service");
8
9/// Check if a systemd service is installed.
10pub fn is_installed(label: &str) -> bool {
11    dirs::home_dir()
12        .map(|h| {
13            h.join(format!(".config/systemd/user/{label}.service"))
14                .exists()
15        })
16        .unwrap_or(false)
17}
18
19/// Install a systemd service.
20pub fn install(rendered: &str, label: &str) -> Result<()> {
21    let unit_name = format!("{label}.service");
22
23    let unit_dir = dirs::home_dir()
24        .ok_or_else(|| anyhow::anyhow!("cannot determine home directory"))?
25        .join(".config/systemd/user");
26    std::fs::create_dir_all(&unit_dir)?;
27    std::fs::create_dir_all(&*LOGS_DIR)?;
28
29    let unit_path = unit_dir.join(&unit_name);
30    std::fs::write(&unit_path, rendered)?;
31    println!("wrote {}", unit_path.display());
32
33    let status = std::process::Command::new("systemctl")
34        .args(["--user", "enable", "--now", &unit_name])
35        .status()?;
36    if status.success() {
37        println!("service enabled and started");
38    } else {
39        anyhow::bail!("systemctl enable failed (exit {})", status);
40    }
41    Ok(())
42}
43
44/// Uninstall a systemd service.
45pub fn uninstall(label: &str) -> Result<()> {
46    let unit_name = format!("{label}.service");
47
48    let unit_path = dirs::home_dir()
49        .ok_or_else(|| anyhow::anyhow!("cannot determine home directory"))?
50        .join(".config/systemd/user")
51        .join(&unit_name);
52
53    if !unit_path.exists() {
54        anyhow::bail!("service not installed ({})", unit_path.display());
55    }
56
57    let status = std::process::Command::new("systemctl")
58        .args(["--user", "disable", "--now", &unit_name])
59        .status()?;
60    if !status.success() {
61        eprintln!("warning: systemctl disable exited with {}", status);
62    }
63
64    std::fs::remove_file(&unit_path)?;
65    println!("service uninstalled");
66    Ok(())
67}