许多sysv init脚本使用
/etc/default
中的相应文件来允许管理员进行配置。可以使用.override
文件来修改Upstart作业。现在Ubuntu默认使用systemd,我该如何覆盖或配置systemd单元?/etc/default
中的相应文件来允许管理员进行配置。可以使用.override
文件来修改Upstart作业。现在Ubuntu默认使用systemd,我该如何覆盖或配置systemd单元?systemd
单元不需要遵守/etc/default
中的文件。 systemd
易于配置,但需要您了解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
$ systemctl cat getty@tty2
# /lib/systemd/system/getty@.service
# 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 serial-getty@.service, 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
ExecStart
,因为它是一个添加设置,类似于其他列表,如Environment
(作为整体,而不是每个变量)和EnvironmentFile
;与覆盖设置相反,如RestartSec
或Type
。只有对于Type=oneshot
服务,ExecStart
才能具有多个条目。请注意,依赖关系设置,如Before
、After
、Wants
等也是列表,但不能使用此方法清除。您将不得不覆盖/替换整个服务(见下文)。
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
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/grub
只包含赋值而没有shell语法,您可以将其用作EnvironmentFile
。Environment
条目[Service]
Environment=FOO=bar
如果您想对现有单元进行大规模更改,以至于实际上是完全替换它,您可以简单地执行以下操作:
systemctl edit --full foo
在systemd文件层次结构中,/run
优先于/etc
,而/etc
又优先于/lib
。前面所说的一切也适用于使用/run/systemd/system
代替/etc/systemd/system
。通常,/run
是一个临时文件系统,在重新启动时其内容会丢失,因此如果您只想在重启之前覆盖一个单元,可以执行以下操作:
systemctl edit --runtime foo
systemctl daemon-reload
来让systemd读取更新后的单元定义。systemctl revert foo
通过这种机制,覆盖 systemd
单元变得非常容易,同样也可以通过简单删除覆盖文件来撤销这些更改。这些并不是唯一可以修改的设置。
以下链接可能会有用:
ExecStart=
清除继承值的信息,就像这个答案中所示吗? - Mark Edingtonsystemd.service(5)
手册,ExecStart
部分的翻译:"除非Type=是oneshot,否则必须给出一个命令。当使用Type=oneshot时,可以指定零个或多个命令。可以通过在同一指令中提供多个命令行来指定命令,或者,可以多次指定此指令并具有相同的效果。如果将空字符串分配给此选项,则会重置要启动的命令列表,先前分配此选项的操作将不起作用。" - murusystemctl
移除覆盖?我不能只是清空文件。 - Tomilov Anatoliysudo rm
命令删除覆盖文件,然后执行systemctl daemon-reload
命令,或者你可以使用systemctl edit
命令,在覆盖文件中用注释替换所有内容。服务文件中的注释以#
符号开头。 - murusystemctl revert foo
- AyellExecStart
,但是我不知道可执行文件的路径,我该如何做呢?我需要复制可执行文件的路径吗?还是有一种方法可以保留它?另外,如果这是一个累加设置,似乎意味着应该创建一个“默认”命令,可以通过追加更多选项来覆盖先前的选项。 - CMCDragonkaisystemctl cat
或 systemctl show
很容易地获取到。它是累加的意思,多个实例会被添加到一个列表中,而不是添加到列表中的某个项目上。 - muruExecStart
是否实际上是必需的,还是只是为了隐藏systemctl show
中的先前值? - xenoterracideAfter
,基于这句话:“在重新设置之前,我必须明确地清除ExecStart,因为它是一种可加性设置,类似于After...”
尽管它确实是一个列表/可加性设置 - 正如我从其他地方找到的链接 - 但你无法重置依赖类型的设置... - Krisztián Szegisystemd
的文档,但在Ubuntu上(至少在18.04版本),它们似乎不起作用。 - cueedee
ExecStart=
时,您不能在其后添加注释,例如:ExecStart= # 清除先前的条目。
这将被视为另一个ExecStart=
条目并添加到列表中。附言:由于我的声望较低,我无法对muru的回答进行评论。 - tysik