![如何使 systemd 服务成为启动时的最后一项服务?](https://linux22.com/image/1349358/%E5%A6%82%E4%BD%95%E4%BD%BF%20systemd%20%E6%9C%8D%E5%8A%A1%E6%88%90%E4%B8%BA%E5%90%AF%E5%8A%A8%E6%97%B6%E7%9A%84%E6%9C%80%E5%90%8E%E4%B8%80%E9%A1%B9%E6%9C%8D%E5%8A%A1%EF%BC%9F.png)
很多年前,我们可以将我们的启动脚本写入/etc/rc.local
。当所有系统服务加载完成后,你的脚本就会运行。
现在,我们使用 systemd,我们不再有其他rc.local
服务了。Systemd 并行启动服务。您可以编写自己的服务来充当 rc.local`,但您无法确保它会在所有系统服务加载后运行。
有办法吗?或者我们必须在 systemd 服务文件中使用Before
和?After
答案1
在 systemd 中,建议使用Before=
并After=
妥善安排您的服务与其他服务之间的联系。
但是既然您要求一种不使用Before
和的方法After
,那么您可以使用:
Type=idle
也就是man systemd.service
解释:
的行为
idle
与 非常相似simple
;但是,服务程序的实际执行会延迟,直到所有活动作业都已调度完毕。这可用于避免 shell 服务的输出与控制台上的状态输出交错。请注意,此类型仅用于改进控制台输出,不能用作通用单元排序工具,并且此服务类型的效果会受到 5 秒超时的影响,在此之后,服务程序仍会被调用。
答案2
确保我们的服务在所有其他启用的服务之后执行的最佳方法是创建您自己的目标并使其在之后运行multi-user.target
。
通常:
/etc/systemd/system/custom.target
使用以下方式创建目标单元文件AllowIsolate=yes
[Unit]
Description=My Custom Target
Requires=multi-user.target
After=multi-user.target
AllowIsolate=yes
/etc/systemd/system/last_command.service
使用After=multi-user.target
和创建服务单元文件WantedBy=custom.target
[Unit]
Description=My custom command
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/local/bin/my_last_command.sh
[Install]
WantedBy=custom.target
- 创建
/etc/systemd/system/custom.target.wants
目录 last_command.service
链接您的/etc/systemd/system/custom.target.wants
ln -s /etc/systemd/system/last_command.service \
/etc/systemd/system/custom.target.wants/last_command.service
- 使用以下命令重新加载 systemd
systemctl daemon-reload
- 将系统默认目标设置为
custom.target
systemctl set-default custom.target
- 或者,您可能希望立即应用
custom.target
systemctl isolate custom.target
这样,每次重启后,达到 last_command 服务就会被执行multi-user.target
。
答案3
这实际上取决于您对“启动”的定义。我假设您希望它在 getty 启动后立即运行。为此,您需要将您的服务添加到/etc/systemd/system/getty.target.wants/
目录中。您还应确保您的文件使用的代码与此目录中的其他服务类似。要在启动和关闭时运行自定义服务(只需发出主板蜂鸣器的声音),我使用以下脚本/etc/systemd/system/getty.target.wants/service_name.service
[Unit]
After=systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service
Before=getty.target
IgnoreOnIsolate=yes
[Service]
ExecStart=/usr/bin/myinitscript.sh start
ExecStop=/usr/bin/myinitscript.sh stop
Type=oneshot
RemainAfterExit=true
[Install]
WantedBy=basic.target
/usr/bin/myinitscript.sh
是可执行的并且在开始时有一个shebang。
请注意,此时启动时并非所有程序都会启动,但此时登录提示会出现在用户面前
虽然这确实使用了Before=
和After=
,但对我来说更容易理解,而且确实有效;我发现上面的答案不够有用。这也允许您同时使用ExecStart=
和ExecStop=
,而不是仅限于Type=simple
类似服务。