我需要systemd-tmpfiles --create
在启动过程中使用 systemd 发行版运行。所以我需要创建一个 systemd .service 文件来完成这项工作。
在这个问题中,您可以阅读有关我需要什么及其原因的所有详细信息:systemd-tmpfiles 如何工作?
我已经阅读了一些有关它的文档,并且正在编写以下测试:
[Unit]
Description=Execute tmpfiles to disable usb-wakeup # see details in the link above
Requires=multi-user.target # see details in the link above
After=multi-user.target # see details in the link above
[Service]
Type=oneshot
ExecStart=/usr/bin/systemd-tmpfiles --create
[Install]
WantedBy=multi-user.target
但我不确定,因为systemd-tmpfiles
它不是一个简单的程序,而是 systemd 本身的一部分。我不想破坏我的系统。
关于正确的 .service 文件有什么建议吗?
答案1
[这并不能直接解决 systemd-tmpfiles 的问题,但我认为您已经认识到,在这种特殊情况下,您最好只使用 echo。]
首先,“multi-user.target”可能是也可能不是您想要使用的。如果您熟悉 SysV 风格的 init 内容中的运行级别概念,那么多用户相当于运行级别 3 的 systemd,它是启动到控制台而不是 GUI 的多用户系统。相当于启动到 X 的运行级别 5 是图形目标。默认值由 中的符号链接/etc/systemd/system
(和/或/lib/systemd/system
;中的符号链接/etc
将否决 中的符号链接/lib
)确定默认目标,使用 ls 查找它指向的位置:
»ls -l /etc/systemd/system/default.target
default.target -> /usr/lib/systemd/system/multi-user.target
systemctl get-default
在这种情况下会告诉你“multi-user.target”。对于普通的 Linux 桌面来说是图形目标。如果您希望无论默认运行级别/目标是什么都启动您正在创建的引导服务,这实际上并不重要 - 在这种情况下,我们可以只使用 default.target,而不必担心它的别名是什么。但是,如果您使用多用户,并且您的默认设置是图形化的,则您的服务将不会发生。
根据服务的不同,您可能想要启动与其相关的更合适和更具体的目标或服务。根据您的其他问题,default.target 可能没问题。请注意,“目标”和“服务”之间的区别在于,服务包含[Service]
实际运行进程的部分;目标只是通过各种“depends”和“requires”指令将服务分组在一起的一种方式;除了触发其他目标或服务之外,它本身不会执行任何操作。
服务何时启动取决于哪些其他服务明确依赖于它。对于像这样的简单独立事件,我们希望在启动过程后期运行,我们可以使用以下指令组合:
[Unit]
Requires=local-fs.target
After=local-fs.target
[Install]
WantedBy=default.target
安装服务时使用“安装”部分。 “WantedBy=”指定我们希望该服务包含在其中的目标,这意味着如果该目标包含该服务,它将运行。如果您没有特定的依赖项,那么让单元稍后而不是更快运行可能需要查看正常情况并选择某些内容用作依赖项或可选先决条件。
区分:通过依赖性我的意思是你的单位也需要激活一些东西,并且通过可选先决条件我的意思是应该在你的单位之前运行的东西如果它正在被使用,但不是必需的。这些术语是我的,但这是 systemd 文档中使用的一个重要区别,特别是在这个意义上如果您的设备是,则保证启动所需的依赖项,但是这个要求不影响它们启动的顺序,这意味着,只是依赖项的东西实际上可能会在之后启动(是的,因为这意味着您的单元可能会首先启动,所以依赖项不能保证成功)。
上面的Requires
onlocal-fs.target
可能有点毫无意义,除非您认为您的单元将在一个可能不包含它的系统上使用,但将其与 结合起来After
意味着您的单元保证在它被包含后启动 - 所以您可以这样做没有Requires
(您可以将一个单元设置为在它不依赖的单元之后启动,因此“After”没有“Requires”=可选先决条件)。这里的例子只是为了介绍概念以及依赖关系和执行顺序之间的区别:一个并不决定另一个。
请注意,“开始于”仍然并不意味着先决条件将达到其自身执行的任何特定点。例如,如果它是关于安装远程文件系统,并且这对您的设备很重要,您将需要使用Requires
并且可能需要After
建立该服务,但您仍然需要正在执行的实际进程来执行正确的错误处理,以防远程文件系统损坏。文件系统尚不可访问(例如,通过在循环中休眠直到可访问)。
例如,我将仅向控制台回显“hello world”。该服务本身在以下[Service]
部分中进行了描述:
[Service]
Type=simple
ExecStart=/usr/local/bin/helloworld
该命令需要完整路径。我不只是使用的原因/usr/bin/echo "hello world"
是它不起作用(我认为输出会转到 /dev/null),虽然服务执行意愿echo "hello world" > /dev/console
,但实验表明在 ExecStart 指令中使用 shell 重定向不会起作用,因为ExecStart
命令不是由 shell 运行。但你可以这样做: /usr/local/bin/helloworld 是一个 shell 脚本,其中包含一行echo "hello world" > /dev/console
. 1
请注意Type=simple
.这对于helloworld
所做的事情以及许多其他事情来说都很好。如果您的服务运行时间较长(超过几秒),systemd 会在使用 时将其分叉到后台simple
,这正是您想要的(另一个选项是因为它在前台停留的时间太长而将其杀死)。但是,如果程序自行进行此分叉(就像服务器和守护程序经常做的那样),您应该使用Type=forking
.在 下simple
,它将作为流浪孤儿进程被杀死。中详细介绍了“类型”参数,man systemd.service
无论您要做什么,都应该阅读该部分。2
我们完整的、最小的服务文件只有这三个部分([Unit]
、[Service]
和[Install]
)。要安装,请将文件或其符号链接放置在 /etc/systemd/system 或 /usr/lib/systemd/system 中,然后:
systemctl --system enable helloworld
它应该打印ln -s ...
。这不会运行该服务,它只是将其配置为在启动时运行,如上所述。
简而言之就是这样。 man systemd.unit
并man systemd.service
有更多详细信息(顺便说一句,所有这些内容都有一个索引man systemd.directives
)。
您可以使用块中的
StandardOutput
和StandardError
参数重定向输出[Service]
,请参阅man systemd.exec
。中有所有服务文件指令的索引
man systemd-directives
,指示记录在哪个手册页中,例如:After= systemd.unit(5) Alias= systemd.unit(5)
答案2
对于 systemd-tmpfiles 服务:它应该随您的发行版一起提供,但您始终可以从上游 git 存储库