1
2
3
4
19
20 package initsystem
21
22 import (
23 "fmt"
24 "time"
25
26 "github.com/pkg/errors"
27 "golang.org/x/sys/windows/svc"
28 "golang.org/x/sys/windows/svc/mgr"
29 )
30
31
32 type WindowsInitSystem struct{}
33
34
35 func (sysd WindowsInitSystem) EnableCommand(service string) string {
36 return fmt.Sprintf("Set-Service '%s' -StartupType Automatic", service)
37 }
38
39
40
41 func (sysd WindowsInitSystem) ServiceStart(service string) error {
42 m, err := mgr.Connect()
43 if err != nil {
44 return err
45 }
46 defer m.Disconnect()
47
48 s, err := m.OpenService(service)
49 if err != nil {
50 return errors.Wrapf(err, "could not access service %s", service)
51 }
52 defer s.Close()
53
54
55 status, err := s.Query()
56 if err != nil {
57 return errors.Wrapf(err, "could not query service %s", service)
58 }
59
60 if status.State != svc.Stopped && status.State != svc.StopPending {
61 return nil
62 }
63
64 timeout := time.Now().Add(10 * time.Second)
65 for status.State != svc.Stopped {
66 if timeout.Before(time.Now()) {
67 return errors.Errorf("timeout waiting for %s service to stop", service)
68 }
69 time.Sleep(300 * time.Millisecond)
70 status, err = s.Query()
71 if err != nil {
72 return errors.Wrapf(err, "could not retrieve %s service status", service)
73 }
74 }
75
76
77 err = s.Start("is", "manual-started")
78 if err != nil {
79 return errors.Wrapf(err, "could not start service %s", service)
80 }
81
82
83 status, err = s.Query()
84 if err != nil {
85 return errors.Wrapf(err, "could not query service %s", service)
86 }
87 timeout = time.Now().Add(10 * time.Second)
88 for status.State != svc.Running {
89 if timeout.Before(time.Now()) {
90 return errors.Errorf("timeout waiting for %s service to start", service)
91 }
92 time.Sleep(300 * time.Millisecond)
93 status, err = s.Query()
94 if err != nil {
95 return errors.Wrapf(err, "could not retrieve %s service status", service)
96 }
97 }
98 return nil
99 }
100
101
102 func (sysd WindowsInitSystem) ServiceRestart(service string) error {
103 if err := sysd.ServiceStop(service); err != nil {
104 return errors.Wrapf(err, "couldn't stop service %s", service)
105 }
106 if err := sysd.ServiceStart(service); err != nil {
107 return errors.Wrapf(err, "couldn't start service %s", service)
108 }
109
110 return nil
111 }
112
113
114
115 func (sysd WindowsInitSystem) ServiceStop(service string) error {
116 m, err := mgr.Connect()
117 if err != nil {
118 return err
119 }
120 defer m.Disconnect()
121
122 s, err := m.OpenService(service)
123 if err != nil {
124 return errors.Wrapf(err, "could not access service %s", service)
125 }
126 defer s.Close()
127
128
129 status, err := s.Query()
130 if err != nil {
131 return errors.Wrapf(err, "could not query service %s", service)
132 }
133
134 if status.State == svc.Stopped {
135 return nil
136 }
137
138
139 if status.State == svc.StopPending {
140 timeout := time.Now().Add(10 * time.Second)
141 for status.State != svc.Stopped {
142 if timeout.Before(time.Now()) {
143 return errors.Errorf("timeout waiting for %s service to stop", service)
144 }
145 time.Sleep(300 * time.Millisecond)
146 status, err = s.Query()
147 if err != nil {
148 return errors.Wrapf(err, "could not retrieve %s service status", service)
149 }
150 }
151 return nil
152 }
153
154
155 status, err = s.Control(svc.Stop)
156 if err != nil {
157 return errors.Wrapf(err, "could not stop service %s", service)
158 }
159
160
161 status, err = s.Query()
162 if err != nil {
163 return errors.Wrapf(err, "could not query service %s", service)
164 }
165 timeout := time.Now().Add(10 * time.Second)
166 for status.State != svc.Stopped {
167 if timeout.Before(time.Now()) {
168 return errors.Errorf("timeout waiting for %s service to stop", service)
169 }
170 time.Sleep(300 * time.Millisecond)
171 status, err = s.Query()
172 if err != nil {
173 return errors.Wrapf(err, "could not retrieve %s service status", service)
174 }
175 }
176 return nil
177 }
178
179
180 func (sysd WindowsInitSystem) ServiceExists(service string) bool {
181 m, err := mgr.Connect()
182 if err != nil {
183 return false
184 }
185 defer m.Disconnect()
186 s, err := m.OpenService(service)
187 if err != nil {
188 return false
189 }
190 defer s.Close()
191
192 return true
193 }
194
195
196 func (sysd WindowsInitSystem) ServiceIsEnabled(service string) bool {
197 m, err := mgr.Connect()
198 if err != nil {
199 return false
200 }
201 defer m.Disconnect()
202
203 s, err := m.OpenService(service)
204 if err != nil {
205 return false
206 }
207 defer s.Close()
208
209 c, err := s.Config()
210 if err != nil {
211 return false
212 }
213
214 return c.StartType != mgr.StartDisabled
215 }
216
217
218 func (sysd WindowsInitSystem) ServiceIsActive(service string) bool {
219 m, err := mgr.Connect()
220 if err != nil {
221 return false
222 }
223 defer m.Disconnect()
224 s, err := m.OpenService(service)
225 if err != nil {
226 return false
227 }
228 defer s.Close()
229
230 status, err := s.Query()
231 if err != nil {
232 return false
233 }
234 return status.State == svc.Running
235 }
236
237
238
239
240 func GetInitSystem() (InitSystem, error) {
241 m, err := mgr.Connect()
242 if err != nil {
243 return nil, errors.Wrap(err, "no supported init system detected")
244 }
245 defer m.Disconnect()
246 return &WindowsInitSystem{}, nil
247 }
248
View as plain text