Documentation
¶
Overview ¶
Package runit provides a native Go library for controlling runit services without shelling out to the sv command.
The core functionality centers around the Client type, which provides direct control and status operations for a single runit service:
client, err := runit.New("/etc/service/myapp")
if err != nil {
log.Fatal(err)
}
// Start the service
err = client.Up(context.Background())
// Get status
status, err := client.Status(context.Background())
fmt.Printf("Service state: %v, PID: %d\n", status.State, status.PID)
Manager for Bulk Operations ¶
The Manager type is provided as a convenience for applications that need to control multiple services concurrently. It's particularly useful for:
- System initialization/shutdown sequences
- Health monitoring dashboards
- Service orchestration tools
- Testing frameworks that manage multiple services
If your application already has its own concurrency framework or only manages single services, you may not need the Manager. It's designed to be optional - the Client type provides all core functionality.
manager := runit.NewManager(
runit.WithConcurrency(5),
runit.WithTimeout(10 * time.Second),
)
// Start multiple services concurrently
err = manager.Up(ctx, "/etc/service/web", "/etc/service/db", "/etc/service/cache")
Design Philosophy ¶
This library prioritizes:
- Zero external process spawning (no exec of sv/runsv)
- Direct communication with supervise control/status endpoints
- Zero allocations on hot paths (status decode, state strings)
- Context-aware operations with proper timeouts
- Type safety (no string-based operation codes)
The Manager is included because many runit deployments involve coordinating multiple services, and having a tested, concurrent implementation prevents users from reimplementing the same patterns. However, it remains optional - all its functionality can be replicated using Client instances directly.
Index ¶
- Constants
- Variables
- type ChpstBuilder
- type Client
- func (c *Client) Alarm(ctx context.Context) error
- func (c *Client) Cont(ctx context.Context) error
- func (c *Client) Down(ctx context.Context) error
- func (c *Client) ExitSupervise(ctx context.Context) error
- func (c *Client) HUP(ctx context.Context) error
- func (c *Client) Interrupt(ctx context.Context) error
- func (c *Client) Kill(ctx context.Context) error
- func (c *Client) Once(ctx context.Context) error
- func (c *Client) Pause(ctx context.Context) error
- func (c *Client) Quit(ctx context.Context) error
- func (c *Client) Status(_ context.Context) (Status, error)
- func (c *Client) Term(ctx context.Context) error
- func (c *Client) Up(ctx context.Context) error
- func (c *Client) Watch(ctx context.Context) (<-chan WatchEvent, func() error, error)
- type DevTree
- func (d *DevTree) DisableService(_ string) error
- func (d *DevTree) EnableService(_ string) error
- func (d *DevTree) EnabledDir() string
- func (d *DevTree) Ensure() error
- func (d *DevTree) EnsureRunsvdir() error
- func (d *DevTree) LogDir() string
- func (d *DevTree) PIDFile() string
- func (d *DevTree) ServicesDir() string
- func (d *DevTree) StopRunsvdir() error
- type Flags
- type Manager
- func (m *Manager) Down(ctx context.Context, services ...string) error
- func (m *Manager) Kill(ctx context.Context, services ...string) error
- func (m *Manager) Status(ctx context.Context, services ...string) (map[string]Status, error)
- func (m *Manager) Term(ctx context.Context, services ...string) error
- func (m *Manager) Up(ctx context.Context, services ...string) error
- type ManagerOption
- type MultiError
- type OpError
- type Operation
- type Option
- type ServiceBuilder
- func NewServiceBuilder(name, dir string) *ServiceBuilder
- func NewServiceBuilderWithConfig(name, dir string, config *ServiceConfig) *ServiceBuilder
- func ServiceBuilderDaemontools(name, dir string) *ServiceBuilder
- func ServiceBuilderRunit(name, dir string) *ServiceBuilder
- func ServiceBuilderS6(name, dir string) *ServiceBuilder
- func (b *ServiceBuilder) Build() error
- func (b *ServiceBuilder) WithChpst(fn func(*ChpstBuilder)) *ServiceBuilder
- func (b *ServiceBuilder) WithChpstPath(path string) *ServiceBuilder
- func (b *ServiceBuilder) WithCmd(cmd []string) *ServiceBuilder
- func (b *ServiceBuilder) WithCwd(cwd string) *ServiceBuilder
- func (b *ServiceBuilder) WithEnv(key, value string) *ServiceBuilder
- func (b *ServiceBuilder) WithFinish(cmd []string) *ServiceBuilder
- func (b *ServiceBuilder) WithStderrPath(path string) *ServiceBuilder
- func (b *ServiceBuilder) WithSvlogd(fn func(*SvlogdBuilder)) *ServiceBuilder
- func (b *ServiceBuilder) WithSvlogdPath(path string) *ServiceBuilder
- func (b *ServiceBuilder) WithUmask(umask fs.FileMode) *ServiceBuilder
- type ServiceConfig
- type ServiceType
- type State
- type Status
- type SvlogdBuilder
- type VersionInfo
- type WatchEvent
Constants ¶
const ( // SuperviseDir is the subdirectory containing runit control files SuperviseDir = "supervise" // ControlFile is the control socket/FIFO file name ControlFile = "control" // StatusFile is the binary status file name StatusFile = "status" // StatusFileSize is the exact size of the binary status record in bytes // Reference: https://github.com/g-pape/runit/blob/master/src/sv.c#L53 // char svstatus[20]; StatusFileSize = 20 // DefaultWatchDebounce is the default debounce time for status file watching DefaultWatchDebounce = 25 * time.Millisecond // DefaultDialTimeout is the default timeout for control socket connections DefaultDialTimeout = 2 * time.Second // DefaultWriteTimeout is the default timeout for control write operations DefaultWriteTimeout = 1 * time.Second // DefaultReadTimeout is the default timeout for status read operations DefaultReadTimeout = 1 * time.Second // DefaultBackoffMin is the minimum backoff duration for retries DefaultBackoffMin = 10 * time.Millisecond // DefaultBackoffMax is the maximum backoff duration for retries DefaultBackoffMax = 1 * time.Second // DefaultMaxAttempts is the default maximum number of retry attempts DefaultMaxAttempts = 10 )
Runit directory and file constants
const ( // DefaultChpstPath is the default path to the chpst binary DefaultChpstPath = "chpst" // DefaultSvlogdPath is the default path to the svlogd binary DefaultSvlogdPath = "svlogd" // DefaultRunsvdirPath is the default path to the runsvdir binary DefaultRunsvdirPath = "runsvdir" // DefaultSvPath is the default path to the sv binary (for fallback mode) DefaultSvPath = "sv" )
Binary paths with defaults that can be overridden
const ( // DirMode is the default mode for created directories DirMode = 0o755 // FileMode is the default mode for created files FileMode = 0o644 // ExecMode is the default mode for executable scripts ExecMode = 0o755 )
File modes
const ( // TAI64Base is the TAI64 epoch offset from Unix epoch (1970-01-01 00:00:10 TAI) // Reference: https://github.com/g-pape/runit/blob/master/src/tai.h#L12 // #define tai_unix(t,u) ((void) ((t)->x = 4611686018427387914ULL + (uint64) (u))) // This value is 2^62 + 10 seconds (TAI is 10 seconds ahead of UTC at Unix epoch) // Calculated as: (1 << 62) + 10 TAI64Base = uint64(1<<62) + 10 // 4611686018427387914 )
TAI64N constants for timestamp decoding
const Version = "1.0.0"
Version is the current version of the go-runit library
Variables ¶
var ( // ErrNotSupervised indicates the service directory lacks a supervise subdirectory ErrNotSupervised = errors.New("runit: supervise dir missing") // ErrControlNotReady indicates the control socket/FIFO is not accepting connections ErrControlNotReady = errors.New("runit: control not accepting connections") // ErrTimeout indicates an operation exceeded its timeout ErrTimeout = errors.New("runit: timeout") // ErrDecode indicates the status file could not be decoded ErrDecode = errors.New("runit: status decode") )
Common errors returned by runit operations
var DefaultUmask fs.FileMode = 0o022
DefaultUmask is the default umask for created files
Functions ¶
This section is empty.
Types ¶
type ChpstBuilder ¶
type ChpstBuilder struct {
// User to run the process as
User string
// Group to run the process as
Group string
// Nice value for process priority
Nice int
// IONice value for I/O priority
IONice int
// LimitMem sets memory limit in bytes
LimitMem int64
// LimitFiles sets maximum number of open files
LimitFiles int
// LimitProcs sets maximum number of processes
LimitProcs int
// LimitCPU sets CPU time limit in seconds
LimitCPU int
// Root changes the root directory
Root string
}
ChpstBuilder configures chpst options for process control
type Client ¶
type Client struct {
// ServiceDir is the canonical path to the service directory
ServiceDir string
// DialTimeout is the timeout for establishing control socket connections
DialTimeout time.Duration
// WriteTimeout is the timeout for writing control commands
WriteTimeout time.Duration
// ReadTimeout is the timeout for reading status information
ReadTimeout time.Duration
// BackoffMin is the minimum duration between retry attempts
BackoffMin time.Duration
// BackoffMax is the maximum duration between retry attempts
BackoffMax time.Duration
// MaxAttempts is the maximum number of retry attempts for control operations
MaxAttempts int
// WatchDebounce is the debounce duration for watch events to coalesce rapid changes
WatchDebounce time.Duration
// Config holds optional supervision system configuration for compatibility
Config *ServiceConfig
// contains filtered or unexported fields
}
Client provides control and status operations for a single runit service. It communicates directly with the service's supervise process through control sockets/FIFOs and status files, without shelling out to sv.
func New ¶
New creates a new Client for the specified service directory. It verifies the service has a supervise directory and applies any provided options.
func NewClientWithConfig ¶ added in v1.1.0
func NewClientWithConfig(serviceDir string, config *ServiceConfig, opts ...Option) (*Client, error)
NewClientWithConfig creates a new client with the specified service configuration
func (*Client) ExitSupervise ¶
ExitSupervise terminates the supervise process for this service
func (*Client) Status ¶
Status reads and decodes the service's binary status file. It returns typed Status information without shelling out to sv.
type DevTree ¶
type DevTree struct {
Base string
}
DevTree represents a development runit service tree (stub implementation)
func NewDevTree ¶
NewDevTree creates a new DevTree (stub implementation)
func (*DevTree) DisableService ¶
DisableService disables a service in the dev tree
func (*DevTree) EnableService ¶
EnableService enables a service in the dev tree
func (*DevTree) EnabledDir ¶
EnabledDir returns the enabled services directory path
func (*DevTree) EnsureRunsvdir ¶
EnsureRunsvdir ensures runsvdir is running for the dev tree
func (*DevTree) ServicesDir ¶
ServicesDir returns the services directory path
func (*DevTree) StopRunsvdir ¶
StopRunsvdir stops the runsvdir process for the dev tree
type Flags ¶
type Flags struct {
// WantUp indicates the service is configured to be up
WantUp bool
// WantDown indicates the service is configured to be down
WantDown bool
// NormallyUp indicates the service should be started on boot
NormallyUp bool
}
Flags represents service configuration flags from the status file
type Manager ¶
type Manager struct {
// Concurrency is the maximum number of concurrent operations
Concurrency int
// Timeout is the per-operation timeout
Timeout time.Duration
}
Manager handles operations on multiple runit services concurrently. It provides bulk operations with configurable concurrency and timeouts.
func NewManager ¶
func NewManager(opts ...ManagerOption) *Manager
NewManager creates a new Manager with default settings
type ManagerOption ¶
type ManagerOption func(*Manager)
ManagerOption configures a Manager
func WithConcurrency ¶
func WithConcurrency(n int) ManagerOption
WithConcurrency sets the maximum number of concurrent operations
func WithTimeout ¶
func WithTimeout(d time.Duration) ManagerOption
WithTimeout sets the per-operation timeout
type MultiError ¶
type MultiError struct {
// Errors contains all accumulated errors
Errors []error
}
MultiError aggregates multiple errors from bulk operations
func (*MultiError) Add ¶
func (m *MultiError) Add(err error)
Add appends an error to the collection if it's not nil
func (*MultiError) Err ¶
func (m *MultiError) Err() error
Err returns nil if no errors occurred, otherwise returns the MultiError itself
func (*MultiError) Error ¶
func (m *MultiError) Error() string
Error returns a summary of the accumulated errors
type OpError ¶
type OpError struct {
// Op is the operation that failed
Op Operation
// Path is the file path involved in the operation
Path string
// Err is the underlying error
Err error
}
OpError represents an error from a runit operation
type Operation ¶
type Operation int
Operation represents a control operation type
const ( // OpUnknown represents an unknown operation OpUnknown Operation = iota // OpUp starts the service (want up) OpUp // OpOnce starts the service once OpOnce // OpDown stops the service (want down) OpDown // OpTerm sends SIGTERM to the service OpTerm // OpInterrupt sends SIGINT to the service OpInterrupt // OpHUP sends SIGHUP to the service OpHUP // OpAlarm sends SIGALRM to the service OpAlarm // OpQuit sends SIGQUIT to the service OpQuit // OpKill sends SIGKILL to the service OpKill // OpPause sends SIGSTOP to the service OpPause // OpCont sends SIGCONT to the service OpCont // OpExit terminates the supervise process OpExit // OpStatus represents a status query operation OpStatus )
type Option ¶
type Option func(*Client)
Option configures a Client
func WithBackoff ¶
WithBackoff sets the minimum and maximum backoff durations for retries
func WithDialTimeout ¶
WithDialTimeout sets the timeout for control socket connections
func WithMaxAttempts ¶
WithMaxAttempts sets the maximum number of retry attempts
func WithReadTimeout ¶
WithReadTimeout sets the timeout for status read operations
func WithWatchDebounce ¶
WithWatchDebounce sets the debounce duration for watch events
func WithWriteTimeout ¶
WithWriteTimeout sets the timeout for control write operations
type ServiceBuilder ¶
type ServiceBuilder struct {
// Name is the service name
Name string
// Dir is the base directory where the service will be created
Dir string
// Cmd is the command and arguments to execute
Cmd []string
// Cwd is the working directory for the service
Cwd string
// Umask sets the file mode creation mask
Umask fs.FileMode
// Env contains environment variables for the service
Env map[string]string
// Chpst configures process limits and user context
Chpst *ChpstBuilder
// Svlogd configures logging
Svlogd *SvlogdBuilder
// Finish is the command to run when the service stops
Finish []string
// StderrPath is an optional path to redirect stderr (if different from stdout)
StderrPath string
// ChpstPath is the path to the chpst binary
ChpstPath string
// SvlogdPath is the path to the svlogd binary
SvlogdPath string
}
ServiceBuilder provides a fluent interface for creating runit service directories with run scripts, environment variables, logging, and process control settings.
func NewServiceBuilder ¶
func NewServiceBuilder(name, dir string) *ServiceBuilder
NewServiceBuilder creates a new ServiceBuilder with default settings
func NewServiceBuilderWithConfig ¶ added in v1.1.0
func NewServiceBuilderWithConfig(name, dir string, config *ServiceConfig) *ServiceBuilder
NewServiceBuilderWithConfig creates a service builder for the specified supervision system
func ServiceBuilderDaemontools ¶ added in v1.1.0
func ServiceBuilderDaemontools(name, dir string) *ServiceBuilder
ServiceBuilderDaemontools creates a service builder configured for daemontools
func ServiceBuilderRunit ¶ added in v1.1.0
func ServiceBuilderRunit(name, dir string) *ServiceBuilder
ServiceBuilderRunit creates a service builder configured for runit
func ServiceBuilderS6 ¶ added in v1.1.0
func ServiceBuilderS6(name, dir string) *ServiceBuilder
ServiceBuilderS6 creates a service builder configured for s6
func (*ServiceBuilder) Build ¶
func (b *ServiceBuilder) Build() error
Build creates the service directory structure and scripts
func (*ServiceBuilder) WithChpst ¶
func (b *ServiceBuilder) WithChpst(fn func(*ChpstBuilder)) *ServiceBuilder
WithChpst configures process control settings
func (*ServiceBuilder) WithChpstPath ¶
func (b *ServiceBuilder) WithChpstPath(path string) *ServiceBuilder
WithChpstPath sets the path to the chpst binary
func (*ServiceBuilder) WithCmd ¶
func (b *ServiceBuilder) WithCmd(cmd []string) *ServiceBuilder
WithCmd sets the command to execute
func (*ServiceBuilder) WithCwd ¶
func (b *ServiceBuilder) WithCwd(cwd string) *ServiceBuilder
WithCwd sets the working directory
func (*ServiceBuilder) WithEnv ¶
func (b *ServiceBuilder) WithEnv(key, value string) *ServiceBuilder
WithEnv adds an environment variable
func (*ServiceBuilder) WithFinish ¶
func (b *ServiceBuilder) WithFinish(cmd []string) *ServiceBuilder
WithFinish sets the command to run when the service stops
func (*ServiceBuilder) WithStderrPath ¶
func (b *ServiceBuilder) WithStderrPath(path string) *ServiceBuilder
WithStderrPath sets a separate path for stderr output
func (*ServiceBuilder) WithSvlogd ¶
func (b *ServiceBuilder) WithSvlogd(fn func(*SvlogdBuilder)) *ServiceBuilder
WithSvlogd configures logging settings
func (*ServiceBuilder) WithSvlogdPath ¶
func (b *ServiceBuilder) WithSvlogdPath(path string) *ServiceBuilder
WithSvlogdPath sets the path to the svlogd binary
func (*ServiceBuilder) WithUmask ¶
func (b *ServiceBuilder) WithUmask(umask fs.FileMode) *ServiceBuilder
WithUmask sets the file mode creation mask
type ServiceConfig ¶ added in v1.1.0
type ServiceConfig struct {
// Type specifies which supervision system this is for
Type ServiceType
// ServiceDir is the base service directory (e.g., /etc/service, /service, /run/service)
ServiceDir string
// ChpstPath is the path to the privilege/resource control tool
ChpstPath string
// LoggerPath is the path to the logger tool
LoggerPath string
// RunsvdirPath is the path to the service scanner
RunsvdirPath string
// SupportedOps contains the set of supported operations
SupportedOps map[Operation]struct{}
}
ServiceConfig contains configuration for different supervision systems
func DaemontoolsConfig ¶ added in v1.1.0
func DaemontoolsConfig() *ServiceConfig
DaemontoolsConfig returns the default configuration for daemontools
func RunitConfig ¶ added in v1.1.0
func RunitConfig() *ServiceConfig
RunitConfig returns the default configuration for runit
func S6Config ¶ added in v1.1.0
func S6Config() *ServiceConfig
S6Config returns the default configuration for s6
func (*ServiceConfig) IsOperationSupported ¶ added in v1.1.0
func (c *ServiceConfig) IsOperationSupported(op Operation) bool
IsOperationSupported checks if an operation is supported by this service type
type ServiceType ¶ added in v1.1.0
type ServiceType int
ServiceType represents the type of service supervision system
const ( // ServiceTypeUnknown represents an unknown supervision system ServiceTypeUnknown ServiceType = iota // ServiceTypeRunit represents runit supervision ServiceTypeRunit // ServiceTypeDaemontools represents daemontools supervision ServiceTypeDaemontools // ServiceTypeS6 represents s6 supervision ServiceTypeS6 )
func (ServiceType) String ¶ added in v1.1.0
func (st ServiceType) String() string
String returns the string representation of ServiceType
type State ¶
type State int
State represents the current state of a runit service
const ( // StateUnknown indicates the state could not be determined StateUnknown State = iota // StateDown indicates the service is down and wants to be down StateDown // StateStarting indicates the service wants to be up but is not running yet StateStarting // StateRunning indicates the service is running and wants to be up StateRunning // StatePaused indicates the service is paused (SIGSTOP) StatePaused // StateStopping indicates the service is running but wants to be down StateStopping // StateFinishing indicates the finish script is executing StateFinishing // StateCrashed indicates the service is down but wants to be up StateCrashed // StateExited indicates the supervise process has exited StateExited )
type Status ¶
type Status struct {
// State is the inferred service state
State State
// PID is the process ID of the service (0 if not running)
PID int
// Since is the timestamp when the service entered its current state
Since time.Time
// Uptime is the duration since the service entered its current state.
// This field provides a snapshot of the uptime at the moment of status read.
// Note: This value becomes stale immediately after reading as time progresses.
// It's included for convenience and compatibility with sv output format.
// For accurate time calculations, use Since with time.Since(status.Since).
Uptime time.Duration
// Flags contains service configuration flags
Flags Flags
// Raw contains the original 20-byte status record as an array (stack allocated)
Raw [StatusFileSize]byte
}
Status represents the decoded state of a runit service
type SvlogdBuilder ¶
type SvlogdBuilder struct {
// Size is the maximum size of current log file in bytes
Size int64
// Num is the number of old log files to keep
Num int
// Timeout is the maximum age of current log file in seconds
Timeout int
// Processor is an optional processor script for log files
Processor string
// Config contains additional svlogd configuration lines
Config []string
// Timestamp adds timestamps to log lines
Timestamp bool
// Replace replaces non-printable characters
Replace bool
// Prefix adds a prefix to each log line
Prefix string
}
SvlogdBuilder configures svlogd logging options
type VersionInfo ¶
type VersionInfo struct {
// Version is the semantic version
Version string
// Protocol is the runit protocol version supported
Protocol string
// Compatible indicates compatibility with daemontools
Compatible bool
}
VersionInfo contains detailed version information
type WatchEvent ¶
WatchEvent represents a status change event from watching a service
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
basic
command
Package main provides a basic example of using the go-runit library.
|
Package main provides a basic example of using the go-runit library. |
|
compat
command
Package main demonstrates using go-runit with different supervision systems (runit, daemontools, s6) through the factory functions.
|
Package main demonstrates using go-runit with different supervision systems (runit, daemontools, s6) through the factory functions. |
|
manager
command
Package main provides an example of managing multiple runit services.
|
Package main provides an example of managing multiple runit services. |
|
watch
command
Package main provides an example of watching runit service status changes.
|
Package main provides an example of watching runit service status changes. |
|
internal
|
|
|
unix
Package unix provides platform-specific Unix constants.
|
Package unix provides platform-specific Unix constants. |