使用 systemd 计时器在每天的不同确切时间启动实用程序并传递参数

使用 systemd 计时器在每天的不同确切时间启动实用程序并传递参数

马尔普特是一个命令行实用程序,用于捕获流星 2 号卫星的数据。卫星每天在不同的时间经过头顶,我想使用 systemd 计时器以mlrpt正确的参数开始。

我从从 API 获取的时间开始

    startDate start_times end_times duration
1  2019-08-25       17:51     18:05       14
2  2019-08-25       19:31     19:45       14
3  2019-08-26       05:07     05:21       14
4  2019-08-26       06:47     07:01       14
5  2019-08-26       19:11     19:25       14
6  2019-08-27       06:27     06:42       15
7  2019-08-27       18:51     19:06       15
8  2019-08-28       06:07     06:22       15
9  2019-08-28       18:31     18:46       15
10 2019-08-29       05:47     06:02       15
11 2019-08-29       18:11     18:26       15
12 2019-08-30       05:27     05:42       15
13 2019-08-30       17:51     18:06       15
14 2019-08-30       19:31     19:45       14
15 2019-08-31       05:08     05:22       14
16 2019-08-31       06:48     07:02       14
17 2019-08-31       19:11     19:26       15
18 2019-09-01       06:27     06:42       15
19 2019-09-01       18:51     19:07       16
20 2019-09-02       06:07     06:23       16
21 2019-09-02       18:31     18:47       16
22 2019-09-03       05:47     06:03       16

对于每次想要运行 mlrpt 的格式mlrpt $startT-$stopT -t $durationMin

我从这个服务文件开始

~/.config/systemd/user/mlrpt.service
[Unit]
Description=Capture Meteor satellite data using mlrpt
DefaultDependencies=no
Wants=local-fs.target time-sync.target
After=local-fs.target time-sync.target

[Service]

Type=simple
ExecStart=/usr/local/bin/mlrpt $START_TIME-$END_TIME -t $DURATION

我如何设置计时器文件,以便它不仅mlrpt在正确的时间启动,而且能够将正确的参数传递给实用程序(它们每次都不同)?我想我需要一个类似的模板

~/.config/systemd/user/mlrpt.timer
[Unit]
Description=Run mlrpt when a satellite is overhead

[Timer]
OnCalendar=
Persistent=true

[Install]
WantedBy=timers.target

但不知道下一步该去哪里。如果我有正确的计时器文件的示例,我就具备生成计时器文件的脚本技能。

答案1

对于这些一次性的、非重复性的任务,我认为我找到了更好的解决方案systemd-run。对于列表中的第一个条目,我会编写一个脚本来运行systemd-run --user --on-calendar="2019-08-25 19:51" /usr/local/bin/mlrpt "17:51-18:05" -t 14

答案2

另一种方法是将多个元素组合在一个服务文件中(无计时器)。这些要素是:

  • “自重启”Type=oneshot服务,其EnvironmentFile=/path/to/mlrpt-textfile指令读取单个卫星通道的 mlrpt 参数,编码为来自“mlrpt-textfile”的自定义 varenv。这些参数为 1) $START_TIME 和 2) $END_TIME(用于卫星传递),3) 传递 $DURATION,以及 4) $WAIT 直到下一次传递的时间。

  • 两个文本文件。例如,一个称为“mlrpt-list”,其中包含自定义 mlrpt 参数的完整列表,与包含 22 个条目的列表类似但不相同。另一个文本文件仅包含一个条目(这是上面提到的“mlrpt-textfile”)

  • 一种机制(包括一个简单的脚本),从“mlrpt-list”开头读取第一个条目,将其复制到“mlrpt-textfile”,然后删除“mlrpt-list”中的第一个条目,并重复相同的过程按需,直到“mlrpt-list”中没有任何条目为止(注意:复制到“mlrpt-textfile”不应追加而是覆盖)。

现在,oneshot-service 文件应大致如下所示,将所有三个元素合并到一个工作解决方案中。使用 oneshot 的主要原因是它不仅能够容纳一个指令,而且能够容纳多个ExecStart=指令。根据设计,这些ExecStart指令是一个接一个地执行的。这使我们能够通过单个一次性服务单元来创建和执行上述“机制”。

# /etc/systemd/system/myservice.service

[Unit]
Description=my service Service
ConditionPathExists=/path/to/mlrpt-textfile # contains $START_TIME, $END_TIME, $WAIT,     
                                            # and $DURATION for a single pass
ConditionFileNotEmpty=/path/to/mlrpt-textfile
EnvironmentFile=/path/to/mlrpt-textfile

[Service]
Type=oneshot
ExecStart=/usr/local/bin/mlrpt $START_TIME-$END_TIME -t $DURATION
ExecStart=/bin/sleep $WAIT
ExecStart=/path/to/script # script copies one entry from mlrpt-list to mlrpt-textfile
ExecStopPost=/bin/systemctl restart myservice.service

[Install]

当然,这需要更多的细化(例如需要根据需要添加依赖项)。该脚本还应用于使服务在最后一次传递后失败,例如通过在最后一次传递后擦除“mlrpt-textfile”中的条目(以便ConditionFileNotEmpty重新启动时失败)。

相关内容