Systemd的设计理念尽可能启动更少进程当SysVinit程序初始化系统的时,会将所有可能用到的后台服务进程全部运行起来。然而用户需要等待系统将所有服务都启动完成之后,才能够登录。这种做法会带来两个问题:系统的启动时间过长和系统资源的浪费。Systemd提供了服务按需启动的能力,使得特定的服务只有在被真正请求的时候才启动。特别是具体硬件相关的服务,比如蓝牙服务仅在蓝牙适配器被插入时才需要运行,打印服务仅在打印机连接或程序要打印时才需要运行,甚至sshd服务也只需要在用户使用ssh连接到服务器时才需要启动。这种能力是建立在对Systemd对DBus总线或特定Socket端口监听的特性上的,这种设计相比于传统启动程序具有颠覆性的进步。尽可能将更多进程并行启动在SysVinit的时代,将每个服务项目编号的方式依次执行启动脚本。后来Ubuntu的Upstart解决了没有直接依赖的启动项之间的并行启动。而Systemd通过Socket缓存、DBus缓存和建立临时挂载点等方法进一步解决了启动进程之间的依赖,做到了所有系统服务并发启动,这一设计同样是Systemd独具特色的创意。当然,对于用户自定义的服务,Systemd允许配置其启动依赖项目,从而确保服务按必要的顺序运行,稍后会详细描述具体的使用方法。Systemd启动模型与其它启动模型的对比采用Cgroup跟踪和管理进程的生命周期Cgroup的全称是controllergroup,是将任意进程进行分组化管理的Linux内核功能,最初由Google的工程师提出,从Linux内核版本2.6.24正式启用。拿Android来说,它的应用程序隔离就是使用的这种技术。而很长一段时间里,在更广阔的服务器领域,一直并没有一种主流的服务管理程序能够充分利用这种早已在手机端带来广泛好处的特性。而Systemd正是Cgroup方面的行家,它的出现正好弥补了这个领域的缺漏。通过Cgroup,Systemd不仅实现了服务之间的访问隔离,还能够限制特定应用程序对系统资源访问配额(比如CPU的用量、内存的量),以及精确的管理服务的生命周期。在这篇文章的后面部分会讲述相关操作具体的做法。统一管理服务日志使用Systemd必须知道的还有它的伙伴:Journald日志服务,这个服务的设计初衷是克服现有syslog服务的日志内容易伪造和日志格式不统一等缺点,而它现在已经是Systemd的一个标准子服务了。Journald用二进制格式保存所有日志信息,用户需要使用journalctl命令来查看日志信息。在这篇文章的后面会介绍如何查看服务的日志。第一个HelloWorld服务Unit和Target先介绍两个概念,Unit和Target。Unit是Systemd管理服务的基本单元,可以认为每个服务就是一个Unit,并使用一个Unit文件定义。Unit文件中需要包含相应服务的描述、属性以及需要运行的命令。在CoreOS中服务运行的命令通常是一系列的容器操作,而将具体的服务进程封装在容器中。Target是Systemd中用于指定服务启动组的方式(相当于SysVinit中的“运行级别”,如果不清楚这个概念也没有关系,搜索“Linux运行级别”可以查到很多相关文章)。每次系统启动的时候都会运行与当前系统相同级别Target关联的所有服务,如果服务不需要跟随系统自动启动,则完全可以忽略这个Target的内容。通常来说我们大多数的Linux用户平时使用的都是“多用户模式”这个级别,对应的Target值为“multi-user.target”。