Documentation ¶
Overview ¶
Package daemon 0.11.0 for use with Go (golang) services.
Package daemon provides primitives for daemonization of golang services. This package is not provide implementation of user daemon, accordingly must have root rights to install/remove service. In the current implementation is only supported Linux and Mac Os X daemon.
Example:
// Example of a daemon with echo service package main import ( "fmt" "log" "net" "os" "os/signal" "syscall" "github.com/takama/daemon" ) const ( // name of the service name = "myservice" description = "My Echo Service" // port which daemon should be listen port = ":9977" ) // dependencies that are NOT required by the service, but might be used var dependencies = []string{"dummy.service"} var stdlog, errlog *log.Logger // Service has embedded daemon type Service struct { daemon.Daemon } // Manage by daemon commands or run the daemon func (service *Service) Manage() (string, error) { usage := "Usage: myservice install | remove | start | stop | status" // if received any kind of command, do it if len(os.Args) > 1 { command := os.Args[1] switch command { case "install": return service.Install() case "remove": return service.Remove() case "start": return service.Start() case "stop": return service.Stop() case "status": return service.Status() default: return usage, nil } } // Do something, call your goroutines, etc // Set up channel on which to send signal notifications. // We must use a buffered channel or risk missing the signal // if we're not ready to receive when the signal is sent. interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM) // Set up listener for defined host and port listener, err := net.Listen("tcp", port) if err != nil { return "Possibly was a problem with the port binding", err } // set up channel on which to send accepted connections listen := make(chan net.Conn, 100) go acceptConnection(listener, listen) // loop work cycle with accept connections or interrupt // by system signal for { select { case conn := <-listen: go handleClient(conn) case killSignal := <-interrupt: stdlog.Println("Got signal:", killSignal) stdlog.Println("Stoping listening on ", listener.Addr()) listener.Close() if killSignal == os.Interrupt { return "Daemon was interrupted by system signal", nil } return "Daemon was killed", nil } } // never happen, but need to complete code return usage, nil } // Accept a client connection and collect it in a channel func acceptConnection(listener net.Listener, listen chan<- net.Conn) { for { conn, err := listener.Accept() if err != nil { continue } listen <- conn } } func handleClient(client net.Conn) { for { buf := make([]byte, 4096) numbytes, err := client.Read(buf) if numbytes == 0 || err != nil { return } client.Write(buf[:numbytes]) } } func init() { stdlog = log.New(os.Stdout, "", log.Ldate|log.Ltime) errlog = log.New(os.Stderr, "", log.Ldate|log.Ltime) } func main() { srv, err := daemon.New(name, description, dependencies...) if err != nil { errlog.Println("Error: ", err) os.Exit(1) } service := &Service{srv} status, err := service.Manage() if err != nil { errlog.Println(status, "\nError: ", err) os.Exit(1) } fmt.Println(status) }
Go daemon ¶
Package daemon windows version
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ( // ErrUnsupportedSystem appears if try to use service on system which is not supported by this release ErrUnsupportedSystem = errors.New("Unsupported system") // ErrRootPrivileges appears if run installation or deleting the service without root privileges ErrRootPrivileges = errors.New("You must have root user privileges. Possibly using 'sudo' command should help") // ErrAlreadyInstalled appears if service already installed on the system ErrAlreadyInstalled = errors.New("Service has already been installed") // ErrNotInstalled appears if try to delete service which was not been installed ErrNotInstalled = errors.New("Service is not installed") // ErrAlreadyRunning appears if try to start already running service ErrAlreadyRunning = errors.New("Service is already running") // ErrAlreadyStopped appears if try to stop already stopped service ErrAlreadyStopped = errors.New("Service has already been stopped") )
View Source
var ( // WinErrCode - List of system errors from Microsoft source: // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681385(v=vs.85).aspx WinErrCode = map[int]SystemError{ 5: SystemError{ Title: "ERROR_ACCESS_DENIED", Description: "Access denied.", Action: "Administrator access is needed to install a service.", }, 1051: SystemError{ Title: "ERROR_DEPENDENT_SERVICES_RUNNING", Description: "A stop control has been sent to a service that other running services are dependent on.", }, 1052: SystemError{ Title: "ERROR_INVALID_SERVICE_CONTROL", Description: "The requested control is not valid for this service.", }, 1053: SystemError{ Title: "ERROR_SERVICE_REQUEST_TIMEOUT", Description: "The service did not respond to the start or control request in a timely fashion.", }, 1054: SystemError{ Title: "ERROR_SERVICE_NO_THREAD", Description: "A thread could not be created for the service.", }, 1055: SystemError{ Title: "ERROR_SERVICE_DATABASE_LOCKED", Description: "The service database is locked.", }, 1056: SystemError{ Title: "ERROR_SERVICE_ALREADY_RUNNING", Description: "An instance of the service is already running.", }, 1057: SystemError{ Title: "ERROR_INVALID_SERVICE_ACCOUNT", Description: "The account name is invalid or does not exist, or the password is invalid for the account name specified.", }, 1058: SystemError{ Title: "ERROR_SERVICE_DISABLED", Description: "The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.", }, 1060: SystemError{ Title: "ERROR_SERVICE_DOES_NOT_EXIST", Description: "The specified service does not exist as an installed service.", }, 1061: SystemError{ Title: "ERROR_SERVICE_CANNOT_ACCEPT_CTRL", Description: "The service cannot accept control messages at this time.", }, 1062: SystemError{ Title: "ERROR_SERVICE_NOT_ACTIVE", Description: "The service has not been started.", }, 1063: SystemError{ Title: "ERROR_FAILED_SERVICE_CONTROLLER_CONNECT", Description: "The service process could not connect to the service controller.", }, 1064: SystemError{ Title: "ERROR_EXCEPTION_IN_SERVICE", Description: "An exception occurred in the service when handling the control request.", }, 1066: SystemError{ Title: "ERROR_SERVICE_SPECIFIC_ERROR", Description: "The service has returned a service-specific error code.", }, 1068: SystemError{ Title: "ERROR_SERVICE_DEPENDENCY_FAIL", Description: "The dependency service or group failed to start.", }, 1069: SystemError{ Title: "ERROR_SERVICE_LOGON_FAILED", Description: "The service did not start due to a logon failure.", }, 1070: SystemError{ Title: "ERROR_SERVICE_START_HANG", Description: "After starting, the service hung in a start-pending state.", }, 1071: SystemError{ Title: "ERROR_INVALID_SERVICE_LOCK", Description: "The specified service database lock is invalid.", }, 1072: SystemError{ Title: "ERROR_SERVICE_MARKED_FOR_DELETE", Description: "The specified service has been marked for deletion.", }, 1073: SystemError{ Title: "ERROR_SERVICE_EXISTS", Description: "The specified service already exists.", }, 1075: SystemError{ Title: "ERROR_SERVICE_DEPENDENCY_DELETED", Description: "The dependency service does not exist or has been marked for deletion.", }, 1077: SystemError{ Title: "ERROR_SERVICE_NEVER_STARTED", Description: "No attempts to start the service have been made since the last boot.", }, 1078: SystemError{ Title: "ERROR_DUPLICATE_SERVICE_NAME", Description: "The name is already in use as either a service name or a service display name.", }, 1079: SystemError{ Title: "ERROR_DIFFERENT_SERVICE_ACCOUNT", Description: "The account specified for this service is different from the account specified for other services running in the same process.", }, 1083: SystemError{ Title: "ERROR_SERVICE_NOT_IN_EXE", Description: "The executable program that this service is configured to run in does not implement the service.", }, 1084: SystemError{ Title: "ERROR_NOT_SAFEBOOT_SERVICE", Description: "This service cannot be started in Safe Mode.", }, } )
Functions ¶
Types ¶
type Daemon ¶
type Daemon interface { // Install the service into the system Install(args ...string) (string, error) // Remove the service and all corresponding files from the system Remove() (string, error) // Start the service Start() (string, error) // Stop the service Stop() (string, error) // Status - check the service status Status() (string, error) // Run - run executable service Run(e Executable) (string, error) }
Daemon interface has a standard set of methods/commands
type Executable ¶ added in v0.11.0
type Executable interface { // Start - non-blocking start service Start() // Stop - non-blocking stop service Stop() // Run - blocking run service Run() }
Executable interface defines controlling methods of executable service
type SystemError ¶ added in v0.11.0
SystemError contains error description and corresponded action helper to fix it
Source Files ¶
Click to show internal directories.
Click to hide internal directories.