summaryrefslogtreecommitdiff
path: root/examples/var_service/README
blob: 02d98751567f4a0221af2df88b8b09c9f935bd15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
	Daemontools and runit

Tired of PID files, needing root access, and writing init scripts just
to have your UNIX apps start when your server boots? Want a simpler,
better alternative that will also restart them if they crash? If so,
this is an introduction to process supervision with runit/daemontools.


	Background

Classic init scripts, e.g. /etc/init.d/apache, are widely used for
starting processes at system boot time, when they are executed by init.
Sadly, init scripts are cumbersome and error-prone to write, they must
typically be edited and run as root, and the processes they launch do
not get restarted automatically if they crash.

In an alternative scheme called "process supervision", each important
process is looked after by a tiny supervising process, which deals with
starting and stopping the important process on request, and re-starting
it when it exits unexpectedly. Those supervising processes can in turn
be supervised by other supervising processes.

Dan Bernstein wrote the process supervision toolkit, "daemontools",
which is a set of small, reliable programs that cooperate in the
UNIX tradition to manage process supervision trees.

Runit is a more conveniently licensed and more actively maintained
reimplementation of daemontools, written by Gerrit Pape.

Here I’ll use runit, however, the ideas are the same for other
daemontools-like projects (there are several).


	Service directories and scripts

In runit parlance a "service" is simply a directory containing a script
named "run".

There are just two key programs in runit. Firstly, runsv supervises the
process for an individual service. Service directories themselves sit
inside a containing directory, and the runsvdir program supervises that
directory, running one child runsv process for the service in each
subdirectory. A typical choice is to start an instance of runsvdir
which supervises services in subdirectories of /var/service/.

If /var/service/SERVICE_DIR/log/ exists, runsv will supervise two services,
and will connect stdout of main service to the stdin of log service.
This is primarily used for logging.

You can debug an individual service by running its SERVICE_DIR/run script.
In this case, its stdout and stderr go to your terminal.

You can also run "runsv SERVICE_DIR", which runs both the service
and its logger service (SERVICE_DIR/log/run) if logger service exists.
If logger service exists, the output will go to it instead of the terminal.

"runsvdir /var/service" merely runs "runsv SERVICE_DIR" for every subdirectory
in /var/service.


	Examples

This directory contains some examples of services:

    var_service/getty_<tty>

Runs a getty on <tty>. (run script looks at $PWD and extracts suffix
after "_" as tty name). Create copies (or symlinks) of this directory
with different names to run many gettys on many ttys.

    var_service/gpm

Runs gpm, the cut and paste utility and mouse server for text consoles.

    var_service/inetd

Runs inetd. This is an example of a service with log. Log service
writes timestamped, rotated log data to /var/log/service/inetd/*
using "svlogd -tt". p_log and w_log scripts demonstrage how you can
"page log" and "watch log".

Other services which have logs handle them in the same way.

    var_service/nmeter

Runs nmeter '%t %c ....' with output to /dev/tty9. This gives you
a 1-second sampling of server load and health on a dedicated text console.


	Networking examples

In many cases, network configuration makes it necessary to run several daemons:
dhcp, zeroconf, ppp, openvpn and such. They need to be controlled,
and in many cases you also want to babysit them.

They present a case where different services need to control (start, stop,
restart) each other.

    var_service/dhcp_if

controls a udhcpc instance which provides DHCP-assigned IP
address on interface named "if". Copy/rename this directory as needed to run
udhcpc on other interfaces (var_service/dhcp_if/run script uses _foo suffix
of the parent directory as interface name).

When IP address is obtained or lost, var_service/dhcp_if/dhcp_handler is run.
It saves new config data to /var/run/service/fw/dhcp_if.ipconf and (re)starts
/var/service/fw service. This example can be used as a template for other
dynamic network link services (ppp/vpn/zcip).

This is an example of service with has a "finish" script. If downed ("sv d"),
"finish" is executed. For this service, it removes DHCP address from
the interface. This is useful when ifplugd detects that the the link is dead
(cable is no longer attached anywhere) and downs us - keeping DHCP configured
addresses on the interface would make kernel still try to use it.

    var_service/zcip_if

Zeroconf IP service: assigns a 169.254.x.y/16 address to interface "if".
This allows to talk to other devices on a network without DHCP server
(if they also assign 169.254 addresses to themselves).

    var_service/ifplugd_if

Watches link status of interface "if". Downs and ups /var/service/dhcp_if
service accordingly. In effect, it allows you to unplug/plug-to-different-network
and have your IP properly re-negotiated at once.

    var_service/dhcp_if_pinger

Uses var_service/dhcp_if's data to determine router IP. Pings it.
If ping fails, restarts /var/service/dhcp_if service.
Basically, an example of watchdog service for networks which are not reliable
and need babysitting.

    var_service/supplicant_if

Wireless supplicant (wifi association and encryption daemon) service for
interface "if".

    var_service/fw

"Firewall" script, although it is tasked with much more than setting up firewall.
It is responsible for all aspects of network configuration.

This is an example of *one-shot* service.

It reconfigures network based on current known state of ALL interfaces.
Uses conf/*.ipconf (static config) and /var/run/service/fw/*.ipconf
(dynamic config from dhcp/ppp/vpn/etc) to determine what to do.

One-shot-ness of this service means that it shuts itself off after single run.
IOW: it is not a constantly running daemon sort of thing.
It starts, it configures the network, it shuts down, all done
(unlike infamous NetworkManagers which sit in RAM forever).

However, any dhcp/ppp/vpn or similar service can restart it anytime
when it senses the change in network configuration.
This even works while fw service runs: if dhcp signals fw to (re)start
while fw runs, fw will not stop after its execution, but will re-execute once,
picking up dhcp's new configuration.
This is achieved very simply by having
	# Make ourself one-shot
	sv o .
at the very beginning of fw/run script, not at the end.

Therefore, any "sv u fw" command by any other script "undoes" o(ne-shot)
command if fw still runs, thus runsv will rerun it; or start it
in a normal way if fw is not running.

This mechanism is the reason why fw is a service, not just a script.

System administrators are expected to edit fw/run script, since
network configuration needs are likely to be very complex and different
for non-trivial installations.

    var_service/ftpd
    var_service/httpd
    var_service/tftpd
    var_service/ntpd

Examples of typical network daemons.


	Process tree

Here is an example of the process tree from a live system with these services
(and a few others). An interesting detail are ftpd and vpnc services, where
you can see only logger process. These services are "downed" at the moment:
their daemons are not launched.

PID TIME COMMAND
553 0:04 runsvdir -P /var/service
561 0:00   runsv sshd
576 0:00     svlogd -tt /var/log/service/sshd
589 0:00     /usr/sbin/sshd -D -e -p22 -u0 -h /var/service/sshd/ssh_host_rsa_key
562 0:00   runsv dhcp_eth0
568 0:00     svlogd -tt /var/log/service/dhcp_eth0
850 0:00     udhcpc -vv --foreground --interface=eth0
                --pidfile=/var/service/dhcp_eth0/udhcpc.pid
                --script=/var/service/dhcp_eth0/dhcp_handler
                -x hostname bbox
563 0:00   runsv ntpd
573 0:01     svlogd -tt /var/log/service/ntpd
845 0:00     busybox ntpd -dddnNl -S ./ntp.script -p 10.x.x.x -p 10.x.x.x
564 0:00   runsv ifplugd_wlan0
598 0:00     svlogd -tt /var/log/service/ifplugd_wlan0
614 0:05     ifplugd -apqns -t3 -u0 -d0 -i wlan0
                -r /var/service/ifplugd_wlan0/ifplugd_handler
565 0:08   runsv dhcp_wlan0_pinger
911 0:00     sleep 67
566 0:00   runsv unscd
583 0:03     svlogd -tt /var/log/service/unscd
599 0:02     nscd -dddd
567 0:00   runsv dhcp_wlan0
591 0:00     svlogd -tt /var/log/service/dhcp_wlan0
802 0:00     udhcpc -vv -C -o -V  --foreground --interface=wlan0
                --pidfile=/var/service/dhcp_wlan0/udhcpc.pid
                --script=/var/service/dhcp_wlan0/dhcp_handler
569 0:00   runsv fw
570 0:00   runsv ifplugd_eth0
597 0:00     svlogd -tt /var/log/service/ifplugd_eth0
612 0:05     ifplugd -apqns -t3 -u8 -d8 -i eth0
                -r /var/service/ifplugd_eth0/ifplugd_handler
571 0:00   runsv zcip_eth0
590 0:00     svlogd -tt /var/log/service/zcip_eth0
607 0:01     zcip -fvv eth0 /var/service/zcip_eth0/zcip_handler
572 0:00   runsv ftpd
604 0:00     svlogd -tt /var/log/service/ftpd
574 0:00   runsv vpnc
603 0:00     svlogd -tt /var/log/service/vpnc
575 0:00   runsv httpd
602 0:00     svlogd -tt /var/log/service/httpd
622 0:00     busybox httpd -p80 -vvv -f -h /home/httpd_root
577 0:00   runsv supplicant_wlan0
627 0:00     svlogd -tt /var/log/service/supplicant_wlan0
638 0:03     wpa_supplicant -i wlan0
                -c /var/service/supplicant_wlan0/wpa_supplicant.conf -d