Documentation
¶
Overview ¶
Package daemon implements background-process lifecycle for wick: Start/Stop/Restart/Status with a PID file. Targets headless environments where the system tray is not usable (Termux, SSH sessions, Linux servers).
The daemon re-execs the same binary with the existing `all` subcommand (server + worker in one process), detached from the caller's terminal so the parent shell can exit without killing it. Output goes to a log file alongside the PID file so users can tail it after start.
Index ¶
- Variables
- func InstallService(p Paths, appName string) error
- func ReadPID(p Paths) (int, time.Time, error)
- func Restart(p Paths, timeout time.Duration, args []string) (int, error)
- func SelfRegister(p Paths, src Source) error
- func ServiceActive(appName string) bool
- func ServiceCtl(appName, verb string) error
- func ServiceManaged(appName string) bool
- func Start(p Paths, args []string) (int, error)
- func Stop(p Paths, timeout time.Duration) error
- func TailLog(p Paths, n int64, w io.Writer) error
- func UninstallService(p Paths, appName string) error
- func WriteSource(p Paths, src Source)
- type Paths
- type ServiceState
- type Source
- type Status
Constants ¶
This section is empty.
Variables ¶
var ErrAlreadyRunning = errors.New("daemon already running")
ErrAlreadyRunning signals Start was called while a live daemon was already recorded in the PID file.
var ErrNotInstalled = errors.New("service not installed")
ErrNotInstalled signals UninstallService was called when no service integration was found.
var ErrNotRunning = errors.New("daemon not running")
ErrNotRunning signals Stop was called with no live daemon recorded.
Functions ¶
func InstallService ¶
InstallService registers the binary to launch at user login / boot. Routing depends on the runtime environment:
GUI present (Win / Mac / desktop Linux) → forwards to the same internal/autostart entry the tray uses AND flips userconfig.AutoStartApp=true so the tray's `Auto-start app at login` checkbox stays in sync with what the CLI did. Headless (Termux, Linux server / RPi) → writes a daemon-style auto-start unit (systemd-user or Termux:Boot script) that runs `<exe> all` directly.
Re-running install over an existing install is safe — the GUI path rewrites the autostart entry, the headless path rewrites the unit.
func ReadPID ¶ added in v0.16.13
ReadPID returns the PID recorded in p.PIDFile plus the file mtime (best-effort start time). Exported for the systemd jalur in `status`, where Check() can't be used — the systemd-spawned process self-writes run.pid but no `start` parent verified it. os.ErrNotExist is returned verbatim when the file is absent.
func Restart ¶
Restart stops the running daemon (if any) then starts a fresh instance with the supplied argv tail.
func SelfRegister ¶ added in v0.16.13
SelfRegister writes the running process's own PID + source to the daemon files. Called from `<app> all` on boot so the PID file is accurate no matter who spawned the process — systemd, the daemon parent, or a direct foreground run. Idempotent across restarts.
func ServiceActive ¶ added in v0.16.13
ServiceActive reports whether systemctl considers the unit active (running). Best-effort; used by `status` for the systemd jalur.
func ServiceCtl ¶ added in v0.16.13
ServiceCtl runs `systemctl --user <verb> <app>.service` and returns the combined error. verb is start | stop | restart. Intentional stop/restart here means systemd does NOT treat the exit as a failure, so Restart=on-failure won't respawn behind our back.
func ServiceManaged ¶ added in v0.16.13
ServiceManaged reports whether a systemd-user unit for appName is installed AND enabled — i.e. systemd is the authority for this app's lifecycle, so start/stop/restart must delegate to systemctl rather than spawn a second PID-file daemon. False on Termux (no systemd) and when the unit file is absent.
func Start ¶
Start spawns the binary with the supplied subcommand detached from the caller's terminal, redirecting stdout+stderr to the daemon log file. Returns ErrAlreadyRunning if a live daemon is already recorded in the PID file.
args is the full argv tail passed to the spawned binary — callers choose between "all" (headless server + worker, default daemon mode) and "tray" (interactive tray icon on GUI hosts).
func Stop ¶
Stop sends SIGTERM (or the OS equivalent) to the running daemon and waits up to timeout for it to exit. Falls back to a force kill if the process is still alive at the deadline. ErrNotRunning is returned if no live daemon was recorded.
func TailLog ¶
TailLog copies the last n bytes of the daemon log to w. Convenience for `status` output. Returns nil if the log doesn't exist yet.
func UninstallService ¶
UninstallService removes whichever auto-start mechanism is in place. ErrNotInstalled is returned if nothing was registered. On the GUI path it also flips userconfig.AutoStartApp=false so the tray's checkbox follows the CLI.
func WriteSource ¶ added in v0.16.13
WriteSource records the spawn Source next to run.pid. Best-effort — a failure here only degrades `status` reporting, never blocks boot.
Types ¶
type Paths ¶
type Paths struct {
Dir string // ~/.<appname>/
PIDFile string // run.pid
LogFile string // daemon.log
ExePath string // resolved path to the currently running binary
}
Paths bundles the per-app filesystem locations used by the daemon.
func ResolvePaths ¶
ResolvePaths returns the canonical daemon paths for an app. The directory is created if missing.
type ServiceState ¶
type ServiceState struct {
Installed bool // unit / script / login-item is registered with the OS
Active bool // best-effort runtime check; not always supported
Path string // canonical location of the registration
Backend string // "autostart-gui", "systemd-user", "termux-boot", "headless-unsupported"
Note string // free-form hint shown in `service status`
}
ServiceState describes whether per-OS auto-start integration is installed and (where the platform exposes it) whether the service is currently active.
func ServiceStatus ¶
func ServiceStatus(p Paths, appName string) (ServiceState, error)
ServiceStatus reports the registration state for whichever backend applies to the current host. On GUI hosts Installed/Active reflects the actual OS entry (what fires at login); a separate note flags when userconfig.AutoStartApp disagrees so the user can spot drift.
type Source ¶ added in v0.16.13
type Source string
Source labels the spawn origin of a running daemon, recorded in the run.source file next to run.pid so `status` can report it without guessing.
func DetectSource ¶ added in v0.16.13
func DetectSource() Source
DetectSource inspects the current process environment to decide how it was spawned. systemd injects INVOCATION_ID into every unit it starts, which is the most reliable signal that systemd owns this process. The caller (`<app> all`) records the result so later `status`/`stop` calls know the supervisor without re-deriving it from a different process.
func ReadSource ¶ added in v0.16.13
ReadSource returns the recorded spawn Source, or SourceUnknown when the file is missing / unreadable.