1 | Windows Service Support for svnserve |
---|
2 | ==================================== |
---|
3 | |
---|
4 | svnserve can now be run as a native Windows service. This means that the |
---|
5 | service can be started at system boot, or at any other time, without the |
---|
6 | need for any wrapper code to start the service. The service can be managed |
---|
7 | like any other Windows service, using command-line tools ("net start", |
---|
8 | "net stop", or sc.exe) or GUI tools (the Services administrative tool). |
---|
9 | |
---|
10 | |
---|
11 | Installation |
---|
12 | ------------ |
---|
13 | |
---|
14 | For now, no means is provided to install the service. Most Windows |
---|
15 | OSes derived from Windows NT (such as Windows XP, Windows 2000, |
---|
16 | Windows 2003 Server) provide a command-line tool for installing |
---|
17 | services, called SC.EXE for "Service Control". To create a service for |
---|
18 | svnserve, use SC.EXE: |
---|
19 | |
---|
20 | sc create <name> |
---|
21 | binpath= "c:\svn\bin\svnserve.exe --service <svn-args>" |
---|
22 | displayname= "Subversion Repository" |
---|
23 | depend= Tcpip |
---|
24 | |
---|
25 | where <name> is any service name you want, e.g. "svnserve", and |
---|
26 | <svn-args> are the arguments to svnserve, such as --root, |
---|
27 | --listen-port, etc. (All of this should be specified on a single |
---|
28 | line, of course.) |
---|
29 | |
---|
30 | In order for svnserve to run as a Windows service, you MUST specify |
---|
31 | the --service argument, and you must NOT specify any other run mode |
---|
32 | argument, such as --daemon, --tunnel, --inetd, or any of their short |
---|
33 | forms. There is no short form for --service. |
---|
34 | |
---|
35 | If the path to svnserve.exe contains spaces or other characters that |
---|
36 | must be escaped, then you must enclose the path to svnserve.exe with |
---|
37 | double-quotes, which themselves must be quoted using a backslash. |
---|
38 | Fortunately the syntax is similar to that on Unix platforms: |
---|
39 | |
---|
40 | sc create <name> |
---|
41 | binpath= "\"c:\program files\subversion\bin\svnserve.exe\" ..." |
---|
42 | |
---|
43 | SC has many options; use "sc /?". The most relevant are: |
---|
44 | |
---|
45 | sc create <name> create a new service |
---|
46 | sc qc <name> query config for a service |
---|
47 | sc query <name> query status |
---|
48 | sc delete <name> delete any service -- BE CAREFUL! |
---|
49 | sc config <name> ... update service config; same args as sc create |
---|
50 | sc start <name> start a service (does NOT wait for completion!) |
---|
51 | sc stop <name> stop a service (does NOT wait for it to stop!) |
---|
52 | |
---|
53 | Note that the command-line syntax for SC is rather odd. Key/value |
---|
54 | pairs are specified as "key= value" (without the double-quotes). The |
---|
55 | "key=" part must not have any spaces, and the "value" part MUST be |
---|
56 | separated from the "key=" by a space. |
---|
57 | |
---|
58 | If you want to be able to see the command shell, add these arguments |
---|
59 | to the "sc create" command-line: |
---|
60 | |
---|
61 | type= own type= interact |
---|
62 | |
---|
63 | This sets the "interactive" bit on the service, which allows it to |
---|
64 | interact with the local console session. |
---|
65 | |
---|
66 | You can create as many services as you need; there is no restriction |
---|
67 | on the number of services, or their names. I use a prefix, like |
---|
68 | "svn.foo", "svn.bar", etc. Each service runs in a separate process. |
---|
69 | As usual, it is your responsbility as an administrator to make sure |
---|
70 | that no two service instances use the same repository root path, or |
---|
71 | the same combination of --listen-port and --listen-host. |
---|
72 | |
---|
73 | |
---|
74 | Uninstalling |
---|
75 | ------------ |
---|
76 | |
---|
77 | To uninstall a service, stop the service, then delete it, using "sc |
---|
78 | delete <name>". Be very careful with this command, since you can |
---|
79 | delete any system service, including essential Windows services, |
---|
80 | accidentally. |
---|
81 | |
---|
82 | Also, make sure that you stop the service before you delete it. If |
---|
83 | you delete the service before stopping it, the Service Control Manager |
---|
84 | will mark the service "deleted", but will intentionally not stop the |
---|
85 | service. The service will be deleted when the system reboots, or when |
---|
86 | the service finally exits. After all, you only asked to delete the |
---|
87 | service, not to stop it. |
---|
88 | |
---|
89 | That's all there is to it. |
---|
90 | |
---|
91 | |
---|
92 | Automatically Starting Service on System Boot |
---|
93 | --------------------------------------------- |
---|
94 | |
---|
95 | By default, SC creates the service with the start mode set to "demand" |
---|
96 | (manual). If you want the service to start automatically when the |
---|
97 | system boots, add "start= auto" to the command line. You can change |
---|
98 | the start mode for an existing service using "sc config <name> start= |
---|
99 | auto", or also by using the Windows GUI interface for managing |
---|
100 | services. (Start, All Programs, Administrative Tools, Services, or |
---|
101 | just run "services.msc" from Start/Run or from a command-line.) |
---|
102 | |
---|
103 | Note: In order for svnserve to start correctly on system boot, you |
---|
104 | must properly declare its startup dependencies. The Service Control |
---|
105 | Manager will start services as early as it can, and if you do not |
---|
106 | properly declare its startup dependencies, it can potentially start |
---|
107 | before the TCP/IP stack has been started. This is why you must |
---|
108 | provide specify 'depend= Tcpip' to SC.EXE when creating the service. |
---|
109 | |
---|
110 | |
---|
111 | Starting and Stopping the Service |
---|
112 | --------------------------------- |
---|
113 | |
---|
114 | You start and stop the service like any other Windows service. You |
---|
115 | can use the command-line "net start <name>", use the GUI Services |
---|
116 | interface. |
---|
117 | |
---|
118 | |
---|
119 | Debugging |
---|
120 | --------- |
---|
121 | |
---|
122 | Debugging a Windows service can be difficult, because the service runs |
---|
123 | in a very different context than a user who is logged in. By default, |
---|
124 | services run in a "null" desktop environment. They cannot interact |
---|
125 | with the user (desktop) in any way, and vice versa. |
---|
126 | |
---|
127 | Also, by default, services run as a special user, called LocalSystem. |
---|
128 | LocalSystem is not a "user" in the normal sense; it is an NT security |
---|
129 | ID (SID) that is sort of like root, but different. LocalSystem |
---|
130 | typically does NOT have access to any network shares, even if you use |
---|
131 | "net use" to connect to a remote file server. Again, this is because |
---|
132 | services run in a different login session. |
---|
133 | |
---|
134 | Depending on which OS you are running, you may have difficulty |
---|
135 | attaching a debugger to a running service process. Also, if you are |
---|
136 | having trouble *starting* a service, then you can't attach to the |
---|
137 | process early enough to debug it. |
---|
138 | |
---|
139 | So what's a developer to do? Well, there are several ways you can |
---|
140 | debug services. First, you'll want to enable "interactive" access for |
---|
141 | the service. This allows the service to interact with the local |
---|
142 | desktop -- you'll be able to see the command shell that the service |
---|
143 | runs in, see console output, etc. To do this, you can either use the |
---|
144 | standard Windows Services tool (services.msc), or you can do it using |
---|
145 | sc.exe. |
---|
146 | |
---|
147 | * With the GUI tool, open the properties page for a service, and go |
---|
148 | to the "Log On" page. Select "Local System account", and make |
---|
149 | sure the "Allow service to interact with desktop" box is checked. |
---|
150 | |
---|
151 | * With SC.EXE, configure the service using the command: |
---|
152 | |
---|
153 | sc <name> config type= own type= interact |
---|
154 | |
---|
155 | Yes, you must specify type= twice, and with exactly the spacing |
---|
156 | shown. |
---|
157 | |
---|
158 | In both cases, you'll need to restart the service. When you do, if |
---|
159 | the service started successfully, you'll see the console window of the |
---|
160 | service. By default, it doesn't print anything out. |
---|
161 | |
---|
162 | Next, you'll want to attach a debugger, or configure the service to |
---|
163 | start under a debugger. Attaching a debugger should be |
---|
164 | straightforward -- just find the process ID. But if you need to debug |
---|
165 | something in the service startup path, you'll need to have a debugger |
---|
166 | attached from the very beginning. There are two ways to do this. |
---|
167 | |
---|
168 | In the first method, you alter the command-line of the service (called |
---|
169 | the "binary path"). To do this, use SC.EXE to set the binary path to |
---|
170 | whatever debugger you are going to use. I use the most recent version |
---|
171 | of WinDbg, which is excellent, and is available at: |
---|
172 | |
---|
173 | http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx |
---|
174 | |
---|
175 | For example, this command would configure the service to start under a |
---|
176 | debugger: |
---|
177 | |
---|
178 | sc config <name> binpath= "d:\dbg\windbg.exe -g -G d:\svn\bin\svnserve.exe |
---|
179 | --root d:\path\root --listen-port 9000" |
---|
180 | depend= Tcpip |
---|
181 | |
---|
182 | The entire command must be on a single line, of course, and the binary |
---|
183 | path must be in double-quotes. Also, the spacing MUST be: binpath= "..." |
---|
184 | |
---|
185 | Substitute whatever debugger you want, with whatever command-line you |
---|
186 | want, in place of windbg.exe. Then start the service (sc start |
---|
187 | <name>), and the Service Control Manager should execute the |
---|
188 | command-line you provided as the binary path. Then your debugger |
---|
189 | should start, and should launch the svnserve process. |
---|
190 | |
---|
191 | |
---|
192 | Known Issues |
---|
193 | ------------ |
---|
194 | |
---|
195 | * No management tool (installer, etc.). For the first version, this |
---|
196 | is intentional; we just want to get the service functionality tested |
---|
197 | and committed before dealing with installation. |
---|
198 | |
---|
199 | * Right now, I don't know of a way to cleanly stop the svnserve |
---|
200 | process. Instead, the implementation closes the listen socket, |
---|
201 | which causes the main loop to exit. This isn't as bad as it sounds, |
---|
202 | and is a LOT better than other options (such as terminating a |
---|
203 | thread). |
---|
204 | |
---|
205 | |
---|
206 | To Do |
---|
207 | ----- |
---|
208 | |
---|
209 | * The support for running svnserve as a Windows service is complete, |
---|
210 | but there is still more work to be done for installing and managing |
---|
211 | services. |
---|