systemd

package
v3.0.0-alpha.2 Latest Latest
Warning

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

Go to latest
Published: Nov 5, 2026 License: BSD-2-Clause Imports: 14 Imported by: 0

Documentation

Overview

Package systemd writes the systemd units that run the instances of an application installed in the system scope, and the mark that tells the instance commands which instances the units manage (decisions 20 and 39). It takes what the units are made of and knows nothing of how tt finds an application or runs an instance.

Units

An application gets one template unit, <app>@.service. Its ExecStart runs tt instance start --foreground <app>:%i: tt stays in the foreground while the instance runs under a watchdog that never restarts it, and exits when the instance does (decision 37), so the restart is up to systemd. The unit gives tt the root of the system scope in TT_SYSTEM_ROOT, since tt run by systemd would look for the application in the default root otherwise, and its own name in TT_SYSTEMD_UNIT (UnitEnv), by which tt tells the start the unit asks for from a start next to the unit.

A template is one for all its instances, so what differs between them goes into a drop-in of every instance, <app>@<inst>.service.d/tt.conf: Restart= from the restart field of its record, whose values are those of systemd, and TimeoutStopSec= from its stop_timeout. The template carries the defaults of both for an instance without a drop-in.

tt stops the instance itself: it sends the instance its stop signal and kills it once its stop_timeout is up (decision 31). So the stop signal of systemd, SIGTERM, goes to tt alone (KillMode=mixed), and TimeoutStopSec= leaves tt its stop_timeout and a margin to kill the instance and exit; SIGKILL to the whole unit comes after that, or once tt has exited, for what is left.

Mark

tt service systemd install writes the units and the mark, <root>/etc/<app>/ systemd.yaml (MarkFileName): the unit directory, the template, the user and the group the units run the instances as, which an install that names none keeps, and the unit of every instance the units manage. tt instance start, stop, restart and kill refuse those instances, pointing at systemctl: a watchdog of tt next to the unit would supervise the instance twice, and a stop behind the back of the unit would leave it out of step. tt service systemd uninstall removes the units and the mark.

The files tt writes start with GeneratedHeader. install overwrites only such files, and uninstall removes only such files: a unit of the same name written by someone else is not tt's to replace or remove.

Index

Constants

View Source
const (
	// GeneratedHeader starts every file tt writes (IsGenerated).
	GeneratedHeader = "# Generated by tt service systemd"
	// UnitEnv is the variable the template unit sets to the name of the
	// unit, %n: tt instance start --foreground started with it is the start
	// the unit of the instance asks for, which the instance commands do not
	// refuse.
	UnitEnv = "TT_SYSTEMD_UNIT"
	// DefaultRunAs is the user and the group the units run the instances as
	// by default: the system user the deb and rpm packages of tt create, as
	// the units tt2 packed ran them.
	DefaultRunAs = "tarantool"
	// DropInName is the name of the drop-in of an instance in its drop-in
	// directory.
	DropInName = "tt.conf"
)
View Source
const MarkFileName = "systemd.yaml"

MarkFileName is the mark of the units of an application in the directory of its host files, <root>/etc/<app>/.

Variables

View Source
var (
	// ErrForeignFile is wrapped by the error for a file in the place of a
	// unit that tt did not write: tt does not replace it.
	ErrForeignFile = errors.New("was not written by tt service systemd")
	// ErrNoUnitDir is wrapped by the error for a unit directory that does
	// not exist.
	ErrNoUnitDir = errors.New("no unit directory")
)
View Source
var (
	// ErrUnitName is wrapped by the error for an application or an instance
	// whose name cannot go into the name of a unit as it is.
	ErrUnitName = errors.New("cannot name a systemd unit")
	// ErrUnitPath is wrapped by the error for a path that cannot go into a
	// unit as it is.
	ErrUnitPath = errors.New("cannot be written into a systemd unit")
	// ErrUnitAccount is wrapped by the error for a user or a group whose
	// name cannot go into a unit as it is.
	ErrUnitAccount = errors.New("cannot be written into a systemd unit")
)
View Source
var ErrInvalidMark = errors.New("invalid mark of systemd units")

ErrInvalidMark is wrapped by the error for a mark that cannot be read.

Functions

func DropInPath

func DropInPath(unit string) string

DropInPath returns the path of the drop-in of the unit, relative to the unit directory: <unit>.d/tt.conf.

func Install

func Install(installation Installation) error

Install writes the units and the mark of installation, and removes the stale files of the units installed before.

The unit directory must exist: it is the directory of the service manager, which tt does not create. A file in the place of a unit that tt did not write is an error before anything is written (ErrForeignFile).

The units go next to their places first, then the mark is written, then the units are moved into their places. A unit directory tt cannot write to fails the install before the mark is written, and once the mark is there the instance commands leave the instances to the units before the units can start them: tt never supervises an instance next to a unit that has not been marked.

func IsGenerated

func IsGenerated(content []byte) bool

IsGenerated reports whether content is that of a file tt wrote.

func MarkPath

func MarkPath(hostDir string) string

MarkPath returns the path of the mark in hostDir, the directory of the host files of an application.

func RemoveMark

func RemoveMark(hostDir string) error

RemoveMark removes the mark in hostDir, if there is one.

func TemplateName

func TemplateName(app string) string

TemplateName returns the name of the template unit of the application app, <app>@.service.

func Uninstall

func Uninstall(hostDir string, mark Mark) ([]string, error)

Uninstall removes the files of the units mark records from the unit directory of mark, then the drop-in directories it leaves empty, and then the mark in hostDir. A file tt did not write is left in place and returned in kept, by its path; a file that is gone already is no failure.

A failure stops the removal before the mark is removed, so that tt service systemd uninstall can be run again.

func UnitName

func UnitName(app, inst string) string

UnitName returns the name of the unit of the instance inst of the application app, <app>@<inst>.service.

func WriteFiles

func WriteFiles(dir string, files []File) error

WriteFiles writes files into dir, which it creates if need be, as tt service systemd generate writes them into a directory: without a mark, and replacing only the files tt wrote (ErrForeignFile).

func WriteMark

func WriteMark(hostDir string, mark Mark) error

WriteMark writes mark into hostDir, which it creates if need be, replacing the mark there at once: a reader sees the old mark or the new one.

Types

type File

type File struct {
	// Name is the path of the file relative to the unit directory.
	Name string
	// Content is what the file holds.
	Content []byte
}

File is a file of the units.

func Generate

func Generate(units Units) ([]File, error)

Generate returns the files of units: the template unit, then the drop-in of every instance, in their order.

A name or a path that a unit would have to escape or quote is an error rather than escaped: %i passes the instance name to tt as the unit name has it, so a name must be one that needs no escaping in a unit name, and the paths go into ExecStart= and Environment= as they are.

type Installation

type Installation struct {
	// UnitDir is the directory the units go to.
	UnitDir string
	// HostDir is the directory of the host files of the application, which
	// the mark goes to.
	HostDir string
	// Files are the files of the units.
	Files []File
	// Mark is the mark of the units.
	Mark Mark
	// Stale are the files of the units installed before, relative to
	// UnitDir, that the new ones do not have: the drop-ins of instances gone
	// from the description. Install removes them.
	Stale []string
}

Installation is what Install writes.

type Instance

type Instance struct {
	// Name is the name of the instance.
	Name string
	// Restart is the restart field of its record.
	Restart instances.RestartPolicy
	// StopTimeout is TimeoutStopSec= of the instance: how long systemd waits
	// for tt to stop it before it kills what is left.
	StopTimeout time.Duration
}

Instance is what the drop-in of an instance is made of.

type Mark

type Mark struct {
	// UnitDir is the directory the units are in.
	UnitDir string `yaml:"unit_dir"`
	// Template is the name of the template unit, <app>@.service.
	Template string `yaml:"template"`
	// RunAs is the user and the group the units run the instances as,
	// <user>:<group>, so that an install that names none keeps them. Empty
	// is the default, DefaultRunAs.
	RunAs string `yaml:"run_as,omitempty"`
	// Instances maps the name of every instance the units manage to its
	// unit, <app>@<inst>.service.
	Instances map[string]string `yaml:"instances"`
}

Mark tells which instances of an application run under the systemd units tt service systemd install wrote, and where the units are.

func ReadMark

func ReadMark(hostDir string) (Mark, bool, error)

ReadMark reads the mark in hostDir. found is false when there is none. A mark that does not parse, or lacks what it must hold, is an error wrapping ErrInvalidMark: what it says the units manage cannot be told then.

func (*Mark) Files

func (mark *Mark) Files() []string

Files returns the paths of the files of the units the mark records, relative to UnitDir: the template and the drop-in of every instance, in the order of the instances' names.

type RunAs

type RunAs struct {
	// User is the name or the numeric id of the user.
	User string
	// Group is the name or the numeric id of the group.
	Group string
}

RunAs is the user and the group the units run the instances as, User= and Group= of the template.

func ParseRunAs

func ParseRunAs(value string) (RunAs, error)

ParseRunAs parses <user>[:<group>]; without a group the group is the user's name. A name is made of what a unit takes without escaping (checkAccount).

func (RunAs) String

func (runAs RunAs) String() string

String returns the user and the group as ParseRunAs takes them, <user>:<group>.

type Units

type Units struct {
	// App is the name of the application.
	App string
	// RunAs is the user and the group the units run the instances as.
	RunAs RunAs
	// Root is the root of the system scope the application is installed in,
	// which the units pass to tt as TT_SYSTEM_ROOT.
	Root string
	// TT is the tt executable the units run, an absolute path.
	TT string
	// StopTimeout is TimeoutStopSec= of the template, for an instance without
	// a drop-in: how long systemd waits for tt to stop an instance whose
	// record sets no stop_timeout.
	StopTimeout time.Duration
	// Instances are the instances of the application, in the order of its
	// description.
	Instances []Instance
}

Units is what the units of an application are made of.

Jump to

Keyboard shortcuts

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