systemd.exec 中文手册

译者:金步国


版权声明

本文译者是一位开源理念的坚定支持者,所以本文虽然不是软件,但是遵照开源的精神发布。

其他作品

本文译者十分愿意与他人分享劳动成果,如果你对我的其他翻译作品或者技术文章有兴趣,可以在如下位置查看现有的作品集:

联系方式

由于译者水平有限,因此不能保证译文内容准确无误。如果你发现了译文中的错误(哪怕是错别字也好),请来信指出,任何提高译文质量的建议我都将虚心接纳。


手册索引 . 指令索引systemd-231

名称

systemd.exec — 执行环境配置

大纲

service.service, socket.socket, mount.mount, swap.swap

描述

本手册列出了 service, socket, mount, swap 单元所共有的、 用于定义进程执行环境的配置选项(亦称"配置指令"或"单元属性")。

根据单元类型的不同, 这些共有的选项(亦称"指令"或"属性")分别位于单元文件的 [Service], [Socket], [Mount], [Swap] 小节。 通用于所有单元类型的配置选项位于 systemd.unit(5) 手册。 上述四种单元各自专用的配置选项分别位于 systemd.service(5), systemd.socket(5), systemd.swap(5), systemd.mount(5) 手册。

自动依赖

某些选项会导致自动添加额外的依赖关系。

设置了 WorkingDirectory=RootDirectory= 的单元,将自动获得 对访问指定路径所需的所有 mount 单元的 Requires=After= 依赖。 这等同于将这些 mount 单元明确的在 RequiresMountsFor= 中列出来。

同样的,设置了 PrivateTmp= 的单元, 将自动获得对访问 /tmp/var/tmp 所需的 所有 mount 单元的 Requires=After= 依赖。

如果单元的标准输出(StandardOutput=)或标准错误(StandardError=)中含有 journal, syslog, kmsg 之一, 那么该单元将会自动获得 After=systemd-journald.socket 依赖。

选项

WorkingDirectory=

设置进程的工作目录。 既可以设为特殊值 "~" 表示 User= 用户的家目录, 也可以设为一个以 RootDirectory= 为基准的绝对路径。 例如当 RootDirectory=/sysroot 并且 WorkingDirectory=/work/dir 时, 实际的工作目录将是 /sysroot/work/dir 。 当 systemd 作为系统实例运行时,此选项的默认值是 / ; 当 systemd 作为用户实例运行时,此选项的默认值是对应用户的家目录。 如果给目录加上 "-" 前缀, 那么表示即使此目录不存在,也不算致命错误。 如果未设置 RootDirectory= 选项, 那么为 WorkingDirectory= 设置的绝对路径 将以主机(或容器)的根目录(也就是运行 systemd 的系统根目录)为基准。 注意,设置此选项将会导致自动添加额外的依赖关系(见上文)。

RootDirectory=

设置以 chroot(2) 方式执行进程时的根目录。 必须设为一个以主机(或容器)的根目录(也就是运行 systemd 的系统根目录)为基准的绝对路径。 如果设置了此选项, 必须确保进程及其辅助文件在 chroot() 监狱中确实可用。 注意,设置此选项将会导致自动添加额外的依赖关系(见上文)。

User=, Group=

设置进程在执行时使用的用户与组。 既可以设为数字形式的ID也可以设为字符串形式的名称。 如果没有明确设置 Group= 选项,则使用 User= 所属的默认组。 此选项不影响带有 "+" 前缀的命令。

SupplementaryGroups=

设置进程在执行时使用的附加组。 值是一个空格分隔的组名或组ID列表。 可以多次使用此选项,以添加更多的附加组。 若设为空,则表示清空先前已设置的列表。 注意,此选项并不覆盖系统现有的附加组, 而只是在现有的附加组基础上进行扩展。 此选项不影响带有 "+" 前缀的命令。

Nice=

设置进程的默认谦让值。 可以设为 -20(最高优先级) 到 19(最低优先级) 之间的整数值。详见 setpriority(2) 手册。

OOMScoreAdjust=

设置进程因内存不足而被杀死的优先级。 可设为 -1000(禁止被杀死) 到 1000(最先被杀死)之间的整数值。 详见 proc.txt 文档。

IOSchedulingClass=

设置进程的IO调度类型。 可设为 0 到 3 之间的数字或对应的 none, realtime, best-effort, idle 字符串。详见 ioprio_set(2) 手册。

IOSchedulingPriority=

设置进程的IO调度优先级。 可设为 0(最高优先级) 到 7(最低优先级) 之间的数字。 实际可用的优先级取决于 IOSchedulingClass= 的设置。参见 ioprio_set(2) 手册。

CPUSchedulingPolicy=

设置进程的CPU调度策略。 可设为 other, batch, idle, fifo, rr 之一。 详见 sched_setscheduler(2) 手册。

CPUSchedulingPriority=

设置进程的CPU调度优先级。 有效值范围取决于 CPUSchedulingPolicy= 的设置。 例如对于实时调度策略(fifo, rr)来说, 可以设为 1(最低优先级) 到 99(最高优先级) 之间的整数。 详见 sched_setscheduler(2) 手册。

CPUSchedulingResetOnFork=

是否为派生(fork)的子进程重置CPU调度策略与优先级。 若设为 yes 则表示:当父进程的CPU调度策略与优先级高于默认值时, 将重置派生的子进程的CPU调度策略与优先级为默认值。 这样就可以阻止派生的子进程继承不应有的高优先级。详见 sched_setscheduler(2) 手册。 默认值为 no 。

CPUAffinity=

设置进程的CPU亲和性。 值是一个空格或逗号分隔的CPU编号与CPU范围列表。 CPU范围可以用"编号下限-编号上限"格式表示。 若多次设置此选项, 则表示将多个选项值的CPU亲和性以掩码的方式相融合。 若设为空,则表示重置掩码并清空先前设置的所有CPU编号列表。 详见 sched_setaffinity(2) 手册。

UMask=

设置文件创建掩码。详见 umask(2) 手册。默认值为 0022

Environment=

设置进程的环境变量, 值是一个空格分隔的 VAR=VALUE 列表。 可以多次使用此选项以增加新的变量或者修改已有的变量 (同一个变量以最后一次的设置为准)。 若设为空, 则表示清空先前所有已设置的变量。 注意: (1)不会在字符串内部进行变量展开(也就是"$"没有特殊含义); (2)如果值中包含空格, 那么必须在字符串两边使用双引号(")界定。

例如:

Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"

设置了 "VAR1", "VAR2", "VAR3" 三个变量,其值分别为 "word1 word2", "word3", "$word 5 6"

详见 environ(7) 手册。

EnvironmentFile=

Environment= 类似, 不同之处在于此选项是从文本文件中读取环境变量的设置。 文件中的空行以及以分号(;)或井号(#)开头的行会被忽略, 其他行的格式必须符合 VAR=VALUE 的shell变量赋值语法。 行尾的反斜杠(\)将被视为续行符, 这与shell语法类似。 若想在变量值中包含空格, 则必须在值的两端加上双引号(")界定。

文件必须用绝对路径表示(可以包含通配符)。 但可在路径前加上"-"前缀表示忽略不存在的文件。 可以多次使用此选项, 以从多个不同的文件中读取设置。 若设为空, 则表示清空所有先前已经从文件中读取的环境变量。

这里列出的文件将在进程启动前的瞬间被读取, 因此可以由前一个单元生成配置文件, 再由后一个单元去读取它。

从文件中读取的环境变量会覆盖 Environment= 中设置的同名变量。 文件的读取顺序就是它们出现在单元文件中的顺序, 并且对于同一个变量,以最后读取的文件中的设置为准。

PassEnvironment=

将某些 systemd 的环境变量(也就是PID=1的进程所持有的环境变量)传递给该单元所派生的进程, 接受一个空格分隔的变量名称列表。 可以多次使用此选项以增加新的变量。 若设为空,则表示清空先前所有已设置的变量。 如果此处设置的变量并不是 systemd 的环境变量, 那么将被悄无声息的忽略掉。

注意,通过此选项传递过来的环境变量的值会被 Environment=EnvironmentFile= 选项中的同名变量所覆盖。

例如:

PassEnvironment=VAR1 VAR2 VAR3

传递了 "VAR1", "VAR2", "VAR3" 三个变量,其值等于PID=1的进程所持有的值。

参见 environ(7) 以了解更多环境变量的细节。

StandardInput=

设置进程的标准输入(STDIN)。 可设为 null, tty, tty-force, tty-fail, socket 之一。

null 表示 /dev/null , 也就是所有的读取都只会得到一个文件结束标记(EOF)。

tty 表示 TTY(由 TTYPath= 设置), 也就是该进程将会成为终端的控制进程。 若终端已被其他进程控制, 则一直等到其他进程释放为止。

tty-forcetty 类似, 不同之处在于, 该进程将会强制立即取得终端的控制权, 并剥夺其他进程的控制权。

tty-failtty 类似, 不同之处在于,若终端已被其他进程控制, 则会导致该进程自身启动失败。

socket 仅可用于基于套接字启动的服务单元, 并且要求在套接字单元文件 (systemd.socket(5)) 中只设置了一个套接字。 主要用于兼容那些依赖于传统 inetd(8) 的守护进程。

默认值是 null

StandardOutput=

设置进程的标准输出(STDOUT)。 可设为 inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+console, socket 之一。

inherit 表示使用 StandardInput= 设置的值。

null 表示 /dev/null , 也就是所有写入都会被丢弃。

tty 表示 TTY(由 TTYPath= 设置), 如果仅用于输出, 那么进程将无需取得终端的控制权, 亦无需等待其他进程释放终端控制权。

journal 表示 systemd 日志服务(通过 journalctl(1) 访问)。 注意,所有发到 syslogkmsg 的日志都会 隐含的复制一份到 journal 中。

syslog 表示 syslog(3) 日志服务。 注意,此时所有日志都会隐含的复制一份到 journal 中。

kmsg 表示内核日志缓冲区(通过 dmesg(1) 访问)。 注意,此时所有日志都会隐含的复制一份到 journal 中。

journal+console, syslog+console, kmsg+console 与上面三个值类似, 不同之处在于所有日志都会再复制一份到系统的控制台上。

socket 的解释与 StandardInput= 中的解释完全相同。

如果单元的标准输出(StandardOutput=)或标准错误(StandardError=)中含有 journal, syslog, kmsg 之一, 那么该单元将会自动获得 After=systemd-journald.socket 依赖(见上文)。

此选项的默认值等于 systemd-system.conf(5) 中的 DefaultStandardOutput= 选项的值(默认为 journal)。 注意,设置此选项将会导致自动添加额外的依赖关系(见上文)。

StandardError=

设置进程的标准错误(STDERR)。 取值范围及含义与 StandardOutput= 相同。 但有个例外: inherit 表示使用 StandardOutput= 的值。 默认值是 systemd-system.conf(5)DefaultStandardError= 的值 (默认为 inherit)。 注意,设置此选项将会导致自动添加额外的依赖关系(见上文)。

TTYPath=

设置用于 STDIN, STDOUT, STDERR 的终端设备节点文件(参见前面三个选项)。 默认值是 /dev/console

TTYReset=

是否在进程执行前与进程退出后,重置 TTYPath= 终端设备。 默认值是 "no"

TTYVHangup=

是否在进程执行前与进程退出后, 断开所有已打开 TTYPath= 终端设备的客户端。 默认值是 "no"

TTYVTDisallocate=

TTYPath= 是一个虚拟控制台终端时, 是否尝试在进程执行前与进程退出后,释放该终端, 以确保清空屏幕与回滚缓冲区。 默认值是 "no"

SyslogIdentifier=

设置日志标识符(发送日志消息时加在行首的字符串)。 默认值是进程的名称。 此选项仅在 StandardOutput=StandardError= 的值包含 syslog(+console), journal(+console), kmsg(+console) 之一时才有意义。

SyslogFacility=

设置 syslog(3) 的 facility 值。 可设为 kern, user, mail, daemon, auth, syslog, lpr, news, uucp, cron, authpriv, ftp, local0, local1, local2, local3, local4, local5, local6, local7 之一。仅在将 StandardOutput=StandardError= 设为 syslog 时有意义。 默认值是 daemon

SyslogLevel=

设置默认的 syslog(3) 日志级别。 可设为 emerg, alert, crit, err, warning, notice, info, debug 之一。仅在将 StandardOutput=StandardError= 设为 syslogkmsg 时有意义。 注意,进程可以在某些日志行的头部附加一个自定义的日志级别标记, 以覆盖此处设置的默认级别。 但是可以通过设置 SyslogLevelPrefix=no 来禁止识别自定义的日志级别(见后)。 参见 sd-daemon(3) 手册。 默认值是 info

SyslogLevelPrefix=

此选项仅在 StandardOutput=StandardError=syslog, kmsg, journal 之一时有意义。 设为 yes 表示按照日志行头部附加的日志级别发送日志 (在实际发送时,头部的日志级别标记将被移除)。 设为 no 则表示将日志行按原样发送而不作任何解析。 参见 sd-daemon(3) 手册。 默认值是 yes

TimerSlackNSec=

设置进程的定时器粒度。 详见 prctl(2) 手册。 定时器的粒度大小控制着进程被操作系统定时器唤醒的时间精度(也就是最小时间片)。 如果仅设为一个整数而没有单位,那么单位是纳秒。 也可以在整数后面加上时间单位后缀: "ms"(毫秒), "s"(秒), "min"(分钟), "h"(小时), "d"(天)

LimitCPU=, LimitFSIZE=, LimitDATA=, LimitSTACK=, LimitCORE=, LimitRSS=, LimitNOFILE=, LimitAS=, LimitNPROC=, LimitMEMLOCK=, LimitLOCKS=, LimitSIGPENDING=, LimitMSGQUEUE=, LimitNICE=, LimitRTPRIO=, LimitRTTIME=

设置进程的各种软/硬资源限制。详见 setrlimit(2) 手册。 这些指令的值有两种表示法,一个单独的 value 值表示将软硬两种限制设为同一个值。 而冒号分隔的 soft:hard 值表示分别设置软限制与硬限制(例如 LimitAS=4G:16G)。 特殊值 infinity 表示没有限制。 对于以字节为单位的选项,可以使用以1024为基数的 K, M, G, T, P, E 后缀(例如 LimitAS=16G)。 对于时间限制,可以加上 "ms"(毫秒), "s"(秒), "min"(分钟), "h"(小时), "d"(天), "w"(周) 等明确的时间单位后缀(systemd.time(7))。 如果仅设置了一个整数而没有单位,那么对于 LimitCPU= 来说默认单位是秒。 而对于 LimitRTTIME= 来说默认单位是微秒(百万分之一秒)。 注意,这些资源限制值的实际效果可能会受到各自有效粒度的影响。 例如 LimitCPU= 所设置的时间会被向上取整到一秒钟的整数倍。 LimitNICE= 的值有两种表示法: 可以设为带有 "+" 或 "-" 前缀的谦让值(介于 -20 到 19 之间)。 也可以设为无前缀的原始资源限制参数(介于 1 到 40 之间)。

注意,对进程的资源限制是针对单个进程的, 当父进程派生出一个子进程的时候, 子进程便获得了一个全新的资源集(重新计算资源限制), 而不是共享父进程的资源限制,这可能会导致资源超限。 而且 LimitRSS= 在Linux平台是没有意义的(因为没有被Linux实现)。 建议使用 systemd.resource-control(5) 中的资源限制方法,而不是此处这些针对单个进程的限制指令, 因为前者的限制是针对整个单元的,并且可以在运行时动态调整,所以是更好的选择。 例如 MemoryLimit= 就是对 LimitRSS= 的上佳替代。

表 1. 限制指令及其对应的 ulimit 命令

指令等价的 ulimit 命令单位
LimitCPU=ulimit -t
LimitFSIZE=ulimit -f字节
LimitDATA=ulimit -d字节
LimitSTACK=ulimit -s字节
LimitCORE=ulimit -c字节
LimitRSS=ulimit -m字节
LimitNOFILE=ulimit -n文件描述符的数量
LimitAS=ulimit -v字节
LimitNPROC=ulimit -u进程的数量
LimitMEMLOCK=ulimit -l字节
LimitLOCKS=ulimit -x锁的数量
LimitSIGPENDING=ulimit -i信号队列的长度(排队的信号数量)
LimitMSGQUEUE=ulimit -q字节
LimitNICE=ulimit -e谦让度
LimitRTPRIO=ulimit -r实时优先级
LimitRTTIME=不存在微秒

PAMName=

设置建立PAM会话所使用的PAM服务名称。 此选项仅在与 User= 连用时才有意义。 若设置,那么将以设置的名称为进程注册一个PAM会话。 若未设置,那么将不会为进程打开任何PAM会话。 详见 pam(8) 手册。

CapabilityBoundingSet=

设置进程的 capability 集合(bounding, effective, permitted, inheritable)中应该包含哪些 capabilities(7) 。 选项值是一个空格分隔的、可被 cap_from_name(3) 读取的 capability 名称列表, 例如 CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, CAP_SYS_PTRACE 。 列表中的 capabilities 将会被包含在 capability 集合中, 而所有其他不在列表中的 capabilities 则会被剔除。 如果列表以 "~" 符号开头,那么表示取反, 也就是所有列表之外的 capabilities 将会被包含在 capability 集合中。 若未设置此选项,则表示不修改进程的 capability 集合。 若多次设置此选项,则表示将多个设置的 capability 集合合并。 若设为空,则表示清空所有已设置的 capability 集合。 若设为一个单独的 "~" 字符, 则表示清空先前的所有设置,并将 capability 集合重置为包含所有的 capabilities 。 此选项不影响带有 "+" 前缀的命令。

AmbientCapabilities=

设置进程的 ambient capability 集合中应该包含哪些 capabilities(7) 。 选项值是一个空格分隔的、可被 cap_from_name(3) 读取的 capability 名称列表, 例如 CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, CAP_SYS_PTRACE 。 若多次设置此选项, 则表示将多个设置的 ambient capability 集合合并。 如果列表以 "~" 符号开头,那么表示取反, 也就是所有列表之外的 capabilities 将会被包含在 ambient capability 集合中。 若设为空,则表示清空所有已设置的 ambient capability 集合。 若设为一个单独的 "~" 字符, 则表示清空先前的所有设置, 并将 ambient capability 集合重置为包含所有的 capabilities 。 注意,添加到 ambient capability 集合中的 capabilities 也会被 添加到进程的 inherited capability 集合中。

你可以使用 ambient capability 集合 给以普通用户身份运行的进程赋予某些 capabilities 。 注意,此时 keep-caps 将被自动添加到 SecureBits= 中, 以确保此处设置的 capabilities 不受用户设置的影响。 此选项不影响带有 "+" 前缀的命令。

SecureBits=

设置进程的安全位。 值是一个空格分隔的列表。 可用列表项如下: keep-caps, keep-caps-locked, no-setuid-fixup, no-setuid-fixup-locked, noroot, noroot-locked 。 可以多次使用此选项,以合并(OR)多个安全位。 若设为空,则表示将安全位重置为"0"。 此选项不影响带有 "+" 前缀的命令。 参见 capabilities(7) 手册。

ReadWritePaths=, ReadOnlyPaths=, InaccessiblePaths=

为进程设置一个新的文件系统名字空间。 也就是限制进程可访问的文件系统范围。 每个选项的值都是一个空格分隔的绝对路径列表。 注意,这里所说的"绝对路径"实际上是 以主机(或容器)根目录(也就是运行 systemd 的系统根目录)为基准的绝对路径。 注意,如果路径是一个软连接, 那么在追踪软连接时也同样以主机(或容器)根目录(也就是运行 systemd 的系统根目录)为基准。 对于 ReadWritePaths= 中的文件与目录, 进程从名字空间内访问与从外部访问的权限是一样的。 对于 ReadOnlyPaths= 中的文件与目录, 进程从名字空间内访问时仅有只读权限, (即使从外部访问时拥有写入权限)。 对于 InaccessiblePaths= 中的文件与目录, 进程从名字空间内访问时没有任何权限(既不能读取也不能写入), 并且禁止包含任何其他挂载点(包括那些位于 ReadWritePaths=ReadOnlyPaths= 中的挂载点)。 注意,如果在这些目录的子目录中随后又挂载了新的文件系统, 那么这些选项所设置的限制并不会传递到这些新挂载的文件系统上。 选项值列表中的项可以是目录、文件、软连接。 可以多次使用这些选项, 以在文件系统名字空间内增加更多的受限路径。 若将某选项设为空, 则表示撤消该选项先前设置的所有目录列表。

可以在 ReadOnlyPaths=InaccessiblePaths= 的绝对路径前加上 "-" 前缀, 表示忽略不存在的目录。 注意, 使用这些选项后, 文件系统的挂载将无法从主机向服务传递 (但从服务向主机的传递依然有效)。 因此,不可将这些选项用于 需要在主机名字空间中挂载文件系统的服务。

PrivateTmp=

设为 yes 表示在进程的文件系统名字空间中 挂载私有的 /tmp/var/tmp 目录, 也就是不与名字空间外的其他进程共享临时目录。 这样做会增加进程的临时文件安全性, 但同时也让进程之间无法通过 /tmp/var/tmp 目录进行通信。 同时,当服务停止之后, 所有先前在临时目录中创建的文件都将被删除。 默认值是 no 。 可以通过 JoinsNamespaceOf= 选项(参见 systemd.unit(5) 手册)将多个单元 运行在同一个名字空间的私有 /tmp/var/tmp 中。 注意,使用此选项之后, 文件系统的挂载将无法从主机向服务传递 (但从服务向主机的传递依然有效)。 因此,不可将该选项用于需要在主机名字空间中挂载文件系统的服务。

PrivateDevices=

设为 yes 表示为进程设置一个新的 /dev 名字空间, 并仅在其中添加虚拟设备(不对应任何物理设备)。 例如 /dev/null, /dev/zero, /dev/random, /dev/ptmx, /dev/pts/ 都是虚拟设备的例子;而 /dev/sda, /dev/md0 都是物理设备的例子。 这样可以有效的关闭进程对物理设备的访问。默认值是 no 。 设为 yes 将会强行从 CapabilityBoundingSet= 中移除 CAP_MKNOD 项, 并且强行设置 DevicePolicy=closed (详见 systemd.resource-control(5) 手册)。 注意,使用此选项之后, 文件系统的挂载将无法从主机向服务传递 (但从服务向主机的传递依然有效)。 因此,不可将该选项用于需要在主机名字空间中挂载文件系统的服务。 注意:(1)此 /dev 名字空间将以 "ro,noexec" 选项挂载(只读,不可执行)。 (2)"noexec"可能会导致某些老旧的程序故障,因为这些程序企图通过对 /dev/zero 使用 mmap(2) 来设置可执行内存,而不是使用新式的 MAP_ANON 方法。

PrivateNetwork=

设为 yes 表示为进程设置一个新的网络名字空间, 并在其中仅配置一个 "lo" 本地回环设备(没有任何物理网络设备)。 这可以有效关闭进程对物理网络的访问。 可以通过 JoinsNamespaceOf= 选项(参见 systemd.unit(5) 手册)将多个单元运行在同一个私有的网络名字空间中。 注意,此选项将会从主机断开所有套接字(包括 AF_NETLINK 与 AF_UNIX), 同时, 进程亦无法访问那些位于抽象套接字名字空间中的AF_UNIX套接字 (不过依然可以访问位于文件系统上的AF_UNIX套接字)。 默认值是 no 。

ProtectSystem=

若设为 yes 则表示为该单元以只读模式挂载 /usr/boot 目录。 若设为 "full" 则表示为该单元以只读模式挂载 /etc/usr/boot 目录。 这样可以有效禁止该单元对操作系统以及配置文件进行任何修改。 推荐为所有需要长时间运行的服务开启此选项, 除非该单元确实需要对系统进行修改。 注意,因为具有 CAP_SYS_ADMIN capability 的进程可以无视此设置, 所以还需要使用 CapabilityBoundingSet= 去除 CAP_SYS_ADMIN capability 。 默认值为 no 。

ProtectHome=

若设为 yes 则表示对该单元屏蔽 /home, /root, /run/user 目录(内容为空且不可写入)。 若设为 "read-only" 则表示 /home, /root, /run/user 目录对该单元仅为只读(不可写入)。 推荐为所有需要长时间运行的服务开启此选项(特别是面向网络的服务), 以确保其无法访问隐私数据。 注意,因为具有 CAP_SYS_ADMIN capability 的进程可以无视此设置, 所以还需要使用 CapabilityBoundingSet= 去除 CAP_SYS_ADMIN capability 。 默认值为 no 。

MountFlags=

设置文件系统的挂载传递标记,可设为 shared, slave, private 之一。 这些标记控制着文件系统挂载点的挂载和卸载动作如何在主机与容器之间传递。 参见 mount(2) 手册。 shared 表示 挂载和卸载将会在主机和容器之间同步(双向可见); slave 表示容器内的挂载和卸载不会传递到主机, 但主机中挂载的文件系统依然对容器内的进程可见。 private 表示主机的挂载和卸载不会传递到容器, 同时容器中的挂载亦不会传递到主机中(双向不可见)。 本选项的默认值一般是 shared , 但如果使用了 PrivateTmp=, PrivateDevices=, ProtectSystem=, ProtectHome=, ReadOnlyPaths=, InaccessiblePaths=, ReadWritePaths= 选项之一, 那么本选项的默认值将会 自动从 slave 降级到 slave , 因为这些选项要求挂载和卸载必须不能从容器传递到主机。

UtmpIdentifier=

设置一个4字符长度的标识符, 用于在 utmp(5) 与 wtmp 中标识自己。 若长度超过4个字符,则截取4个结尾字符。 该选项应该仅用于 agetty(8) 之类的服务, 以及好像是被 getty 进程运行的服务 (见下文 UtmpMode= 选项), 因为它必须在执行前和退出后在 utmp/wtmp 中创建和清除记录。 该选项可以识别 %I 风格的字符串。 默认值为空, 也就是不在 utmp/wtmp 中创建和清除日志。

UtmpMode=

此选项仅在设置了 UtmpIdentifier= 时才有意义, 表示为此服务生成哪种类型的 utmp(5) 与 wtmp 记录。 "init" 表示仅生成 INIT_PROCESS 项, 被调用的进程必须实现与 getty 兼容的 utmp/wtmp 逻辑。 "login" 表示依次生成 INIT_PROCESSLOGIN_PROCESS 项, 被调用的进程必须实现与 login(1) 兼容的 utmp/wtmp 逻辑。 "user" 表示依次生成 INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS 项, 被调用的进程必须作为一个会话首进程(session leader)运行。 默认值是 "init" 。

SELinuxContext=

设置进程的 SELinux 安全上下文。 设置此选项会覆盖自动域名转换,不过,安全策略依然需要对转换进行授权。 此选项仅在 SELinux 确实被开启的情况下才有意义。 若加上 "-" 前缀则表示忽略一切错误。 此选项不影响带有 "+" 前缀的命令。 详见 setexeccon(3) 文档。

AppArmorProfile=

设置进程的 profile 名称,进程将在启动时切换到此 profile 。 设置的 profile 必须已经加载到内核中,否则该单元将无法启动。 此选项仅在 AppArmor 确实被开启的情况下才有意义。 若加上 "-" 前缀则表示忽略一切错误。 此选项不影响带有 "+" 前缀的命令。

SmackProcessLabel=

设置进程的 SMACK64 安全标签。 进程将以设定的标签启动, SMACK 将会根据此标签决定是否允许该进程启动。 若允许,进程将继续以此标签运行, 除非该可执行文件有其自身的 SMACK64EXEC 标签 (此时将会切换到其自身标签运行)。 默认值是 systemd 的运行时标签。 该选项仅在 SMACK 已启用的情况下才有意义。

若加上 "-" 前缀则表示忽略一切错误。 设为空表示撤消先前的设置。 此选项不影响带有 "+" 前缀的命令。

IgnoreSIGPIPE=

默认值 yes 表示忽略发送给进程的 SIGPIPE 信号, 因为该信号通常仅对shell管道有意义。

NoNewPrivileges=

若设为 yes 则表示该服务的 所有进程与子进程都不能获得任何新权限。 此选项比 SecureBits= 的限制更强悍, 因为该选项还禁止以任何方式更改进程的UID 。 该选项是最简单也是最有效的防止进程提升其既有权限的方法。

SystemCallFilter=

设置进程的系统调用过滤器。 值是一个空格分隔的系统调用名称列表(默认为白名单)。 如果进程使用了列表之外的系统调用, 将会立即被 SIGSYS 信号杀死。 可以在列表开头添加 "~" 字符表示反转(变成黑名单), 也就是仅禁止使用列表中列出的系统调用。 如果以用户模式运行或者以不含 CAP_SYS_ADMIN capability 的系统模式运行(例如设置了 User=nobody), 则同时也隐含设置了 NoNewPrivileges=yes 。 该选项依赖于内核的 Secure Computing Mode 2 接口("seccomp filtering"), 常用于强制建立一个最小化的沙盒环境。 注意, execve, rt_sigreturn, sigreturn, exit_group, exit 系统调用是默认隐含于白名单中的。 可以多次使用此选项以融合多个过滤器。 若设为空,则表示清空先前所有已设置的过滤器。 此选项不影响带有 "+" 前缀的命令。

如果同时设置了白名单和黑名单, 那么以先出现的名单为基准, 后出现的名单将基于第一个名单对列表项进行加减。 例如, 首个列表为白名单, 包含 read, write 两项, 随后又是一个仅包含一个 write 的黑名单, 那么最终结果将是一个仅包含 read 的白名单。

因为系统调用的数量非常巨大, 所以 systemd 预定义了一些以 "@" 字符开头的系统调用的集合, 以方便使用。

表 2. 预定义的系统调用集合

集合名字描述
@clock更改系统时钟 (adjtimex(2), settimeofday(2), ...)
@cpu-emulation CPU 模拟 (vm86(2) ...)
@debug调试、性能监控、跟踪 (ptrace(2), perf_event_open(2) ...)
@io-event事件循环 (poll(2), select(2), epoll(7), eventfd(2) ...)
@ipcSysV IPC, POSIX 消息队列, 其他IPC (mq_overview(7), svipc(7))
@keyring内核密钥环 (keyctl(2) ...)
@module内核模块控制 (init_module(2), delete_module(2) ...)
@mount文件系统挂载与卸载 (mount(2), chroot(2), ...)
@network-ioSocket I/O (包括 AF_UNIX): socket(7), unix(7)
@obsolete不常用/反对使用/未实现的系统调用 (create_module(2), gtty(2), ...)
@privileged所有需要特权的调用 (capabilities(7))
@process进程控制、执行、名字空间 (execve(2), kill(2), namespaces(7), ...
@raw-io原始 I/O 端口访问 (ioperm(2), iopl(2), pciconfig_read(), ...


当内核增加新的系统调用时,上述集合的内容可能会随之发生变化。

SystemCallErrorNumber=

如果将此选项设为一个 "errno" 名称 (EPERM, EACCES, EUCLEAN), 那么当进程触犯 SystemCallFilter= 规则时, 将会得到一个这里设定的 "errno" , 而不是被 SIGSYS 信号杀死。 若未设置此选项或设为空, 则按常规使用 SIGSYS 信号杀死违规进程。

SystemCallArchitectures=

设置进程可以使用哪些体系结构的系统调用, 选项值是一个空格分隔的体系结构标识符列表。 可以使用的标识符有: x86, x86-64, x32, arm, native(编译 systemd 时的目标架构)。 该选项可用于强制仅允许执行特定体系结构的二进制程序。 比如禁止在 x86-64 机器上执行32位的 x86 二进制程序。 如果以用户模式运行或者以不含 CAP_SYS_ADMIN capability 的系统模式运行(例如设置了 User=nobody), 则同时也隐含设置了 NoNewPrivileges=yes 。 该选项的默认值为空, 表示不作任何限制。 但若设为非空, 则 native 将被隐含的包含在列表中。

RestrictAddressFamilies=

限制进程可以访问的套接字类型。 值是一个空格分隔的套接字类型列表, 可用类型为: AF_UNIX, AF_INET, AF_INET6 。 列表默认解释为白名单。 若在列表前加上 "~" 前缀, 则表示将列表解释为黑名单。 注意,此选项仅可用于限制 socket(2) 系统调用。 通过其他方式传递给进程的套接字 (例如,基于套接字启动的单元,参见 systemd.socket(5)) 不受此选项的影响。 通过 socketpair() 创建的套接字(仅能创建 AF_UNIX 套接字)亦不受此选项的影响。 注意,此选项在 32-bit x86 架构上无效(但在 x86-64 架构上有效),因而会被忽略。 如果以用户模式运行或者以不含 CAP_SYS_ADMIN capability 的系统模式运行(例如设置了 User=nobody), 则同时也隐含设置了 NoNewPrivileges=yes 。 若未设置此选项,则不设任何限制,进程可以访问任何类型的套接字。 若设为空,则表示清空先前已有的黑白名单。

此选项可用于限制进程与远程主机的沟通,特别是通过互联网与外部沟通。 注意,一般情况下, 应该将仅可用于本机通信的 AF_UNIX 套接字放置到白名单中, 例如通过 syslog(2) 发送日志就需要使用 AF_UNIX 套接字。 此选项不影响带有 "+" 前缀的命令。

Personality=

当进程调用 uname(2) 时, 应该返回哪种体系结构标识符,可设为 x86, x86-64, ppc, ppc-le, ppc64, ppc64-le, s390, s390x 之一。 必须按照硬件的实际情况设置此选项。 通常,64位架构都隐含支持与其对应的32位架构。 例如 x86-64 同时支持 x86-64x86 。 这主要用于在 x86-64 平台上运行 32-bit 服务的场合。 若未设置,则返回未经修改的原始值(取决于主机的内核)。

RuntimeDirectory=, RuntimeDirectoryMode=

设置运行时目录: RuntimeDirectory= 是一组空格分隔的目录名称列表; RuntimeDirectoryMode= 是目录的访问权限(例如"0755")。 若设置了此选项,在单元启动时,将会在 /run (对于系统服务) 或 $XDG_RUNTIME_DIR (对于用户服务) 目录中, 按照 RuntimeDirectoryMode= 指定的权限, 创建一系列 RuntimeDirectory= 指定的目录, 并将目录的属主与属组分别设为 User=Group= 指定的用户与组。 在单元停止时,亦会自动删除这些目录。 注意,在 RuntimeDirectory= 中设置的目录名称必须是 不包含 "/" 符号的简单目录名称(也就是说,不能是一个路径)。 这些选项对于非特权守护进程意义重大, 因为这些进程自身缺乏直接在 /run 中创建目录的权限。 对于需要更复杂配置或者生存期保证的运行时目录, 可以考虑使用 tmpfiles.d(5) 功能。

MemoryDenyWriteExecute=

设为 yes 表示禁止创建可写可执行的内存映射,以及禁止将已存在的内存映射修改为可执行。 具体说来就是将会拒绝同时设置了 PROT_EXECPROT_WRITEmmap(2) 系统调用,以及拒绝设置了 PROT_EXECmprotect(2) 系统调用。 注意,此选项与那些会在运行时动态生成可执行代码的程序有冲突, 例如JIT(运行时编译执行)执行引擎,或者利用了C编译器"trampoline"特性生成的可执行程序。 此选项可用于提升服务的安全性,因为它使得利用软件漏洞来动态改变运行时代码变得困难。

RestrictRealtime=

设为 yes 表示禁止实时调度单元中的进程。 也就是禁止访问 SCHED_FIFO, SCHED_RR, SCHED_DEADLINE 这些实时任务调度策略(参见 sched(7) 手册)。 实时调度策略可能会导致CPU被长时间独占,进而导致系统失去响应或导致拒绝服务攻击。 应该仅允许个别确实需要实时调度的单元使用实时调度策略。 默认值为 no

环境变量

进程在启动的时候,会有一个干净的初始环境,最初仅包含本小节列出的环境变量。 对于由系统实例(PID=1)启动的进程来说, 它们并不从 systemd(PID=1) 继承任何环境变量; 但是对于由用户实例(PID≠1)启动的进程来说, 则会从 systemd(PID≠1) 继承全部环境变量。

$PATH

冒号分隔的目录列表(绝对路径), 此值固定为 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

$LANG

本地化设置。可以通过 locale.conf(5) 文件设置,也可以通过内核引导选项(参见 systemd(1)kernel-command-line(7))设置。

$USER, $LOGNAME, $HOME, $SHELL

用户名, 用户名, 家目录, 登录shell 。 这几个变量仅对设置了 User= 选项的单元有效(包括 systemd 用户实例)。参见 passwd(5) 手册。

$XDG_RUNTIME_DIR

保存运行时数据的目录。 此变量针对 systemd 用户实例以及用户会话设置。 参见 pam_systemd(8) 手册。

$XDG_SESSION_ID, $XDG_SEAT, $XDG_VTNR

会话ID, 席位名称, 会话虚拟终端。 由 pam_systemd(8) 对登录会话设置。$XDG_SEAT 仅在会话被附加到一个席位时才设置; $XDG_VTNR 仅在会话被附加到一个虚拟终端时才设置。

$MAINPID

单元主进程的PID(如果能确定的话)。 仅对由 ExecReload= 之类启动的控制进程设置。

$MANAGERPID

systemd 用户实例的PID , 仅为从 systemd 用户实例派生的进程设置。

$LISTEN_FDS, $LISTEN_PID, $LISTEN_FDNAMES

传递给服务的基于套接字启动的文件描述符的相关信息。 参见 sd_listen_fds(3) 手册。

$NOTIFY_SOCKET

sd_notify() 所使用的套接字。参见 sd_notify(3) 手册。

$WATCHDOG_PID, $WATCHDOG_USEC

关于看门狗 keep-alive 通知的相关信息。参见 sd_watchdog_enabled(3) 手册。

$TERM

终端类型。 仅为连接到终端的单元设置(StandardInput=tty, StandardOutput=tty, StandardError=tty) 。参见 termcap(5) 手册。

$JOURNAL_STREAM

如果进程的标准输出(STDOUT)或标准错误(STDERR)被连接到了日志文件(例如 StandardError=journal), 那么 $JOURNAL_STREAM 将是形如 "device:inode" 格式的字符串, 其中 "device" 是日志文件所在的设备,而 "inode" 则是日志文件描述符的 inode 号(以十进制数表示)。 这将允许进程安全的检测其标准输出(STDOUT)或标准错误(STDERR)是否被连接到了日志文件。 进程应该将自己实际使用的 "device:inode" 与环境变量中的值进行对比, 以检测进程的标准输出(STDOUT)或标准错误(STDERR)是否依然连接在日志文件上。 注意,仅检查是否设置了 $JOURNAL_STREAM 环境变量是远远不够的, 因为服务进程有可能调用外部进程来替换标准输出(STDOUT)或标准错误(STDERR), 而不撤销此环境变量。

此环境变量主要用于让服务单元将日志协议升级到 systemd 日志协议(使用 sd_journal_print(3) 等函数)。 如果服务进程的标准输出(STDOUT)或标准错误(STDERR)被连接到了日志文件, 那么就可以伴随日志消息一起保存相关的结构化元数据。

可以通过以下方法配置额外的变量: 对于单元中派生的进程,可以使用前文的 Environment=, EnvironmentFile=, PassEnvironment= 选项; 若要设置全局变量,可以使用 DefaultEnvironment= (参见 systemd-system.conf(5)) 或 systemd.setenv= 内核引导选项(参见 systemd(1)); 还可以通过 PAM (参见 pam_env(8))

参见

systemd(1), systemctl(1), journalctl(8), systemd.unit(5), systemd.service(5), systemd.socket(5), systemd.swap(5), systemd.mount(5), systemd.kill(5), systemd.resource-control(5), systemd.time(7), systemd.directives(7), tmpfiles.d(5), exec(3)