Running GO as a Windows Service

Lately I've been spending time writing GO (or GOLANG) applications. I'm a big fan of the language. Often what I write needs to run as a Windows service. I've found a few things you can do to make your life easier.

Use a Shell

There are three "shells" I've found that you can wrap your code in. That means you plug your code into these "shell" applications.

  • The standard GO Windows service shell. This provides basic functionality to install, debug, remove, start, and stop the service. It also includes a package to write to the Windows Event Log.
  • My modified version of the GO Windows service shell at https://github.com/billgraziano/go-windows-svc. It includes all the features of the official version and adds a few things I've found helpful.
    • The code is reorganized to make it more explicit where to make your changes and add your code. All your work can be done in main.go.
    • It has a setup() routine that will exit the service if it returns an error. I use that to configure basic logging and configuration and anything else I can't continue without.
    • I added the excellent https://github.com/pkg/errors package for better errors.
  • The Kardianos "service" package. This works on Windows, Linux, OSX, etc. I haven't worked with it but it seems well used. If I'd known this was available when I was starting I might be using it instead.

Fix the Directory

Windows services run in C:\windows\system32 by default. So that's where your logging will probably go. And that's where it will look for configuration files. I use code like this to look for these next to my executable.

var s string  
var err error  
s, err = os.Executable()  
if err != nil {  
  return "", errors.Wrap(err, "os.executable")
}
ext := filepath.Ext(s)  
outfile := s[0:len(s)-len(ext)] + ".toml"  
return outfile, nil  

Change the Startup Account

After installing the service, I usually change it to run as a domain or managed service account if there's database access involved. You'll also need to set it to start Automatically.

Grant Permissions on the Directory

And of course, that service account probably won't have permissions to read your configuration file or write to a log file. So make sure to grant those on the directory where your EXE lives.

Check the Event Log

If you're using my shell or the GO version, any errors preventing the service from starting should be logged to the Windows Application Log. I'm not sure about the Kardionos version.