335 lines
8.3 KiB
Text
335 lines
8.3 KiB
Text
#!/usr/bin/env nu
|
|
# Service management abstraction
|
|
# Provides OS-agnostic service operations (enable, start, stop, status, etc.)
|
|
|
|
use std
|
|
use ./detect.nu as os_detect
|
|
|
|
# Helper: Result type
|
|
def ok [value: any] { {ok: $value, err: null} }
|
|
def err [message: string] { {ok: null, err: $message} }
|
|
def is-ok [result: record] { $result.err == null }
|
|
|
|
# Enable service (start on boot)
|
|
export def enable [service: string] {
|
|
# GUARD: Validate input
|
|
if ($service | is-empty) {
|
|
return (err "service name cannot be empty")
|
|
}
|
|
|
|
let current_os = (os_detect detect)
|
|
|
|
let result = match $current_os {
|
|
"debian" | "ubuntu" => {
|
|
(^systemctl enable $service 2>&1 | complete)
|
|
}
|
|
|
|
"nixos" => {
|
|
err "Use NixOS modules to enable services"
|
|
}
|
|
|
|
"alpine" => {
|
|
(^rc-service $service start 2>&1 | complete)
|
|
}
|
|
|
|
"macos" => {
|
|
(^launchctl load $"/Library/LaunchDaemons/($service).plist" 2>&1 | complete)
|
|
}
|
|
|
|
_ => {
|
|
return (err $"Service enable not supported on ($current_os)")
|
|
}
|
|
}
|
|
|
|
if $result.exit_code == 0 {
|
|
ok $"Service ($service) enabled"
|
|
} else {
|
|
err $"Failed to enable ($service): ($result.stderr)"
|
|
}
|
|
}
|
|
|
|
# Disable service (prevent start on boot)
|
|
export def disable [service: string] {
|
|
# GUARD: Validate input
|
|
if ($service | is-empty) {
|
|
return (err "service name cannot be empty")
|
|
}
|
|
|
|
let current_os = (os_detect detect)
|
|
|
|
let result = match $current_os {
|
|
"debian" | "ubuntu" => {
|
|
(^systemctl disable $service 2>&1 | complete)
|
|
}
|
|
|
|
"nixos" => {
|
|
err "Use NixOS modules to disable services"
|
|
}
|
|
|
|
"alpine" => {
|
|
(^rc-update del $service default 2>&1 | complete)
|
|
}
|
|
|
|
"macos" => {
|
|
(^launchctl unload $"/Library/LaunchDaemons/($service).plist" 2>&1 | complete)
|
|
}
|
|
|
|
_ => {
|
|
return (err $"Service disable not supported on ($current_os)")
|
|
}
|
|
}
|
|
|
|
if $result.exit_code == 0 {
|
|
ok $"Service ($service) disabled"
|
|
} else {
|
|
err $"Failed to disable ($service): ($result.stderr)"
|
|
}
|
|
}
|
|
|
|
# Start service (immediately)
|
|
export def start [service: string] {
|
|
# GUARD: Validate input
|
|
if ($service | is-empty) {
|
|
return (err "service name cannot be empty")
|
|
}
|
|
|
|
let current_os = (os_detect detect)
|
|
|
|
let result = match $current_os {
|
|
"debian" | "ubuntu" => {
|
|
(^systemctl start $service 2>&1 | complete)
|
|
}
|
|
|
|
"nixos" => {
|
|
(^systemctl start $service 2>&1 | complete)
|
|
}
|
|
|
|
"alpine" => {
|
|
(^rc-service $service start 2>&1 | complete)
|
|
}
|
|
|
|
"macos" => {
|
|
(^launchctl start $service 2>&1 | complete)
|
|
}
|
|
|
|
_ => {
|
|
return (err $"Service start not supported on ($current_os)")
|
|
}
|
|
}
|
|
|
|
if $result.exit_code == 0 {
|
|
ok $"Service ($service) started"
|
|
} else {
|
|
err $"Failed to start ($service): ($result.stderr)"
|
|
}
|
|
}
|
|
|
|
# Stop service
|
|
export def stop [service: string] {
|
|
# GUARD: Validate input
|
|
if ($service | is-empty) {
|
|
return (err "service name cannot be empty")
|
|
}
|
|
|
|
let current_os = (os_detect detect)
|
|
|
|
let result = match $current_os {
|
|
"debian" | "ubuntu" => {
|
|
(^systemctl stop $service 2>&1 | complete)
|
|
}
|
|
|
|
"nixos" => {
|
|
(^systemctl stop $service 2>&1 | complete)
|
|
}
|
|
|
|
"alpine" => {
|
|
(^rc-service $service stop 2>&1 | complete)
|
|
}
|
|
|
|
"macos" => {
|
|
(^launchctl stop $service 2>&1 | complete)
|
|
}
|
|
|
|
_ => {
|
|
return (err $"Service stop not supported on ($current_os)")
|
|
}
|
|
}
|
|
|
|
if $result.exit_code == 0 {
|
|
ok $"Service ($service) stopped"
|
|
} else {
|
|
err $"Failed to stop ($service): ($result.stderr)"
|
|
}
|
|
}
|
|
|
|
# Restart service
|
|
export def restart [service: string] {
|
|
# GUARD: Validate input
|
|
if ($service | is-empty) {
|
|
return (err "service name cannot be empty")
|
|
}
|
|
|
|
let current_os = (os_detect detect)
|
|
|
|
let result = match $current_os {
|
|
"debian" | "ubuntu" => {
|
|
(^systemctl restart $service 2>&1 | complete)
|
|
}
|
|
|
|
"nixos" => {
|
|
(^systemctl restart $service 2>&1 | complete)
|
|
}
|
|
|
|
"alpine" => {
|
|
(^rc-service $service restart 2>&1 | complete)
|
|
}
|
|
|
|
"macos" => {
|
|
(^launchctl stop $service 2>&1 | complete)
|
|
(^launchctl start $service 2>&1 | complete)
|
|
}
|
|
|
|
_ => {
|
|
return (err $"Service restart not supported on ($current_os)")
|
|
}
|
|
}
|
|
|
|
if $result.exit_code == 0 {
|
|
ok $"Service ($service) restarted"
|
|
} else {
|
|
err $"Failed to restart ($service): ($result.stderr)"
|
|
}
|
|
}
|
|
|
|
# Get service status
|
|
export def status [service: string] {
|
|
# GUARD: Validate input
|
|
if ($service | is-empty) {
|
|
return (err "service name cannot be empty")
|
|
}
|
|
|
|
let current_os = (os_detect detect)
|
|
|
|
let status_output = match $current_os {
|
|
"debian" | "ubuntu" => {
|
|
let status_result = (^systemctl status $service 2>&1 | complete)
|
|
$status_result.stdout
|
|
}
|
|
|
|
"nixos" => {
|
|
let status_result = (^systemctl status $service 2>&1 | complete)
|
|
$status_result.stdout
|
|
}
|
|
|
|
"alpine" => {
|
|
let status_result = (^rc-service $service status 2>&1 | complete)
|
|
$status_result.stdout
|
|
}
|
|
|
|
"macos" => {
|
|
let status_result = (^launchctl list $service 2>&1 | complete)
|
|
$status_result.stdout
|
|
}
|
|
|
|
_ => {
|
|
return (err $"Service status not supported on ($current_os)")
|
|
}
|
|
}
|
|
|
|
ok ($status_output | str trim)
|
|
}
|
|
|
|
# Check if service is running
|
|
export def is-running [service: string] {
|
|
# GUARD: Validate input
|
|
if ($service | is-empty) {
|
|
return (err "service name cannot be empty")
|
|
}
|
|
|
|
let current_os = (os_detect detect)
|
|
|
|
let is_running = match $current_os {
|
|
"debian" | "ubuntu" => {
|
|
(^systemctl is-active $service 2>&1 | complete).exit_code == 0
|
|
}
|
|
|
|
"nixos" => {
|
|
(^systemctl is-active $service 2>&1 | complete).exit_code == 0
|
|
}
|
|
|
|
"alpine" => {
|
|
(^rc-service $service status 2>&1 | complete).exit_code == 0
|
|
}
|
|
|
|
"macos" => {
|
|
let list_result = (^launchctl list $service 2>&1 | complete)
|
|
$list_result.exit_code == 0
|
|
}
|
|
|
|
_ => {
|
|
return (err $"Service check not supported on ($current_os)")
|
|
}
|
|
}
|
|
|
|
ok $is_running
|
|
}
|
|
|
|
# Reload service configuration (for services that support it)
|
|
export def reload [service: string] {
|
|
# GUARD: Validate input
|
|
if ($service | is-empty) {
|
|
return (err "service name cannot be empty")
|
|
}
|
|
|
|
let current_os = (os_detect detect)
|
|
|
|
let result = match $current_os {
|
|
"debian" | "ubuntu" => {
|
|
(^systemctl reload $service 2>&1 | complete)
|
|
}
|
|
|
|
"nixos" => {
|
|
(^systemctl reload $service 2>&1 | complete)
|
|
}
|
|
|
|
"alpine" => {
|
|
# Alpine doesn't have reload, use restart
|
|
(^rc-service $service restart 2>&1 | complete)
|
|
}
|
|
|
|
"macos" => {
|
|
# macOS doesn't have reload, use restart
|
|
(^launchctl stop $service 2>&1 | complete)
|
|
(^launchctl start $service 2>&1 | complete)
|
|
}
|
|
|
|
_ => {
|
|
return (err $"Service reload not supported on ($current_os)")
|
|
}
|
|
}
|
|
|
|
if $result.exit_code == 0 {
|
|
ok $"Service ($service) reloaded"
|
|
} else {
|
|
err $"Failed to reload ($service): ($result.stderr)"
|
|
}
|
|
}
|
|
|
|
# Main: Show usage
|
|
export def main [] {
|
|
print "Service management abstraction library"
|
|
print ""
|
|
print "Usage:"
|
|
print " svc enable <service>"
|
|
print " svc disable <service>"
|
|
print " svc start <service>"
|
|
print " svc stop <service>"
|
|
print " svc restart <service>"
|
|
print " svc reload <service>"
|
|
print " svc status <service>"
|
|
print " svc is-running <service>"
|
|
print ""
|
|
print "Supported OS: debian, ubuntu, alpine, nixos, macos"
|
|
print ""
|
|
print "Note: NixOS services are defined via configuration.nix, not imperatively"
|
|
}
|