Anatomy of a typical TCP service

The http6d service in the regular services collection is an example of a typical and commonly used TCP service. Its start, stop, and restart programs are fairly trivial and straightforward. The meat of the service is its run and service programs.

The service could be arranged as a single run program. However, that does not permit adjustment of the service program, including its command-line arguments, whilst the service is up. Having a separate service program, that is chained to for each new TCP connection, permits an administrator to adjust the main service program without taking the service down. Of course, this has to be done carefully, because a live service could run the service program at any time, including halfway through when a text editor is updating the script. So always edit a "service.new" script and then, after setting execute permission, atomically rename it to service.

The run and service programs are as follows:

#!/bin/nosh
#HTTP socket capable of single-stack IPV6 and IPV6-mapped IPV4
tcp-socket-listen --backlog 2 --combine4and6 "::0" http
envuidgid publicfile
hardlimit -o 20 -d 500000
softlimit -o hard -d hard
tcp-socket-accept --connection-limit 16
ucspi-socket-rules-check
./service
#!/bin/nosh
#HTTP service over IPv4/IPv6 using Bernstein's publicfile
sh -c 'exec httpd ~publicfile/public'

Like many of the pre-packaged services, these scripts are in fact automatically generated from a description file that is in the source package. (In fact, that description is a slight variant on a systemd unit file.) Both invoke nosh as their script interpreter, and comprise a series of utility commands, each chain-loading to the next, passing along what program arguments it has not itself absorbed.

In the run program:

In the service program:

The amount of setup in the run and service scripts depends from what the service program itself does, of course. If publicfile did not change working directory and root directory, for example, one could do so with the chain-loading chdir and chroot commands.

Some run programs pass tcp-socket-listen the --systemd-compatibility option, if the program that accepts the socket connections require systemd's LISTEN_FDS protocol for knowing which open file descriptor is the listening TCP socket. This protocol also permits one to build up a list of listening sockets, for the final accepting service program to use, by simple dint of chaining multiple programs such as tcp-socket-listen, udp-socket-listen, and local-stream-socket-listen one after another.

Looking at the rest of the service bundle, one finds the standard things for a "server" service. The service is auto-started (when enabled) by the "server" system target. It is stopped by the "shutdown" system target. It requires for correct operation that all services in the "basic" system target be started, before it itself is started. Its output is sent to a logger service.