|
|
Subscribe / Log in / New account

Systemd programming part 1: modularity and configuration

February 5, 2014

This article was contributed by Neil Brown

Systemd's positive and negative features have been discussed at length; one of the first positives I personally noticed was seen from my perspective as an upstream package maintainer. As the maintainer of mdadm and still being involved in the maintenance of nfs-utils, one of my frustrations was the lack of control over, or even much visibility into, the way these packages were integrated into the "init" system on each distribution. Systemd has the potential to give back some of that control while still giving flexibility to distributors and administrators; this article (and the one that follows) will look at systemd's programming features to show how that works.

Once upon a time, all the major distributions were using SysVinit and each had their own hand-crafted scripts to handle the startup of "my" packages. While I could possibly have copied all of those scripts into the upstream package and tried to unify them, it would have been problematic trying to do this for all distributions, and it is unlikely that many distributions would have actually used what was offered. We did have scripts for Debian in the nfs-utils package for a while, but it turned out that this didn't really help the Debian developer at the time and they were ultimately removed when they proved to be more of a hindrance.

Not all packagers will care about having this visibility or control. However, with both mdadm and nfs-utils there are issues with recovery after failures which are not entirely straightforward to deal with. It is very possible for a distribution maintainer to put together an init script which works perfectly well in most cases, but can fail strangely in rare cases. I first came across this problem with nfs-utils, which has subtle ordering requirements for starting daemons on the server if a client held a lock while the server rebooted. Most (possibly all) distributions got this wrong. The best I could do to fix it was to get a fix into the distribution I was using at the time and update the README file. Whether that actually helped any other distribution is something I'll never know.

It was against this backdrop that I first considered systemd. The contrast to SysVinit was and is substantial. While the configuration files for SysVinit are arbitrary shell scripts with plenty of room for individual expressiveness and per-distribution policy, the configuration for systemd is much more constrained. Systemd allows you to say the things you need to say but provides very little flexibility in how you say them; systemd also makes it impossible to say things irrelevant to the task at hand, such as color coding status messages. This means that there is much less room for per-distribution differences and, thus, much less motivation for distribution packager to deviate from a configuration provided by upstream.

So when it came time to replace the SysVinit scripts that openSUSE uses for nfs-utils with some systemd unit files I decided to see if I could do it "properly." My initial baseline definition for "properly" was that the unit files should be suitable for inclusion in the upstream nfs-utils package. This in turn means they must be suitable for every distribution to use, and must be of sufficient quality to pass review by my peers without undue embarrassment.

This effort, together with the work I had already done to convert mdadm to use systemd unit files, caused me to look at systemd from the perspective of programming and programming language design. Systemd is a powerful and flexible tool that can be programmed through a special-purpose language to unite the various tools in the packages that I help maintain, in order to provide holistic functionality.

Modularity

In the early days of Unix, there was a script called /etc/rc which started all the standard daemons, and maybe it would run /etc/rc.local to start a few non-standard ones. When you only have 32KB of RAM, you probably don't want to run so many daemons that the lack of modularity provided by these files becomes a problem. As the capacity of hardware increased so too did the need for modularity, with modern SysVinit allowing a separate script (or possibly scripts in the plural) for each distinct package.

Systemd takes this one step further by allowing, and in fact requiring, a separate unit file for each daemon or for each distinct task. For packages that just provide a single daemon this is probably ideal. For nfs-utils, this requirement borders on being clumsy.

The draft unit-file collection I recently posted for review has 14 distinct unit files with a total of 168 lines (including blanks and occasional comments). They replace two SysVinit scripts totaling 801 lines, so the economy of expression cannot be doubted. However, it does mean that I cannot simply open "the unit files" in an editor window and look over them to remind myself how it works or look for particular issues. For mdadm, which has 4 systemd unit files this is a minor inconvenience. For nfs-utils it really feels like a barrier.

These 14 files include eight which actually run daemon processes, two which mount special virtual filesystems which the tools use for communicating with the kernel, and four which are "target" units. "Targets" are sometimes described as "synchronization points" in the systemd documentation. A target might represent a particular level of service such as network-online.target or multi-user.target. For nfs-utils we have, for example, nfs-server.target. This target starts all the various services required for, or useful to, NFS service. The individual daemons don't necessarily depend on each other, but the service as a whole depends on the collection and so gets a separate target.

These target units are well placed to provide a clean module structure. There is sometimes a need for unit files belonging to one package to reference unit files belonging to another package, such as the reliance on rpcbind.target in several nfs services. Restricting such references to target units would allow a clean separation between the API (.target) and the implementation (.service etc). Unfortunately the "systemctl" command handles an abbreviated unit name but it assumes a ".service" suffix rather than a ".target" suffix. This tends to discourage the use of targets and blurs the line between API and implementation.

This ability to collect units together into a virtual unit while allowing the individual details of the units to be managed separately is a distinct "plus" for systemd from the modularity perspective. The insistence that units each have their own file, together with systemctl's unfortunate default behaviour, are small "minuses".

Configuration

As a programmer I try to choose sensible defaults but also to allow users of my code to customize or configure some settings to meet their particular needs. As a programmer using the systemd language I have two sorts of users to keep in mind: distribution maintainers who will package my project for particular distributions, and system administrators who will use it to create a useful computer system.

I want both of these groups to be able to make any configuration changes they need, but at the same time I want to retain some degree of control. If I find a bug, for example some subtle ordering issue for different daemons, then I want to be able to fix that in the upstream package and have some confidence that the changes will flow through to all users. In this I seem at variance with the systemd developers, or at least with an opinion expressed two and a half years ago in systemd for Administrators, part IX.

That document asserts that "systemd unit files do not include code", and that "they are very easy to modify: just copy them from /lib/systemd/system to /etc/systemd/system and edit them there". The first of these points is largely a philosophical one, but one which the attentive reader will already see that I disagree with. Any time I am writing specific instructions to bring about a specific effect, I am writing code — whether it is written in C, Python, or systemd unit-file language.

The second is a more practical concern. If system administrators were to take this advice and replace one of my carefully crafted unit files, then the bug-fix I release may not have a chance to work for them — an outcome I would rather avoid.

So I don't want system administrators to feel the need to edit my unit files, but equally I don't want distribution packagers to edit them either. Partly this is a pride issue — I want upstream to be a perfect fit for everyone. Partly this is a quest for uniformity — packagers should feel free to send any patches they require upstream so that everyone benefits. And partly it is a support issue. If I get a bug report, I want to be able to ask the reporter to fetch and install the current upstream version and be fairly confident that it won't break any distribution-specific features.

So my goal, as a programmer, is to ensure my users can configure what they need without having to change my code. Once again systemd gets a mixed score-card.

Systemd allows for so-called "drop-ins" to extend any unit file. When looking for the file to load a particular unit, systemd will search a standard list of directories for a file with the right name. Early in this list are directories for local overrides such as /etc/systemd/system mentioned above. Late in the list is the location for the primary file to use — /lib/systemd/system in the quote above, though often /usr/lib/systemd/system on modern installations.

After finding the unit file, systemd will search again, this time for a directory with the same name as the file except with ".d" appended. If that is found, any files in the directory with names ending ".conf" are read and can extend the unit description. These ".conf" files are referred to as "drop-ins."

The ordering of directives in unit files is largely irrelevant so any directive can be replaced or, if relevant, extended by a drop-in file. So for example an "ExecStartPre" directive could be given to add an extra program to be run before the service starts. This facility allows both the packager and sysadmin to impose a variety of configuration changes without having to edit my precious unit files. Things like WorkingDirectory, User and Group, CPUSchedulingPriority, and more can easily be set if that is desired to meet some local need. However, there is one common area of configuration that isn't so amenable to change through drop-in files: the command-line arguments for the process being run.

When I examine the configuration that openSUSE SysVinit scripts allow for various daemons in nfs-utils, the one that stands out is the adding of extra command-line options. This may involve setting the number of threads that the NFS server might use, allowing mountd to run multi-threaded or provide alternate management of group IDs, or setting an explicit port number for statd to use, among others.

It is certainly true that a drop-in file can contain text like:

    ExecStart=
    ExecStart=/some/program --my --list=of arguments

where the assignment of an empty string removes any previous assignment (ExecStart is defined as a list, so that a "one-shot" service can run a list of processes) and the second assignment gives the desired complete list of command line arguments. However this approach can only replace the full set of arguments, it cannot extend them.

This gets back to my desire for control. If an upstream fix adds or changes a command-line argument, then any installation which uses a drop-in to replace the arguments to that daemon will miss out on my change.

There is also a question of management here. Many distributions don't expect system administrators to edit files directly but, instead, provide a tool like YaST (on openSUSE) or debconf (on Debian) which manages the configuration through a GUI interface or a series of prompts. For such a tool, it is much easier to manipulate a file with a well-defined and simple structure — such as the /etc/sysconfig files in openSUSE and Fedora or the similar /etc/defaults files in Debian — which are essentially a list of variable assignments. It is quite straightforward for user-interface tools to manipulate this file, and then for the SysVinit scripts to interpret the values and choose the required command line arguments.

While systemd can certainly read these same configuration files (with the EnvironmentFile directive) and can expand environment variables in command line arguments to programs, it lacks any sophistication. Non-optional parameters are easily handled, so:

    /usr/sbin/rpc.nfsd -n $USE_KERNEL_NFSD_NUMBER

would work as expected, but optional parameters cannot be managed so easily. While the Bourne shell (which interprets SysVinit scripts) and Upstart would both support:

    /usr/sbin/rpc.mountd ${MOUNTD_PORT:+-p $MOUNTD_PORT}

to include the "-p" only if $MOUNTD_PORT were non-empty, systemd cannot do this. It could be argued that this syntax has little to recommend it and that systemd might be better off without it. However, there is a clear need for this sort of functionality, at least unless or until various configuration management tools learn to create complete command lines directly.

There are at least two possible responses that are worth considering to address this need. The first is to modify all the daemons to accept any command line configuration also from environment variables. For example mountd could be changed to examine the MOUNTD_PORT environment variable if no -p option were given, and use that value instead.

This could be seen as a rather intrusive change. However, since I am looking from the perspective of an upstream developer, writing code in each daemon is not really harder or easier than writing code in systemd unit files. It is also very much in the style of systemd, which seems to encourage authors of daemons to design them to work optimally with systemd, recommending use of libsystemd-daemon, for example, when appropriate. This can maximize the effective communication between systemd and the services it runs, and remove any "middle-men" which don't really add any long-term value.

So this seems the best solution for the longer term, but as it requires some degree of agreement among developers and co-ordination between distributions, it doesn't seem like the best short-term solution.

The other option is to create a "middle-man" exactly as suggested. That is, have a script which can read a distribution-specific configuration file, interpret the contents, and construct the complete command lines for a collection of daemons. These command lines would be written to a temporary file which systemd could read before running the daemons.

So we could have an "nfs-config.service" unit like:

    [Unit]
    Description=Preprocess NFS configuration
    [Service]
    type=oneshot
    RemainAfterExit=yes
    ExecStart=/usr/lib/systemd/scripts/nfs-utils_env.sh

which is tasked with creating /run/sysconfig/nfs-utils. The "nfs-utils_env.sh" script would be distribution-specific to allow the packager to create a perfect match for the configuration options that the local config tool supports.

Then each nfs-utils unit file would contain something like:

    [Unit]
    Wants=nfs-config.service
    After=nfs-config.service
    [Service]
    EnvironmentFile=-/run/sysconfig/nfs-utils
    ExecStart=/usr/sbin/rpc.mountd $MOUNTD_ARGS

so that the "nfs-config" service would be sure to have run first and created the required EnvironmentFile, which would contain, among other things, the value of MOUNTD_ARGS.

Assessing this support that systemd provides (or fails to provide) for configuration objectively is hard. On the one hand, it seems to require me to create this "nfs-config" service which seems a bit like a hack. On the other it encourages me to press forward and change my daemon processes to examine the environment directly which is probably a better solution than any sort of service that systemd could provide to convert environment variables directly.

So, generally, for configuration, systemd gets a thumbs-up, but I'm reserving final judgment for now.

Thus far, we have seen a pattern with modularity and service configuration, where it provides good functionality but also a few significant frustrations. This pattern will continue in the second part when we look at how unit files may be "activated" to become running services, and how the set of unit directives as a whole fare when viewed as a programming language.

Index entries for this article
GuestArticlesBrown, Neil


to post comments

Systemd programming part 1: modularity and configuration

Posted Feb 5, 2014 23:54 UTC (Wed) by zuki (subscriber, #41808) [Link] (5 responses)

The daemon could read a configuration file (say /etc/nfsd.conf) directly...

Systemd programming part 1: modularity and configuration

Posted Feb 6, 2014 4:40 UTC (Thu) by zenaan (guest, #3778) [Link] (2 responses)

Many daemons provide just such an option.

Also:

> While systemd can certainly read these same configuration files (with the EnvironmentFile directive) and can expand environment variables in command line arguments to programs, it lacks any sophistication. Non-optional parameters are easily handled, so:
>⋅
> /usr/sbin/rpc.nfsd -n $USE_KERNEL_NFSD_NUMBER
>⋅
> would work as expected, but optional parameters cannot be managed so easily. While the Bourne shell (which interprets SysVinit scripts) and Upstart would both support:
>⋅
> /usr/sbin/rpc.mountd ${MOUNTD_PORT:+-p $MOUNTD_PORT}

So change MOUNTD_PORT to MOUNTD_PORT_ARG:

/usr/sbin/rpc.mountd $MOUNTD_PORT_ARG ...

Where eg, /etc/default/my-service.conf contains eg:

MOUNTD_PORT_ARG="-p 12345"

I know it's clunky, but it is trivial to implement, and the author Neil _is_ talking transition here ("longer term" vs "short-term")...

Systemd programming part 1: modularity and configuration

Posted Feb 6, 2014 6:00 UTC (Thu) by raven667 (subscriber, #5198) [Link] (1 responses)

That does seem very "transitional". One of the benefits that you get with the config file arrangement for systemd is a standard supported way to override configs without conflicting with the packaged default files. You could create a new service file in /etc/systemd which changes the default command to include whatever arguments you want, and then audit any such changes with systemd-delta to show what you've hand-edited and exactly where it differs from the default. That removes a lot of the need for /etc/default or /etc/sysconfig files in the first place, which was the inherent conflict when editing /etc/init.d scripts between your edits and the packaged versions.

Systemd programming part 1: modularity and configuration

Posted Feb 6, 2014 6:49 UTC (Thu) by raven667 (subscriber, #5198) [Link]

Sometimes I need to shut my mouth and read the article rather than just the Unread Comments interface as then I would have seen that Neil had this well under control in the main article and wouldn't have been redundant.

Now that I've read the article I understand Neil's point but it is my opinion that giving the system admin good tools to audit changes which diverge from the default is sufficient, although sure there could be an even better system which doesn't even require the audit and integration, I'd rather keep the system simple, his example of having units run scripts to generate environment files which alter the behavior of other units is too abstract and complex (hacky) for me.

The straightforwardness of systemd-delta appeals to me, in the same way that other tools which show you diffs between the packaged and modified version of a config and allow you to merge the changes when you update.

Systemd programming part 1: modularity and configuration

Posted Feb 7, 2014 21:54 UTC (Fri) by bfields (subscriber, #19510) [Link] (1 responses)

"The daemon could read a configuration file (say /etc/nfsd.conf) directly..."

Yeah, I think that would be better in the long run.

Code at git://linux-nfs.org/nfs-utils, patches to linux-nfs@vger.kernel.org....

Systemd programming part 1: modularity and configuration

Posted Feb 7, 2014 22:45 UTC (Fri) by neilbrown (subscriber, #359) [Link]

Looking forward to reviewing those patches.

Make sure they include plugins for all knows configuration UIs to work with this new config file.

Given that

- configurators can already read/write environment files
- systemd can already load them into the environment, as can the shell
- daemons can get them out of the environment using "getenv()", which is already in the standard library

there seems little point in creating new config files for any configuration that can be provided by a simple environment file.

What is why I won't be providing patches to read config files.

Please do not reintroduce shell scripts when we don't need them

Posted Feb 6, 2014 9:23 UTC (Thu) by Siosm (subscriber, #86882) [Link] (9 responses)

I don't really like the "nfs-config.service" approach as this brings unnecessary complexity, introduce another specific file for configuration and spawn a mostly useless shell.

Using ".d" directory or copy-pasting the unit file feels like the sensible way to go, using systemd-delta to track changes.

The author is concerned that administrators won't see the changes if the units are copied/tweaked. This should be fixed elsewhere, for example in packages update scripts where a warning could say:
"<unit> file has changed since the previous version. There are differences between /etc/systemd/system/<unit> and the /usr/lib/systemd/system/<unit> file included in this packages. Please review them using systemd-delta".

This is a new way to manage services and administrators must learn how to use systemd.

Please do not reintroduce shell scripts when we don't need them

Posted Feb 6, 2014 10:09 UTC (Thu) by josh (subscriber, #17465) [Link]

Agreed entirely; if the override mechanism feels deficient in some way, extend it in systemd, not by creating a magic custom mechanism.

Please do not reintroduce shell scripts when we don't need them

Posted Feb 7, 2014 15:24 UTC (Fri) by Shewmaker (guest, #1126) [Link] (7 responses)

I've found that config services can be extremely useful in cluster settings where I don't want to have hundreds or thousands of slightly different config files to manage. The config services can look up a host's name and ip address in a flat-file describing the entire cluster and generate all of the configuration files necessary to customize the host.

That way you get one system image instead of many, and can treat a cluster like a single system instead of thousands.

I'm not saying that everything should be optimized for the cluster use case, but it would be nice if distributions kept that more in mind and didn't actively make it more difficult with their new configuration tools (e.g. RedHat's NetworkManager has been unfriendly towards automation, although I've heard it has a command line now).

Please do not reintroduce shell scripts when we don't need them

Posted Feb 7, 2014 15:59 UTC (Fri) by Siosm (subscriber, #86882) [Link] (6 responses)

> The config services can look up a host's name and ip address in a flat-file describing the entire cluster and generate all of the configuration files necessary to customize the host.

As far as I understand this looks like a one time process, not really a case for a systemd unit and more adapted to "configuration management" tools usage.

Moreover, you could use systemd unit specifiers (http://www.freedesktop.org/software/systemd/man/systemd.u...) to tell your service to start using a particular configuration depending on the hostname.

Also, why is the maintainer discussing this issue here and not on the systemd mailing list where he could get official recommendations/suggestions from the developers themselves?

Please do not reintroduce shell scripts when we don't need them

Posted Feb 7, 2014 16:07 UTC (Fri) by Siosm (subscriber, #86882) [Link] (5 responses)

From the article:
> Unfortunately the "systemctl" command handles an abbreviated unit name but it assumes a ".service" suffix rather than a ".target" suffix. This tends to discourage the use of targets and blurs the line between API and implementation.

Maybe this issue should also be reported upstream?

Please do not reintroduce shell scripts when we don't need them

Posted Feb 10, 2014 10:43 UTC (Mon) by Darkmere (subscriber, #53695) [Link] (4 responses)

It used to be that systemctl would throw a big "huh? Whatchatalkingabout?" When you didn't specify .service, which made "systemctl restart sshd" annoying and hard to use. So they made .service be the default.

Maybe it should balk if there's an ambigious selection (".service and .target? I'm not making a choice!" )

Please do not reintroduce shell scripts when we don't need them

Posted Feb 13, 2014 11:12 UTC (Thu) by kisko (guest, #95529) [Link] (3 responses)

In this case sshd would be an ambigious selection because there's also sshd.socket unit present.

Please do not reintroduce shell scripts when we don't need them

Posted Feb 13, 2014 13:02 UTC (Thu) by Darkmere (subscriber, #53695) [Link] (2 responses)

I have to read up more on what socket-activated things I have on my system, going to be interesting I think.

I'm a tad worried that I might have some things socket-activated where I thought they were disabled.

Please do not reintroduce shell scripts when we don't need them

Posted Feb 13, 2014 14:17 UTC (Thu) by mathstuf (subscriber, #69389) [Link] (1 responses)

If you run "systemctl disable sshd", you get a warning that sshd.socket may still cause its activation and a command you can use to disable it as well. I don't know which version this was implemented in, but in pretty sure it was after 204.

Please do not reintroduce shell scripts when we don't need them

Posted Feb 13, 2014 17:13 UTC (Thu) by Darkmere (subscriber, #53695) [Link]

Yep, looking over the socket activations, I found some of my traditional bastards were there and enabled. PCMCIA, iscsi-related things and so on.

Off with their heads! Though I should look a bit at what
Listen: @ISCSIADM_ABSTRACT_NAMESPACE (Stream)
means.

Systemd programming part 1: modularity and configuration

Posted Feb 6, 2014 15:32 UTC (Thu) by dashesy (guest, #74652) [Link] (2 responses)

Any modular programming language deserves (and benefits from) a nice IDE. If there are 14 files that one needs to read in order to get the overall picture, it needs a project workspace associating them together. Syntax highlighting, code assist, and go-to-definition also become handy to investigate (and perhaps fix) a foreign code base of more than few files.

Systemd programming part 1: modularity and configuration

Posted Feb 6, 2014 18:16 UTC (Thu) by vonbrand (subscriber, #4458) [Link]

Way overkill if the typical configuration is a single file, or at most three, with a dozen lines or so each.

Systemd programming part 1: modularity and configuration

Posted Feb 21, 2014 6:15 UTC (Fri) by sethml (guest, #8471) [Link]

I honestly cannot tell if you're being serious or sarcastic. I vote for sarcastic.

Systemd programming part 1: modularity and configuration

Posted Feb 7, 2014 4:30 UTC (Fri) by Alphix (subscriber, #7543) [Link] (1 responses)

I've looked at the init.d scripts in Debian (and I've toyed with converting a few of them to systemd unit files as a learning experience). I think it's worth mentioning that the nfs scripts are actually some of the most complex init.d scripts that I've seen so far (multiple daemons which depend on each other, kernel modules, virtual file systems, parameters, etc).

Just something to keep in mind when reading this article.

Systemd programming part 1: modularity and configuration

Posted Feb 7, 2014 16:12 UTC (Fri) by iq-0 (subscriber, #36655) [Link]

Which can be seen as a testament that systemd is capable enough to not need all sorts of workarounds for this complex case (the configuration file customization discussion aside, not that it doesn't matter but that's more a bikeshed discussion).

Systemd programming part 1: modularity and configuration

Posted Feb 10, 2014 13:43 UTC (Mon) by lmb (subscriber, #39048) [Link]

I had a similar experience with one of my smallish pet projects - a shared storage poison pill based fencing mechanism. It has rather strong requirements of where in the cluster stack's start/stop sequence it must be run. And whether admins should be allowed to start/stop it manually (the answer being no, too much potential for shooting themselves in the foot and then complaining about data corruption.)

While simple in theory, this was not possible to achieve easily with LSB compliant init scripts (the dependency model just isn't powerful enough), and one ended up patching init scripts for corosync or pacemaker to put it in the proper place.

With systemd, this was a breeze: https://github.com/l-mb/sbd/blob/master/src/sbd.service The dependency model is just that much more powerful, and it allows the maintainer to insert hard requirements in other services. This greatly improves modularity.

As for the options on the commandline, I decided to handle this in a wrapper instead of the daemon itself. Mostly, I guess, because I was a bit lazy and this made it a little bit easier to remain compatible with previous code and ways of integrating sbd.

If I ever transition to being compatible just with systemd (or an init system at least as powerful), I'd probably remain in the foreground, handle a proper config file, etc.

Systemd programming part 1: modularity and configuration

Posted Feb 11, 2014 12:57 UTC (Tue) by robbe (guest, #16131) [Link] (1 responses)

> /usr/sbin/rpc.mountd ${MOUNTD_PORT:+-p $MOUNTD_PORT}
A few comments to this problem
"sh -c ..." should work and give you the desired shell syntax. Seems clumsy, though.

When does systemd split the line into arguments? If it does it after expanding environment variables, putting -p into the variable would work.

At least for debconf, I don't see the big problem. There's always a .postinst file (usually written in bourne shell), which generates a configuration file from the contents of the debconf database. So if your original version would do something like (error handling elided):

db_get nfs-utils/mountd_port
echo "MOUNTD_PORT=$RET" >> $configfile
db_get nfs-utils/mountd_descriptors
echo "MOUNTD_DESCRIPTORS=$RET" >> $configfile

An alternative would be

db_get nfs-utils/mountd_port
port="$RET"
db_get nfs-utils/mountd_descriptors
descr="$RET"
printf "ExecStart=\nExecStart=/usr/sbin/mountd -p $port -d $descr" >> $dropinfile

Systemd programming part 1: modularity and configuration

Posted Feb 11, 2014 13:15 UTC (Tue) by mchapman (subscriber, #66589) [Link]

> When does systemd split the line into arguments? If it does it after expanding environment variables, putting -p into the variable would work.

The docs [1] say:

> Basic environment variable substitution is supported. Use "${FOO}" as part of a word, or as a word of its own on the command line, in which case it will be replaced by the value of the environment variable including all whitespace it contains, resulting in a single argument. Use "$FOO" as a separate word on the command line, in which case it will be replaced by the value of the environment variable split up at whitespace, resulting in zero or more arguments. [...]

So yes, it would be possible to put -p into the variable itself -- just use the no-brace form.

This does seem a bit of a round-about way of doing things though. If a daemon can't read a config file of its own, and if it can't work with the environment variables given to it, it might make sense just to use a wrapper script to convert the environment variables to appropriate command-line options fo0r the daemon. The wrapper script would then be used in ExecStart. Seems a lot neater than having a separate nfs-config.service to generate the command-line options in just the right form.

[1] http://www.freedesktop.org/software/systemd/man/systemd.s...

Systemd programming part 1: modularity and configuration

Posted Feb 13, 2014 14:08 UTC (Thu) by farnz (subscriber, #17727) [Link] (3 responses)

When it comes to sysadmin overrides, it's worth mentioning systemd-delta; this is a command provided by systemd to let system administrators look at their changes in a diff format.

It tells you what you've done, and where you did it, so that you can undo unnecessary changes later.

Systemd programming part 1: modularity and configuration

Posted Feb 13, 2014 21:34 UTC (Thu) by neilbrown (subscriber, #359) [Link] (2 responses)

I can't seem to get excited about systemd-delta. It seems to be a tool for sysadmins, yet it doesn't seem to scale to multiple systems in a sensible way. To me, this is a contradiction.
Sysadmins who administer a single machine are a tiny minority I suspect.

Systemd programming part 1: modularity and configuration

Posted Feb 15, 2014 19:30 UTC (Sat) by nix (subscriber, #2304) [Link]

It's probably most interesting for developers' development machines. These are often systems in which the developer *is* the sysadmin, and which accumulate all sorts of hacks over time. With systemd-delta, you can easily see what those hacks are (in one domain) so as to more easily drop them when no longer necessary.

Systemd programming part 1: modularity and configuration

Posted Feb 19, 2014 11:02 UTC (Wed) by farnz (subscriber, #17727) [Link]

It's useful in conjunction with your configuration management tool (cfengine, puppet, chef, ansible, whatever you use). Your CM tool tells you what you're pushing, systemd-delta tells you how that differs on a given system from what the distro shipped. In this use case (the one I've used it on), you run it on your test system whenever you update the underlying distro, to check that your overrides are still as you'd expect.

Alternatively, you can plumb it into your monitoring tools - check that the output of systemd-delta matches the expected delta, given your CM tool configuration, and complain if it changes.

It's more of a low level piece of plumbing than a complete tool - it gives you just enough to hook into your higher level processes so that you can easily check that you're doing what you expect.

Systemd programming part 1: modularity and configuration

Posted Mar 16, 2014 10:10 UTC (Sun) by g1pi (guest, #95996) [Link] (3 responses)

"The first is to modify all the daemons to accept any command line configuration also from environment variables."

In my opinion, this is going to cause lots of headaches to sysadms and users of all distributions. Currently a glance at the output of "ps -elf" tells everybody (even non-privileged users) how the daemon is configured at runtime.

If configuration migrates into environment, only privileged users can examine it. Imagine a dumb sysadm reports a problem and before you can help him, you have to explain how to dump the environment of a running process, and then try to guess why the environment differs from the one he (or you) expected.

Systemd programming part 1: modularity and configuration

Posted Mar 16, 2014 12:06 UTC (Sun) by khim (subscriber, #9252) [Link] (1 responses)

Currently a glance at the output of "ps -elf" tells everybody (even non-privileged users) how the daemon is configured at runtime.

And with environment variables you can get the same info with “ps axel” (again, even non-privileged users can do that). Is it such a big difference?

Systemd programming part 1: modularity and configuration

Posted Mar 16, 2014 19:59 UTC (Sun) by g1pi (guest, #95996) [Link]

On my linux system (rel. 3.2) an unprivileged user cannot read the environment of other users' processes, either via "ps axel" or directly.

Don't know if that depends on some sysctl variable, but I always get an -EACCESS (permission denied) whenever I try "cat /proc/X/environ" (for X not a process of mine).

Systemd programming part 1: modularity and configuration

Posted Mar 16, 2014 12:11 UTC (Sun) by khim (subscriber, #9252) [Link]

Imagine a dumb sysadm reports a problem and before you can help him, you have to explain how to dump the environment of a running process, and then try to guess why the environment differs from the one he (or you) expected.

This is already needed (things like LANG or LC_ALL can effect daemons in funny way). Thankfully with systemd it's easier to trace since it cleans up environment by default (while sysvinit scripts don't do that and distribution-specific helpers do that in not-entirely-consistent-way).


Copyright © 2014, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds