• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

daemon/H04-Oct-2016-

gsptcall/H04-Oct-2016-

.travis.ymlH A D04-Oct-2016358

README.mdH A D04-Oct-201610 KiB

service.goH A D04-Oct-20168.2 KiB

service_test.goH A D04-Oct-20161.1 KiB

service_unix.goH A D04-Oct-20164.5 KiB

service_windows.goH A D04-Oct-20166.5 KiB

README.md

1service: Write daemons in Go
2============================
3
4[![GoDoc](https://godoc.org/gopkg.in/hlandau/service.v2?status.svg)](https://godoc.org/gopkg.in/hlandau/service.v2) [![Build Status](https://travis-ci.org/hlandau/service.svg?branch=master)](https://travis-ci.org/hlandau/service)
5
6This package enables you to easily write services in Go such that the following concerns are taken care of automatically:
7
8  - Daemonization
9  - Fork emulation (not recommended, though)
10  - PID file creation
11  - Privilege dropping
12  - Chrooting
13  - Status notification (supports setproctitle and systemd notify protocol; this support is Go-native and does not introduce any dependency on any systemd library)
14  - Operation as a Windows service
15  - Orderly shutdown
16
17Standard Interface
18------------------
19
20Here's a usage example:
21
22```go
23import "gopkg.in/hlandau/service.v2"
24import "gopkg.in/hlandau/easyconfig.v1"
25
26func main() {
27  easyconfig.ParseFatal(nil, nil)
28
29  service.Main(&service.Info{
30      Title:       "Foobar Web Server",
31      Name:        "foobar",
32      Description: "Foobar Web Server is the greatest webserver ever.",
33
34      RunFunc: func(smgr service.Manager) error {
35          // Start up your service.
36          // ...
37
38          // Once initialization requiring root is done, call this.
39          err := smgr.DropPrivileges()
40          if err != nil {
41              return err
42          }
43
44          // When it is ready to serve requests, call this.
45          // You must call DropPrivileges first.
46          smgr.SetStarted()
47
48          // Optionally set a status.
49          smgr.SetStatus("foobar: running ok")
50
51          // Wait until stop is requested.
52          <-smgr.StopChan()
53
54          // Do any necessary teardown.
55          // ...
56
57          // Done.
58          return nil
59      },
60  })
61}
62```
63
64You should import the package as "gopkg.in/hlandau/service.v2". Compatibility will be preserved. (Please note that this compatibility guarantee does not extend to subpackages.)
65
66Simplified Interface
67--------------------
68
69If you implement the following interface, you can use the simplified interface. This example also demonstrates how to use easyconfig to handle your configuration.
70
71```go
72  func() (Runnable, error)
73
74  type Runnable interface {
75    Start() error
76    Stop() error
77  }
78```
79
80Usage example:
81
82```go
83import "gopkg.in/hlandau/service.v2"
84import "gopkg.in/hlandau/easyconfig.v1"
85
86type Config struct{}
87
88// Server which doesn't do anything
89type Server struct{}
90
91func New(cfg Config) (*Server, error) {
92  // Instantiate the service and bind to ports here
93  return &Server{}, nil
94}
95
96func (*Server) Start() error {
97  // Start handling of requests here (must return)
98  return nil
99}
100
101func (*Server) Stop() error {
102  // Stop the service here
103  return nil
104}
105
106func main() {
107  cfg := Config{}
108
109  easyconfig.Configurator{
110    ProgramName: "foobar",
111  }.ParseFatal(&cfg)
112
113  service.Main(&service.Info{
114    Name:        "foobar",
115
116    NewFunc: func() (service.Runnable, error) {
117      return New(cfg)
118    },
119  })
120}
121```
122
123Changes since v1
124----------------
125
126v1 used the "flag" package to register service configuration options like UID, GID, etc.
127
128v2 uses the "[configurable](https://github.com/hlandau/configurable)" package
129to register service configuration options. "configurable" is a neutral
130[integration nexus](http://www.devever.net/~hl/nexuses), so it increases the
131generality of `service`. However, bear in mind that you are responsible for
132ensuring that configuration is loaded before calling service.Main.
133
134Configurables
135-------------
136
137The following configurables are automatically registered under a group configurable named "service":
138
139    chroot          (string) path       (*nix only) chroot to a directory (must set UID, GID) ("/" disables)
140    daemon          (bool)              (*nix only) run as daemon? (doesn't fork)
141                                        (remaps stdin, stdout, stderr to /dev/null; calls setsid)
142    fork            (bool)              (*nix only) fork?
143    uid             (string) username   (*nix only) UID or username to setuid to
144    gid             (string) groupname  (*nix only) GID or group name to setgid to
145    pidfile         (string) path       (*nix only) Path of PID file to write and lock (default: no PID file)
146
147    do              (string) start|stop|install|remove  (Windows only) Service control.
148
149    cpuprofile      (string) path       Write CPU profile to file
150    debugserveraddr (string) ip:port    Bind the net/http DefaultServeMux to the given address
151                                        (expvars, pprof handlers will be registered; intended for debug use only;
152                                        set UsesDefaultHTTP in the Info type to disable the presence of this flag)
153
154If you call `easyconfig.ParseFatal(nil, nil)` as suggested above, these manifest as "flag" flags named -service.X,
155for each name X above. e.g. `-service.chroot=/`
156
157Using as a Windows service
158--------------------------
159
160You can use the `-service.do=install` and `-service.do=remove` flags to install and
161remove the service as a Windows service. Please note that:
162
163  - You will need to run these commands from an elevated command prompt
164    (right click on 'Command Prompt' and select 'Run as administrator').
165
166  - The absolute path of the executable in its current location will be used
167    as the path to the service.
168
169  - You may need to tweak the command line arguments for the service
170    to your liking using `services.msc` after installation.
171
172  - You may also use any other method that you like to install or remove
173    services. No particular command line flag is required; the service will
174    detect when it is being run as a Windows service automatically.
175
176### Manifests
177
178If your service *always* needs to run privileged, you may want to apply a manifest file to your binary to make elevation automatic. You should avoid this if your service can be configured to usefully operate without elevation, as it denies the user choice in how to run the service.
179
180Here is an example manifest:
181
182```xml
183<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
184<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
185    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
186        <security>
187            <requestedPrivileges>
188                <requestedExecutionLevel
189                     level="requireAdministrator"
190                     uiAccess="false"/>
191            </requestedPrivileges>
192        </security>
193    </trustInfo>
194</assembly>
195```
196
197You can use this manifest either as a sidecar file by naming it `<exe-name>.exe.manifest`, or by embedding it into the binary. You may wish to investigate Microsoft's `mt` tool or [akavel/rsrc](https://github.com/akavel/rsrc), which provides a Go-specific solution.
198
199For more information on manifests, see MSDN.
200
201Use with systemd
202----------------
203
204Here is an example systemd unit file with privilege dropping and auto-restart:
205
206    [Unit]
207    Description=short description of the daemon
208    ;; Optionally make the service dependent on other services
209    ;Requires=other.service
210
211    [Service]
212    Type=notify
213    ExecStart=/path/to/foobar/foobard -service.uid=foobar -service.gid=foobar -service.daemon=1
214    Restart=always
215    RestartSec=30
216
217    [Install]
218    WantedBy=multi-user.target
219
220Bugs
221----
222
223  - If you don't consume registered configurables, the user cannot configure
224    the options of this package, rendering it somewhat unusable. You must handle
225    registered configurables. The easyconfig example above suffices.
226
227  - Testing would be nice, but a library of this nature isn't too susceptible
228    to unit testing. Something to think about.
229
230  - **Severe**: A bug in Go 1.5 means that privilege dropping does not work correctly, but instead hangs forever ([#12498](https://github.com/golang/go/issues/12498)). A patch is available but is not yet part of any release. As a workaround, use Go 1.4 or do not use privilege dropping (e.g. run as a non-root user and do not specify `-uid`, `-gid` or `-chroot`). If you need to bind to low ports, you can use `setcap` on Linux to grant those privileges. (This bug is fixed in Go 1.5.2 and later.)
231
232Platform Support
233----------------
234
235The package should work on Windows or any UNIX-like platform, but has been
236tested only on the following platforms:
237
238  - Linux
239  - FreeBSD
240  - Darwin/OS X
241  - Windows
242
243On Linux **you may need to install the libcap development package** (`libcap-dev` on Debian-style distros, `libcap-devel` on Red Hat-style distros), as this package uses libcap to make sure all capabilities are dropped on Linux.
244
245Reduced Functionality Mode
246--------------------------
247
248When built without cgo, the following limitations are imposed:
249
250  - Privilege dropping is not supported at all on Linux.
251  - UIDs and GIDs must be specified numerically, not as names.
252  - No supplementary GIDs are configured when dropping privileges (the empty set is configured).
253  - setproctitle is not supported; status setting is a no-op.
254
255Utility Library
256---------------
257
258This package provides a simplified interface built on some functionality
259exposed in [hlandau/svcutils](https://github.com/hlandau/svcutils). People who
260want something less “magic” may find functions there useful.
261
262Some functions in that repository may still be useful to people using this
263package. For example, the chroot package allows you to (try to) relativize a
264path to a chroot, allowing you to address files by their absolute path after
265chrooting.
266
267Licence
268-------
269
270    ISC License
271
272    Permission to use, copy, modify, and distribute this software for any
273    purpose with or without fee is hereby granted, provided that the above
274    copyright notice and this permission notice appear in all copies.
275
276    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
277    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
278    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
279    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
280    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
281    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
282    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
283
284