如何编写运行 systemd-tmpfiles 的 systemd .service 文件

ean*_*ang 16 arch-linux systemd

我需要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
Run Code Online (Sandbox Code Playgroud)

但我不确定,因为systemd-tmpfiles它不是一个简单的程序,而是一个 systemd 本身。我不想破坏我的系统。

关于正确的 .service 文件的任何提示?

gol*_*cks 32

[这并没有直接解决 systemd-tmpfiles 的问题,但我认为您已经认识到,在这种特殊情况下,您最好只使用 echo。]

首先,“multi-user.target”可能是也可能不是您想要使用的。如果您熟悉 SysV 风格的 init 东西中的运行级别概念,多用户是 systemd 相当于运行级别 3,它是一个多用户系统,可以引导到控制台,而不是 GUI。相当于启动到 X 的运行级别 5 是graphics.target。默认值由/etc/systemd/system(和/或/lib/systemd/system; 中的一个/etc将覆盖 ) 中的一个符号链接确定,/lib称为default.target,使用 ls 找到它指向的位置:

»ls -l /etc/systemd/system/default.target
default.target -> /usr/lib/systemd/system/multi-user.target
Run Code Online (Sandbox Code Playgroud)

systemctl get-default在这种情况下会告诉你“multi-user.target”。对于普通的 linux 桌面,它将是graphics.target。如果您希望正在创建的引导服务启动而不管默认运行级别/目标是什么,这实际上并不重要——在这种情况下,我们可以只使用 default.target,而不必担心它是什么别名。但是,如果您使用多用户,并且您的默认设置是图形,您的服务将不会发生。

根据服务的不同,可能有更合适和更具体的目标或服务,您希望启动该目标或服务。根据您的其他问题, default.target 可能没问题。请注意,“目标”和“服务”之间的区别在于服务包含[Service]实际运行进程的部分;目标只是通过各种“依赖”和“需要”指令将服务组合在一起的一种方式;除了触发其他目标或服务之外,它自己不会做任何事情。

服务何时启动取决于其他哪些服务明确依赖它。对于像这样的简单独立事件,我们希望在引导过程中延迟运行,我们可以使用以下指令组合:

[Unit]
Requires=local-fs.target
After=local-fs.target 

[Install]
WantedBy=default.target
Run Code Online (Sandbox Code Playgroud)

安装服务时使用“安装”部分。“WantedBy=”指定了我们希望包含此服务的目标,这意味着如果该目标存在,它将运行。如果您没有特定的依赖项,那么让单元运行得更晚而不是更早可能是查看正常情况并选择一些用作依赖项或先决条件的问题。

为了区分:通过依赖我意味着什么,你的单位要求也被激活,并通过先决条件我的意思是什么,应该你的单位之前运行,如果正在使用它,但它不是必需的。这些术语是我的,但这是 systemd 文档中使用的一个重要区别,特别是在这种意义上,如果您的单元是则保证启动所需的依赖项,但此要求不会影响它们的启动顺序,这意味着, 一些只是依赖的东西实际上可能会在之后启动(是的,因为这意味着您的单元可能首先启动,依赖不能保证成功)。

以上,Requireslocal-fs.target可能有点毫无意义,除非你认为你的单位将被它可能不包括否则的系统上使用,但相结合After的单元可以保证被启动后,它是手段-这样你就可以做没有Requires(您可以设置一个单位在它不依赖的单位之后开始)。这里的例子只是为了介绍依赖和执行顺序的概念和区别:一个不决定另一个。

请注意,“之后开始”仍然并不意味着 prereq 将达到它自己执行的任何特定点。例如,如果它是关于挂载远程文件系统并且您这对您的单元很重要,您将想要使用Requires并且可能After是建立该服务的服务,但您仍然需要您正在执行的实际进程来执行正确的错误处理,以防远程文件系统尚不可访问(例如,通过在循环中休眠直到它们被访问)。

例如,我将向控制台回显“hello world”。服务本身在以下[Service]部分中进行了描述:

[Service]
Type=simple
ExecStart=/usr/local/bin/helloworld
Run Code Online (Sandbox Code Playgroud)

该命令需要完整路径。我不只是使用/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,但是如果你有一些需要超过一秒钟左右的时间,你应该先把它分叉到后台(例如,通过&启动脚本)并使用Type=forking. “类型”参数在 中有详细介绍,man systemd.service无论您尝试做什么,您都应该阅读该部分。

我们完整的,最小的服务文件只是这三个部分([Unit][Service],和[Install])。要安装,请将文件或指向它的符号链接放在 /etc/systemd/system 或 /usr/lib/systemd/system 中,然后:

systemctl --system enable helloworld
Run Code Online (Sandbox Code Playgroud)

它应该打印ln -s .... 这不会运行该服务,它只是将其配置为在启动时运行,如上所述。

简而言之就是这样。 man systemd.unitman systemd.service有更多细节(顺便说一句,在 中有所有这些东西的索引man systemd.directives)。


  1. 您可以使用块中的StandardOutputStandardError参数重定向输出[Service],请参阅man systemd.exec