覆盖命令参数

覆盖命令参数

许多 sysv init 脚本使用相应的文件来/etc/default允许管理员对其进行配置。可以使用.override文件修改 Upstart 作业。既然 systemd 现在是 Ubuntu 中的默认设置,我该如何覆盖或配置 systemd 单元?

答案1

systemd单元不需要遵循 中的文件/etc/defaultsystemd很容易配置,但要求您了解 systemd 单元文件的语法。

软件包通常以 的形式发送单元文件/lib/systemd/system/。这些是不是进行编辑。相反,systemd允许您通过在 中创建适当的文件来覆盖这些文件/etc/systemd/system/

对于给定的服务foo,该包将提供/lib/systemd/system/foo.service。您可以使用 检查其状态systemctl status foo,或使用 查看其日志journalctl -u foo。要覆盖 定义中的某些内容foo,请执行以下操作:

sudo systemctl edit foo

这将创建一个以/etc/systemd/system单位名称命名的目录,并override.conf在该目录中创建一个文件(/etc/systemd/system/foo.service.d/override.conf)。您可以使用此文件(或.conf中的其他文件/etc/systemd/system/foo.service.d/)添加或覆盖设置。这也适用于非服务单位 - 您可以执行systemctl edit foo.mount、等。如果您未指定类型,systemctl edit foo.timer它将假定为默认类型。.service

覆盖命令参数

getty服务为例。假设我想让 TTY2 自动登录到我的用户(这不是明智之举,只是举个例子)。TTY2 由服务运行getty@tty2tty2作为模板的一个实例)。为此,我必须修改服务。/lib/systemd/system/[email protected]getty@tty2

$ systemctl cat getty@tty2
# /lib/systemd/system/[email protected]
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service

# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes

# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by [email protected], not this
# unit.
ConditionPathExists=/dev/tty0

[Service]
# the VT is cleared by TTYVTDisallocate
ExecStart=-/sbin/agetty --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=

[Install]
WantedBy=getty.target
DefaultInstance=tty1

特别是,我必须更改此ExecStart行,目前它是:

$ systemctl cat getty@tty2 | grep Exec     
ExecStart=-/sbin/agetty --noclear %I $TERM

要覆盖此设置,请执行以下操作:

sudo systemctl edit getty@tty2

并添加:

[Service]
ExecStart=
ExecStart=-/sbin/agetty -a muru --noclear %I $TERM

注意:

  1. 在再次设置之前,我必须明确清除ExecStart它,因为它是一个附加设置,类似于其他列表Environment(作为一个整体,而不是每个变量)和EnvironmentFile;与覆盖设置(如RestartSec或)不同Type。如果我没有清除它,systemd 将执行每一ExecStart行,但您只能为服务设置多个ExecStart条目。Type=oneshot

    • 依赖项设置(如BeforeAfterWants等)也是列表,但无法使用此方法清除。您必须为此覆盖/替换整个服务(见下文)。
  2. 我必须使用正确的节标题。在原始文件中,ExecStart位于[Service]节中,所以我的覆盖也必须放在节ExecStart[Service]。通常,查看实际使用的服务文件systemctl cat会告诉您需要覆盖什么以及它位于哪个节中。

通常,如果您编辑 systemd 单元文件,为了使其生效,您需要运行:

sudo systemctl daemon-reload

但是,systemctl edit它会自动为您完成这一操作。

现在:

$ systemctl cat getty@tty2 | grep Exec
ExecStart=-/sbin/agetty --noclear %I $TERM
ExecStart=
ExecStart=-/sbin/agetty -a muru --noclear %I $TERM

$ systemctl show getty@tty2 | grep ExecS
ExecStart={ path=/sbin/agetty ; argv[]=/sbin/agetty -a muru --noclear %I $TERM ; ... }

如果我这么做:

sudo systemctl restart getty@tty2

然后按下CtrlAltF2,瞧!我将在该 TTY 上登录我的帐户。

正如我之前所说,getty@tty2是模板的一个实例。那么,如果我想覆盖该模板的所有实例怎么办?可以通过编辑模板本身来完成(删除实例标识符 - 在本例中tty2):

systemctl edit getty@

覆盖环境

文件的一个常见用例/etc/default是设置环境变量。通常,/etc/default是 shell 脚本,因此您可以在其中使用 shell 语言结构。systemd但是,使用 ,情况并非如此。您可以通过两种方式指定环境变量:

通过文件

假设您已在文件中设置了环境变量:

$ cat /path/to/some/file
FOO=bar

然后,您可以添加到覆盖:

[Service]
EnvironmentFile=/path/to/some/file

特别是,如果您的/etc/default/foo仅包含作业而不包含 shell 语法,则可以将其用作EnvironmentFile

通过Environment条目

上述操作也可以使用以下覆盖来实现:

[Service]
Environment=FOO=bar

但是,如果存在多个变量、空格等,这可能会变得很棘手。看看我的另一个答案作为此类实例的一个例子。

编辑变化

完全替换现有设备

如果您想要对现有单元进行大规模更改,以便有效地将其完全替换,那么您可以这样做:

systemctl edit --full foo

临时编辑

在 systemd 文件层次结构中,/etc优先于/run,而 又优先于/lib。到目前为止所说的所有内容也适用于使用/run/systemd/system而不是/etc/systemd/system。通常/run是一个临时文件系统,其内容在重启时会丢失,因此如果您只想在重启之前覆盖一个单元,您可以执行以下操作:

systemctl edit --runtime foo

但是,您不能使用此方法临时覆盖已存在的内容/etc(例如,快照服务文件通常直接在中创建/etc/systemd/system,因此您只能使用中的文件覆盖它们/etc/system/system/<snap-service-name>.service.d)。

覆盖用户单位

到目前为止所说的所有内容也适用于用户单元,使用systemctl --user editsystemctl --user daemon-reload等代替相应的系统单元命令。覆盖文件转到~/.config/systemd/user而不是/etc/systemd/system。如果您作为管理员想要覆盖所有用户的用户单元,则使用/etc/systemd/user代替。

设置特定属性

许多资源控制属性可以直接使用命令进行设置systemctl set-property。手册页中的示例:

systemctl set-property foobar.service CPUWeight=200 MemoryMax=2G IPAccounting=yes

更改会立即应用,并会持久保存以覆盖文件。例如,以下命令将立即更新服务的资源配置:

systemctl --user set-property foobar.service CPUWeight=200 MemoryMax=2G

并且在用户的主目录中添加以下文件(因为--user使其成为用户单元):

% head .config/systemd/user.control/cann.service.d/50-*
==> .config/systemd/user.control/cann.service.d/50-CPUWeight.conf <==
# This is a drop-in unit file extension, created via "systemctl set-property"
# or an equivalent operation. Do not edit.
[Service]
CPUWeight=200

==> .config/systemd/user.control/cann.service.d/50-MemoryMax.conf <==
# This is a drop-in unit file extension, created via "systemctl set-property"
# or an equivalent operation. Do not edit.
[Service]
MemoryMax=2147483648

撤消更改

您可以简单地删除相应的覆盖文件,然后让systemctl daemon-reloadsystemd 读取更新的单元定义。

你也可以恢复所有更改(包括来自的更改systemctl set-property):

systemctl revert foo

进一步阅读

通过这种机制,可以非常轻松地覆盖systemd单位,以及撤消此类更改(只需删除覆盖文件即可)。这些并不是唯一可以修改的设置。

以下链接很有用:

相关内容