service

package module
v0.0.0-...-6fb5cb7 Latest Latest
Warning

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

Go to latest
Published: Dec 10, 2020 License: Zlib Imports: 23 Imported by: 0

README

service GoDoc

service will install / un-install, start / stop, and run a program as a service (daemon). Currently supports Windows XP+, Linux/(systemd | Upstart | SysV), and OSX/Launchd.

Windows controls services by setting up callbacks that is non-trivial. This is very different then other systems. This package provides the same API despite the substantial differences. It also can be used to detect how a program is called, from an interactive terminal or from a service manager.

BUGS

  • Dependencies field is not implemented for Linux systems and Launchd.
  • OS X when running as a UserService Interactive will not be accurate.

Documentation

Overview

Package service provides a simple way to create a system service. Currently supports Windows, Linux/(systemd | Upstart | SysV), and OSX/Launchd.

Windows controls services by setting up callbacks that is non-trivial. This is very different then other systems. This package provides the same API despite the substantial differences. It also can be used to detect how a program is called, from an interactive terminal or from a service manager.

Examples in the example/ folder.

package main

import (
	"log"

	"github.com/ianatha/service"
)

var logger service.Logger

type program struct{}

func (p *program) Start(s service.Service) error {
	// Start should not block. Do the actual work async.
	go p.run()
	return nil
}
func (p *program) run() {
	// Do work here
}
func (p *program) Stop(s service.Service) error {
	// Stop should not block. Return with a few seconds.
	return nil
}

func main() {
	svcConfig := &service.Config{
		Name:        "GoServiceTest",
		DisplayName: "Go Service Test",
		Description: "This is a test Go service.",
	}

	prg := &program{}
	s, err := service.New(prg, svcConfig)
	if err != nil {
		log.Fatal(err)
	}
	logger, err = s.Logger(nil)
	if err != nil {
		log.Fatal(err)
	}
	err = s.Run()
	if err != nil {
		logger.Error(err)
	}
}

Index

Constants

View Source
const (
	CREATE_BREAKAWAY_FROM_JOB = 0x01000000
	CREATE_NEW_CONSOLE        = 0x00000010
	CREATE_NEW_PROCESS_GROUP  = 0x00000200

	MAX_PATH = 260
)
View Source
const (
	CLIENTNAME_LENGTH     = 20
	DOMAIN_LENGTH         = 17
	USERNAME_LENGTH       = 20
	CLIENTADDRESS_LENGTH  = 30
	WINSTATIONNAME_LENGTH = 32
)

Misc consts from WtsApi32.h

View Source
const (
	WTSActive       = 0
	WTSConnected    = 1
	WTSConnectQuery = 2
	WTSShadow       = 3
	WTSDisconnected = 4
	WTSIdle         = 5
	WTSListen       = 6
	WTSReset        = 7
	WTSDown         = 8
	WTSInit         = 9
)

WTS_CONNECTSTATE_CLASS enumeration

View Source
const (
	WTSInitialProgram     = 0
	WTSApplicationName    = 1
	WTSWorkingDirectory   = 2
	WTSOEMId              = 3
	WTSSessionId          = 4
	WTSUserName           = 5
	WTSWinStationName     = 6
	WTSDomainName         = 7
	WTSConnectState       = 8
	WTSClientBuildNumber  = 9
	WTSClientName         = 10
	WTSClientDirectory    = 11
	WTSClientProductId    = 12
	WTSClientHardwareId   = 13
	WTSClientAddress      = 14
	WTSClientDisplay      = 15
	WTSClientProtocolType = 16
	WTSIdleTime           = 17
	WTSLogonTime          = 18
	WTSIncomingBytes      = 19
	WTSOutgoingBytes      = 20
	WTSIncomingFrames     = 21
	WTSOutgoingFrames     = 22
	WTSClientInfo         = 23
	WTSSessionInfo        = 24
	WTSSessionInfoEx      = 25
	WTSConfigInfo         = 26
	WTSValidationInfo     = 27
	WTSSessionAddressV4   = 28
	WTSIsRemoteSession    = 29
)

WTS_INFO_CLASS enumeration

View Source
const ERROR_SUCCESS = 0

Variables

View Source
var (
	// ErrNameFieldRequired is returned when Config.Name is empty.
	ErrNameFieldRequired = errors.New("Config.Name field is required.")
	// ErrNoServiceSystemDetected is returned when no system was detected.
	ErrNoServiceSystemDetected = errors.New("No service system detected.")
	// ErrNotInstalled is returned when the service is not installed
	ErrNotInstalled = errors.New("the service is not installed")
)
View Source
var ConsoleLogger = consoleLogger{}

ConsoleLogger logs to the std err.

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

ControlAction list valid string texts to use in Control.

Functions

func BstrToString

func BstrToString(bstr *uint16) string

func ChooseSystem

func ChooseSystem(a ...System)

ChooseSystem chooses a system from the given system services. SystemServices are considered in the order they are suggested. Calling this may change what Interactive and Platform return.

func Control

func Control(s Service, action string) error

Control issues control functions to the service from a given action string.

func GetElevatedUserToken

func GetElevatedUserToken(hToken windows.Handle) (windows.Handle, error)

func GetTokenInformation

func GetTokenInformation(tokenHandle windows.Handle, tokenInformationClass TOKEN_INFORMATION_CLASS, tokenInformation *byte, tokenInformationLength uint32, returnLength *uint32) (err error)

func GetTokenUser

func GetTokenUser(hToken windows.Handle) (*windows.SID, error)

func GetUserNameEx

func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error)

func GetUserProfileDirectory

func GetUserProfileDirectory(hToken windows.Handle, lpProfileDir *uint16, lpcchSize *uint32) (err error)

func GetUserSid

func GetUserSid() (sid *windows.SID, err error)

func Interactive

func Interactive() bool

Interactive returns false if running under the OS service manager and true otherwise.

func InteractiveUserToken

func InteractiveUserToken(timeout time.Duration) (hToken windows.Handle, err error)

InteractiveUserToken returns a user token (security context) for the interactive desktop session attached to the default console (i.e. what would be seen on a display connected directly to the computer, rather than a remote RDP session). It must be called from a process which is running under LocalSystem account in order to have the necessary privileges (typically a Windows service). Since the service might be running before a local logon occurs, a timeout can be specified for waiting for a successful logon (via winlogon) to occur. The returned token can be used in e.g. CreateProcessAsUser system call, which allows e.g. a Windows service to run a process in the interactive desktop session, as if the logged in user had executed the process directly. The function additionally waits for the user profile directory to exist, before returning.

func LpstrToString

func LpstrToString(lpstr *uint16) string

func MakeDoubleNullTerminatedLpstr

func MakeDoubleNullTerminatedLpstr(items ...string) *uint16

func Platform

func Platform() string

Platform returns a description of the system service.

func ProfileDirectory

func ProfileDirectory(hToken windows.Handle) (string, error)

ProfileDirectory returns the profile directory of the user represented by the given user handle

func SidToUsername

func SidToUsername(sid *windows.SID) (string, error)

func TranslateName

func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error)

func WTSCloseServer

func WTSCloseServer(handle syscall.Handle)

func WTSEnumerateSessions

func WTSEnumerateSessions(server syscall.Handle, reserved uint32, version uint32, pSessionInfo **WTS_SESSION_INFO, count *uint32) error

func WTSFreeMemory

func WTSFreeMemory(memory *byte)

func WTSGetActiveConsoleSessionId

func WTSGetActiveConsoleSessionId() (sessionId uint32, err error)

func WTSLogoffSession

func WTSLogoffSession(handle syscall.Handle, sessionId uint32, wait bool) error

func WTSOpenServer

func WTSOpenServer(serverName *uint16) syscall.Handle

func WTSQuerySessionInformation

func WTSQuerySessionInformation(hServer windows.Handle, sessionId uint32, WTSInfoClass WTS_INFO_CLASS, buffer *uintptr, bytesReturned *uint32) (err error)

func WTSQueryUserToken

func WTSQueryUserToken(sessionId uint32, phToken *windows.Handle) (err error)

Types

type AddressFamily

type AddressFamily uint32
const (
	AddressFamilyUnspecified AddressFamily = wrappers.AF_UNSPEC
	AddressFamilyIP          AddressFamily = wrappers.AF_INET
	AddressFamilyIPX         AddressFamily = wrappers.AF_IPX
	AddressFamilyAppleTalk   AddressFamily = wrappers.AF_APPLETALK
	AddressFamilyNetBIOS     AddressFamily = wrappers.AF_NETBIOS
	AddressFamilyIPv6        AddressFamily = wrappers.AF_INET6
	AddressFamilyIrDA        AddressFamily = wrappers.AF_IRDA
	AddressFamilyBluetooth   AddressFamily = wrappers.AF_BTH
)

type Config

type Config struct {
	Name        string   // Required name of the service. No spaces suggested.
	DisplayName string   // Display name, spaces allowed.
	Description string   // Long description of service.
	UserName    string   // Run as username.
	Arguments   []string // Run with arguments.

	// Optional field to specify the executable for service.
	// If empty the current executable is used.
	Executable string

	// Array of service dependencies.
	// Not yet fully implemented on Linux or OS X:
	//  1. Support linux-systemd dependencies, just put each full line as the
	//     element of the string array, such as
	//     "After=network.target syslog.target"
	//     "Requires=syslog.target"
	//     Note, such lines will be directly appended into the [Unit] of
	//     the generated service config file, will not check their correctness.
	Dependencies []string

	// The following fields are not supported on Windows.
	WorkingDirectory string // Initial working directory.
	ChRoot           string

	// System specific options.
	//  * OS X
	//    - LaunchdConfig string ()      - Use custom launchd config
	//    - KeepAlive     bool   (true)
	//    - RunAtLoad     bool   (false)
	//    - UserService   bool   (false) - Install as a current user service.
	//    - SessionCreate bool   (false) - Create a full user session.
	//  * POSIX
	//    - SystemdScript string ()                 - Use custom systemd script
	//    - UpstartScript string ()                 - Use custom upstart script
	//    - SysvScript    string ()                 - Use custom sysv script
	//    - RunWait       func() (wait for SIGNAL)  - Do not install signal but wait for this function to return.
	//    - ReloadSignal  string () [USR1, ...]     - Signal to send on reaload.
	//    - PIDFile       string () [/run/prog.pid] - Location of the PID file.
	//    - LogOutput     bool   (false)            - Redirect StdErr & StandardOutPath to files.
	//    - Restart       string (always)           - How shall service be restarted.
	//    - SuccessExitStatus string ()             - The list of exit status that shall be considered as successful,
	//                                                in addition to the default ones.
	Option KeyValue

	WindowsExtraEvents chan WindowsEvent
}

Config provides the setup for a Service. The Name field is required.

type Interface

type Interface interface {
	// Start provides a place to initiate the service. The service doesn't not
	// signal a completed start until after this function returns, so the
	// Start function must not take more then a few seconds at most.
	Start(s Service) error

	// Stop provides a place to clean up program execution before it is terminated.
	// It should not take more then a few seconds to execute.
	// Stop should not call os.Exit directly in the function.
	Stop(s Service) error
}

Interface represents the service interface for a program. Start runs before the hosting process is granted control and Stop runs when control is returned.

  1. OS service manager executes user program.
  2. User program sees it is executed from a service manager (IsInteractive is false).
  3. User program calls Service.Run() which blocks.
  4. Interface.Start() is called and quickly returns.
  5. User program runs.
  6. OS service manager signals the user program to stop.
  7. Interface.Stop() is called and quickly returns. - For a successful exit, os.Exit should not be called in Interface.Stop().
  8. Service.Run returns.
  9. User program should quickly exit.

type KeyValue

type KeyValue map[string]interface{}

KeyValue provides a list of platform specific options. See platform docs for more details.

type Logger

type Logger interface {
	Error(v ...interface{}) error
	Warning(v ...interface{}) error
	Info(v ...interface{}) error

	Errorf(format string, a ...interface{}) error
	Warningf(format string, a ...interface{}) error
	Infof(format string, a ...interface{}) error
}

Logger writes to the system log.

type Service

type Service interface {
	// Run should be called shortly after the program entry point.
	// After Interface.Stop has finished running, Run will stop blocking.
	// After Run stops blocking, the program must exit shortly after.
	Run() error

	// Start signals to the OS service manager the given service should start.
	Start() error

	// Stop signals to the OS service manager the given service should stop.
	Stop() error

	// Restart signals to the OS service manager the given service should stop then start.
	Restart() error

	// Install setups up the given service in the OS service manager. This may require
	// greater rights. Will return an error if it is already installed.
	Install() error

	// Uninstall removes the given service from the OS service manager. This may require
	// greater rights. Will return an error if the service is not present.
	Uninstall() error

	// Opens and returns a system logger. If the user program is running
	// interactively rather then as a service, the returned logger will write to
	// os.Stderr. If errs is non-nil errors will be sent on errs as well as
	// returned from Logger's functions.
	Logger(errs chan<- error) (Logger, error)

	// SystemLogger opens and returns a system logger. If errs is non-nil errors
	// will be sent on errs as well as returned from Logger's functions.
	SystemLogger(errs chan<- error) (Logger, error)

	// String displays the name of the service. The display name if present,
	// otherwise the name.
	String() string

	// Platform displays the name of the system that manages the service.
	// In most cases this will be the same as service.Platform().
	Platform() string

	// Status returns the current service status.
	Status() (Status, error)
}

Service represents a service that can be run or controlled.

func New

func New(i Interface, c *Config) (Service, error)

New creates a new service based on a service interface and configuration.

type Status

type Status byte

Status represents service status as an byte value

const (
	StatusUnknown Status = iota // Status is unable to be determined due to an error or it was not installed.
	StatusRunning
	StatusStopped
)

Status of service represented as an byte

type System

type System interface {
	// String returns a description of the system.
	String() string

	// Detect returns true if the system is available to use.
	Detect() bool

	// Interactive returns false if running under the system service manager
	// and true otherwise.
	Interactive() bool

	// New creates a new service for this system.
	New(i Interface, c *Config) (Service, error)
}

System represents the service manager that is available.

func AvailableSystems

func AvailableSystems() []System

AvailableSystems returns the list of system services considered when choosing the system service.

func ChosenSystem

func ChosenSystem() System

ChosenSystem returns the system that service will use.

type TOKEN_INFORMATION_CLASS

type TOKEN_INFORMATION_CLASS uint32

type TOKEN_LINKED_TOKEN

type TOKEN_LINKED_TOKEN struct {
	LinkedToken windows.Handle // HANDLE
}

https://msdn.microsoft.com/en-us/library/windows/desktop/bb530719(v=vs.85).aspx

typedef struct _TOKEN_LINKED_TOKEN {
  HANDLE LinkedToken;
} TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN;

type TOKEN_USER

type TOKEN_USER struct {
	User windows.SIDAndAttributes
}

type WTSCLIENT

type WTSCLIENT struct {
	ClientName          [CLIENTNAME_LENGTH + 1]uint16
	Domain              [DOMAIN_LENGTH + 1]uint16
	UserName            [USERNAME_LENGTH + 1]uint16
	WorkDirectory       [MAX_PATH + 1]uint16
	InitialProgram      [MAX_PATH + 1]uint16
	EncryptionLevel     byte
	ClientAddressFamily uint32
	ClientAddress       [CLIENTADDRESS_LENGTH + 1]uint16
	HRes                uint16
	VRes                uint16
	ColorDepth          uint16
	ClientDirectory     [MAX_PATH + 1]uint16
	ClientBuildNumber   uint32
	ClientHardwareId    uint32
	ClientProductId     uint16
	OutBufCountHost     uint16
	OutBufCountClient   uint16
	OutBufLength        uint16
	DeviceId            [MAX_PATH + 1]uint16
}

type WTSClientDisplayStruct

type WTSClientDisplayStruct struct {
	HorizontalResolution uint
	VerticalResolution   uint
	ColorDepth           uint
}

WTSClientDisplayStruct - go version of WTS_CLIENT_DISPLAY structure

type WTSClientInfoStruct

type WTSClientInfoStruct struct {
	ClientName          string
	Domain              string
	UserName            string
	WorkDirectory       string
	InitialProgram      string
	EncryptionLevel     byte
	ClientAddressFamily AddressFamily

	HRes              uint
	VRes              uint
	ColorDepth        uint
	ClientDirectory   string
	ClientBuildNumber uint
	ClientHardwareId  uint
	ClientProductId   uint
	OutBufCountHost   uint
	OutBufCountClient uint
	OutBufLength      uint
	DeviceID          string
	// contains filtered or unexported fields
}

WTSClientInfoStruct - go version of WTSCLIENT structure

func (*WTSClientInfoStruct) ClientAddressToIP

func (ci *WTSClientInfoStruct) ClientAddressToIP() (net.IP, error)

type WTSClientProtocolTypeEnum

type WTSClientProtocolTypeEnum uint32

WTSClientProtocolType enum type go version of WTSClientProtocolType

const (
	WTSClientProtocolConsoleSession WTSClientProtocolTypeEnum = 0
	WTSClientProtocolInternal       WTSClientProtocolTypeEnum = 1
	WTSClientProtocolRDP            WTSClientProtocolTypeEnum = 2
)

type WTSConnectStateEnum

type WTSConnectStateEnum uint32

WTSConnectState enum type - Go version of WTS_CONNECTSTATE_CLASS

const (
	WTSConnectStateActive       WTSConnectStateEnum = WTSActive
	WTSConnectStateConnected    WTSConnectStateEnum = WTSConnected
	WTSConnectStateConnectQuery WTSConnectStateEnum = WTSConnectQuery
	WTSConnectStateShadow       WTSConnectStateEnum = WTSShadow
	WTSConnectStateDisconnected WTSConnectStateEnum = WTSDisconnected
	WTSConnectStateIdle         WTSConnectStateEnum = WTSIdle
	WTSConnectStateListen       WTSConnectStateEnum = WTSListen
	WTSConnectStateReset        WTSConnectStateEnum = WTSReset
	WTSConnectStateDown         WTSConnectStateEnum = WTSDown
	WTSConnectStateInit         WTSConnectStateEnum = WTSInit
)

type WTSINFO

type WTSINFO struct {
	State                   uint32
	SessionId               uint32
	IncomingBytes           uint32
	OutgoingBytes           uint32
	IncomingFrames          uint32
	OutgoingFrames          uint32
	IncomingCompressedBytes uint32
	OutgoingCompressedBytes uint32
	WinStationName          [WINSTATIONNAME_LENGTH]uint16
	Domain                  [DOMAIN_LENGTH]uint16
	UserName                [USERNAME_LENGTH + 1]uint16
	ConnectTime             int64
	DisconnectTime          int64
	LastInputTime           int64
	LogonTime               int64
	CurrentTime             int64
}

type WTSInfo

type WTSInfo struct {
	State                   WTSConnectStateEnum
	SessionID               uint
	IncomingBytes           uint
	OutgoingBytes           uint
	IncomingFrames          uint
	OutgoingFrames          uint
	IncomingCompressedBytes uint
	OutgoingCompressedBytes uint
	WinStationName          string
	Domain                  string
	UserName                string
	ConnectTime             time.Time
	DisconnectTime          time.Time
	LastInputTime           time.Time
	LogonTime               time.Time
	CurrentTime             time.Time
}

Info - go version of WTSINFO structure

type WTSSESSION_NOTIFICATION

type WTSSESSION_NOTIFICATION struct {
	Size      uint32
	SessionId uint32
}

type WTSServer

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

func OpenWTSServer

func OpenWTSServer(serverName string) *WTSServer

func (*WTSServer) Close

func (wts *WTSServer) Close()

func (*WTSServer) EnumerateSessions

func (wts *WTSServer) EnumerateSessions() ([]WTSSessionInfoStruct, error)

func (*WTSServer) LogoffSession

func (wts *WTSServer) LogoffSession(sessionID uint, wait bool) error

func (*WTSServer) QuerySessionAddressV4

func (wts *WTSServer) QuerySessionAddressV4(sessionID uint) (wrappers.WTS_CLIENT_ADDRESS, error)

func (*WTSServer) QuerySessionApplicationName

func (wts *WTSServer) QuerySessionApplicationName(sessionID uint) (string, error)

func (*WTSServer) QuerySessionClientAddress

func (wts *WTSServer) QuerySessionClientAddress(sessionID uint) (net.IP, error)

func (*WTSServer) QuerySessionClientBuildNumber

func (wts *WTSServer) QuerySessionClientBuildNumber(sessionID uint) (uint32, error)

func (*WTSServer) QuerySessionClientDirectory

func (wts *WTSServer) QuerySessionClientDirectory(sessionID uint) (string, error)

func (*WTSServer) QuerySessionClientDisplay

func (wts *WTSServer) QuerySessionClientDisplay(sessionID uint) (WTSClientDisplayStruct, error)

func (*WTSServer) QuerySessionClientHardwareId

func (wts *WTSServer) QuerySessionClientHardwareId(sessionID uint) (uint32, error)

func (*WTSServer) QuerySessionClientInfo

func (wts *WTSServer) QuerySessionClientInfo(sessionID uint) (WTSClientInfoStruct, error)

func (*WTSServer) QuerySessionClientName

func (wts *WTSServer) QuerySessionClientName(sessionID uint) (string, error)

func (*WTSServer) QuerySessionClientProductId

func (wts *WTSServer) QuerySessionClientProductId(sessionID uint) (uint16, error)

func (*WTSServer) QuerySessionClientProtocolType

func (wts *WTSServer) QuerySessionClientProtocolType(sessionID uint) (WTSClientProtocolTypeEnum, error)

func (*WTSServer) QuerySessionConnectState

func (wts *WTSServer) QuerySessionConnectState(sessionID uint) (WTSConnectStateEnum, error)

func (*WTSServer) QuerySessionDomainName

func (wts *WTSServer) QuerySessionDomainName(sessionID uint) (string, error)

func (*WTSServer) QuerySessionID

func (wts *WTSServer) QuerySessionID(sessionID uint) (uint, error)

func (*WTSServer) QuerySessionInitialProgram

func (wts *WTSServer) QuerySessionInitialProgram(sessionID uint) (string, error)

func (*WTSServer) QuerySessionIsRemoteSession

func (wts *WTSServer) QuerySessionIsRemoteSession(sessionID uint) (bool, error)

func (*WTSServer) QuerySessionSesionInfo

func (wts *WTSServer) QuerySessionSesionInfo(sessionID uint) (WTSInfo, error)

func (*WTSServer) QuerySessionUserName

func (wts *WTSServer) QuerySessionUserName(sessionID uint) (string, error)

func (*WTSServer) QuerySessionWinStationName

func (wts *WTSServer) QuerySessionWinStationName(sessionID uint) (string, error)

func (*WTSServer) QuerySessionWorkingDirectory

func (wts *WTSServer) QuerySessionWorkingDirectory(sessionID uint) (string, error)

func (*WTSServer) QueryUserToken

func (wts *WTSServer) QueryUserToken(sessionID uint) (*syscall.Handle, error)

type WTSSessionInfoStruct

type WTSSessionInfoStruct struct {
	SessionID      uint
	WinStationName string
	State          WTSConnectStateEnum
}

WTSSessionInfoStruct - go version of WTS_SESSION_INFO structure

type WTS_CLIENT_ADDRESS

type WTS_CLIENT_ADDRESS struct {
	AddressFamily uint32
	Address       [20]byte
}

type WTS_CLIENT_DISPLAY

type WTS_CLIENT_DISPLAY struct {
	HorizontalResolution uint32
	VerticalResolution   uint32
	ColorDepth           uint32
}

type WTS_INFO_CLASS

type WTS_INFO_CLASS uint32

type WTS_SESSION_INFO

type WTS_SESSION_INFO struct {
	SessionId      uint32
	WinStationName *uint16
	State          uint32
}

Directories

Path Synopsis
example
logging
Simple service that only works by printing a log message every few seconds.
Simple service that only works by printing a log message every few seconds.
runner
Simple service that only works by printing a log message every few seconds.
Simple service that only works by printing a log message every few seconds.
simple
simple does nothing except block while running the service.
simple does nothing except block while running the service.
stopPause
simple does nothing except block while running the service.
simple does nothing except block while running the service.

Jump to

Keyboard shortcuts

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