Quite a lot of clock-cycles are being devoted to the discussion of dependencies among services.
I would like to suggest that not all dependencies are created equal. That is, some (if not most) dependencies are really of no practical consequence -- and we don't need to worry about them in terms of sequentializing service start-up. Other dependencies (and their number is fewer) may in fact require our attention through simple handling within the runscript. First a preliminary statement: service dependencies are of a different nature than, say, build dependencies or package installation dependencies. Efforts to use these paradigms for ordering service start-up will generally lead to unnecessary complexity. Unnecessary complexity is a Bad Thing. As the system becomes complex, it becomes opaque, confusing, prone to error, hard to troubleshoot, and difficult to administer. Then you are right back to the problems of, say, sysvinit or systemd from which you are trying to escape. To the extent that we can recognize and categorize service dependencies, we may simplify our runscripts considerably. What follows below is an effort (admittedly a first-cut) to describe a "taxonomy" of service dependencies. 0) No dependency. A service has no functional dependency on any other service. (Mentioned here for completeness). Nothing to worry about. 1) Logical only dependency. A service has only a logical dependency on another service; in terms of functional behavior however, arranging for ordered start-up is unnecessary. There is no pathological functional behavior associated with starting in parallel or in any particular order. Again, nothing to worry about. 2) Functional dependency - soft. A service has a functional dependency on another service, as in, it cannot perform it's task without the other service running. Yet there is no pathological functional behavior exhibited by the service in cases where the dependency is not running. That is, the service simply defers connections or reports not ready until the dependency is running. Once again, still nothing for us to worry about in terms of special handling within runscripts, as the services may be started in any order. 3) Functional dependency - medium. A service has a functional dependency on another service, and fails to start if the dependency is not running. This is actually quite a nice arrangement, because the service itself is testing for its dependency without any additional effort on our part. Under a supervision framework, failure of a service starting is absolutely ok. (Many novices fail to grasp the elegance of this essential feature.) The system will automatically attempt to restart the failed service at intervals until the dependency is met. Yet again, nothing to worry about in our runscripts. 4) Functional dependency - hard. A service has a functional dependency on another service, yet will start and run no error without the dependency, and doing so results in some kind of pathological behavior. The pathological behavior may expose the system to security vulnerability, resource blockage, or provide users with erroneous data or bad results. Now -- finally -- this is a case we have to worry about. The runscripts must be designed to explicitly require the dependency before starting the service. When working with dependencies in this last category #4, all we have to to do is to make runscripts that effectively turn them into category #3. That is, we simply want to immediately fail any service whose required dependency is not running. An example of dependency handling under the perp system is illustrated in the perpok(8) manual page in the EXAMPLES section: http://b0llix.net/perp/site.cgi?page=perpok.8 Alternatively, one may write purpose-specific dependency checking utilities, such as with ncat, etc., to make sure that the dependency is not only running, but serving a set of expected results. Note also that in no case is it necessary for a service runscript to try starting dependencies itself -- this is all left to the supervisor. All the runscript needs for category #4 dependencies is to check for the dependency, and fail immediately if that check fails. Simplissimo. -- Wayne http://b0llix.net/perp/