防止 systemd 计时器在按流量计费的连接上运行

防止 systemd 计时器在按流量计费的连接上运行

我有一个 systemd 计时器,每 10 分钟运行一次,用于下载我的电子邮件offlineimap。问题是,我有时会收到大量邮件或大附件,同时我可能会在路上使用手机的按流量计费的连接。

现在我有一个自定义脚本,用于查询当前活动的连接nmcli并检查它是否是计量连接。如果是这样,它offlineimap根本就不会运行。

我的问题是,systemd 计时器可以做同样的事情吗?沿着这些思路:

[Timer]
OnUnitInactiveSec=10m
RunOnMetered=no

答案1

您首先需要一个单位来依赖它指示连接是否按流量计费,例如:

[Unit]
Description=Check if the current connection is metered

[Service]
Type=oneshot
ExecStart=check-metered-connection.sh

check-metered-connection.sh是一个简单的 dbus 检查:

#! /usr/bin/bash

metered_status=$(dbus-send --system --print-reply=literal \
        --system --dest=org.freedesktop.NetworkManager \
          /org/freedesktop/NetworkManager \
          org.freedesktop.DBus.Properties.Get \
          string:org.freedesktop.NetworkManager string:Metered \
          | grep -o ".$")

if [[ $metered_status =~ (1|3) ]]; then
  echo Current connection is metered
  exit 1
else 
  exit 0
fi

那么您的单位将依赖于该服务,您就可以开始了,例如:

Requires=unmetered-connection.service
After=unmetered-connection.service

有人已经考虑到了这一点,并且很友善地在 Github 上发布了代码,请参阅jdorel/systemd 计量连接依赖项获取完整代码。

这里的所有代码示例都不是我的,而是从链接存储库中逐字复制的。为了完整起见,只是复制到这里。

答案2

这是对马克回答的补充:

使用的一个缺点unmetered-connection.service是,当您有按流量计费的连接时,Systemd 会认为它“失败”,这将导致systemctl status报告“降级”,即使实际上没有任何问题。这可能适合你,但如果你不喜欢它,我有一个替代解决方案。


诀窍是使用一个相当新的选项ExecCondition=所以问答,man systemd.service)在你的.service文件中。它确实需要 Systemd v243 或更高版本,您可以使用 进行检查systemctl --version

该选项允许运行任意命令,因此您实际上可以非常方便地检查您想要的任何内容。我们将重用check-metered-connection.sh来自jdorel/systemd 计量连接依赖项对于这个例子。

将以下代码添加到您的设备中:

# only run when system is on an unmetered connection
# requires https://github.com/jdorel/systemd-metered-connection-dependency
[Service]
ExecCondition=check-metered-connection.sh

假设您的服务是系统单元(而不是用户单元;有关差异,请参见man systemd.unit)命名为offlineimap.service,这将是位于 的嵌入式配置文件/etc/systemd/system/offlineimap.service.d/only-on-unmetered.conf

并且不要忘记[sudo] systemctl [--user] daemon-reload完成后跑步。


聚苯乙烯

请注意,Systemd 允许您通过多种方式进行自定义,这些方式可能看起来都可以实现相同的目标,但实际上有细微的不同。除非你非常熟悉 Systemd,否则我会强烈推荐在修改任何内容之前花一些时间阅读man systemd.unit。但这里有一些一般提示:

  1. 不要直接修改安装在/usr/lib/systemd.这些通常由您的包管理器管理,并且可以在更新后重置为默认值。
  2. 对于小的更改(像这样),优先选择插入配置文件(修改)而不是将整个单元复制到/etc/systemd~/.config/systemd(覆盖)。这可以确保您的单元仍然由包管理器更新(例如,当单元接受额外的强化时)。再次,请参阅man systemd.unit获取有关此内容的更多信息。

此外,此方法对服务而不是计时器进行更改(即使您使用嵌入式配置文件),如果其他单位依赖于该服务而没有这种新的不计量限制,则这可能并不理想。在这种情况下,最好通过复制到不同的名称来创建新的自定义单位计时器对,然后仅对自定义服务进行更改。

相关内容