Commit abc74081 authored by Nemanja Zbiljić's avatar Nemanja Zbiljić Committed by GitHub

Support start as Windows service (#1060)

parent 9c5bf9c2
...@@ -29,10 +29,15 @@ import ( ...@@ -29,10 +29,15 @@ import (
"github.com/ethersphere/bee/pkg/node" "github.com/ethersphere/bee/pkg/node"
"github.com/ethersphere/bee/pkg/resolver/multiresolver" "github.com/ethersphere/bee/pkg/resolver/multiresolver"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
"github.com/kardianos/service"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const (
serviceName = "SwarmBeeSvc"
)
func (c *command) initStartCmd() (err error) { func (c *command) initStartCmd() (err error) {
cmd := &cobra.Command{ cmd := &cobra.Command{
...@@ -61,6 +66,19 @@ func (c *command) initStartCmd() (err error) { ...@@ -61,6 +66,19 @@ func (c *command) initStartCmd() (err error) {
return fmt.Errorf("unknown verbosity level %q", v) return fmt.Errorf("unknown verbosity level %q", v)
} }
isWindowsService, err := isWindowsService()
if err != nil {
return fmt.Errorf("failed to determine if we are running in service: %w", err)
}
if isWindowsService {
var err error
logger, err = createWindowsEventLogger(serviceName, logger)
if err != nil {
return fmt.Errorf("failed to create windows logger %w", err)
}
}
// If the resolver is specified, resolve all connection strings // If the resolver is specified, resolve all connection strings
// and fail on any errors. // and fail on any errors.
var resolverCfgs []multiresolver.ConnectionConfig var resolverCfgs []multiresolver.ConnectionConfig
...@@ -136,12 +154,15 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -136,12 +154,15 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
interruptChannel := make(chan os.Signal, 1) interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, syscall.SIGINT, syscall.SIGTERM) signal.Notify(interruptChannel, syscall.SIGINT, syscall.SIGTERM)
p := &program{
start: func() {
// Block main goroutine until it is interrupted // Block main goroutine until it is interrupted
sig := <-interruptChannel sig := <-interruptChannel
logger.Debugf("received signal: %v", sig) logger.Debugf("received signal: %v", sig)
logger.Info("shutting down") logger.Info("shutting down")
},
stop: func() {
// Shutdown // Shutdown
done := make(chan struct{}) done := make(chan struct{})
go func() { go func() {
...@@ -162,6 +183,27 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -162,6 +183,27 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
logger.Debugf("received signal: %v", sig) logger.Debugf("received signal: %v", sig)
case <-done: case <-done:
} }
},
}
if isWindowsService {
s, err := service.New(p, &service.Config{
Name: serviceName,
DisplayName: "Bee",
Description: "Bee, Swarm client.",
})
if err != nil {
return err
}
if err = s.Run(); err != nil {
return err
}
} else {
// start blocks until some interrupt is received
p.start()
p.stop()
}
return nil return nil
}, },
...@@ -175,6 +217,22 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -175,6 +217,22 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
return nil return nil
} }
type program struct {
start func()
stop func()
}
func (p *program) Start(s service.Service) error {
// Start should not block. Do the actual work async.
go p.start()
return nil
}
func (p *program) Stop(s service.Service) error {
p.stop()
return nil
}
type signerConfig struct { type signerConfig struct {
signer crypto.Signer signer crypto.Signer
address swarm.Address address swarm.Address
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !windows
package cmd
import (
"errors"
"github.com/ethersphere/bee/pkg/logging"
)
func isWindowsService() (bool, error) {
return false, nil
}
func createWindowsEventLogger(svcName string, logger logging.Logger) (logging.Logger, error) {
return nil, errors.New("cannot create Windows event logger")
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package cmd
import (
"fmt"
"io"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/debug"
"golang.org/x/sys/windows/svc/eventlog"
"github.com/ethersphere/bee/pkg/logging"
"github.com/sirupsen/logrus"
)
func isWindowsService() (bool, error) {
return svc.IsWindowsService()
}
func createWindowsEventLogger(svcName string, logger logging.Logger) (logging.Logger, error) {
el, err := eventlog.Open(svcName)
if err != nil {
return nil, err
}
winlog := &windowsEventLogger{
logger: logger,
winlog: el,
}
return winlog, nil
}
type windowsEventLogger struct {
logger logging.Logger
winlog debug.Log
}
func (l *windowsEventLogger) Tracef(format string, args ...interface{}) {
// ignore
}
func (l *windowsEventLogger) Trace(args ...interface{}) {
// ignore
}
func (l *windowsEventLogger) Debugf(format string, args ...interface{}) {
// ignore
}
func (l *windowsEventLogger) Debug(args ...interface{}) {
// ignore
}
func (l *windowsEventLogger) Infof(format string, args ...interface{}) {
l.winlog.Info(1633, fmt.Sprintf(format, args...))
}
func (l *windowsEventLogger) Info(args ...interface{}) {
l.winlog.Info(1633, fmt.Sprint(args...))
}
func (l *windowsEventLogger) Warningf(format string, args ...interface{}) {
l.winlog.Warning(1633, fmt.Sprintf(format, args...))
}
func (l *windowsEventLogger) Warning(args ...interface{}) {
l.winlog.Warning(1633, fmt.Sprint(args...))
}
func (l *windowsEventLogger) Errorf(format string, args ...interface{}) {
l.winlog.Error(1633, fmt.Sprintf(format, args...))
}
func (l *windowsEventLogger) Error(args ...interface{}) {
l.winlog.Error(1633, fmt.Sprint(args...))
}
func (l *windowsEventLogger) WithField(key string, value interface{}) *logrus.Entry {
return l.logger.WithField(key, value)
}
func (l *windowsEventLogger) WithFields(fields logrus.Fields) *logrus.Entry {
return l.logger.WithFields(fields)
}
func (l *windowsEventLogger) WriterLevel(level logrus.Level) *io.PipeWriter {
return l.NewEntry().WriterLevel(level)
}
func (l *windowsEventLogger) NewEntry() *logrus.Entry {
return l.logger.NewEntry()
}
...@@ -19,6 +19,7 @@ require ( ...@@ -19,6 +19,7 @@ require (
github.com/gorilla/mux v1.7.4 github.com/gorilla/mux v1.7.4
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/ipfs/go-log/v2 v2.1.1 // indirect github.com/ipfs/go-log/v2 v2.1.1 // indirect
github.com/kardianos/service v1.2.0
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/libp2p/go-libp2p v0.10.0 github.com/libp2p/go-libp2p v0.10.0
github.com/libp2p/go-libp2p-autonat v0.3.0 // indirect github.com/libp2p/go-libp2p-autonat v0.3.0 // indirect
...@@ -62,7 +63,7 @@ require ( ...@@ -62,7 +63,7 @@ require (
golang.org/x/mod v0.3.0 // indirect golang.org/x/mod v0.3.0 // indirect
golang.org/x/net v0.0.0-20200707034311-ab3426394381 golang.org/x/net v0.0.0-20200707034311-ab3426394381
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211
golang.org/x/text v0.3.3 // indirect golang.org/x/text v0.3.3 // indirect
golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f // indirect
google.golang.org/protobuf v1.25.0 // indirect google.golang.org/protobuf v1.25.0 // indirect
......
...@@ -409,6 +409,8 @@ github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM5 ...@@ -409,6 +409,8 @@ github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM5
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 h1:ZHuwnjpP8LsVsUYqTqeVAI+GfDfJ6UNPrExZF+vX/DQ= github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 h1:ZHuwnjpP8LsVsUYqTqeVAI+GfDfJ6UNPrExZF+vX/DQ=
github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kardianos/service v1.2.0 h1:bGuZ/epo3vrt8IPC7mnKQolqFeYJb7Cs8Rk4PSOBB/g=
github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
...@@ -1194,8 +1196,8 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w ...@@ -1194,8 +1196,8 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment