Help us shape the future of Go! Take the 2026 Go Developer Survey

service

package
v0.2.28 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: GPL-3.0 Imports: 15 Imported by: 0

Documentation

Overview

Package service runs Ether as an operating-system service: systemd on Linux, launchd on macOS and the Service Control Manager on Windows, via github.com/kardianos/service.

The integrator in cmd/ether wires it roughly like this:

svc, err := service.New(app.Run, service.Options{
    DataDir: config.DefaultDataDir(),
    Logger:  log,
})
if err != nil { return err }
// `ether service install|uninstall|start|stop|restart|status`
if handled, err := service.HandleCommand(os.Args[1:], svc, os.Stdout); handled {
    return err
}
return svc.Run() // blocks; interactive runs also stop on SIGINT/SIGTERM

A nil RunFunc is allowed for control-only use (the tray app): Install, Start, Stop, Restart, Uninstall and Status work, Run returns ErrNoRunner.

Index

Constants

View Source
const ExitCodeRestart = 3

ExitCodeRestart is the process exit code used for ErrRestartRequested.

Variables

View Source
var Commands = []string{"install", "uninstall", "start", "stop", "restart", "status"}

Commands accepted after the "service" subcommand.

View Source
var ErrNoRunner = errors.New("service: no RunFunc configured (control-only service)")

ErrNoRunner is returned by Run on a control-only Service.

View Source
var ErrNotInstalled = ksvc.ErrNotInstalled

ErrNotInstalled reports a status query against an unregistered service.

View Source
var ErrRestartRequested = errors.New("service: restart requested")

ErrRestartRequested is returned by a RunFunc that wants the service manager to start a fresh process (e.g. after a self-update). Under a service manager the process exits with ExitCodeRestart; interactively Run returns it to the caller.

Functions

func HandleCommand

func HandleCommand(args []string, svc *Service, out io.Writer) (handled bool, err error)

HandleCommand implements `ether service <cmd>` for cmd/ether. args is os.Args[1:]. It returns handled=false (and nil error) when args do not start with "service", so the caller can fall through to serving. Usage/help text goes to out; a bare `ether service` prints usage and is handled without error.

func Interactive

func Interactive() bool

Interactive reports whether we are running in a terminal rather than under the service manager.

Types

type Options

type Options struct {
	// Name is the service-manager name. Default "ether".
	Name string
	// DisplayName is shown in service listings. Default "Ether".
	DisplayName string
	// Description for service listings.
	Description string
	// Executable registered with the service manager. Default: os.Executable.
	Executable string
	// Arguments passed to Executable when the service manager starts it.
	// Default: ["serve"] is NOT assumed; empty means no arguments, so the
	// binary's default action must be to serve (or to call Service.Run).
	Arguments []string
	// WorkingDirectory for the service process.
	WorkingDirectory string
	// DataDir, when set, is exported to the service as ETHER_DATA_DIR.
	DataDir string
	// KeepInstalledDataDir makes Install, when the service is already
	// registered, keep the registered ETHER_DATA_DIR instead of DataDir
	// (an upgrade that did not ask for a data directory must not move
	// the owner's). Fresh installs always use DataDir.
	KeepInstalledDataDir bool
	// EnvVars are extra environment variables for the service process.
	EnvVars map[string]string
	// UserName runs the service as this user (systemd/Windows). On Linux
	// packages this is the dedicated "ether" user.
	UserName string
	// UserService installs a per-user service (launchd LaunchAgent /
	// systemd --user semantics where supported) instead of a system one.
	// macOS installs are user services by default (see DefaultOptions).
	UserService bool
	// Dependencies are service-manager dependency lines (systemd [Unit]).
	Dependencies []string
	// StopTimeout bounds how long Stop waits for RunFunc to return before
	// giving up (the process is exiting anyway). Default 30s.
	StopTimeout time.Duration
	Logger      *slog.Logger
}

Options configures the Ether service. Zero values get Ether defaults.

func DefaultOptions

func DefaultOptions() Options

DefaultOptions returns Options for a stock Ether install on this OS.

func (Options) Config

func (o Options) Config() (*ksvc.Config, error)

Config renders Options into the kardianos/service config that will be registered with the OS. Exported for tests and for installer tooling that wants to preview the registration.

type RunFunc

type RunFunc func(ctx context.Context) error

RunFunc is the server body. It must return promptly after ctx is cancelled.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service is Ether's OS-service handle.

func New

func New(run RunFunc, opts Options) (*Service, error)

New builds a Service around run. run may be nil for control-only use.

func (*Service) Config

func (s *Service) Config() *ksvc.Config

Config returns the registration config in effect.

func (*Service) Install

func (s *Service) Install() error

Install registers the service with the OS, or updates an existing registration in place (see InstallOrUpdate). May require elevation.

func (*Service) InstallOrUpdate added in v0.2.20

func (s *Service) InstallOrUpdate() (updated bool, err error)

InstallOrUpdate registers the service or, when it is already registered and the platform supports it (Windows), updates the registration in place instead of deleting and recreating it: binary path, names, start type, restart policy and environment. An update keeps the registered ETHER_DATA_DIR, and leaves that directory's ACL alone, when Options.KeepInstalledDataDir is set. A running service keeps running the old binary until it is restarted. updated reports which path was taken.

func (*Service) Platform

func (s *Service) Platform() string

Platform names the service manager in use (e.g. "linux-systemd").

func (*Service) Restart

func (s *Service) Restart() error

Restart asks the service manager to restart Ether.

func (*Service) Run

func (s *Service) Run() error

Run blocks serving until the service manager stops us or, interactively, until SIGINT/SIGTERM. The RunFunc's context is cancelled on stop and Run returns its error (context cancellation is treated as a clean stop).

Under a service manager, a RunFunc that returns or panics without a stop request terminates the process (ExitCodeRestart for ErrRestartRequested, non-zero otherwise) so the manager's restart policy applies; Run does not return in that case. Interactively the error is returned to the caller.

func (*Service) Start

func (s *Service) Start() error

Start asks the service manager to start Ether.

func (*Service) Status

func (s *Service) Status() (Status, error)

Status reports whether the service is running, stopped, or unknown (not installed / undeterminable).

func (*Service) Stop

func (s *Service) Stop() error

Stop asks the service manager to stop Ether (graceful: the RunFunc context is cancelled in the service process).

func (*Service) Uninstall

func (s *Service) Uninstall() error

Uninstall removes the service registration. May require elevation.

type Status

type Status string

Status is Ether's service status.

const (
	StatusUnknown Status = "unknown"
	StatusRunning Status = "running"
	StatusStopped Status = "stopped"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL