CentOS7之Systemd详解之单元配置systemd.unit

英文网址:https://www.freedesktop.org/software/systemd/man/systemd.unit.html

名称

systemd.unit - systemd 单元配置

概要

service.service, socket.socket, device.device, mount.mount, automount.automount, swap.swap, target.target, path.path, timer.timer, slice.slice, scope.scope /etc/systemd/system/* /run/systemd/system/* /usr/lib/systemd/system/* ... $XDG_CONFIG_HOME/systemd/user/* $HOME/.config/systemd/user/* /etc/systemd/user/* $XDG_RUNTIME_DIR/systemd/user/* /run/systemd/user/* $XDG_DATA_HOME/systemd/user/* $HOME/.local/share/systemd/user/* /usr/lib/systemd/user/* ...

描述

单元文件封装了有关下述对象的信息:服务(service)、套接字(socket)、设备(device)、挂载点(mount)、自动挂载点(automount)、启动目标(target)、 交换分区或交换文件(swap)、被监视的文件(path)、任务计划(timer)、资源控制组(slice)、一组外部创建的进程(scope)。 单元文件的语法与 XDG Desktop Entry Specification 规定的 .desktop 文件以及 Microsoft Windows 的 .ini 文件相同。 本文列出了各类型单元所共有的配置选项,这些选项位于单元文件的 [Unit] 或 [Install] 小节。 有些选项可以指定多次,这通常是为了设定一个列表,但对某些选项而言,再次设定的值则会取代先前设定的值(此种情况会有特别的说明)。 注意,允许多次重复设定同一个选项,使得单元文件的语法超出了 XDG .desktop 文件格式的规定,因此并不与其兼容。 单元文件将会从多个编译时设定的目录中加载,下一小节将会详细解释。 除了手册中列出的选项之外,单元文件还可以包含更多其他选项。无法识别的选项不会中断单元文件的加载,但是 systemd 会输出一条警告日志。 如果选项或者小节的名字以"X-"开头,那么 systemd 将会完全忽略它。以"X-"开头的小节中的选项没必要再以"X-"开头,因为整个小节都已经被忽略。 应用程序可以利用这个特性在单元文件中包含额外的信息。 单元文件中的布尔型值可以有多种写法。[ 1, yes, true, on ] 含义相同,[ 0, no, false, off ] 含义相同。 单元文件中表示时长的值可以有多种写法。一个单独的无后缀数字表示秒数,同时也可以通过特定的后缀表示不同的时间单位: s(秒), min(分钟), h(小时), d(天), w(星期), ms(毫秒), us(微秒) 。 空行和以 # 或 ; 开头的行都被忽略。行尾的反斜线(\)视为续行符,并在续行时被替换为一个空格符。 对于例如 foo.service 这样的单元文件,可以同时存在相应的 foo.service.wants/ 与 foo.service.requires/ 目录, 其中可以放置许多指向其他单元文件的软连接。软连接所指向的单元将会被隐含的添加到 foo.service 相应的 Wants= 与 Requires= 依赖中。 这样就可以方便的为单元添加依赖关系,而无需修改单元文件本身。 向 .wants/ 与 .requires/ 目录中添加软连接的首选方法是"systemctl enable ..."命令,它会读取单元文件的 [Install] 小节(详见后面的小节)。 对于例如 foo.service 这样的单元文件,可以同时存在相应的 foo.service.d/ 目录, 其中所有以".conf"结尾的文件,都会被按照文件名顺序,依次附加到单元文件结尾(视为单元文件的一部分)。 这样就可以方便的修改单元的设置,或者为单元添加额外的设置,而无需修改单元文件本身。 需要特别注意的是,所有".conf"文件必须在配置指令前包含明确的小节头(例如"[Service]"之类)。 注意,对于从模板文件中实例化而来的单元来说,systemd 会优先读取与此实例对应的".d/"目录中的".conf"文件, 然后才会读取与模板对应的".d/"目录中的".conf"文件。 为了便于识别,有些单元的名字刻意与文件系统上的某个路径相对应。例如将 dev-sda.device 与 /dev/sda 相对应。 这样,就需要对路径中特殊字符进行特殊处理:(1)将单纯的根目录"/"替换为"-",而将其他路径中首尾的"/"删除后再将剩余的"/"替换为"-"; (2)"_"保持不变;(3)仅当"."是首字符时替换为"\x2e",否则保持不变;(4)将所有其他非ASCII字母与数字替换为C风格的"\x??"转义序列。 建议使用systemd-escape工具来生成转义序列。 可选地,单元可以在运行时从一个模板文件实例化而来,这样就可以用同一个模板文件衍生出多个单元。 当 systemd 查找单元文件时,会首先查找与单元名称完全吻合的单元文件,如果没有找到,并且单元名称包含"@"字符, 那么 systemd 将会继续查找拥有相同前缀的模板文件,如果找到,那么将从这个模板文件实例化一个单元来使用。 例如,对于"[email protected]"单元来说,其对应的模板文件是"[email protected]"(也就是去掉"@"与后缀名之间的部分)。 可以在模板文件内部通过"%i"引用实例字符串(也就是上例中的"tty3"),详见后面的小节。 如果一个单元文件的大小为零字节或者是指向 /dev/null 的软连接,那么它的配置文件(".conf"文件)将被忽略。 同时,该单元的状态将被标记为"masked",并且无法被激活。这样就可以彻底禁用一个单元(即使手动激活也不行)。 单元文件的格式在未来将保持稳定(参见 Interface Stability Promise)。

自动依赖

需要注意的是,虽然 systemd 为明确设定单元间的依赖关系提供了灵活的方法,但是我们反对使用这些方法,你应该仅在万不得已的时候才使用它。 我们鼓励你使用基于 D-Bus 或 socket 的激活机制,以将单元间的依赖关系隐含化,从而得到一个更简单也更健壮的系统。 许多依赖关系是根据单元文件中的设置自动创建的。除此之外,对于所有未明确设置 DefaultDependencies=no 的单元, 根据其类型的不同,还会分别额外添加一组固定的依赖关系。 对于所有未明确设置 DefaultDependencies=no 的单元,如果被其他的 .target 单元通过 Wants= 或 Requires= 引用, 那么可能会同时再自动创建一个 Before= 依赖。

单元文件加载路径

systemd 将会从一组在编译时确定好的目录中加载单元文件,并且较先列出的目录拥有更高的优先级(细节见后文)。 也就是说,较先目录中的单元文件,会覆盖较后目录中的同名单元文件。 如果设置了 $SYSTEMD_UNIT_PATH 环境变量,那么它将会取代预设的单元文件加载路径。 如果 $SYSTEMD_UNIT_PATH 以":"结尾,那么预设的加载路径将会被添加到该变量值的末尾。 当 systemd 以系统实例(--system)运行时,单元加载的先后顺序(较前的优先级较高): /etc/systemd/system 本地的配置 /run/systemd/system 运行时的单元 /usr/lib/systemd/system 软件包安装的单元 当 systemd 以用户实例(--user)运行时,单元加载的先后顺序(较前的优先级较高): $XDG_CONFIG_HOME/systemd/user 用户的配置(仅当 $XDG_CONFIG_HOME 已被设置时有效) $HOME/.config/systemd/user 用户的配置(仅当 $XDG_CONFIG_HOME 未被设置时有效) /etc/systemd/user 本地的配置 $XDG_RUNTIME_DIR/systemd/user 运行时的单元(仅当 $XDG_RUNTIME_DIR 已被设置时有效) /run/systemd/user 运行时的单元 $XDG_DATA_HOME/systemd/user 软件包安装在用户家目录中的单元(仅当 $XDG_DATA_HOME 已被设置时有效) $HOME/.local/share/systemd/user 软件包安装在用户家目录中的元(仅当 $XDG_DATA_HOME 未被设置时有效) /usr/lib/systemd/user 软件包面向全系统安装的单元 可以通过"systemctl link ..."命令向 systemd 中添加额外的单元(不在上述单元目录中的单元)。

[Unit]小节选项

单元文件中的 [Unit] 小节包含与单元类型无关的通用信息。 Description= 对单元进行简单描述的字符串。用于UI中紧跟单元名称之后的简要描述文字。例如,"Apache2 Web Server"就是一个好例子。 不好的例子:"high-performance light-weight HTTP server"(太通用) 或 "Apache2"(信息太少)。 Documentation= 一组用空格分割的文档URI列表,这些文档是对此单元的详细说明。可接受 "http://", "https://", "file:", "info:", "man:" 五种URI类型。 有关URI语法的详细说明,参见uri手册。这些URI应该按照相关性由高到低列出。 比如,将解释该单元作用的文档放在第一个就是一个好主意。最好再紧跟着单元的配置说明,最后再附加上其他文档。 可以多次使用此选项,以依次向文档列表尾部添加新的文档。但是,如果为此选项设置一个空字符串,那么先前已存在的列表将会被清空。 Requires= 设置此单元所必须依赖的其他单元。当此单元被启动时,所有这里列出的其他单元也必须被启动。 如果有某个单元未能成功启动,则此单元也不会被启动。想要添加多个单元,可以多次使用此选项,也可以设置一个空格分割的单元列表。 注意,此选项并不影响单元的启动或停止顺序。想要调整单元间的启动或停止顺序,请使用 After= 与 Before= 选项。 例如,在 foo.service 中设置了"Requires=bar.service"但是并未用 After= 或 Before= 设定两者的启动顺序, 那么,当需要启动 foo.service 的时候,这两个单元会被并行的同时启动。 建议使用 Wants= 代替 Requires= 来设置单元间非致命的依赖关系,从而有助于获得更好的健壮性,特别是在某些单元启动失败的时候。 注意,此种依赖关系也可以在单元文件之外通过向 .requires/ 目录中添加软连接来设置,详见前文。 Requisite= 与相应的 Requires= 类似。唯一的不同之处在于:当单元启动时,这里列出的单元必须已经全部处于成功启动的状态, 否则,将不会启动此单元(也就是直接返回此单元启动失败的消息),并且同时也不会启动那些尚未成功启动的单元。 Wants= 与 Requires= 类似,唯一的不同之处在于:它是 Requires= 的弱化版,当此单元被启动时,所有这里列出的其他单元只是尽可能被启动。 但是,即使某些单元不存在或者未能成功启动,也不会影响此单元的启动。推荐使用此选项(而不是"Requires=")来设置单元间的依赖关系。 注意,此种依赖关系也可以在单元文件之外通过向 .wants/ 目录中添加软连接来设置,详见前文。 BindsTo= 与 Requires= 类似,唯一的不同之处在于:如果这里列出的单元停止运行或者崩溃,那么也会连带导致该单元自身被停止。 这就意味着该单元可能因为某个单元的主动退出、某个设备被拔出、某个挂载点被卸载,而被强行停止。 PartOf= 与 Requires= 类似,唯一的不同之处在于:仅作用于单元的停止或重启。 其含义是,当 systemd 停止或重启这里列出的某个单元时,也会同时停止或重启该单元自身。 注意,这个依赖是单向的,该单元自身的停止或重启并不影响这里列出的单元。 Conflicts= 指定单元间的冲突关系。接受一个空格分割的单元列表,表明该单元不能与列表中的任何单元共存, 也就是说:(1)当此单元启动的时候,列表中的所有单元都将被停止;(2)当列表中的某个单元启动的时候,该单元同样也将被停止。 注意,此选项与 After= 和 Before= 选项没有任何关系。 如果两个相互冲突的单元A与B需要在同一个事务内作为B启动,那么这个事务要么会失败(A与B都是事务中的必要部分[Requires]), 要么就是必须被修改(A与B中至少有一个是事务中的非必要部分)。 在后一种情况下,将会剔除一个非必要的单元(若两个都是非必要的单元,则优先剔除A)。 Before=, After= 强制指定单元间的先后顺序。接受一个空格分割的单元列表。假定 foo.service 单元包含"Before=bar.service"设置, 那么当两个单元都需要启动的时候,bar.service 将会一直延迟到 foo.service 启动完毕之后再启动。 注意,停止顺序与启动顺序正好相反,也就是说,只有当 bar.service 完全停止后,才会停止 foo.service 单元。 After= 的含义与 Before= 正好相反,假定 foo.service 单元包含"After=bar.service"设置, 那么当两个单元都需要启动的时候,foo.service 将会一直延迟到 bar.service 启动完毕之后再启动。 注意,停止顺序与启动顺序正好相反,也就是说,只有当 foo.service 完全停止后,才会停止 bar.service 单元。 注意,此选项仅用于指定先后顺序,与 Requires= 选项没有任何关系。 不过在实践中也经常遇见将某个单元同时设置到 After= 与 Requires= 选项中的情形。 可以多次使用此选项,以添加多个单元列表。 假定两个单元之间存在先后顺序(无论谁先谁后),并且一个要停止而另一个要启动,那么永远是先停止后启动的顺序。 但如果两个单元之间没有先后顺序,那么它们的停止和启动就都是相互独立的,并且是并行的。 OnFailure= 接受一个空格分割的单元列表。当该单元进入"failed"状态时,列表中的单元将被启动。 PropagatesReloadTo=, ReloadPropagatedFrom= 接受一个空格分割的单元列表。 PropagatesReloadTo= 表示在"reload"该单元时,也同时"reload"所有列表中的单元。 ReloadPropagatedFrom= 表示在"reload"列表中的某个单元时,也同时"reload"该单元。 JoinsNamespaceOf= 接受一个空格分割的单元列表,表示将该单元所启动的进程加入到列表单元的网络及临时文件(/tmp, /tmp/var)的命名空间中。 如果单元列表中仅有一个单元处于已启动状态,那么该单元将加入到这个唯一已启动单元的命名空间中。 如果单元列表中有多个单元处于已启动状态,那么该单元将随机加入一个已启动单元的命名空间中。 此选项仅适用于支持 PrivateNetwork= 与 PrivateTmp= 指令的单元(对加入者与被加入者都适用)。 RequiresMountsFor= 接受一个空格分割的绝对路径列表,表示该单元将会使用到这些文件系统路径。 所有这些路径中涉及的挂载点所对应的 mount 单元,都会被隐式的添加到 Requires= 与 After= 选项中。 也就是说,这些路径中所涉及的挂载点都会在启动此单元之前被自动挂载。 注意,如果路径列表中涉及的挂载点带有"noauto"标记,那么此挂载点将会被忽略(也就是不会被自动挂载)。 如果你想让某个带有"noauto"标记的挂载点(对应着一个 mount 单元)成为必须满足的依赖条件, 那么应该明确地将此挂载点所对应的 mount 单元添加到 Requires= 与 After= 选项中。 OnFailureJobMode= 可设为 "fail", "replace"(默认值), "replace-irreversibly", "isolate", "flush", "ignore-dependencies", "ignore-requirements" 之一。 指定 OnFailure= 中列出的单元应以何种方式排队。值的含义参见systemctl手册对 --job-mode= 选项的说明。 如果设为"isolate",那么只能在 OnFailure= 中设置一个单独的单元。 IgnoreOnIsolate= 如果设为"true",那么此单元在隔离(isolate)其他单元时不会停止。默认值是"false"。 StopWhenUnneeded= 如果设为"true",那么当此单元不再被任何已启动的单元依赖时,将会被自动停止。 默认值"false"的含义是,除非此单元与其他即将启动的单元冲突,否则即使此单元已不再被任何已启动的单元依赖,也不会自动停止它。 RefuseManualStart=, RefuseManualStop= 如果设为"true",那么此单元将拒绝被手动启动(RefuseManualStart=)或拒绝被手动停止(RefuseManualStop=)。 也就是说,此单元只能作为其他单元的依赖条件而存在,只能因为依赖关系而被间接启动或者间接停止,不能由用户以手动方式直接启动或者直接停止。 设置此选项的目的主要是为了禁止用户意外的启动或者停止某些特定的单元。默认值是"false"。 AllowIsolate= 如果设为"true",那么此单元将允许被"systemctl isolate ..."命令操作,否则将会被拒绝。建议保持默认值"false"。 为了兼容SysV初始化系统大概是唯一一个将此选项设为"true"的理由,此时应该仅考虑对 target 单元进行设置,以防止系统进入不可用状态。 DefaultDependencies= 默认值"true"表示为此单元隐式地创建默认依赖。不同类型的单元,其默认依赖也不同,详见各自的手册页。例如对于 service 单元来说, 默认的依赖关系是指:(1)开机时,必须在基础系统初始化完成之后才能启动该服务;(2)关机时,必须在该服务完全停止后才能关闭基础系统。 通常,只有那些在系统启动的早期就必须启动的单元,以及那些必须在系统关闭的末尾才能关闭的单元,才应该将此选项设为"false"。 注意,设为"false"并不表示取消所有的默认依赖,只是表示取消非关键的默认依赖。 强烈建议对绝大多数普通的单元保持此选项的默认值"true"。 JobTimeoutSec=, JobTimeoutAction=, JobTimeoutRebootArgument= JobTimeoutSec= 用于设置该单元等候外部任务(job)完成的最长时限,如果超时,那么超时的 job 将被撤销,并且该单元将保持其现有状态不变。 对于非 device 单元,此选项的默认值是"0"(永不超时)。注意,此选项的超时不是指单元自身的超时(例如 TimeoutStartSec= 就是指单元自身的超时), 而是指该单元在启动或者停止等状态变化过程中,等候某个外部任务完成的最长时限。 换句话说,适用于单元自身的超时设置(例如 TimeoutStartSec=),用于指定单元自身在改变其状态时,总共允许使用多长时间; 而 JobTimeoutSec= 则是设置此单元在改变其状态的过程中,等候某个外部任务完成所能容忍的最长时间。 JobTimeoutAction= 用于指定当超时发生时,触发什么样的额外动作。默认值为空。可设置的值与 StartLimitAction= 相同,参见systemd.service手册页。 JobTimeoutRebootArgument= 用于指定传递给reboot系统调用的字符串参数。 ConditionArchitecture=, ConditionVirtualization=, ConditionHost=, ConditionKernelCommandLine=, ConditionSecurity=, ConditionCapability=, ConditionACPower=, ConditionNeedsUpdate=, ConditionFirstBoot=, ConditionPathExists=, ConditionPathExistsGlob=, ConditionPathIsDirectory=, ConditionPathIsSymbolicLink=, ConditionPathIsMountPoint=, ConditionPathIsReadWrite=, ConditionDirectoryNotEmpty=, ConditionFileNotEmpty=, ConditionFileIsExecutable= 这组选项用于在单元启动之前,首先测试特定的条件是否为真。若为真则开始启动,否则将不会启动(仅是不启动,而不是进入"failed"状态)。 注意,即使此单元由于测试条件为假而不被启动,那些由于依赖关系而必须先于此单元启动的单元并不会受到影响(也就是会照常启动)。 ConditionArchitecture= 检测是否运行于特定的硬件平台:x86, x86-64, ppc, ppc-le, ppc64, ppc64-le, ia64, parisc, parisc64, s390, s390x, sparc, sparc64, mips, mips-le, mips64, mips64-le, alpha, arm, arm-be, arm64, arm64-be, sh, sh64, m86k, tilegx, cris 可以在这些关键字前面加上感叹号(!)前缀,表示逻辑反转。 ConditionVirtualization= 检测是否运行于特定的虚拟环境中:true(某种虚拟环境), false(实体机), vm(某种虚拟机), container(某种容器), qemu, kvm, zvm, vmware, microsoft, oracle, xen, bochs, uml, openvz, lxc, lxc-libvirt, systemd-nspawn, docker 。 如果嵌套在多个虚拟化环境内,那么以最贴近的一个为准。可以在这些关键字前面加上感叹号(!)前缀,表示逻辑反转。 ConditionHost= 检测系统的 hostname 或者 machine ID 。参数可以是一个主机名字符串(首尾可加引号界定), 或者是一个 machine ID 格式的字符串(首尾不可加引号)。 可以在字符串前面加上感叹号(!)前缀,表示逻辑反转。 ConditionKernelCommandLine= 检测是否设置了某个特定的内核命令行选项。参数可以是一个单独的单词,也可以是一个"var=val"格式的赋值字符串。 如果参数是一个单独的单词,那么以下两种情况都算是检测成功:(1)恰好存在一个完全匹配的单词选项, (2)在某个"var=val"格式的内核命令行选项中等号前的"var"恰好与该单词完全匹配。 如果参数是一个"var=val"格式的赋值字符串,那么必须恰好存在一个完全匹配的"var=val"格式的内核命令行选项,才算检测成功。 可以在字符串前面加上感叹号(!)前缀,表示逻辑反转。 ConditionSecurity= 检测是否启用了特定的安全模块: selinux, apparmor, ima, smack, audit 。 可以在这些关键字前面加上感叹号(!)前缀,表示逻辑反转。 ConditionCapability= 检测 systemd 的 capability 集合中是否存在特定的 capability 。参数应设为诸如"CAP_MKNOD"这样的 capability 名称。 注意,此选项不是检测特定的 capability 在实际上是否可用,而仅仅是检测在绑定集合中是否存在。 可以在名称前面加上感叹号(!)前缀,表示逻辑反转。 ConditionACPower= 检测系统是否正在使用交流电源。"true"表示至少在使用一个交流电源,或者更本不存在任何交流电源。 "false"表示存在交流电源,但是没有使用其中的任何一个。 ConditionNeedsUpdate= 检测 /usr 目录的最后更新时间(mtime),是否比 /etc/.updated 或 /var/.updated 文件的最后更新时间(mtime)更晚。 可设置的有效值是 /etc 或 /var ,也就是检测指定的目录是否需要更新。可以在值前面加上感叹号(!)前缀,表示逻辑反转。 当更新了 /usr 中的资源之后,可以通过使用此选项,实现在下一次启动时更新 /etc 或 /var 目录的目的。 使用此选项的单元必须设置"Before=systemd-update-done.service",以确保在 .updated 文件被更新之前启动完毕。 ConditionFirstBoot= 检测 /etc 目录是否处于未填充的原始状态(也就是系统出厂后的首次启动)。可设置为"true"或"false"。 此选项可以用于系统出厂后,首次开机时执行必要的初始化操作。 ConditionPathExists= 检测指定的路径是否存在,必须使用绝对路径。可以在路径前面加上感叹号(!)前缀,表示逻辑反转。 ConditionPathExistsGlob= 与 ConditionPathExists= 类似,唯一的不同是支持通配符。 ConditionPathIsDirectory= 检测指定的路径是否存在并且是一个目录,必须使用绝对路径。可以在路径前面加上感叹号(!)前缀,表示逻辑反转。 ConditionPathIsSymbolicLink= 检测指定的路径是否存在并且是一个软连接,必须使用绝对路径。可以在路径前面加上感叹号(!)前缀,表示逻辑反转。 ConditionPathIsMountPoint= 检测指定的路径是否存在并且是一个挂载点,必须使用绝对路径。可以在路径前面加上感叹号(!)前缀,表示逻辑反转。 ConditionPathIsReadWrite= 检测指定的路径是否存在并且可读写(rw),必须使用绝对路径。可以在路径前面加上感叹号(!)前缀,表示逻辑反转。 ConditionDirectoryNotEmpty= 检测指定的路径是否存在并且是一个非空的目录,必须使用绝对路径。可以在路径前面加上感叹号(!)前缀,表示逻辑反转。 ConditionFileNotEmpty= 检测指定的路径是否存在并且是一个非空的普通文件,必须使用绝对路径。可以在路径前面加上感叹号(!)前缀,表示逻辑反转。 ConditionFileIsExecutable= 检测指定的路径是否存在并且是一个可执行文件,必须使用绝对路径。可以在路径前面加上感叹号(!)前缀,表示逻辑反转。 如果在条件之前加上管道符(|),那么这个条件就是"触发条件",其含义是只要有一个触发条件被满足,该单元就会被启动; 如果在条件之前没有管道符(|),那么这个条件就是"普通条件",其含义是必须全部普通条件都被满足,该单元才会被启动。 如果在一个单元文件内,同时存在"触发条件"与"普通条件",那么必须全部普通条件都被满足,并且至少有一个触发条件被满足,该单元才会被启动。 如果需要对某个条件同时使用"|"与"!",那么"|"必须位于"!"之前。 除 ConditionPathIsSymbolicLink= 之外,其他路径检测选项都会跟随软连接。 如果将上述检测选项中的某个设为空字符串,则表示重置此选项先前的所有设置,也就是让它们全部失效。 AssertArchitecture=, AssertVirtualization=, AssertHost=, AssertKernelCommandLine=, AssertSecurity=, AssertCapability=, AssertACPower=, AssertNeedsUpdate=, AssertFirstBoot=, AssertPathExists=, AssertPathExistsGlob=, AssertPathIsDirectory=, AssertPathIsSymbolicLink=, AssertPathIsMountPoint=, AssertPathIsReadWrite=, AssertDirectoryNotEmpty=, AssertFileNotEmpty=, AssertFileIsExecutable= 与前一组测试选项类似,这一组选项用于在单元启动之前,首先进行相应的断言检查。 不同之处在于,任意一个断言的失败,都会导致该单元启动失败(也就是进入"failure"状态)。 SourcePath= 指定生成此单元时所参考的配置文件。主要用于自动化的单元生成工具,标识此单元生成自何处。普通的单元不应该使用它。

[Install]小节选项

此小节包含单元的安装信息。事实上,systemd并不使用它。 此小节仅对单元的启用|禁用命令"systemctl enable|disable ..."有意义。 Alias= 启用时使用的别名,可以设为一个空格分割的别名列表。每个别名的后缀(也就是单元类型)都必须与该单元自身的后缀相同。 如果多次使用此选项,那么每个选项所设置的别名都会被添加别名列表中。 在启用此单元时,"systemctl enable ..."命令将会为每一个别名创建一个指向该单元的软连接。 WantedBy=, RequiredBy= 接受一个空格分割的单元列表,如果多次使用此选项,那么每个选项的单元列表都会叠加在一起。 在启用此单元时,"systemctl enable ..."命令将会在每个列表单元的 .wants/ 与 .requires/ 目录中创建一个指向该单元的软连接。 这相当于为每个列表中的单元文件添加了"Wants=此单元"与"Requires=此单元"选项。 这样当列表中的任意一个单元启动时,此单元都会被启动。有关 Wants= 与 Requires= 的详细说明,参见前面 [Unit] 小节的说明。 在普通的 bar.service 单元内设置 WantedBy=foo.service 选项与设置 Alias=foo.service.wants/bar.service 选项基本上是等价的。 但是对于模板单元来说,情况则有所不同。虽然必须使用实例名称调用"systemctl enable ..."命令, 但是实际上添加到 .wants/ 与 .requires/ 目录中的软连接,指向的却是模板单元(因为并不存在真正的实例单元文件)。 假设,[email protected] 文件中存在 WantedBy=getty.target 选项, 那么"systemctl enable [email protected]"命令将会创建指向 [email protected] 的软连接 getty.target.wants/[email protected] Also= 设置此单元的附属单元,可以设为一个空格分割的单元列表。 当启用或禁用(systemctl enable|disable ...)此单元时,也同时自动的启用或禁用附属单元。 如果多次使用此选项,那么每个选项所设置的附属单元列表都会叠加在一起。 DefaultInstance= 仅对模板单元有意义,用于指定默认的实例化名称。如果启用此单元时没有指定实例化名称,则使用这里设置的名称。 在 [Install] 小节选项中,可以使用如下特殊符号:%n, %N, %p, %i, %U, %u, %m, %H, %b, %v ,每个符号的具体含义详见下一小节。

特殊符号

在许多选项中都可以使用一些特殊符号,以引用一些运行时才能确定的值,从而可以写出更通用的单元文件。 当前可识别的所有特殊符号及其解释: 符号 含义详解 -------------------------------------- "%n" 已转义的完整单元名称 "%N" 未转义的完整单元名称 "%p" 已转义的前缀名称。对于实例化的单元,这是"@"前面的部分;对于其他单元,这是去掉后缀(即类型)之后剩余的部分。 "%P" 未转义的前缀名称 "%i" 已转义的实例名称。对于实例化的单元,这是"@"和后缀之间的部分。 "%I" 未转义的实例名称 "%f" 未转义的文件名称。对于实例化的单元,这是带有"/"前缀的实例名;对于其他单元,这是带有"/"前缀的前缀名。 "%c" 单元的 cgroup 路径(不包括"/sys/fs/cgroup/systemd/"前缀) "%r" 单元所属的 slice 的 cgroup 路径,这通常是其上级 slice 单元的 cgroup 路径("%c") "%R" 存放所有 slice 以及其他单元的根 cgroup 路径。对于系统实例来说是"/",但若处于容器中则是容器的根 cgroup 路径。 "%t" 运行时目录。对于系统实例来说是"/run",对于用户实例来说则是"$XDG_RUNTIME_DIR"。 "%u" 用户名。运行 systemd 实例的用户,对于系统实例则是"root" "%U" 用户的UID。运行 systemd 实例的用户的UID,对于系统实例则是"0" "%h" 用户的家目录。运行 systemd 实例的用户的家目录,对于系统实例则是"/root" "%s" 用户的shell。运行 systemd 实例的用户的shell,对于系统实例则是"/bin/sh" "%m" 系统的"Machine ID"字符串。 "%b" 系统的"Boot ID"字符串。 "%H" 系统的主机名(hostname) "%v" 内核版本("uname -r"的输出) "%%" 百分号自身(%)。使用"%%"表示一个真正的"%"字符。 -------------------------------------- 注意,"%U", "%h", "%s" 对于以系统实例运行的 systemd 来说是没有意义的。因为 PID=1 的进程无法查询系统账户数据库。

示例1

下面这个 foo.service 单元中的"[Install]"小节表明该单元可以通过"systemctl enable foo.service"命令启用。 [Unit] Description=Foo [Service] ExecStart=/usr/sbin/foo-daemon [Install] WantedBy=multi-user.target 执行"systemctl enable foo.service"启用命令之后, 将会建立一个指向该单元文件的软链接 /etc/systemd/system/multi-user.target.wants/foo.service 表示将 foo.service 包含到 multi-user.target 目标中, 这样,当启动 multi-user.target 单元时,将会起动 foo.service 服务。 同时,"systemctl disable foo.service"命令将会删除这个软连接。

示例2

对于例如 foo.type 这样的单元来说,有两种修改单元文件的方法: (1)将单元文件从 /usr/lib/systemd/system 目录复制到 /etc/systemd/system 目录中,然后直接修改复制的副本。 (2)创建 /etc/systemd/system/foo.type.d/ 目录,并在其中创建一些".conf"文件,然后修改某些选项。 第一种方法的优点是易于修改整个单元,因为原有的单元文件会被完全忽略。 第一种方法的缺点是当原有的单元文件被更新时,更新不能在修改后的副本上自动体现出来。 第二种方法的优点是仅需要修改个别选项,并且原有单元文件的更新能够自动生效,因为".conf"文件只会被追加到原有单元的尾部。 第二种方法的缺点是原有单元文件的更新有可能导致与".conf"文件中的设置不兼容。 注意,对于复制的副本单元,如果想要移除列表选项(例如 ConditionPathExists= 或 ExecStart=)中的某些项, 那么必须首先清空列表(设为空),然后才能添加剔除掉某些项之后剩余的列表项。下文就是这样一个例子。 这同样适用于 systemd 用户实例,只是单元文件的文件系统位置不同而已。参见前文的"单元加载路径"小节。 下面是一个实例,假定原有的单元文件 /usr/lib/systemd/system/httpd.service 包含以下内容: [Unit] Description=Some HTTP server After=remote-fs.target sqldb.service Requires=sqldb.service AssertPathExists=/srv/webserver [Service] Type=notify ExecStart=/usr/sbin/some-fancy-httpd-server Nice=5 [Install] WantedBy=multi-user.target 假定系统管理员想要修改几个设置:(1)本地并不存在 /srv/webserver 目录,需要修改为 /srv/www 目录。 (2)让此服务依赖于本地已经存在的 memcached.service 服务(Requires=),且在其后启动(After=)。 (3)为了加固此服务,添加一个 PrivateTmp= 设置(参见systemd.service手册页) (4)将此服务的 nice 值重置为默认值"0"。 第一种方法,将原有的单元文件复制到 /etc/systemd/system/httpd.service 并做相应的修改: [Unit] Description=Some HTTP server After=remote-fs.target sqldb.service memcached.service Requires=sqldb.service memcached.service AssertPathExists=/srv/www [Service] Type=notify ExecStart=/usr/sbin/some-fancy-httpd-server Nice=0 PrivateTmp=yes [Install] WantedBy=multi-user.target 第二种方法,创建配置文件 /etc/systemd/system/httpd.service.d/local.conf 并在其中填入如下内容: [Unit] After=memcached.service Requires=memcached.service # 重置所有断言,接着重新加入想要的条件 AssertPathExists= AssertPathExists=/srv/www [Service] Nice=0 PrivateTmp=yes 注意,因为依赖关系列表(After= 之类)不能被重置为空,所以: (1)在配置文件(.conf)中只能添加依赖关系; (2)如果你想移除现有的依赖关系,并重新设定,那么只能用第一种方法(先复制,然后直接修改复制的副本)。

你可能感兴趣的:(CentOS7之Systemd详解之单元配置systemd.unit)