Rich Freeman posted on Thu, 18 Feb 2016 07:22:36 -0500 as excerpted: > 4. In the runlevel paradigm you usually think of services running > inside a runlevel (perhaps this isn't strictly true, but most people > think this way, in part because runlevels don't change much). In > systemd this really isn't the case. Services run before targets, or > after them. A target won't be considered running if anything it depends > on isn't running.
Some minor additional notes, with the first one being here. Systemd target units are analogous to edge-triggered interrupts, which they resemble in that they are simply "synchronization points" (the term used in the systemd.target (5) manpage itself). Level-triggered interrupts can be held on or held off (high or low), but edge-triggered a re simply events that occur and then are passed as time moves on. As such, targets can be started, but not normally (while the job queue is idle) stopped, as they de-assert as soon as they are actually reached, tho many of their requirements generally continue to run until stopped by some other event, often conflicts= against some other target or general unit being started, or specific admin systemctl stop. Tho the systemd FAQ suggests this wasn't always so, as it suggests using systemctl list-units --type=target in answer to a question about how to find what "runlevel" you're in. That command seems to return nothing, here, tho, at least while no target is actively starting, so it would seem that answer's a bit dated. It can be noted, however, that certain units, most often specific targets intended to be specifically invokable by users, can be "isolated", as they have the AllowIsolate unit setting. Systemctl isolate <unit> will then cause it to be started exclusively, stopping anything that's not a dependency of that unit. The systemctl emergency, rescue, reboot, shutdown, etc, commands, then become effectively shortcuts to the longer systemctl isolate <named-target-unit> command form. > 5. I'd have to check, but I wouldn't be surprised if systemd doesn't > actually require specifying a target at all. Your default "runlevel" > could be apache2.service, which means the system would boot and launch > everything necessary to get apache working, and it probably wouldn't > even spawn a getty. This is NOT analogous to just putting only apache2 > in /etc/runlevels/default, because in that example openrc is running the > default runlevel, and it only pulls in apache2. Systemd is purely > dependency driven and when you tell it to make graphical.target the > default runlevel it is like running emerge kde-meta. If all you wanted > was kde-runtime you wouldn't redefine kde-meta to pull in only > kde-runtime, you'd just run emerge kde-runtime. Again, I haven't tested > this, but I'd be shocked if it didn't work. Of course, specifying a > service as a default instead of a target is very limiting, but it would > probably work. Heck, you could probably specify a mount as the default > and the system would just boot and mount something and sit there. Or > you could make it a socket and all it would do is sit and listen for a > connection inetd-style. As mentioned both in the systemd FAQ and in the systemd.special (7) manpage, under default.target, this is the default unit started at bootup. Normally, it'll be a symlink to either multi-user.target (analogous to sysvinit semi-standard runlevel 3, CLI, no X), or graphical.target (analogous to sysvinit semi-standard runlevel 5, launching X and and a graphical *DM login). I don't see specific documentation of whether symlinking to a non-target unit is allowed, but systemd does have a commandline option --unit=, which is explicitly documented to take a _unit_, default.target being the default, but other non-target units being possible as well. Presumably systemd would examine said unit, looking for DefaultDependencies=no, and if not specifically set, would start the early "system level" targets, before starting the named unit in place of the normal default.target. So it's definitely possible to do via systemd commandline, but I'm not sure if default.target is followed if it doesn't symlink a target unit, or not. I'd guess yes, but have neither seen it specifically documented nor tested it myself, nor read of anyone else actually testing it. > > I find it more helpful to think of targets as just units that don't do > anything. We don't use them in openrc but I suspect it would work out > of the box, and maybe we should even consider doing it in at least some > cases. For example, right now /etc/init.d/samba uses some scripting to > launch both nmbd/smbd and fancy config file parsing to let the users > control which ones launch. You could instead break that into three > files - smbd, nmbd, and samba. The first two would launch one daemon > each, and the samba init.d script wouldn't actually launch anything, but > would just depend on the others. That would be the systemd target > approach. It should work in openrc, yes, because not all functions need filled in. It's quite possible to have openrc initscripts that have only a start or a stop, not both, for instance, and I remember actually creating custom initscripts of that nature, back when I was still on openrc. So without /both/ start and stop, only dependencies, should work too, unless there's a specific error check for that in openrc, and I can't see why there would be. > Apologies if this is a bit off-topic in an openrc discussion, but I > think the concept of virtual services is a potentially powerful one, and > I think that it might be something openrc would actually benefit from > using. =:^) It would certainly simplify things like the named chroot stuff, that being what I'm familiar with from my openrc days, and from the sounds of it based on other posts, apache, too, as you'd then have a virtual service pulling in multiple modular dependencies, instead of a seriously complex hairball of a single service trying to cram in all this additional functionality that really should be in other modules, making things less complex for both maintainers and admin-users. > However, what I will say is until you actually appreciate that systemd > targets are just virtual units then you'll probably find the entire > systemd startup process to be an indecipherable mess. Not groking this > stuff also makes it easy to incorrectly specify dependencies. I'm sure a > few of us running openrc over the years have accidentially stuck a > service in the wrong runlevel and had something break. Well, in systemd > you might have 47 "runlevels" not actually starting in any particular > order so it is much easier to get it wrong if you don't realize how they > work. They aren't strictly sequential, so there isn't always one > "runlevel" that always comes last that you can be lazy and stick > something "in." Umm... for anyone following systemd documentation, including most non- early/late-system service units whether shipped by systemd itself or other system service upstreams or distro maintainers... multi-user.target is roughly equivalent to the standard sysvinit runlevel 3 (that being CLI operation and default system services). graphical.target is roughly equivalent to the standard sysvinit runlevel 5 (that being X/XDM graphical login). And graphical.target specifically Requires=multi-user.target, thereby pulling in all its dependencies as well. So multi-user.target is the standard "wanted-by/wants" single "runlevel analog" for CLI services and where nearly everything that doesn't have specific reason to be somewhere else ends up, if enabled. But of course, that's not guaranteed, just documented default and the standard nearly all shipped service units use, and individual distros/ sites/installations may well be setup entirely differently, if they have specific reason for it. -- Duncan - List replies preferred. No HTML msgs. "Every nonfree program has a lord, a master -- and if you use the program, he is your master." Richard Stallman