This is a real-world worked example of setting up and running a service with
the nosh package.
The service is the ntpd
daemon.
We start with some things that we pre-prepared, namely an unprivileged user for the ntpd
logging service to run as, and a directory for the logs to go into.
Logging services are first class services in their own right under nosh, and we will be setting up a logging service to take the standard output and standard error of ntpd
and record it in a set of auto-rotated size-capped log files.
Remember that you are not required, with nosh, to have a 1:1 relationship between logging daemons and the daemons whose output they are logging. However:
First, this is the familiar modus operandi for those coming from other daemontools-family daemon supervision systems.
Second, setting things up this way gives us the opportunity to demonstrate a couple more of the mechanisms and features of the nosh toolset.
root /var/sv #fgrep ntp /etc/passwd ntpd-log:*:1005:1006:User &:/home/ntpd-log:/bin/false root /var/sv #ls -dl /var/log/sv/ntpd drwxrwxr-x 2 ntpd-log log 512 Mar 3 2014 /var/log/sv/ntpd root /var/sv #
As you can see, our service bundles are going to be made in the current directory, /var/sv/
, and the log directory is /var/log/sv/
.
(If you want equivalent places for "local" services and log directories, the obvious ones are of course /var/local/sv/
and /var/log/local/sv
.)
For this worked example we will be requiring the contents of the nosh-exec
, nosh-service-management
, nosh-systemd-shims
, and nosh-bundles
packages, as well as a couple of things from the nosh source archive.
ntpd
is in fact one of the pre-packaged service bundles in the nosh-bundles
package.
(The nosh-bundles
package provides a whole load of pre-built service bundles, and it is of course the goal that the world make and publish more and more such service bundles.
In such a scenario one would skip the creation of the service bundle and go straight to the enabling and starting section.
But the purpose of this worked example is in part to show how one gets to a running service from a systemd unit file with nosh.)
We've manually removed the pre-packaged bundle directories that we are hand-rebuilding here.
One of the things in the nosh package's source archive that we're using is the cyclog@.service
service template unit file, which we've copied into the current directory.
This is a systemd service unit file — a templated one.
It invokes the nosh package's cyclog
command to do the logging.
(Of course, you can use another logging program if you like.)
root /var/sv #cat cyclog@.service ## ************************************************************************** ## For copyright and licensing terms, see the file named COPYING. ## ************************************************************************** [Unit] Description=Standard format %P logging service for %I Before=%I.service [Service] WorkingDirectory=/var/log/sv/ User=%I-log ExecStart=%P %I/ Restart=always [Install] WantedBy=workstation.target root /var/sv #
Using the convert-systemd-units
subcommand of the system-control
command, we create a service bundle for the log service, using ntpd
as the template parameter.
(The nosh-systemd-shims
package provides symbolic links that make the system-control
command available as systemctl
.
We use system-control
here to emphasize that convert-system-units
is not a systemd subcommand.
We'll be using some systemd subcommands, and the name systemctl
, later on, though.)
root /var/sv #system-control convert-systemd-units ./cyclog@ntpd.service root /var/sv #
This has generated an entire service bundle, in the current directory, named cyclog@ntpd
.
There's a full description of service bundles in the manual pages of the system-control
and service-manager
commands; so we won't go into that in depth here.
Of particular note are the service/
subdirectory and the run
program, which is a nosh
script.
As you can see, the convert-systemd-units
subcommand has created a script that invokes several chain-loading commands to do the things that the service unit specified, including changing user and working directory.
It has also created some other scripts, not shown here because they are fairly trivial in this case, in particular a restart
program that always exits success, to enact the service unit's Restart=always
setting.
root /var/sv #ls -l cyclog@ntpd/service/ total 32 -rwxr-xr-x 1 root wheel 93 Sep 27 22:32 restart -rwxr-xr-x 1 root wheel 206 Sep 27 22:32 run -rwxr-xr-x 1 root wheel 62 Sep 27 22:32 start -rwxr-xr-x 1 root wheel 61 Sep 27 22:32 stop root /var/sv # root /var/sv # root /var/sv #cat cyclog@ntpd/service/run #!/bin/nosh #Run file generated from ./cyclog@.service #Standard format cyclog logging service for ntpd chdir /var/log/sv/ setuidgid ntpd-log setenv HOME /home/ntpd-log setenv SHELL /bin/false cyclog ntpd/ root /var/sv #
(The setenv
commands are there because of an undocumented feature in systemd, an explanation of which can be found on the page about converting systemd units in the nosh Guide.
The aren't necessary for, or even used by, cyclog
.
But convert-systemd-units
doesn't know that it isn't dealing with a service that relies upon these undocumented features.)
Now we come to making the main ntpd
service.
Again, we're going to use a systemd service unit file taken from the nosh package source archive — ntpd.service
this time.
root /var/sv #cat ntpd.service ## ************************************************************************** ## For copyright and licensing terms, see the file named COPYING. ## ************************************************************************** [Unit] Description=BSD NTP daemon [Service] systemdWorkingDirectory=false ExecStart=ntpd -n -g -f /var/db/ntpd.drift Restart=always StandardError=inherit [Install] WantedBy=workstation.target root /var/sv #
And again we convert it to a service bundle using the convert-systemd-units
subcommand.
(As an aside:
Note that it is -units
plural because one of the things that it can convert is a linked pair of a socket unit file and a service unit file.
It works out what you are converting from the suffix of the filename.
See the system-control
manual page for the details.)
root /var/sv #system-control convert-systemd-units ./ntpd.service root /var/sv #
And again this makes, amongst other things in the service bundle, a service/
directory and a run
program.
root /var/sv #ls -l ntpd/service/ total 32 -rwxr-xr-x 1 root wheel 90 Sep 27 22:34 restart -rwxr-xr-x 1 root wheel 129 Sep 27 22:34 run -rwxr-xr-x 1 root wheel 59 Sep 27 22:34 start -rwxr-xr-x 1 root wheel 58 Sep 27 22:34 stop root /var/sv # root /var/sv # root /var/sv #cat ntpd/service/run #!/bin/nosh #Run file generated from ./ntpd.service #BSD NTP daemon fdmove -c 2 1 ntpd -n -g -f /var/db/ntpd.drift root /var/sv #
You may have noticed the presence of the systemdWorkingDirectory=false
setting in the service unit, and the absence of a chdir
command in the run
script.
There is another undocumented systemd feature with respect to working directories.
But since it's a marked difference from the daemontools world, there's an explicit setting, an extension to the systemd service unit specification, for turning it off for services that don't really need it and are quite happy running with the daemontools conventions for working directories, which is in fact most services.
(The number of services currently known to rely upon the undocumented systemd behaviour stands at just one.)
Again, for more details see the aforementioned nosh Guide page.
A simple symbolic link serves to tell the system-control
command, when it comes to tell the service manager to plumb the services together, where the log service is.
root /var/sv #ln -s ../cyclog@ntpd ntpd/log root /var/sv #
The nosh package supports running things the daemontools way, with the service manager started by some external system initialization system and services managed through symbolic links in a /service/
(or /etc/service/
, or /var/service/
…) directory.
However, for this worked example we are using a system that has the nosh system manager running as process #1, and that has the "standard targets" installed from the nosh-bundles
package.
We want to make sure that the services are "enabled", i.e. that they will be automatically brought up when the system is bootstrapped.
The command to do this is very familiar to those who have used systemd.
(With the systemv shims package installed, one can even use chkconfig on
if one is so minded.)
root /var/sv #systemctl enable ntpd.service cyclog@ntpd.service root /var/sv #
Log services and main services are first-class citizens in nosh, remember. They are both, to the service manager, just plain old services, that just happen to be plumbed together through a pipe in a particular way. So one has to enable both of them.
The fileystem is the database in nosh.
So what enabling does is record in the "wants" list of the workstation
service bundle (which is a standard target) pointers to the service bundles of the log and main services.
For details of the workstation
target, and how it is started through the normal
target at (normal mode) system bootstrap, see the nosh Guide and the system-control
manual page.
root /var/sv #ls -l /etc/service-bundles/targets/workstation/wants/*ntpd lrwxr-xr-x 1 root JdeBP 19 Sep 27 22:37 /etc/service-bundles/targets/workstation/wants/cyclog@ntpd -> /var/sv/cyclog@ntpd lrwxr-xr-x 1 root JdeBP 12 Sep 27 22:37 /etc/service-bundles/targets/workstation/wants/ntpd -> /var/sv/ntpd root /var/sv #
We also want to bring up the services right now, i.e. to "start" them.
Again, this is a familiar command for those from the systemd world.
(And again, if one were so minded one could use service … start
from the systemv shims package instead.)
root /var/sv #systemctl start ntpd cyclog@ntpd root /var/sv #
The svstat
command, familiar in turn to those who have used daemontools, shows that the services are now up.
(A similar svshow
command is provided for generating output that is intended to be machine-readable, rather than human-readable as here.
And yes, systemctl show
and systemctl status
are also there if you have the systemd shim package installed.)
root /var/sv #svstat ntpd cyclog@ntpd ntpd: running (pid 73912) 41s ago cyclog@ntpd: running (pid 73910) 42s ago root /var/sv #
Because this machine is running the nosh system manager, there's a log of the service manager's output (amongst other things) in /run/system-manager/log/
which shows what the service manager was told to do by system-control
.
root /var/sv #fgrep ntpd /run/system-manager/log/current|tai64nlocal 2014-09-27 22:40:22.725985314 service-manager: DEBUG: load cyclog@ntpd 2014-09-27 22:40:22.726334939 service-manager: DEBUG: load ntpd 2014-09-27 22:40:22.727323468 service-manager: DEBUG: plumb ntpd to cyclog@ntpd 2014-09-27 22:40:22.727858659 service-manager: INFO: cyclog@ntpd/start: pid 73909 2014-09-27 22:40:22.731414544 service-manager: INFO: cyclog@ntpd/run: pid 73910 2014-09-27 22:40:23.744722046 service-manager: INFO: ntpd/start: pid 73911 2014-09-27 22:40:23.748205505 service-manager: INFO: ntpd/run: pid 73912 root /var/sv #
As you can see, it loaded up both service bundles, plumbed them together with a pipe (because of the symbolic link made earlier), ran their respective start
commands, and then ran their respective run
commands.
And for those who haven't already figured it out from some offhand tidbits in the aforegiven, here is a surprise. This isn't a Linux system running this worked example, going from systemd unit files to running services, at all.
root /var/sv #uname -sr FreeBSD 10.0-RELEASE-p1 root /var/sv #