DAEMON(7) | daemon | DAEMON(7) |
NAME¶
daemon - 编写与打包系统守护进程描述¶
"守护进程"的意思是在后台运行的服务进程, 常用于监督系统的运行或者提供某种功能。 在传统的 SysV Unix 系统上, 多个守护进程必须严格按照特定的顺序依次启动。 在"新型"的 systemd(1) 系统上, 守护进程的启动顺序非常简单且非常强大。 本手册同时解说了上述两种不同的启动方案, 并特别推荐了应该包含在 systemd 系统中的守护进程。传统的SysV守护进程¶
传统的SysV守护进程在启动的时候, 应该在初始化阶段执行下面的步骤:注意,这些步骤对于下文讲述的新型守护进程是不需要的, 除非为了刻意兼容传统的SysV系统。
新型守护进程¶
Linux 系统上的新型守护进程更容易被监控也更容易实现。守护进程无需实现前文所描述的复杂步骤, 即可直接在 systemd 提供的干净的上下文环境中运行:
环境变量已经被清理、信号处理器与信号掩码已经被重置、没有遗留的文件描述符、守护进程自动在其专属的会话中执行、 标准输入(STDIN)已被连接到 /dev/null 虚拟设备(除非另有配置)、 标准输出(STDOUT)与标准错误(STDERR)已被连接到 systemd-journald.service(8) 日志服务(除非另有配置)、umask 已经被重置 ... 等等
新型守护进程只需要遵守如下要求:
上述要求与 Apple MacOS X Daemon Requirements[2] 类似, 但并不完全相同。
启动¶
systemd 提供了多种启动机制(见下文), 而服务单元也经常同时使用其中的几种。 例如 bluetoothd.service 可以在插入蓝牙硬件时被启动, 也可以在某进程访问其 D-Bus 接口时被启动。 又如打印服务可以在IPP端口有流量接入时被启动, 也可以在插入打印机硬件时被启动, 还可以在有文件进入打印机 spool 目录时被启动。 甚至对于必须在系统启动时无条件启动的服务, 为了尽可能并发启动, 也应该使用某些启动机制。 如果某守护进程实现了一个 D-Bus 服务或者监听一个套接字, 那么使用基于 D-Bus 或基于套接字的启动机制, 将允许该进程与其客户端同时并行启动(从而加快启动速度)。 因为所有的通信渠道都已事先建立, 并且不会丢失任何客户端请求, 同时 D-Bus 总线或者内核会将客户端请求排入队列等候, 直到完成启动。系统启动时启动¶
传统的守护进程一般是在系统启动时通过SysV初始化脚本自动启动, systemd 也支持这种启动方式。对于 systemd 来说, 如果希望确保某单元在系统启动时自动启动, 那么最佳的做法是在默认启动目标 (通常是 multi-user.target 或 graphical.target)的 .wants/ 目录中为该单元建立软链接。 参见 systemd.unit(5) 手册以了解 .wants/ 目录, 参见 systemd.special(7) 手册以了解上述两个特殊的启动目标。
基于套接字的启动¶
为了尽可能提高并行性与健壮性, 以及简化配置与开发, 对于需要监听套接字的服务, 强烈推荐使用基于套接字的启动机制。 使用此机制后, 守护进程不再需要创建和绑定套接字, 而是由 systemd 接管这个工作。 systemd 将会根据单元文件的设置, 预先创建所需的套接字, 并在第一个客户端请求接入的时候启动该服务, 以实现服务的按需启动。 该机制的好处还在于, 预先创建好套接字之后, 所有使用此套接字通信的进程可以并行启动(包括客户端和服务端)。 此外,重启服务只会导致丢失最低限度的客户端连接, 甚至不丢失任何客户端请求 (例如对于 DNS 或 syslog 这样的无状态协议)。 因为套接字在服务重启期间始终保持有效并且可被访问, 同时所有客户端请求也都被排入队列等候处理。使用此机制之后, 守护进程必须要从 systemd 接收已创建好的套接字, 而不能自己创建并绑定套接字。 关于如何使用该机制,参见 sd_listen_fds(3) 与 sd-daemon(3) 手册。 只需要小小的修改, 即可在原有启动机制的基础上添加基于套接字的启动机制, 至于如何移植,详见后文。
systemd 通过 .socket 单元实现该机制,详见 systemd.socket(5) 手册。 必须确保所有为支持基于套接字启动而创建的监听 socket 单元都被包含在 sockets.target 中。 建议在 socket 单元的 "[Install]" 小节加入 WantedBy=sockets.target 设置, 以确保在启用该单元时能够自动添加上述依赖关系。 除非明确设置了 DefaultDependencies=no , 否则会为所有 socket 单元隐含的创建必要的顺序依赖。 有关 sockets.target 的解释,详见 systemd.special(7) 手册。 如果某 socket 单元已被包含在 sockets.target 中, 那么不建议在其中再添加任何额外的依赖关系(例如 multi-user.target 之类)。
基于 D-Bus 的启动¶
如果守护进程使用 D-Bus 与客户端通信, 那么它应该使用基于 D-Bus 的启动机制, 这样当客户端访问其 D-Bus 接口时, 该服务将被自动启动。 该机制是通过 D-Bus service 文件实现的(不要与普通的单元文件混淆)。 为了确保让 D-Bus 使用 systemd 来启动与维护守护进程, 必须在这些 D-Bus service 文件中使用 SystemdService= 指明其匹配的服务单元。 例如,对于文件名为 org.freedesktop.RealtimeKit.service 的 D-Bus service 来说, 为了将其绑定到 rtkit-daemon.service 服务单元, 必须确保在该文件中设置了 SystemdService=rtkit-daemon.service 指令。 注意,必须明确设置 SystemdService= 指令, 否则当服务单元同时使用多种启动机制时, 可能会导致竞争条件的出现。基于设备的启动¶
用于管理特定类型硬件的守护进程, 只应该在符合条件的硬件变为可用或者被插入时,才需要启动。 为了达到上述目的, 可以将服务的启动/停止与硬件的插入/拔出事件绑定。 当带有 "systemd" 标签的设备出现在 sysfs/udev 设备树中时, systemd 将会自动为其创建对应的 device 单元。 通过向这些单元中添加对其他单元的 Wants= 依赖, 就可以实现当该 device 单元被启动(也就是硬件被插入)时, 连带启动其他单元,从而实现基于设备的启动。 这可以通过向 udev 规则库中添加 SYSTEMD_WANTS= 属性来实现, 详见 systemd.device(5) 手册。 通常,并不是将 service 单元直接添加到设备的 Wants= 依赖中, 而是通过专用的 target 单元间接添加。 例如,不是将 bluetoothd.service 添加到各种蓝牙设备的 Wants= 依赖中, 而是将 bluetoothd.service 添加到 bluetooth.target 的 Wants= 依赖中, 同时再将 bluetooth.target 添加到各种蓝牙设备的 Wants= 依赖中。 通过引入 bluetooth.target 这个抽象层, 系统管理员无需批量修改 udev 规则库, 仅通过 systemctl enable|disable ... 命令 修改 bluetooth.target.wants/ 目录中的软链接, 即可控制 bluetoothd.service 的使用。基于路径的启动¶
对于处理 spool 文件或目录的守护进程(例如打印服务)来说, 仅在 spool 文件或目录状态发生变化或者内容非空时, 才需要启动。 通过 .path 单元实现的、 基于路径的启动机制正好适用于这种场合, 详见 systemd.path(5) 手册。基于定时器的启动¶
对于周期性的操作(例如垃圾文件清理或者网络对时), 可以通过基于定时器的启动机制来实现。 这种机制通过 .timer 单元实现,详见 systemd.timer(5) 手册。其他启动方式¶
在其他操作系统上还存在着其他的启动机制, 不过这些机制都可以被前述的各种机制的组合替代。 因此在这里不再赘述。与 SYSTEMD 整合¶
编写 systemd 单元文件¶
在编写单元文件时应当考虑下列建议:安装 service 单元文件¶
当从源代码编译安装(make install)软件包时, 其中的系统服务单元文件会被默认安装到 pkg-config systemd --variable=systemdsystemunitdir 命令返回的目录中(通常是 /usr/lib/systemd/system); 而其中的用户服务单元文件会被默认安装到 pkg-config systemd --variable=systemduserunitdir 命令返回的目录中(通常是 /usr/lib/systemd/user); 但并不应该使用 systemctl enable ... 命令启用它们。 当从包管理器安装(rpm -i)二进制软件包时, 其中的单元文件应该同样安装到上述位置。 但不同之处在于, 还应该使用 systemctl enable ... 命令启用它们, 因此安装的单元有可能会在开机时自动启动。移植已有的守护进程¶
虽然 systemd 兼容传统的 SysV 初始化系统, 但是移植旧有的守护进程可以更好的利用 systemd 的先进特性。 建议对旧有的 SysV 守护进程做如下改进: ...[省略]...放置守护进程的数据¶
建议遵守 file-hierarchy(7) 所建议的通用准则。参见¶
systemd(1), sd-daemon(3), sd_listen_fds(3), sd_notify(3), daemon(3), systemd.service(5), file-hierarchy(7)NOTES¶
- 1.
- LSB recommendations for SysV init scripts
- 2.
- Apple MacOS X Daemon Requirements
跋¶
本页面中文版由中文 man 手册页计划提供。翻译人员:金步国
金步国作品集:http://www.jinbuguo.com
中文 man
手册页计划:https://github.com/man-pages-zh/manpages-zh
systemd 231 |