Coder Social home page Coder Social logo

service's Introduction

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.

service's People

Contributors

aleksi avatar chbuescher avatar djdv avatar inconshreveable avatar jessecarbon avatar jmccarthy avatar jvehent avatar kardianos avatar lawrencewoodman avatar mpfz0r avatar n8felton avatar nollan avatar oderwat avatar oliverkra avatar phommel avatar rnapier avatar rozenlin avatar rs avatar rusq avatar rychipman avatar simonbackx avatar steelphase avatar tgulacsi avatar tmaczukin avatar tomfeigin avatar trawler avatar turtlemonvh avatar utkarsh-extc avatar wolanx avatar zhausong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

service's Issues

Windows: Failed to start service. The service did not respond to the start or control request in a timely manner. What am i doing wrong?

Hello,

I can install the service from the command line and see the service in the windows services panel but when I try to start it I get the following.

E: 10:58:06 Failed to start Go Service Example: The service did not respond to t
he start or control request in a timely fashion.

What am I doing wrong?

package main

import (
    "flag"
    "log"
    "time"
    "github.com/kardianos/service"
    "fmt"
)

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
    for {
        fmt.Println("Working...")
        time.Sleep(3 * time.Second)
    }
}
func (p *program) Stop(s service.Service) error {
    // Stop should not block. Return with a few seconds.
    return nil
}

func main() {

    flag.Parse()

    svcConfig := &service.Config{
        Name:        "GoServiceExampleSimple",
        DisplayName: "Go Service Example",
        Description: "This is an example 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)
    }

    if len(flag.Args()) > 0 {
        err = service.Control(s, flag.Args()[0])
        if err != nil {
            logger.Error(err)
        }
        return
    }

}

Point to godoc.org in the README.

Thanks for the library. I went through the example and used simple as reference: https://github.com/kardianos/service/blob/master/example/simple/main.go

Here is my run function:

// run the program
func (p *program) run() {
configuration := InitConfiguration()

log.Printf("Running Web Socket Server")

c := wsServer.NewServer()
c.Run(port)

}

When I run my app using:

$GOROOT/bin/myApp

My app seems to block the run call forever, I was expecting Run to be executed in the background. Am I missing something here?

It would be great if you can update the README.md with additional information on usage.

Thanks once again.

service + httpserver + graceful shutdown

Hi,

I'd like to use "service" with my webservice.
I use https://github.com/facebookgo/grace for graceful shutdown.
-> server waits until connections are closed so no data gets lost.

This only works when I change your code to not being async.

// Program structures.
//  Define Start and Stop methods.
type program struct {

}

func (p *program) Start(s service.Service) error {
        //go p.run()
    //return nil
    return gracehttp.Serve(e.Routes().Server("0.0.0.0:3000"))
}

func (p *program) Stop(s service.Service) error {
    // Any work in Stop should be quick, usually a few seconds at most.
    logger.Info("I'm Stopping!")
    return nil
}

Does it have to be async? Will I have problems using "service"?

best
ps: govendor is great! Saved my sanity today :)

Start service is failed in ubuntu 10.04 version

I tried to run service in ubuntu 15,14,12...version.In these ubuntu versions service is started successfully.
When i tried to run service in ubuntu 10.04,it is showing error when am starting service.
err = s.Install()
if err != nil {
fmt.Println("service not Installed successfully, ErrorInfo : ",err)
}
err = s.Start()
if err != nil {
fmt.Println("service not Started , ErrorInfo : ",err)
}
O/P:-
service not Started , ErrorInfo : "initctl" failed: exit status 1, initctl: Unknown job: SERVICE_NAME.

why service is not started in ubuntu 10.04 version ? and service is started successfully in above versions.
Is this "github.com/kardianos/service" package is platform dependent/independent ?

Test: TestInstallRunRestartStopRemove failed.

Hi,

I have a problem with the TestInstallRunRestartStopRemove test in service_test.go. The test systematically fails:

 [go] ok          github.com/kardianos/osext      0.140s
 [go] --- FAIL: TestInstallRunRestartStopRemove (0.04s)
 [go]     service_test.go:50: restart The requested control is not valid for this service.
 [go] FAIL
 [go] FAIL        github.com/kardianos/service    0.074s

When i add sleeps between Start/Restart/Stop signals, the test is successful.

    err = s.Start()
    if err != nil {
        t.Fatal("start", err)
    }
    time.Sleep(time.Second * 1)
    err = s.Restart()
    if err != nil {
        t.Fatal("restart", err)
    }
    time.Sleep(time.Second * 1)
    err = s.Stop()
    if err != nil {
        t.Fatal("stop", err)
    }
    time.Sleep(time.Second * 1)
    err = s.Uninstall()
    if err != nil {
        t.Fatal("stop", err)
    }

I think that signals do not have the time to be processed. Do you have any idea about this problem ?

Thanks

Log message in function Stop

I don't know if this issue is a bug, but when I stop the service, it does not logs the messages in function 'Stop' (quit 3). In addition, it should log other messages like "quit 1" and "quit 2".
I don't know if it's a problem due to my code.

package main

import (
    "flag"
    "os"
    "time"

    log "github.com/Sirupsen/logrus"
    "github.com/kardianos/service"
)

var (
    FlagInstall   = flag.Bool("install", false, "install setups up the service in the OS")
    FlagUninstall = flag.Bool("uninstall", false, "uninstall removes the service from the OS")
)

func main() {
    flag.Parse()

    serviceConfig := &service.Config{
        Name:        "foo",
        DisplayName: "Foo daemon",
        Description: "tester of daemon",
        UserName:    "ubuntu",
        //Arguments:   []string{},
    }

    serv, err := service.New(Program{}, serviceConfig)
    if err != nil {
        log.Fatal(err)
    }
    serviceManager := service.ChosenSystem()

    if *FlagInstall {
        if !serviceManager.Detect() {
            log.Fatal("the service manager of this system is not available")
        }
        if err = serv.Install(); err != nil {
            log.Fatal(err)
        }
        os.Exit(0)
    } else if *FlagUninstall {
        if err = serv.Uninstall(); err != nil {
            log.Fatal(err)
        }
        os.Exit(0)
    }

    if err = serv.Run(); err != nil {
        log.Fatal(err)
    }
}

type Program struct {
    service service.Service
    //cron    *cron.Cron

    IsRunning bool
    quit      chan bool
}

func (p Program) Start(s service.Service) error {
    p.service = s
    p.quit = make(chan bool)

    ticker := time.NewTicker(20*time.Second)
    for {
        select {
        case <-ticker.C:
            if p.IsRunning {
                continue
            }
            p.IsRunning = true
            log.Info("+") // function to run for a long time
            p.IsRunning = false

        case <-p.quit:
            log.Info("quit 1")
            break
        }
    }

    log.Info("quit 2")
    ticker.Stop()
    close(p.quit)

    return nil
}

func (p Program) Stop(s service.Service) error {
    for i := 0; i < 6; i++ {
        if p.IsRunning {
            time.Sleep(5*time.Second)
            continue
        } else {
            break
        }
    }

    p.quit <- true
    log.Info("quit 3")

    return nil
}

Config.Name must not contain spaces

Service works perfect in interactive mode, but when I try to install via InstallUtil.exe I get the error:

System.BadImageFormatException:
Could not load file or assembly 'file:///C:\Projects\Go\src\github.com\jesusjjf\myservice\main.exe' or one of its dependencies. The module was expected to contain an assembly manifest..

I used the logging service example

Am I missing something? Thanks.

I am using Windows 10, but the end machine to install is a Windows Server 2012 R2

Service in Windows (logs and service ui)

Hi there, I've just tried this out and love it! Just a few questions to know if it's expected behaviour, or something to be planned in the future.

Based on example/logging code on Windows (after doing -service install and -service start :

  1. The Control Panel >> Local Services viewer does not list out the service name.
  2. net start on Windows command line does not list the service at all as running
  3. All the logs from the log viewer listed as the service has event ID 1.

Thanks

Query service state

Would be really nice to have a way to query service state - at least whether it's started or not started. I know though that Windows offers several more states (starting/stopping/paused), but I guess most of them are not applicable to other platforms, so at least basic yes/no should help.

ExecStart line is wrong created at using Arguments

When field 'Arguments' is added to 'Config', the program adds double quotes to every argument.

Looking at '/etc/systemd/system/foo.service', in field 'ExecStart':

ExecStart=/usr/bin/food "-env dev" "-run"

instead of:

ExecStart=/usr/bin/food -env dev -run

Windows Service runs, does not output log

Successfully installed the .exe as a service, and through service manager started it.

However, a logfile is not created in the same directory as the executable. Im not sure what im doing wrong, but if i run the executable through a command prompt the log is created and written to as intended.

   logFile, err := os.OpenFile("LogFile", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
   if err != nil {
     log.Fatalf(err.Error())
   }

   defer logFile.Close()
   log.SetOutput(logFile)
 ...........................

   err = processService.Run()
   if err != nil {
     log.Println(err.Error())
   }

   log.Println("Service Started")

SysV init script can lead to multiple processes running

Problem description

I noticed this when using Graylog Collector Sidecar which uses this library to generate init scripts (see here).

The init script created for SysV systems (CentOS/RedHat 6) doesn't create a consistent PID file, which can lead to multiple processes running, especially if you try restarting the process after it's already been started on boot (very common).

The template here creates a PID file using the name of the running script. The problem is that SysV scripts are symlinked from their runlevel to the main script, and the filenames are different. So the script name called on boot is different from the script called from the service command.

For example when you boot a system into a runlevel, it will look for that level's startup scripts, in this case /etc/rc.d/rc3.d/S99collector-sidecar which is actually a symlink to the main startup script:

# runlevel
N 3

# ls -lh /etc/rc.d/rc3.d/S99collector-sidecar
lrwxrwxrwx. 1 root root 27 Nov  2 15:56 /etc/rc.d/rc3.d/S99collector-sidecar -> ../init.d/collector-sidecar

This means the PID file from the init on boot is named /var/run/S99collector-sidecar.pid. Now if you try to restart the service using the service command it's going to call /etc/rc.d/init.d/collector-sidecar (NOT S99collector-sidecar), and create a PID file at /var/run/collector-sidecar.pid which is different. The result is the is_running() function doesn't find the original PID and now there's two processes running:

# service collector-sidecar restart
Not running
Starting collector-sidecar

# ps -ef | grep -i graylog
root      2819     1  0 15:58 ?        00:00:00 /usr/bin/graylog-collector-sidecar
root      2896  2819  0 15:58 ?        00:00:00 /usr/bin/filebeat -c /etc/graylog/collector-sidecar/generated/filebeat.yml
root      3070     1  0 16:00 pts/0    00:00:00 /usr/bin/graylog-collector-sidecar
root      3104  3070  0 16:00 pts/0    00:00:00 /usr/bin/filebeat -c /etc/graylog/collector-sidecar/generated/filebeat.yml

Proposed solutions

I would suggest setting the name variable to the symlink destination by using the readlink command, so this:

name=$(basename $0)

would become:

name=$(basename $(readlink -f $0))

Now both scripts result in the same filename, whether they were executed via symlink or not:

# basename $(readlink -f /etc/rc.d/init.d/collector-sidecar)
collector-sidecar

# basename $(readlink -f /etc/rc.d/rc3.d/S99collector-sidecar)
collector-sidecar

Optionally (or in addition to this), you could make the name variable itself be configurable in the template so that it can be set statically. Not sure if the template language supports optional parameters.

Windows 10 Defender

Windows 10 Defender considers the 'simple' example as malware and deletes it.

double quotes in ExecPath for systemd service config file breaks start command

On CentOS 7, when the service config file gets written, the field value for ExecPath ends up quoted with double quotes. Printing out my strings before calling the service start looks like there are no double quotes embedded in the string.

/etc/systemd/system/myservice.service looks like:

...
[Service]
ExecPath="/path/to/my/service/myservice"
...

When I try to start, I get:

Failed to issue method call: Unit myservice.service failed to load: Invalid argument. See system logs and 'systemctl status myservice.service' for details.

If I remove the double quotes, disable and reenable the service, it will start fine.

Is there any way to get this field written without the quotes?

thanks
alf

Windows: The Service did not respond to the start or control request in a timely fashion

Hey There! I'ven been using your liberary with success on OSX and Linux but my service fails to start on windows with the error "The service did not respond to the start or control request in a timely fashion". And to get the obvious out of the way my .Start() method doesn't block and starts a goroutine as shown in the examples.

I have limited understanding of windows services but it looks like some callback from the manager takes to long to complete. How can I debug this callback and find out why it is behaving this way?

The source can be found here, the relevant files are main.go and server.go (containing my .Start() and .Run()).

centos7 fails due to chkconfig

the file is in "/etc/rc.d/init.d"
named "mytest"

why can not do this
chkconfig --add mytest

look:

[root@localhost init.d]# chkconfig --add mytest
service mytest does not support chkconfig

give me some help ,thank you very mutch

[MacOS] service start/stop doesn't return error if not installed yet

On macOS Sierra, launchctl load and launchctl unload seems to return 0 (success) even if the config file doesn't exists.

Example:

$ launchctl load /invalid/file/location.plist
/invalid/file/location.plist: No such file or directory
$ echo $?
0

And this has a side effect in this library...

service_darwin.go:

func (s *darwinLaunchdService) Start() error {
	confPath, err := s.getServiceFilePath()
	if err != nil {
		return err
	}
	return run("launchctl", "load", confPath)
}

Doesn't return an error if the service isn't installed yet.

service_unix.go:

func run(command string, arguments ...string) error {
	cmd := exec.Command(command, arguments...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("%q failed: %v, %s", command, err, out)
	}
	return nil
}

Checking for "No such file or directory" could help solve this issue.

Why KeepAlive is default in launchd in osx?

http://apple.stackexchange.com/questions/159532/how-do-i-associate-a-launchd-2-plist-with-its-domain-and-service-targets

Apple suggest avoiding KeepAlive and RunAtLoad because the intention is to avoid ever launching a process without a guarantee of work to be done. Both keys remain and are required for many tasks.

Upstart in linux do the same thing too.

I think it should look like apache2 in ubuntu,the service do not care about keepalive default.

Ps: I can not find any document of this behavior.Is this behavior same across all platform?

Relaunch on crash should be consistent among systems or configurable.

Installing a service allows it to start on boot and in some cases relaunch on crash, but this option is not configurable and is different among different systems, for example:

  • With systemd it will restart after 120 seconds if it crashed
  • With upstart it will restart after 5 seconds but only 10 times
  • With systemv it won't restart (I think)

Should this be part of the "Specific Options" for each system?

Install LaunchAgent on mac under /Library

Currently, when you install a LaunchAgent under MacOS X, it installs it under ~/Library/LaunchAgents.

It would be handy in some cases if you could create an option to install it under /Library/LaunchAgents so that they get loaded for all users.

Choosing linux flavor

The choice of init system on linux is currently determined as follows:

Use systemd if available.
If not, use upstart if available.
If not, use sysvinit.

sysvinit and systemd are mutually exclusive choices because they both only run as pid 1. But it's possible to have upstart installed in addition to sysvinit or systemd, and the caller may have a preference of which they would like to use.

I want different behavior. Specifically: use systemd if available. If not, use upstart. If not, then fail. sysvinit is not an acceptable service manager for me because it does not restart failed processes.

I guess, on the overall, my preference would be to modify the API as follows:

  • Expose System as an exported variable
  • Expose RunningSystem interface
  • Modify RunningSystem interface to include a new method Available() bool
  • Expose each available service system on the current platform as a variable. So for darwin, it would only be Launchd. But on linux, there would be SysvInit, Upstart and Systemd
  • Remove Platform() and Interactive(). These can both now be accessed via System.String() and System.Interactive(), respectively.

This would allow callers to override the choice of flavor if they so desired. It would further open up the ability for kardianos/service to support other service-running systems like supervisord or runit, if someone wanted to add support for that in the future.

Thoughts?

windows winrm: cannot install using internal install method

When installing a windows service via WinRM (via ansible), we get an error saying that "The service process could not connect to the service controller."

This was originally reported in Telegraf: influxdata/telegraf#1760

and here is the issue text:

System info:

Win2012R2

Steps to reproduce:

Running in powershell/console works OK (both interactive and installing the service)
Deploying via winrm (ansible) on the same box rc:0, no stdout or stderr output + eventlog error.

  1. execute telegraf.exe via ansible's raw module (powershell via winrm)
  2. check output (rc:0, no err/stdout) + eventID3 in eventlog

Expected behavior:

installing/running telegraf
rc:0, stderr NOT "" and/or stdout NOT "" and no eventID

Actual behavior:

"rc": 0, "stderr": "", "stdout": "", "stdout_lines": [] + eventID:3 "The service process could not connect to the service controller."

Use case:

testing telegraf on windows works fine, mass-deploying it using ansible (or any other deployment method that uses winrm) doesn't, and this is a blocker for using telegraf on windows.

Using the service flag with Install/Stop/Uninstall/Start hangs

Hi,

This is a very cool project and I'm trying to understand some of the implementation details. To help me understand it some, I ganked some code out of issue #62 and wrote a simple web server that just echoes requests it receives.

Here's the code:

package main

import (
    "bytes"
    "flag"
    "github.com/kardianos/service"
    "log"
    "net"
    "strings"
    "time"
)

var logger service.Logger

type program struct {
    exit chan struct{}
}

func (p *program) Start(s service.Service) error {
    tcpAddr, err := net.ResolveTCPAddr("tcp4", ":1201")
    if err != nil {
        log.Fatal("Failed to discover local address:", err)
    }
    listener, err := net.ListenTCP("tcp4", tcpAddr)
    if err != nil {
        log.Fatal("Failed to create a listener:", err)
    }
    p.exit = make(chan struct{})
    go p.run(listener)
    return nil
}

func (p *program) run(listener net.Listener) {
    ticker := time.NewTicker(2 * time.Second)
    for {
        select {
        case _ = <-ticker.C:
            for {
                conn, err := listener.Accept()
                if err != nil {
                    continue
                }
                go handleRequest(conn)
            }
        case <-p.exit:
            ticker.Stop()
            return
        }
    }
}

func (p *program) Stop(s service.Service) error {
    close(p.exit)
    return nil
}

func handleRequest(conn net.Conn) {
    defer conn.Close()
    var buf [1024]byte
    for {
        _, err := conn.Read(buf[0:])
        if err != nil {
            return
        }
        request := string(bytes.Trim(buf[:], "\x00"))
        request = strings.Replace(request, "\n", "", -1)
        request = strings.Replace(request, "\r", "", -1)
        _, err = conn.Write([]byte("OK\n" + request))
        if err != nil {
            log.Println("error:", err)
        }
    }
}

func main() {
    svcFlag := flag.String("service", "", "Control this binary as a service")
    flag.Parse()

    svcConfig := &service.Config{
        Name:        "TestingService",
        DisplayName: "Testing some stuff",
        Description: "A longer description",
    }
    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)
    }
    if len(*svcFlag) != 0 {
        err := service.Control(s, *svcFlag)
        if err != nil {
            log.Printf("Valid actions: %q\n", service.ControlAction)
            log.Fatal(err)
        }
    }
    err = s.Run()
    if err != nil {
        logger.Error(err)
    }
}

My guess is that the nested for loops under the run() function are what's causing the trouble, maybe.

When I build this code and run it as ./go-service-test -service install it just hangs. However, while it's hanging there, I am able to do:

echo 'blah' | nc [IP of host] 1201
OK
blah

After pressing ctrl+c and then running ./go-service-test -service start I get:

Failed to create a listener:listen tcp4 :1201: bind: address already in use

Running ./go-service-test -service stop also hangs.

What part of the documentation am I missing that would help me understand how to do a proper implementation?

logging example

Just testing this out.
I am using your logging example because it gives interactive feedback to get me going.

My use case if that i need to start the following up on a windows machine, in the following order:

  • rethinkdb.exe
  • a golang appserver (that uses rethinkdb)
  • a golang webserver
  • google chrome portable (a simple exe), that when opened calls the golang webserver

So far:
I used goxc to build for windows, mac and linux.
Easy.

So i have the logging binary, but not sure how to control it ???

the ability to set the Recovery options

I believe the current service package doesn't not offer the ability to set the recovery options for windows, such as on first failure, second failure, subsequent failure, to restart the service, or restart the computer.

s, err = m.CreateService(ws.Name, exepath, mgr.Config{
    DisplayName:      ws.DisplayName,
    Description:      ws.Description,
    StartType:        mgr.StartAutomatic,
    ServiceStartName: ws.UserName,
    Password:         ws.Option.string("Password", ""),
    Dependencies:     ws.Dependencies,
}, ws.Arguments...)

mgr.Config type

type Config struct {
    ServiceType      uint32
    StartType        uint32
    ErrorControl     uint32
    BinaryPathName   string // fully qualified path to the service binary file, can also include arguments for an auto-start service
    LoadOrderGroup   string
    TagId            uint32
    Dependencies     []string
    ServiceStartName string // name of the account under which the service should run
    DisplayName      string
    Password         string
    Description      string
}

what's the best way to set my service to restart on failure ?

remove options in service.Config to make code clear

WorkingDirectory is not work on every supported system.
KeepAlive is work on osx and upstart, and not work on system-V.

I think it is a good idea to put all options in the service.Config,remove the Option field in service.Config and add a comment about which system support which options.

unwanted quotes around parameters

I want to send parameters to the service when it starts so I use code like

svcConfig.Arguments = append(svcConfig.Arguments, "--conf=/foo/bar/conf.file")
err = s.Install()

This generates init script (I tested with upstart) where the exec command looks like

exec /path/service "--conf=/foo/bar/conf.file"

ie there are quotes around parameter which makes it fail (the script is syntactically valid but doesn't do what I want it to do; the service won't receive the param).
Is it a bug or I'm using it wrong?

Process Terminated Unexpectedly error in windows

Im getting the below error msg while stopping the service in windows server 2008 r2.

Errror 1067 :process terminated unexpectedly

Here is my code

package main

import (
	"flag"
	"net"
	"net/http"
	"github.com/kardianos/service"
"./mygopackage"
)

var logger service.Logger
var ln net.Listener

type program struct {
	exit chan struct{}
}

func (p *program) Start(s service.Service) error {
	if service.Interactive() {
		logger.Info("Running in terminal.")
	} else {
		logger.Info("Running under service manager.")
	}
	p.exit = make(chan struct{})
	// Start should not block. Do the actual work async.
	go p.run()
	return nil
}
func (p *program) run() {
	log.Info("Listening on :8081")
	ln, err := net.Listen("tcp", ":8081")
	if err != nil {
		log.Error("Err listening specified port:", err)
	}
go mygopackage.do()
	http.HandleFunc("/plugins", plugins)
	http.Serve(ln, nil)
}
func (p *program) Stop(s service.Service) error {
	// Any work in Stop should be quick, usually a few seconds at most.
	ln.Close()

	log.Info("Stopping SaaSAgent...!")
	close(p.exit)
	return nil
}
func main() {
	svcFlag := flag.String("service", "", "Control the system service.")
	flag.Parse()
	svcConfig := &service.Config{
		Name:        "myapp",
		DisplayName: "myapp",
		Description: "myapp Service :)",
	}
	prg := &program{}
	s, err := service.New(prg, svcConfig)
	if err != nil {
		log.Error(err)
	}
	errs := make(chan error, 5)
	logger, err = s.Logger(errs)
	if err != nil {
		log.Error(err)
	}
	go func() {
		for {
			err := <-errs
			if err != nil {
				log.Error(err)
			}
		}
	}()

	if len(*svcFlag) != 0 {
		err := service.Control(s, *svcFlag)
		if err != nil {
			log.Info("Valid actions: %q\n", service.ControlAction)
			log.Error(err)
		}
		return
	}
	err = s.Run()
	if err != nil {
		logger.Error(err)
	}
}

Did I do any mistake?

[Windows] Error 1067 when I tried to start service whithin go-ini

I tried to use go-ini to load some configuration when I start my application, and I did run the program as normal as I expected if double click the .exe file, while the error occurred and failed to start it as a service.
I have tried to get rid of the go-ini and it did start the service successfully.

systemd on Ubuntu 16.04 has wrong WorkingDirectory

With current master, upon installing the service, I get a config file like the following:

[Unit]
Description=xxx
ConditionFileIsExecutable=/var/www/xxx/xxx

[Service]
StartLimitInterval=5
StartLimitBurst=10
ExecStart=/var/www/xxx/xxx
RootDirectory="/var/www/xxx"
WorkingDirectory="/var/www/xxx"



Restart=always
RestartSec=120

[Install]
WantedBy=multi-user.target

However, the application gets a working directory of / . syslog from the install shows:

Jun  3 20:59:18 xxx systemd[1]: Reloading.
Jun  3 20:59:18 xxx systemd[1]: [/etc/systemd/system/xxx.service:9] Not an absolute path, ignoring: "/var/www/xxx"
Jun  3 20:59:18 traininglocker systemd[1]: [/etc/systemd/system/xxx.service:10] Working directory path '"/var/www/xxx"' is not absolute, ignoring.
Jun  3 20:59:18 xxx systemd[1]: apt-daily.timer: Adding 10h 2min 11.830881s random time.
Jun  3 20:59:18 xxx systemd[1]: Reloading.
Jun  3 20:59:18 xxx systemd[1]: [/etc/systemd/system/xxx.service:9] Not an absolute path, ignoring: "/var/www/xxx"
Jun  3 20:59:18 xxx systemd[1]: [/etc/systemd/system/xxx.service:10] Working directory path '"/var/www/xxx"' is not absolute, ignoring.

When I removed the quotes around the WorkingDirectory item (but not RootDirectory), and ran systemctl daemon-reload, the service started as expected, with the correct working directory.

As a side note, if I removed quotes from the RootDirectory item, the service wouldn't start, it complained about the application name.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.