Contents

将SystemD服务的输出重定向到文件

1. 简介

在本文中,我们将使用一个简单的 systemd 服务和计时器来演示如何将systemd服务的输出重定向到给定的文件

2. 我们的示例服务和计时器

我们在称为单元文件的特殊文件中定义systemd服务,这些文件以**.service后缀结尾。这些文件是从多个位置加载的,其中两个主要位置是:

  • /usr/lib/systemd/system/(包提供的单位)
  • /etc/systemd/system/(系统管理员将在其中添加单元)

systemd计时器是以*.timer后缀结尾的单元文件。**我们可以使用定时器来控制systemd*服务的执行和调度**。由于它们提供的易于集成,定时器通常被用作cron的替代品。

对于我们的演示,我们将在*/etc/systemd/system/*中放置三个文件:

  • bird_watching.service
  • bird_watching.timer
  • bird_watcher.sh

只有 shell 脚本需要可执行:

$ chmod +x /etc/systemd/system/bird_watcher.sh

2.1. 服务单元文件

我们来看看我们的服务单元文件:

[Unit]
Description=Bird watching service
[Service]
Type=oneshot
ExecStart=/etc/systemd/system/bird_watcher.sh
[Install]
WantedBy=multi-user.target

这是一个非常基本的服务单元文件。激活后,它将执行ExecStart字段中指定的模拟 shell 脚本,该脚本将随机输出鸟类的名称。

2.2. 定时器单元文件

现在让我们看一下我们服务的计时器单元文件:

[Unit]
Description=Activate bird_watching.service every minute
[Timer]
OnUnitInactiveSec=1m
[Install]
WantedBy=timers.target

正如我们从上面计时器文件的内容中看到的,我们的计时器每分钟都会根据它处于非活动状态的时间来激活我们的服务。

创建文件后,我们强制systemd加载单元,然后启用并启动计时器。请注意,我们不会启用或启动服务本身,只有与之关联的计时器

$ systemctl daemon-reload 
$ systemctl --now enable bird_watching.timer

3.重定向服务输出

当我们的服务运行时,我们可以使用journalctl 查看它的输出,它是用于与systemd 的日志记录组件journald 交互的实用程序:

$ journalctl -u bird_watching -f
-- Logs begin at Wed 2021-01-06 00:45:26 UTC. --
Feb 01 03:07:15 localhost systemd[1]: Starting Bird watching service...
Feb 01 03:07:15 localhost bird_watching[2184673]: Baltimore oriole
Feb 01 03:07:15 localhost systemd[1]: bird_watching.service: Succeeded.
Feb 01 03:07:15 localhost systemd[1]: Finished Bird watching service.
Feb 01 03:08:17 localhost systemd[1]: Starting Bird watching service...
Feb 01 03:08:17 localhost bird_watching[2184726]: Black-capped chickadee
Feb 01 03:08:17 localhost systemd[1]: bird_watching.service: Succeeded.
Feb 01 03:08:17 localhost systemd[1]: Finished Bird watching service.
Feb 01 03:09:41 localhost systemd[1]: Starting Bird watching service...
Feb 01 03:09:41 localhost bird_watching[2184985]: House sparrow
Feb 01 03:09:41 localhost systemd[1]: bird_watching.service: Succeeded.
Feb 01 03:09:41 localhost systemd[1]: Finished Bird watching service.

但是,正如本文的主题,我们可能希望我们的服务也记录到特定文件。我们将考虑实现这一目标的两种选择。第一个选项将利用与rsyslog 的集成,而第二个选项直接使用systemd但需要更新版本的systemd

3.1. 与rsyslog集成

在我们的主机上安装并运行rsyslog后,我们在服务单元文件中添加了一些额外的行:

[Unit]
Description=Bird watching service
[Service]
Type=oneshot
ExecStart=/etc/systemd/system/bird_watcher.sh
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=bird_watching
[Install]
WantedBy=multi-user.target

三个新行将指示systemd使用我们的rsyslog服务来管理我们的服务执行的脚本的 stdout 和 stderr。同样,每当我们的服务文件更改时,我们需要让systemd重新加载该单元:

$ systemctl daemon-reload

现在,我们需要在rsyslog中添加配置,以便它知道如何处理我们将发送给它的日志。让我们将以下内容添加到新文件*/etc/rsyslog.d/bird_watching.conf*:

if $programname == 'bird_watching' then /var/log/bird_watching.log
& stop

现在,让我们创建文件并确保syslog用户可以访问和写入它:

$ touch /var/log/bird_watching.log
$ chown syslog /var/log/bird_watching.log
$ ls -l /var/log/bird_watching.log 
-rw-r----- 1 syslog adm 122664 Feb  1 04:17 /var/log/bird_watching.log

完成后,让我们循环rsyslog服务并检查我们的日志文件:

$ systemctl restart rsyslog
$ tail -f /var/log/bird_watching.log
Feb  1 04:12:41 localhost bird_watching[2188458]: Black-capped chickadee
Feb  1 04:13:42 localhost bird_watching[2188511]: Baltimore oriole
Feb  1 04:14:56 localhost bird_watching[2188564]: House sparrow
Feb  1 04:15:57 localhost bird_watching[2188620]: Northern cardinal
Feb  1 04:17:11 localhost bird_watching[2188709]: Blue jay

3.2. 较新的systemd版本的直接集成

如果我们的主机正在运行 240 或更新的systemd版本,我们可以利用一个功能,该功能允许我们重定向我们的标准输出和标准错误,而无需调用 syslog 守护程序的服务:

$ systemctl --version
systemd 245 (245.4-4ubuntu3.13)
[redacted]

通过运行上面的命令,我们可以验证我们是否有一个包含此功能的systemd版本。

现在我们知道该功能可用,让我们配置我们的服务单元文件以使用它:

[Unit]
Description=Bird watching service
[Service]
Type=oneshot
ExecStart=/etc/systemd/system/bird_watcher.sh
StandardOutput=append:/var/log/bird_watching.log
StandardError=append:/var/log/bird_watching.log
[Install]
WantedBy=multi-user.target

如果文件不存在,此配置将创建文件并以附加模式打开它。

接下来,让我们要求systemd重新加载该单元,因为我们已经对其进行了更改:

$ systemctl daemon-reload

现在,我们可以查看服务的 stdout 和 stderr 文件:

$ tail -f /var/log/bird_watching.log 
American robin
House sparrow
Baltimore oriole
American robin
Blue jay

此选项缺少上述rsyslog方法的其他详细信息(时间戳),但具有不需要额外的 syslog 守护程序的好处