我想定期运行一个作业(例如,每 5 分钟),最后在系统关闭时运行一次。
Systemd 支持计时器,可用于定期运行作业。它还支持使用ExecStop
这样的钩子在系统关闭时运行作业:
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=<some command to run at system shutdown>
但我很难将这两种方法结合起来。我能想到的唯一选择是编写两个独立的服务:
- 由定时器任务触发的一项服务
- 另一个使用该
ExecStop
技巧在系统关闭时执行的服务
我认为它应该有效,但这种方法有两个问题:
- 关于安全设置有很多代码重复
- systemd 无法防止并行运行作业。例如,如果在周期性作业刚刚执行时触发关闭,则两个作业将并行运行。
问题:
- 定期运行作业并在系统关闭时运行一次作业的最佳方法是什么?
- 是否可以避免有两个(大部分是重复的)服务文件?
为了了解代码重复的含义,以下是我在运行作业时使用的一些安全设置:
User=foo
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
NoNewPrivileges=yes
PrivateDevices=yes
PrivateUsers=yes
CapabilityBoundingSet=
AmbientCapabilities=
SystemCallFilter=~@clock @module @mount @obsolete @raw-io ptrace
ReadOnlyPaths=-/some/path
在我草拟的方法中,我需要复制此代码(每个服务一份)。
答案1
您可以通过创建两个目录来解决重复问题:foo-at-shutdown.service.d
和 'foo-periodic.service.d`。
在一个文件夹中创建一个名为foo-shared.conf
.
使用符号链接将其添加到第二个文件夹。
这些是“插入”单元,将被拉入主配置文件中。man systemd.unit
如果您在那里搜索“drop-in”,它们会有更多记录。
我认为拥有两个服务文件、一个计时器文件和共享的插入单元文件是一种合理的方法。