Running Go binary as System service

Running a Go Binary as system service

Go is often used to create cli applications of various forms, these can be developer tooling,automation tools or machine agents. The Go binary can run on any system without having install the Go runtime or compiler. CLI applications in Go can be executed by directly executing the binary as:

./binary

This is only suitable for running for testing purposes and it does also not gurantee that it will be running always. There are various approaches to make this run continously and the approach we are going to see is how to run it as a system service on Linux platforms.

Let’s take a very simple program of counting the occurrences of a substring since our main aim is just to have an undertsanding of how to run this as a system service:

package main

import (
	"fmt"
	"log"
	"os"
	"strings"
)

var (
	WarningLogger *log.Logger
	InfoLogger    *log.Logger
	ErrorLogger   *log.Logger
)

func init() {
	file, err := os.OpenFile("syslog.log", os.O_APPEND|os.O_RDWR|os.O_CREATE, 0666)
	if err != nil {
		fmt.Printf("Error opening log file %v", err)
	}

	InfoLogger = log.New(file, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
	WarningLogger = log.New(file, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile)
	ErrorLogger = log.New(file, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)

}

func main() {

	var str string = "Hello, there how is it going?"
	var manyD = "ddddddddddd"
	InfoLogger.Printf("Number of H’s in %s is: ", str)
	InfoLogger.Printf("%d\n", strings.Count(str, "H"))
	InfoLogger.Printf("Number of double d’s in %s is: ", manyD)
	InfoLogger.Printf("%d\n", strings.Count(manyD, "dd"))
}

We are also using the logger system provided by to log the output to a log file.

The steps:

  1. First compile the program and generate the binary as:

    go build main.go
    
  2. You can create a directory in any location,for this purpose I have created a directory substring and put in the binary file there.

  3. Create a main.service file in the following location /lib/systemd/system/ with the following contents:

         ```
         [Unit]
         Description=Substring Service
         ConditionPathExists=/opt/substring
         After=network.target
    
         [Service]
         Type=simple
         User=root
         Group=root
         LimitNOFILE=1024
    
         Restart=on-failure
         RestartSec=10
    
    
         WorkingDirectory=/opt/substring/
         ExecStart=/opt/substring/main
         PermissionsStartOnly=true
         SyslogIdentifier=root
    
         [Install]
         WantedBy=multi-user.target
         ```
    
  4. Change the permission of the service file as

    sudo chmod 755 /lib/systemd/system/main.service
    
    
  5. Now in the final steps, enable the service and start it:

    sudo systemctl daemon-reload
    sudo systemctl enable main
    systemctl start main
    journalctl -u main
    journalctl -f -u main
    

That’s it and your Go binary will start running as a system service.