github.com/aldelo/common@v1.5.1/wrapper/systemd/systemd.go (about)

     1  package systemd
     2  
     3  /*
     4   * Copyright 2020-2023 Aldelo, LP
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   *     http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  import (
    20  	"github.com/kardianos/service"
    21  	"log"
    22  )
    23  
    24  // =====================================================================================================================
    25  // systemd service setup info
    26  // =====================================================================================================================
    27  
    28  /*
    29  	xyz.service for linux systemd setup
    30  
    31  	1) create file 'xyz.service' with following content:
    32  			xyz = name of service app program
    33  
    34  	[Unit]
    35  	Description=XYZ App Title
    36  	After=network.target
    37  	StartLimitIntervalSec=0
    38  
    39  	[Service]
    40  	Type=simple
    41  	ExecStart=/home/ubuntu/xyzFolder/xyzAppName -svc -port=8080
    42  	WorkingDirectory=/home/ubuntu/xyzFolder
    43  	User=ubuntu
    44  	StandardOutput=console
    45  	Restart=always
    46  	RestartSec=1
    47  
    48  	[Install]
    49  	WantedBy=multi-user.target
    50  	Alias=xyzAppName.service
    51  
    52  	2) place 'xyz.service' file at home directory
    53  	3) note: port 80 seems to be restricted on ubuntu, so we use port 8080 rather than having to reconfigure the os
    54  	4) note: -svc -port=8080 are optional based on the xyzAppName flags
    55  
    56  	5) place the xyz.service file to '/etc/systemd/system'
    57  			$> sudo cp xyz.service /etc/systemd/system
    58  
    59  	6) to enable and load service
    60  			$> sudo systemctl enable xyz.service
    61  	7) to start service
    62  			$> sudo systemctl start xyz.service
    63  	8) to stop service
    64  			$> sudo systemctl stop xyz.service
    65  	9) to disable service
    66  			$> sudo systemctl disable xyz.service
    67  */
    68  
    69  /*
    70  	Windows OS Service Creation
    71  
    72  	*) assuming xyz.exe (output from GOOS=windows GOARCH=amd64 go build) is located in windows folder c:\xyzFolder,
    73  			be sure to place any dependency files into this folder or its sub folders as well.
    74  	*) assuming the desired windows service name is xyzService (name it any valid windows service name desired)
    75  
    76  	Create Windows Service Step:
    77  		c:\sc.exe create xyzService binpath= c:\xyzFolder\xyz.exe type= own start= auto
    78  
    79  	More Info, See https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create
    80  */
    81  
    82  // =====================================================================================================================
    83  // systemd usage in main.go
    84  // =====================================================================================================================
    85  
    86  /*
    87  	func main() {
    88  		//
    89  		// define service program base
    90  		//
    91  		svc := &systemd.ServiceProgram{
    92  			ServiceName: "abc.xyz",
    93  			DisplayName: "App Name Descriptive",
    94  			Description: "More info about the app service",
    95  
    96  			Port: 8080,							// port that this service will run on, if port is not used, set to 0
    97  			StartServiceHandler: startHandler,	// startHandler is a function that performs service launch code, such as starting web server or micro service
    98  			StopServiceHandler: stopHandler,	// stopHandler is a function that performs service stop code, such as clean up
    99  		}
   100  
   101  		//
   102  		// launch service
   103  		//
   104  		svc.Launch()
   105  	}
   106  
   107  	func startHandler(port int) {
   108  		// place application logic in handler
   109  		// such as setup gin handlers and start logic handling services etc
   110  	}
   111  
   112  	func stopHandler() {
   113  		// place applicatipn clean up code here
   114  	}
   115  */
   116  
   117  // ---------------------------------------------------------------------------------------------------------------------
   118  // service base definition
   119  // ---------------------------------------------------------------------------------------------------------------------
   120  
   121  // define service logger
   122  var logger service.Logger
   123  
   124  // ServiceProgram defines service program
   125  type ServiceProgram struct {
   126  	ServiceName string
   127  	DisplayName string
   128  	Description string
   129  
   130  	Port                int
   131  	StartServiceHandler func(port int)
   132  	StopServiceHandler  func()
   133  }
   134  
   135  // Launch will initialize and start the service for operations
   136  //
   137  // Launch is called from within main() to start the service
   138  func (p *ServiceProgram) Launch() {
   139  	//
   140  	// define service configuration
   141  	//
   142  	svcConfig := &service.Config{
   143  		Name:        p.ServiceName,
   144  		DisplayName: p.DisplayName,
   145  		Description: p.Description,
   146  	}
   147  
   148  	//
   149  	// instantiate service object
   150  	//
   151  	svc, err := service.New(p, svcConfig)
   152  
   153  	if err != nil {
   154  		log.Fatalf("%s Init Service Failed: %s", p.ServiceName, err.Error())
   155  	}
   156  
   157  	//
   158  	// setup logger
   159  	//
   160  	logger, err = svc.Logger(nil)
   161  
   162  	if err != nil {
   163  		log.Fatalf("%s Init Logger Failed: %s", p.ServiceName, err.Error())
   164  	}
   165  
   166  	//
   167  	// run the service
   168  	//
   169  	err = svc.Run()
   170  
   171  	if err != nil {
   172  		log.Fatalf("%s Run Service Failed: %s", p.ServiceName, err.Error())
   173  	}
   174  }
   175  
   176  // Start the service
   177  func (p *ServiceProgram) Start(s service.Service) error {
   178  	// start service - do not block, actual work should be done async
   179  	go p.run()
   180  	return nil
   181  }
   182  
   183  // run is async goroutine to handle service code
   184  func (p *ServiceProgram) run() {
   185  	// do actual work async in this go-routine
   186  	log.Println("Starting Service Program...")
   187  
   188  	if p != nil {
   189  		if p.Port >= 0 && p.Port < 65535 {
   190  			// run service handler
   191  			if p.StartServiceHandler != nil {
   192  				log.Println("Start Service Handler Invoked...")
   193  				p.StartServiceHandler(p.Port)
   194  			}
   195  		}
   196  	}
   197  }
   198  
   199  // Stop will stop the service
   200  func (p *ServiceProgram) Stop(s service.Service) error {
   201  	// stop the service, should not block
   202  	log.Println("Stopping Service Program...")
   203  
   204  	if p != nil {
   205  		if p.StopServiceHandler != nil {
   206  			log.Println("Stop Service Handler Invoked...")
   207  			p.StopServiceHandler()
   208  		}
   209  	}
   210  
   211  	return nil
   212  }