2021年4月

定时器提供了比 cron 作业更为细粒度的事件控制。

 title=

我正在致力于将我的 cron 作业迁移到 systemd 定时器上。我已经使用定时器多年了,但通常来说,我的学识只足以支撑我当前的工作。但在我研究 systemd 系列 的过程中,我发现 systemd 定时器有一些非常有意思的能力。

与 cron 作业类似,systemd 定时器可以在特定的时间间隔触发事件(shell 脚本和程序),例如每天一次或在一个月中的特定某一天(或许只有在周一生效),或在从上午 8 点到下午 6 点的工作时间内每隔 15 分钟一次。定时器也可以做到 cron 作业无法做到的一些事情。举个例子,定时器可以在特定事件发生后的一段时间后触发一段脚本或者程序去执行,例如开机、启动、上个任务完成,甚至于定时器调用的上个服务单元的完成的时刻。

操作系统维护的计时器

当在一个新系统上安装 Fedora 或者是任意一个基于 systemd 的发行版时,作为系统维护过程的一部分,它会在 Linux 宿主机的后台中创建多个定时器。这些定时器会触发事件来执行必要的日常维护任务,比如更新系统数据库、清理临时目录、轮换日志文件,以及更多其他事件。

作为示例,我会查看一些我的主要工作站上的定时器,通过执行 systemctl status *timer 命令来展示主机上的所有定时器。星号的作用与文件通配相同,所以这个命令会列出所有的 systemd 定时器单元。

[root@testvm1 ~]# systemctl status *timer
● mlocate-updatedb.timer - Updates mlocate database every day
     Loaded: loaded (/usr/lib/systemd/system/mlocate-updatedb.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago
    Trigger: Fri 2020-06-05 00:00:00 EDT; 15h left
   Triggers: ● mlocate-updatedb.service

Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Updates mlocate database every day.

● logrotate.timer - Daily rotation of log files
     Loaded: loaded (/usr/lib/systemd/system/logrotate.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago
    Trigger: Fri 2020-06-05 00:00:00 EDT; 15h left
   Triggers: ● logrotate.service
       Docs: man:logrotate(8)
             man:logrotate.conf(5)

Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Daily rotation of log files.

● sysstat-summary.timer - Generate summary of yesterday's process accounting
     Loaded: loaded (/usr/lib/systemd/system/sysstat-summary.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago
    Trigger: Fri 2020-06-05 00:07:00 EDT; 15h left
   Triggers: ● sysstat-summary.service

Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Generate summary of yesterday's process accounting.

● fstrim.timer - Discard unused blocks once a week
     Loaded: loaded (/usr/lib/systemd/system/fstrim.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago
    Trigger: Mon 2020-06-08 00:00:00 EDT; 3 days left
   Triggers: ● fstrim.service
       Docs: man:fstrim

Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Discard unused blocks once a week.

● sysstat-collect.timer - Run system activity accounting tool every 10 minutes
     Loaded: loaded (/usr/lib/systemd/system/sysstat-collect.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago
    Trigger: Thu 2020-06-04 08:50:00 EDT; 41s left
   Triggers: ● sysstat-collect.service

Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Run system activity accounting tool every 10 minutes.

● dnf-makecache.timer - dnf makecache --timer
     Loaded: loaded (/usr/lib/systemd/system/dnf-makecache.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago
    Trigger: Thu 2020-06-04 08:51:00 EDT; 1min 41s left
   Triggers: ● dnf-makecache.service

Jun 02 08:02:33 testvm1.both.org systemd[1]: Started dnf makecache –timer.

● systemd-tmpfiles-clean.timer - Daily Cleanup of Temporary Directories
     Loaded: loaded (/usr/lib/systemd/system/systemd-tmpfiles-clean.timer; static; vendor preset: disabled)
     Active: active (waiting) since Tue 2020-06-02 08:02:33 EDT; 2 days ago
    Trigger: Fri 2020-06-05 08:19:00 EDT; 23h left
   Triggers: ● systemd-tmpfiles-clean.service
       Docs: man:tmpfiles.d(5)
             man:systemd-tmpfiles(8)

Jun 02 08:02:33 testvm1.both.org systemd[1]: Started Daily Cleanup of Temporary Directories.

每个定时器至少有六行相关信息:

  • 定时器的第一行有定时器名字和定时器目的的简短介绍
  • 第二行展示了定时器的状态,是否已加载,定时器单元文件的完整路径以及预设信息。
  • 第三行指明了其活动状态,包括该定时器激活的日期和时间。
  • 第四行包括了该定时器下次被触发的日期和时间和距离触发的大概时间。
  • 第五行展示了被定时器触发的事件或服务名称。
  • 部分(不是全部)systemd 单元文件有相关文档的指引。我虚拟机上输出中有三个定时器有文档指引。这是一个很好(但非必要)的信息。
  • 最后一行是计时器最近触发的服务实例的日志条目。

你也许有一些不一样的定时器,取决于你的主机。

创建一个定时器

尽管我们可以解构一个或多个现有的计时器来了解其工作原理,但让我们创建我们自己的 服务单元 和一个定时器去触发它。为了保持简单,我们将使用一个相当简单的例子。当我们完成这个实验之后,就能更容易理解其他定时器的工作原理以及发现它们正在做什么。

首先,创建一个运行基础东西的简单的服务,例如 free 命令。举个例子,你可能想定时监控空余内存。在 /etc/systemd/system 目录下创建如下的 myMonitor.server 单元文件。它不需要是可执行文件:

# This service unit is for testing timer units
# By David Both
# Licensed under GPL V2
#

[Unit]
Description=Logs system statistics to the systemd journal
Wants=myMonitor.timer

[Service]
Type=oneshot
ExecStart=/usr/bin/free

[Install]
WantedBy=multi-user.target

这大概是你能创建的最简单的服务单元了。现在我们查看一下服务状态同时测试一下服务单元确保它和我们预期一样可用。

[root@testvm1 system]# systemctl status myMonitor.service
● myMonitor.service - Logs system statistics to the systemd journal
     Loaded: loaded (/etc/systemd/system/myMonitor.service; disabled; vendor preset: disabled)
     Active: inactive (dead)
[root@testvm1 system]# systemctl start myMonitor.service
[root@testvm1 system]#

输出在哪里呢?默认情况下,systemd 服务单元执行程序的标准输出(STDOUT)会被发送到系统日志中,它保留了记录供现在或者之后(直到某个时间点)查看。(在本系列的后续文章中,我将介绍系统日志的记录和保留策略)。专门查看你的服务单元的日志,而且只针对今天。-S 选项,即 --since 的缩写,允许你指定 journalctl 工具搜索条目的时间段。这并不代表你不关心过往结果 —— 在这个案例中,不会有过往记录 —— 如果你的机器以及运行了很长时间且堆积了大量的日志,它可以缩短搜索时间。

[root@testvm1 system]# journalctl -S today -u myMonitor.service
-- Logs begin at Mon 2020-06-08 07:47:20 EDT, end at Thu 2020-06-11 09:40:47 EDT. --
Jun 11 09:12:09 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...
Jun 11 09:12:09 testvm1.both.org free[377966]:               total        used        free      shared  buff/cache   available
Jun 11 09:12:09 testvm1.both.org free[377966]: Mem:       12635740      522868    11032860        8016     1080012    11821508
Jun 11 09:12:09 testvm1.both.org free[377966]: Swap:       8388604           0     8388604
Jun 11 09:12:09 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.
[root@testvm1 system]#

由服务触发的任务可以是单个程序、一组程序或者是一个脚本语言写的脚本。通过在 myMonitor.service 单元文件里的 [Service] 块末尾中添加如下行可以为服务添加另一个任务:

ExecStart=/usr/bin/lsblk

再次启动服务,查看日志检查结果,结果应该看上去像这样。你应该在日志中看到两条命令的结果输出:

Jun 11 15:42:18 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...
Jun 11 15:42:18 testvm1.both.org free[379961]:               total        used        free      shared  buff/cache   available
Jun 11 15:42:18 testvm1.both.org free[379961]: Mem:       12635740      531788    11019540        8024     1084412    11812272
Jun 11 15:42:18 testvm1.both.org free[379961]: Swap:       8388604           0     8388604
Jun 11 15:42:18 testvm1.both.org lsblk[379962]: NAME          MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
Jun 11 15:42:18 testvm1.both.org lsblk[379962]: sda             8:0    0  120G  0 disk
Jun 11 15:42:18 testvm1.both.org lsblk[379962]: ├─sda1          8:1    0    4G  0 part /boot
Jun 11 15:42:18 testvm1.both.org lsblk[379962]: └─sda2          8:2    0  116G  0 part
Jun 11 15:42:18 testvm1.both.org lsblk[379962]:   ├─VG01-root 253:0    0    5G  0 lvm  /
Jun 11 15:42:18 testvm1.both.org lsblk[379962]:   ├─VG01-swap 253:1    0    8G  0 lvm  [SWAP]
Jun 11 15:42:18 testvm1.both.org lsblk[379962]:   ├─VG01-usr  253:2    0   30G  0 lvm  /usr
Jun 11 15:42:18 testvm1.both.org lsblk[379962]:   ├─VG01-tmp  253:3    0   10G  0 lvm  /tmp
Jun 11 15:42:18 testvm1.both.org lsblk[379962]:   ├─VG01-var  253:4    0   20G  0 lvm  /var
Jun 11 15:42:18 testvm1.both.org lsblk[379962]:   └─VG01-home 253:5    0   10G  0 lvm  /home
Jun 11 15:42:18 testvm1.both.org lsblk[379962]: sr0            11:0    1 1024M  0 rom
Jun 11 15:42:18 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.
Jun 11 15:42:18 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal.

现在你知道了你的服务可以按预期工作了,在 /etc/systemd/system 目录下创建 myMonitor.timer 定时器单元文件,添加如下代码:

# This timer unit is for testing
# By David Both
# Licensed under GPL V2
#

[Unit]
Description=Logs some system statistics to the systemd journal
Requires=myMonitor.service

[Timer]
Unit=myMonitor.service
OnCalendar=*-*-* *:*:00

[Install]
WantedBy=timers.target

myMonitor.timer 文件中的 OnCalendar 时间格式,*-*-* *:*:00,应该会每分钟触发一次定时器去执行 myMonitor.service 单元。我会在文章的后面进一步探索 OnCalendar 设置。

到目前为止,在服务被计时器触发运行时观察与之有关的日志记录。你也可以跟踪计时器,跟踪服务可以让你接近实时的看到结果。执行 journalctl 时带上 -f 选项:

[root@testvm1 system]# journalctl -S today -f -u myMonitor.service
-- Logs begin at Mon 2020-06-08 07:47:20 EDT. --

执行但是不启用该定时器,看看它运行一段时间后发生了什么:

[root@testvm1 ~]# systemctl start myMonitor.service
[root@testvm1 ~]#

一条结果立即就显示出来了,下一条大概在一分钟后出来。观察几分钟日志,看看你有没有跟我发现同样的事情:

[root@testvm1 system]# journalctl -S today -f -u myMonitor.service
-- Logs begin at Mon 2020-06-08 07:47:20 EDT. --
Jun 13 08:39:18 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...
Jun 13 08:39:18 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.
Jun 13 08:39:19 testvm1.both.org free[630566]:               total        used        free      shared  buff/cache   available
Jun 13 08:39:19 testvm1.both.org free[630566]: Mem:       12635740      556604    10965516        8036     1113620    11785628
Jun 13 08:39:19 testvm1.both.org free[630566]: Swap:       8388604           0     8388604
Jun 13 08:39:18 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal.
Jun 13 08:39:19 testvm1.both.org lsblk[630567]: NAME          MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
Jun 13 08:39:19 testvm1.both.org lsblk[630567]: sda             8:0    0  120G  0 disk
Jun 13 08:39:19 testvm1.both.org lsblk[630567]: ├─sda1          8:1    0    4G  0 part /boot
Jun 13 08:39:19 testvm1.both.org lsblk[630567]: └─sda2          8:2    0  116G  0 part
Jun 13 08:39:19 testvm1.both.org lsblk[630567]:   ├─VG01-root 253:0    0    5G  0 lvm  /
Jun 13 08:39:19 testvm1.both.org lsblk[630567]:   ├─VG01-swap 253:1    0    8G  0 lvm  [SWAP]
Jun 13 08:39:19 testvm1.both.org lsblk[630567]:   ├─VG01-usr  253:2    0   30G  0 lvm  /usr
Jun 13 08:39:19 testvm1.both.org lsblk[630567]:   ├─VG01-tmp  253:3    0   10G  0 lvm  /tmp
Jun 13 08:39:19 testvm1.both.org lsblk[630567]:   ├─VG01-var  253:4    0   20G  0 lvm  /var
Jun 13 08:39:19 testvm1.both.org lsblk[630567]:   └─VG01-home 253:5    0   10G  0 lvm  /home
Jun 13 08:39:19 testvm1.both.org lsblk[630567]: sr0            11:0    1 1024M  0 rom
Jun 13 08:40:46 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...
Jun 13 08:40:46 testvm1.both.org free[630572]:               total        used        free      shared  buff/cache   available
Jun 13 08:40:46 testvm1.both.org free[630572]: Mem:       12635740      555228    10966836        8036     1113676    11786996
Jun 13 08:40:46 testvm1.both.org free[630572]: Swap:       8388604           0     8388604
Jun 13 08:40:46 testvm1.both.org lsblk[630574]: NAME          MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
Jun 13 08:40:46 testvm1.both.org lsblk[630574]: sda             8:0    0  120G  0 disk
Jun 13 08:40:46 testvm1.both.org lsblk[630574]: ├─sda1          8:1    0    4G  0 part /boot
Jun 13 08:40:46 testvm1.both.org lsblk[630574]: └─sda2          8:2    0  116G  0 part
Jun 13 08:40:46 testvm1.both.org lsblk[630574]:   ├─VG01-root 253:0    0    5G  0 lvm  /
Jun 13 08:40:46 testvm1.both.org lsblk[630574]:   ├─VG01-swap 253:1    0    8G  0 lvm  [SWAP]
Jun 13 08:40:46 testvm1.both.org lsblk[630574]:   ├─VG01-usr  253:2    0   30G  0 lvm  /usr
Jun 13 08:40:46 testvm1.both.org lsblk[630574]:   ├─VG01-tmp  253:3    0   10G  0 lvm  /tmp
Jun 13 08:40:46 testvm1.both.org lsblk[630574]:   ├─VG01-var  253:4    0   20G  0 lvm  /var
Jun 13 08:40:46 testvm1.both.org lsblk[630574]:   └─VG01-home 253:5    0   10G  0 lvm  /home
Jun 13 08:40:46 testvm1.both.org lsblk[630574]: sr0            11:0    1 1024M  0 rom
Jun 13 08:40:46 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.
Jun 13 08:40:46 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal.
Jun 13 08:41:46 testvm1.both.org systemd[1]: Starting Logs system statistics to the systemd journal...
Jun 13 08:41:46 testvm1.both.org free[630580]:               total        used        free      shared  buff/cache   available
Jun 13 08:41:46 testvm1.both.org free[630580]: Mem:       12635740      553488    10968564        8036     1113688    11788744
Jun 13 08:41:46 testvm1.both.org free[630580]: Swap:       8388604           0     8388604
Jun 13 08:41:47 testvm1.both.org lsblk[630581]: NAME          MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
Jun 13 08:41:47 testvm1.both.org lsblk[630581]: sda             8:0    0  120G  0 disk
Jun 13 08:41:47 testvm1.both.org lsblk[630581]: ├─sda1          8:1    0    4G  0 part /boot
Jun 13 08:41:47 testvm1.both.org lsblk[630581]: └─sda2          8:2    0  116G  0 part
Jun 13 08:41:47 testvm1.both.org lsblk[630581]:   ├─VG01-root 253:0    0    5G  0 lvm  /
Jun 13 08:41:47 testvm1.both.org lsblk[630581]:   ├─VG01-swap 253:1    0    8G  0 lvm  [SWAP]
Jun 13 08:41:47 testvm1.both.org lsblk[630581]:   ├─VG01-usr  253:2    0   30G  0 lvm  /usr
Jun 13 08:41:47 testvm1.both.org lsblk[630581]:   ├─VG01-tmp  253:3    0   10G  0 lvm  /tmp
Jun 13 08:41:47 testvm1.both.org lsblk[630581]:   ├─VG01-var  253:4    0   20G  0 lvm  /var
Jun 13 08:41:47 testvm1.both.org lsblk[630581]:   └─VG01-home 253:5    0   10G  0 lvm  /home
Jun 13 08:41:47 testvm1.both.org lsblk[630581]: sr0            11:0    1 1024M  0 rom
Jun 13 08:41:47 testvm1.both.org systemd[1]: myMonitor.service: Succeeded.
Jun 13 08:41:47 testvm1.both.org systemd[1]: Finished Logs system statistics to the systemd journal.

别忘了检查下计时器和服务的状态。

你在日志里大概至少注意到两件事。第一,你不需要特地做什么来让 myMonitor.service 单元中 ExecStart 触发器产生的 STDOUT 存储到日志里。这都是用 systemd 来运行服务的一部分功能。然而,它确实意味着你需要小心对待服务单元里面执行的脚本和它们能产生多少 STDOUT

第二,定时器并不是精确在每分钟的 :00 秒执行的,甚至每次执行的时间间隔都不是刚好一分钟。这是特意的设计,但是有必要的话可以改变这种行为(如果只是它挑战了你的系统管理员的敏感神经)。

这样设计的初衷是为了防止多个服务在完全相同的时刻被触发。举个例子,你可以用例如 Weekly,Daily 等时间格式。这些快捷写法都被定义为在某一天的 00:00:00 执行。当多个定时器都这样定义的话,有很大可能它们会同时执行。

systemd 定时器被故意设计成在规定时间附近随机波动的时间点触发,以避免同一时间触发。它们在一个时间窗口内半随机触发,时间窗口开始于预设的触发时间,结束于预设时间后一分钟。根据 systemd.timer 的手册页,这个触发时间相对于其他已经定义的定时器单元保持在稳定的位置。你可以在日志条目中看到,定时器在启动后立即触发,然后在每分钟后的 46 或 47 秒触发。

大部分情况下,这种概率抖动的定时器是没事的。当调度类似执行备份的任务,只需要它们在下班时间运行,这样是没问题的。系统管理员可以选择确定的开始时间来确保不和其他任务冲突,例如 01:05:00 这样典型的 cron 作业时间,但是有很大范围的时间值可以满足这一点。在开始时间上的一个分钟级别的随机往往是无关紧要的。

然而,对某些任务来说,精确的触发时间是个硬性要求。对于这类任务,你可以向单元文件的 Timer 块中添加如下声明来指定更高的触发时间跨度精确度(精确到微秒以内):

AccuracySec=1us

时间跨度可用于指定所需的精度,以及定义重复事件或一次性事件的时间跨度。它能识别以下单位:

  • usecusµs
  • msecms
  • secondssecondsecs
  • minutesminuteminm
  • hourshourhrh
  • daysdayd
  • weeksweekw
  • monthsmonthM(定义为 30.44 天)
  • yearsyeary(定义为 365.25 天)

所有 /usr/lib/systemd/system 中的定时器都指定了一个更宽松的时间精度,因为精准时间没那么重要。看看这些系统创建的定时器的时间格式:

[root@testvm1 system]# grep Accur /usr/lib/systemd/system/*timer
/usr/lib/systemd/system/fstrim.timer:AccuracySec=1h
/usr/lib/systemd/system/logrotate.timer:AccuracySec=1h
/usr/lib/systemd/system/logwatch.timer:AccuracySec=12h
/usr/lib/systemd/system/mlocate-updatedb.timer:AccuracySec=24h
/usr/lib/systemd/system/raid-check.timer:AccuracySec=24h
/usr/lib/systemd/system/unbound-anchor.timer:AccuracySec=24h
[root@testvm1 system]#

看下 /usr/lib/systemd/system 目录下部分定时器单元文件的完整内容,看看它们是如何构建的。

在本实验中不必让这个定时器在启动时激活,但下面这个命令可以设置开机自启:

[root@testvm1 system]# systemctl enable myMonitor.timer

你创建的单元文件不需要是可执行的。你同样不需要启用服务,因为它是被定时器触发的。如果你需要的话,你仍然可以在命令行里手动触发该服务单元。尝试一下,然后观察日志。

关于定时器精度、事件时间规格和触发事件的详细信息,请参见 systemd.timer 和 systemd.time 的手册页。

定时器类型

systemd 定时器还有一些在 cron 中找不到的功能,cron 只在确定的、重复的、具体的日期和时间触发。systemd 定时器可以被配置成根据其他 systemd 单元状态发生改变时触发。举个例子,定时器可以配置成在系统开机、启动后,或是某个确定的服务单元激活之后的一段时间被触发。这些被称为单调计时器。“单调”指的是一个持续增长的计数器或序列。这些定时器不是持久的,因为它们在每次启动后都会重置。

表格 1 列出了一些单调定时器以及每个定时器的简短定义,同时有 OnCalendar 定时器,这些不是单调的,它们被用于指定未来有可能重复的某个确定时间。这个信息来自于 systemd.timer 的手册页,有一些不重要的修改。

定时器单调性定义
OnActiveSec=X定义了一个与定时器被激活的那一刻相关的定时器。
OnBootSec=X定义了一个与机器启动时间相关的计时器。
OnStartupSec=X定义了一个与服务管理器首次启动相关的计时器。对于系统定时器来说,这个定时器与 OnBootSec= 类似,因为系统服务管理器在机器启动后很短的时间后就会启动。当以在每个用户服务管理器中运行的单元进行配置时,它尤其有用,因为用户的服务管理器通常在首次登录后启动,而不是机器启动后。
OnUnitActiveSec=X定义了一个与将要激活的定时器上次激活时间相关的定时器。
OnUnitInactiveSec=X定义了一个与将要激活的定时器上次停用时间相关的定时器。
OnCalendar= 定义了一个有日期事件表达式语法的实时(即时钟)定时器。查看 systemd.time(7) 的手册页获取更多与日历事件表达式相关的语法信息。除此以外,它的语义和 OnActiveSec= 类似。

Table 1: systemd 定时器定义

单调计时器可使用同样的简写名作为它们的时间跨度,即我们之前提到的 AccuracySec 表达式,但是 systemd 将这些名字统一转换成了秒。举个例子,比如你想规定某个定时器在系统启动后五天触发一次事件;它可能看起来像 OnBootSec=5d。如果机器启动于 2020-06-15 09:45:27,这个定时器会在 2020-06-20 09:45:27 或在这之后的一分钟内触发。

日历事件格式

日历事件格式是定时器在所需的重复时间触发的关键。我们开始看下一些 OnCalendar 设置一起使用的格式。

与 crontab 中的格式相比,systemd 及其计时器使用的时间和日历格式风格不同。它比 crontab 更为灵活,而且可以使用类似 at 命令的方式允许模糊的日期和时间。它还应该足够熟悉使其易于理解。

systemd 定时器使用 OnCalendar= 的基础格式是 DOW YYYY-MM-DD HH:MM:SS。DOW(星期几)是选填的,其他字段可以用一个星号(*)来匹配此位置的任意值。所有的日历时间格式会被转换成标准格式。如果时间没有指定,它会被设置为 00:00:00。如果日期没有指定但是时间指定了,那么下次匹配的时间可能是今天或者明天,取决于当前的时间。月份和星期可以使用名称或数字。每个单元都可以使用逗号分隔的列表。单元范围可以在开始值和结束值之间用 .. 指定。

指定日期有一些有趣的选项,波浪号(~)可以指定月份的最后一天或者最后一天之前的某几天。/ 可以用来指定星期几作为修饰符。

这里有几个在 OnCalendar 表达式中使用的典型时间格式例子。

日期事件格式描述
DOW YYYY-MM-DD HH:MM:SS
*-*-* 00:15:30每年每月每天的 0 点 15 分 30 秒
Weekly每个周一的 00:00:00
Mon *-*-* 00:00:00同上
Mon同上
Wed 2020-*-*2020 年每个周三的 00:00:00
Mon..Fri 2021-*-*2021 年的每个工作日(周一到周五)的 00:00:00
2022-6,7,8-1,15 01:15:002022 年 6、7、8 月的 1 到 15 号的 01:15:00
Mon *-05~03每年五月份的下个周一同时也是月末的倒数第三天
Mon..Fri *-08~04任何年份 8 月末的倒数第四天,同时也须是工作日
*-05~03/2五月末的倒数第三天,然后 2 天后再来一次。每年重复一次。注意这个表达式使用了波浪号(~)。
*-05-03/2五月的第三天,然后每两天重复一次直到 5 月底。注意这个表达式使用了破折号(-)。

Table 2: OnCalendar 事件时间格式例子

测试日历格式

systemd 提供了一个绝佳的工具用于检测和测试定时器中日历时间事件的格式。systemd-analyze calendar 工具解析一个时间事件格式,提供标准格式和其他有趣的信息,例如下次“经过”(即匹配)的日期和时间,以及距离下次触发之前大概时间。

首先,看看未来没有时间的日(注意 Next elapseUTC 的时间会根据你当地时区改变):

[student@studentvm1 ~]$ systemd-analyze calendar 2030-06-17
  Original form: 2030-06-17                
Normalized form: 2030-06-17 00:00:00        
    Next elapse: Mon 2030-06-17 00:00:00 EDT
       (in UTC): Mon 2030-06-17 04:00:00 UTC
       From now: 10 years 0 months left    
[root@testvm1 system]#

现在添加一个时间,在这个例子中,日期和时间是当作无关的部分分开解析的:

[root@testvm1 system]# systemd-analyze calendar 2030-06-17 15:21:16
  Original form: 2030-06-17                
Normalized form: 2030-06-17 00:00:00        
    Next elapse: Mon 2030-06-17 00:00:00 EDT
       (in UTC): Mon 2030-06-17 04:00:00 UTC
       From now: 10 years 0 months left    

  Original form: 15:21:16                  
Normalized form: *-*-* 15:21:16            
    Next elapse: Mon 2020-06-15 15:21:16 EDT
       (in UTC): Mon 2020-06-15 19:21:16 UTC
       From now: 3h 55min left              
[root@testvm1 system]#

为了把日期和时间当作一个单元来分析,可以把它们包在引号里。你在定时器单元里 OnCalendar= 时间格式中使用的时候记得把引号去掉,否则会报错:

[root@testvm1 system]# systemd-analyze calendar "2030-06-17 15:21:16"
Normalized form: 2030-06-17 15:21:16        
    Next elapse: Mon 2030-06-17 15:21:16 EDT
       (in UTC): Mon 2030-06-17 19:21:16 UTC
       From now: 10 years 0 months left    
[root@testvm1 system]#

现在我们测试下 Table2 里的例子。我尤其喜欢最后一个:

[root@testvm1 system]# systemd-analyze calendar "2022-6,7,8-1,15 01:15:00"
  Original form: 2022-6,7,8-1,15 01:15:00
Normalized form: 2022-06,07,08-01,15 01:15:00
    Next elapse: Wed 2022-06-01 01:15:00 EDT
       (in UTC): Wed 2022-06-01 05:15:00 UTC
       From now: 1 years 11 months left
[root@testvm1 system]#

让我们看一个例子,这个例子里我们列出了时间表达式的五个经过时间。

[root@testvm1 ~]# systemd-analyze calendar --iterations=5 "Mon *-05~3"
  Original form: Mon *-05~3                
Normalized form: Mon *-05~03 00:00:00      
    Next elapse: Mon 2023-05-29 00:00:00 EDT
       (in UTC): Mon 2023-05-29 04:00:00 UTC
       From now: 2 years 11 months left    
       Iter. #2: Mon 2028-05-29 00:00:00 EDT
       (in UTC): Mon 2028-05-29 04:00:00 UTC
       From now: 7 years 11 months left    
       Iter. #3: Mon 2034-05-29 00:00:00 EDT
       (in UTC): Mon 2034-05-29 04:00:00 UTC
       From now: 13 years 11 months left    
       Iter. #4: Mon 2045-05-29 00:00:00 EDT
       (in UTC): Mon 2045-05-29 04:00:00 UTC
       From now: 24 years 11 months left    
       Iter. #5: Mon 2051-05-29 00:00:00 EDT
       (in UTC): Mon 2051-05-29 04:00:00 UTC
       From now: 30 years 11 months left    
[root@testvm1 ~]#

这些应该为你提供了足够的信息去开始测试你的 OnCalendar 时间格式。systemd-analyze 工具可用于其他有趣的分析,我会在这个系列的下一篇文章来探索这些。

总结

systemd 定时器可以用于执行和 cron 工具相同的任务,但是通过按照日历和单调时间格式去触发事件的方法提供了更多的灵活性。

虽然你为此次实验创建的服务单元通常是由定时器调用的,你也可以随时使用 systemctl start myMonitor.service 命令去触发它。可以在一个定时器中编写多个维护任务的脚本;它们可以是 Bash 脚本或者其他 Linux 程序。你可以通过触发定时器来运行所有的脚本来运行服务,也可以按照需要执行单独的脚本。

我会在下篇文章中更加深入的探索 systemd 时间格式的用处。

我还没有看到任何迹象表明 cron 和 at 将被废弃。我希望这种情况不会发生,因为至少 at 在执行一次性调度任务的时候要比 systemd 定时器容易的多。

参考资料

网上有大量的关于 systemd 的参考资料,但是大部分都有点简略、晦涩甚至有误导性。除了本文中提到的资料,下列的网页提供了跟多可靠且详细的 systemd 入门信息。

  • Fedora 项目有一篇切实好用的 systemd 入门,它囊括了几乎所有你需要知道的关于如何使用 systemd 配置、管理和维护 Fedora 计算机的信息。
  • Fedora 项目也有一个不错的 备忘录,交叉引用了过去 SystemV 命令和 systemd 命令做对比。
  • 关于 systemd 的技术细节和创建这个项目的原因,请查看 Freedesktop.org 上的 systemd 描述
  • Linux.com 的“更多 systemd 的乐趣”栏目提供了更多高级的 systemd 信息和技巧

此外,还有一系列深度的技术文章,是由 systemd 的设计者和主要实现者 Lennart Poettering 为 Linux 系统管理员撰写的。这些文章写于 2010 年 4 月至 2011 年 9 月间,但它们现在和当时一样具有现实意义。关于 systemd 及其生态的许多其他好文章都是基于这些文章:


via: https://opensource.com/article/20/7/systemd-timers

作者:David Both 选题:lujun9972 译者:tt67wq 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

LLVM 12 已释出 3 天,但是连发布公告都没写完

LLVM 编译器套装项目是一个已经有 18 年历史的重要项目,其更新也算活跃,在很多方面都已经超过了 GCC。4 月 14 日,LLVM 释出了最新的 12.0.0。主要新特性和变化可以参见发布公告。然而,发布公告还没编写完。

没料到 LLVM 在文档更新方面居然拖拖拉拉的,这是觉得没人看么,还是懂的人自然懂?

Firefox 88 将停止支持 FTP

Mozilla 是在去年宣布它计划从浏览器中移除内置的 FTP 实现。即在 4 月 19 日释出的 Firefox 88 将关闭 FTP 实现,在 Firefox 90 将移除 FTP。在停止支持之后,浏览器将会用外部应用打开 ftp:// 链接。

在 Chrome 之后,Firefox 也将停止支持 FTP 协议。这种老旧的网络协议其实是该逐渐淘汰了,虽然更老的协议如 TFTP 依旧在很狭窄的场景中有使用。

近三万家企业使用的代码覆盖量软件陷入软件供应链黑客事件

Codecov 被认为是科技行业衡量代码覆盖率的首选厂商。该公司的工具可以帮助开发人员了解和测量测试套件执行的代码行数,并被广泛部署在大型科技企业的开发管道中。该公司宣称,有超过 29000 家企业使用其代码覆盖率洞察力来检查代码质量和维护代码覆盖率。

该公司表示,该黑客事件发生在四个月前,但直到 2021 年 4 月 1 日才被 Codecov 的一位客户在野发现。其 Bash Uploader 脚本的被替换版本可能导致任何通过 CI 运行器传递的凭证、令牌或密钥被泄露。

软件行业越来越全球化,形成了一条条供应链,在这个链条中任何一个环节出现的问题,都可能通过链条进行放大。对供应链的管理,需要更有预防和响应机制。

“遴选”可以解决 Git 仓库中的很多问题。以下是用 git cherry-pick 修复错误的三种方法。

 title=

在版本控制系统中摸索前进是一件很棘手的事情。对于一个新手来说,这可能是非常难以应付的,但熟悉版本控制系统(如 Git)的术语和基础知识是开始为开源贡献的第一步。

熟悉 Git 也能帮助你在开源之路上走出困境。Git 功能强大,让你感觉自己在掌控之中 —— 没有哪一种方法会让你无法恢复到工作版本。

这里有一个例子可以帮助你理解“ 遴选 cherry-pick ”的重要性。假设你已经在一个分支上做了好几个提交,但你意识到这是个错误的分支!你现在该怎么办?你现在要做什么?要么在正确的分支上重复所有的变更,然后重新提交,要么把这个分支合并到正确的分支上。等一下,前者太过繁琐,而你可能不想做后者。那么,还有没有办法呢?有的,Git 已经为你准备好了。这就是“遴选”的作用。顾名思义,你可以用它从一个分支中手工遴选一个提交,然后转移到另一个分支。

使用遴选的原因有很多。以下是其中的三个原因。

避免重复性工作

如果你可以直接将相同的提交复制到另一个分支,就没有必要在不同的分支中重做相同的变更。请注意,遴选出来的提交会在另一个分支中创建带有新哈希的新提交,所以如果你看到不同的提交哈希,请不要感到困惑。

如果您想知道什么是提交的哈希,以及它是如何生成的,这里有一个说明可以帮助你。提交哈希是用 SHA-1 算法生成的字符串。SHA-1 算法接收一个输入,然后输出一个唯一的 40 个字符的哈希值。如果你使用的是 POSIX 系统,请尝试在您的终端上运行这个命令:

$ echo -n "commit" | openssl sha1

这将输出一个唯一的 40 个字符的哈希值 4015b57a143aec5156fd1444a017a32137a3fd0f。这个哈希代表了字符串 commit

Git 在提交时生成的 SHA-1 哈希值不仅仅代表一个字符串。它代表的是:

sha1(
    meta data
        commit message
        committer
        commit date
        author
        authoring date
    Hash of the entire tree object
)

这就解释了为什么你对代码所做的任何细微改动都会得到一个独特的提交哈希值。哪怕是一个微小的改动都会被发现。这是因为 Git 具有完整性。

撤销/恢复丢失的更改

当你想恢复到工作版本时,遴选就很方便。当多个开发人员在同一个代码库上工作时,很可能会丢失更改,最新的版本会被转移到一个陈旧的或非工作版本上。这时,遴选提交到工作版本就可以成为救星。

它是如何工作的?

假设有两个分支:feature1feature2,你想把 feature1 中的提交应用到 feature2

feature1 分支上,运行 git log 命令,复制你想遴选的提交哈希值。你可以看到一系列类似于下面代码示例的提交。commit 后面的字母数字代码就是你需要复制的提交哈希。为了方便起见,您可以选择复制前六个字符(本例中为 966cf3)。

commit 966cf3d08b09a2da3f2f58c0818baa37184c9778 (HEAD -> master)
Author: manaswinidas <[email protected]>
Date:   Mon Mar 8 09:20:21 2021 +1300

   add instructions

然后切换到 feature2 分支,在刚刚从日志中得到的哈希值上运行 git cherry-pick

$ git checkout feature2
$ git cherry-pick 966cf3.

如果该分支不存在,使用 git checkout -b feature2 来创建它。

这里有一个问题。你可能会遇到下面这种情况:

$ git cherry-pick 966cf3
On branch feature2
You are currently cherry-picking commit 966cf3d.

nothing to commit, working tree clean
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

   git commit --allow-empty

Otherwise, please use 'git reset'

不要惊慌。只要按照建议运行 git commit --allow-empty

$ git commit --allow-empty
[feature2 afb6fcb] add instructions
Date: Mon Mar 8 09:20:21 2021 +1300

这将打开你的默认编辑器,允许你编辑提交信息。如果你没有什么要补充的,可以保存现有的信息。

就这样,你完成了你的第一次遴选。如上所述,如果你在分支 feature2 上运行 git log,你会看到一个不同的提交哈希。下面是一个例子:

commit afb6fcb87083c8f41089cad58deb97a5380cb2c2 (HEAD -&gt; feature2)
Author: manaswinidas &lt;[[email protected]][4]&gt;
Date:   Mon Mar 8 09:20:21 2021 +1300
   add instructions

不要对不同的提交哈希感到困惑。这只是区分 feature1feature2 的提交。

遴选多个提交

但如果你想遴选多个提交的内容呢?你可以使用:

git cherry-pick <commit-hash1> <commit-hash2>... <commit-hashn>

请注意,你不必使用整个提交的哈希值,你可以使用前五到六个字符。

同样,这也是很繁琐的。如果你想遴选的提交是一系列的连续提交呢?这种方法太费劲了。别担心,有一个更简单的方法。

假设你有两个分支:

  • feature1 包括你想复制的提交(从更早的 commitAcommitB)。
  • feature2 是你想把提交从 feature1 转移到的分支。

然后:

  1. 输入 git checkout <feature1>
  2. 获取 commitAcommitB 的哈希值。
  3. 输入 git checkout <branchB>
  4. 输入 git cherry-pick <commitA>^..<commitB> (请注意,这包括 commitAcommitB)。
  5. 如果遇到合并冲突,像往常一样解决,然后输入 git cherry-pick --continue 恢复遴选过程。

重要的遴选选项

以下是 Git 文档 中的一些有用的选项,你可以在 cherry-pick 命令中使用。

  • -e--edit:用这个选项,git cherry-pick 可以让你在提交前编辑提交信息。
  • -s--signoff:在提交信息的结尾添加 Signed-off by 行。更多信息请参见 git-commit(1) 中的 signoff 选项。
  • -S[<keyid>]--pgg-sign[=<keyid>]:这些是 GPG 签名的提交。keyid 参数是可选的,默认为提交者身份;如果指定了,则必须嵌在选项中,不加空格。
  • --ff:如果当前 HEAD 与遴选的提交的父级提交相同,则会对该提交进行快进操作。

下面是除了 --continue 外的一些其他的后继操作子命令:

  • --quit:你可以忘记当前正在进行的操作。这可以用来清除遴选或撤销失败后的后继操作状态。
  • --abort:取消操作并返回到操作序列前状态。

下面是一些关于遴选的例子:

  • git cherry-pick master:应用 master 分支顶端的提交所引入的变更,并创建一个包含该变更的新提交。
  • git cherry-pick master~4 master~2':应用master` 指向的第五个和第三个最新提交所带来的变化,并根据这些变化创建两个新的提交。

感到不知所措?你不需要记住所有的命令。你可以随时在你的终端输入 git cherry-pick --help 查看更多选项或帮助。


via: https://opensource.com/article/21/3/git-cherry-pick

作者:Manaswini Das 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

VeraCrypt 提供跨平台的开源文件加密功能。

 title=

许多年前,有一个名为 TrueCrypt 的加密软件。它的源码是可以得到的,尽管没有任何人声称曾对它进行过审计或贡献过。它的作者是(至今仍是)匿名的。不过,它是跨平台的,易于使用,而且真的非常有用。

TrueCrypt 允许你创建一个加密的文件“保险库”,在那里你可以存储任何类型的敏感信息(文本、音频、视频、图像、PDF 等)。只要你有正确的口令,TrueCrypt 就可以解密保险库,并在任何运行 TrueCrypt 的电脑上提供读写权限。这是一项有用的技术,它基本上提供了一个虚拟的、可移动的、完全加密的驱动器(除了文件以外),你可以在其中安全地存储你的数据。

TrueCrypt 最终关闭了,但一个名为 VeraCrypt 的替代项目迅速兴起,填补了这一空白。VeraCrypt 基于 TrueCrypt 7.1a,比原来的版本有许多改进(包括标准加密卷和引导卷的算法的重大变化)。在 VeraCrypt 1.12 及以后的版本中,你可以使用自定义迭代来提高加密安全性。更好的是,VeraCrypt 可以加载旧的 TrueCrypt 卷,所以如果你是 TrueCrypt 用户,可以很容易地将它们转移到 VeraCrypt 上。

安装 VeraCrypt

你可以从 VeraCrypt 下载页面 下载相应的安装文件,之后在所有主流平台上安装 VeraCrypt。

另外,你也可以自己从源码构建它。在 Linux 上,它需要 wxGTK3、makeself 和通常的开发栈(Binutils、GCC 等)。

当你安装后,从你的应用菜单中启动 VeraCrypt。

创建一个 VeraCrypt 卷

如果你刚接触 VeraCrypt,你必须先创建一个 VeraCrypt 加密卷(否则,你没有任何东西可以解密)。在 VeraCrypt 窗口中,点击左侧的 “Create Volume” 按钮。

 title=

在出现的 VeraCrypt 的卷创建向导窗口中,选择要创建一个加密文件容器还是要加密整个驱动器或分区。向导将为你的数据创建一个保险库,所以请按照提示进行操作。

在本文中,我创建了一个文件容器。VeraCrypt 容器和其他文件很像:它保存在硬盘、外置硬盘、云存储或其他任何你能想到的存储数据的地方。与其他文件一样,它可以被移动、复制和删除。与大多数其他文件不同的是,它可以\_容纳\_更多的文件,这就是为什么我认为它是一个“保险库”,而 VeraCrypt 开发者将其称为“容器”。它的开发者将 VeraCrypt 文件称为“容器”,是因为它可以包含其他数据对象;它与 LXC、Kubernetes 和其他现代 IT 机制所流行的容器技术无关。

选择一个文件系统

在创建卷的过程中,你会被要求选择一个文件系统来决定你放在保险库中的文件的存储方式。微软 FAT 格式是过时的、非日志型,并且限制了卷和文件的大小,但它是所有平台都能读写的一种格式。如果你打算让你的 VeraCrypt 保险库跨平台,FAT 是你最好的选择。

除此之外,NTFS 适用于 Windows 和 Linux。开源的 EXT 系列适用于 Linux。

挂载 VeraCrypt 加密卷

当你创建了 VeraCrypt 卷,你就可以在 VeraCrypt 窗口中加载它。要挂载一个加密库,点击右侧的 “Select File” 按钮。选择你的加密文件,选择 VeraCrypt 窗口上半部分的一个编号栏,然后点击位于 VeraCrypt 窗口左下角的 “Mount” 按钮。

你挂载的卷在 VeraCrypt 窗口的可用卷列表中,你可以通过文件管理器访问该卷,就像访问一个外部驱动器一样。例如,在 KDE 上,我打开 Dolphin,进入 /media/veracrypt1,然后我就可以把文件复制到我的保险库里。

只要你的设备上有 VeraCrypt,你就可以随时访问你的保险库。在你手动在 VeraCrypt 中挂载之前,文件都是加密的,在那里,文件会保持解密,直到你再次关闭卷。

关闭 VeraCrypt 卷

为了保证你的数据安全,当你不需要打开 VeraCrypt 卷时,关闭它是很重要的。这样可以保证数据的安全,不被人窥视,且不被人趁机犯罪。

 title=

关闭 VeraCrypt 容器和打开容器一样简单。在 VeraCrypt 窗口中选择列出的卷,然后点击 “Dismount”。你就不能访问保险库中的文件了,其他人也不会再有访问权。

VeraCrypt 轻松实现跨平台加密

有很多方法可以保证你的数据安全,VeraCrypt 试图为你提供方便,而无论你需要在什么平台上使用这些数据。如果你想体验简单、开源的文件加密,请尝试 VeraCrypt。


via: https://opensource.com/article/21/4/open-source-encryption

作者:Seth Kenlon 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Slackware 还活着,准备发布 15.0

Slackware 是至今仍在维护的历史最悠久的 Linux 发行版。它的上一个稳定版本 Slackware 14.2 还是在 2016 年发布的。最近,它刚刚发布了 15.0 Beta。主要变化包括:KDE Plasma 5.21、Xfce 4.16 和 GNOME 3.36/3.38,内核版本为 Linux Kernel 5.10.x。

天哪,居然又复活了,这是我用过的第一个 Linux 发行版,第一次安装时我遇到了 LILO 错误:满屏幕的 01010101…… 而不知所措。

谷歌 Project Zero 团队调整漏洞披露时限

之前,谷歌 Project Zero 的研究人员会给软件厂商 90 天的时间来修复安全漏洞。当 bug 被修复后,或者在 90 天时间窗口结束时,谷歌研究人员会在网上公布漏洞的细节。新的时限为每次安全漏洞披露增加了 30 天的缓冲期,这样终端用户就有足够的时间来修补软件。此外,对于已经被主动利用的零日漏洞,也在原有的 7 天的基础上增加了 3 天。

其实,有时候你就是给厂商再多时间,它也不着急,不到 DeadLine 不着急。

世界首位官方认证半机械人出现

一位出生时便患有严重的色盲症的男子,看到的世界都是黑白的,成为了世界上第一位头骨植入天线的人,也是政府合法认可与批准的改造人。通过在头骨中植入了天线扩充色彩感知的传感系统,使得他可以通过天线振动频率来感觉不同的色彩,甚至是普通人看不到的红外线紫外线等元素。他在手术之后,大约用了 5 周时间将每种颜色与每种声音相匹配,又用了 5 个月时间破译每种频率,现在他已经可以通过声音“听出”特定的颜色,弥补了他人生之中的最大遗憾。

科幻小说和现实的距离越来越近了……

Steam 对 Linux 游戏玩家来说是最好的东西了。由于 Steam,你可以在 Linux 上玩成百上千的游戏。

如果你还不知道,Steam 是最流行的 PC 游戏平台。2013 年,它开始可以在 Linux 使用。Steam 最新的 Proton 项目 允许你在 Linux 上玩为 Windows 平台创建的游戏。这让 Linux 游戏库增强了许多倍。

Steam 提供了一个桌面客户端,你可以用它从 Steam 商店下载或购买游戏,然后安装并玩它。

过去我们曾讨论过 在 Ubuntu 上安装 Steam。在这个初学者教程中,我将向你展示在 Fedora Linux 上安装 Steam 的步骤。

在 Fedora 上安装 Steam

要在 Fedora 上使用 Steam,你必须使用 RMPFusion 软件库。RPMFusion 是一套第三方软件库,其中包含了 Fedora 选择不与它们的操作系统一起发布的软件。它们提供自由(开源)和非自由(闭源)的软件库。由于 Steam 在非自由软件库中,你将只安装那一个。

我将同时介绍终端和图形安装方法。

方法 1:通过终端安装 Steam

这是最简单的方法,因为它需要的步骤最少。只需输入以下命令即可启用仓库:

sudo dnf install https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm

你会被要求输入密码。然后你会被要求验证是否要安装这些仓库。你同意后,仓库安装就会完成。

要安装 Steam,只需输入以下命令:

sudo dnf install steam

Install Steam via command line

输入密码后按 Y 接受。安装完毕后,打开 Steam,玩一些游戏。

方法 2:通过 GUI 安装 Steam

你可以从软件中心 启用 Fedora 上的第三方仓库。打开软件中心并点击菜单。

在 “软件仓库” 窗口中,你会看到顶部有一个 “第三方软件仓库”。点击 “安装” 按钮。当提示你输入密码时,就完成了。

安装了 Steam 的 RPM Fusion 仓库后,更新你系统的软件缓存(如果需要),并在软件中心搜索 Steam。

Steam in GNOME Software Center

安装完成后,打开 GNOME 软件中心,搜索 Steam。找到 Steam 页面后,点击安装。当被问及密码时,输入你的密码就可以了。

安装完 Steam 后,启动应用,输入你的 Steam 帐户详情或注册它,然后享受你的游戏。

将 Steam 作为 Flatpak 使用

Steam 也可以作为 Flatpak 使用。Fedora 上默认安装 Flatpak。在使用该方法安装 Steam 之前,我们必须安装 Flathub 仓库。

Install Flathub

首先,在浏览器中打开 Flatpak 网站。现在,点击标有 “Flathub repository file” 的蓝色按钮。浏览器会询问你是否要在 GNOME 软件中心打开该文件。点击确定。在 GNOME 软件中心打开后,点击安装按钮。系统会提示你输入密码。

如果你在尝试安装 Flathub 仓库时出现错误,请在终端运行以下命令:

flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo

安装好 Flathub 仓库后,你需要做的就是在 GNOME 软件中心搜索 Steam。找到后,安装它,你就可以开始玩了。

Fedora Repo Select

Flathub 版本的 Steam 也有几个附加组件可以安装。其中包括一个 DOS 兼容工具和几个 Vulkan 和 Proton 工具。

我想这应该可以帮助你在 Fedora 上使用 Steam。享受你的游戏 :smiley:


via: https://itsfoss.com/install-steam-fedora/

作者:John Paul 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出