如何将 systemd 服务的输出重定向到文件

How to redirect output of systemd service to a file

我正在尝试将 systemd 服务的输出重定向到一个文件,但它似乎不起作用:

[Unit]
Description=customprocess
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server
StandardOutput=/var/log1.log
StandardError=/var/log2.log
Restart=always

[Install]
WantedBy=multi-user.target

请指正我的做法

您可能会遇到此错误:

Failed to parse output specifier, ignoring: /var/log1.log

来自 systemd.exec(5) 手册页:

StandardOutput=

Controls where file descriptor 1 (STDOUT) of the executed processes is connected to. Takes one of inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+console or socket.

systemd.exec(5) 手册页解释了与日志记录相关的其他选项。另请参阅 systemd.service(5)systemd.unit(5) 手册页。

或者你可以尝试这样的事情(全部在一条线上):

ExecStart=/bin/sh -c '/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server 2>&1 > /var/log.log' 

我认为有一个更优雅的方法来解决这个问题:将 stdout/stderr 发送到带有标识符的系统日志,并指示您的系统日志管理器按程序名称拆分其输出。

在您的 systemd 服务单元文件中使用以下属性:

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=<your program identifier> # without any quote

然后,假设您的发行版使用 rsyslog 来管理系统日志,请在 /etc/rsyslog.d/<new_file>.conf 中创建一个包含以下内容的文件:

if $programname == '<your program identifier>' then /path/to/log/file.log
& stop

现在使日志文件可由 syslog 写入:

# ls -alth /var/log/syslog 
-rw-r----- 1 syslog adm 439K Mar  5 19:35 /var/log/syslog
# chown syslog:adm /path/to/log/file.log

重新启动 rsyslog (sudo systemctl restart rsyslog) 并享受!您的程序 stdout/stderr 仍可通过 journalctl (sudo journalctl -u <your program identifier>) 使用,但它们也将在您选择的文件中可用。

Source via archive.org

如果由于某种原因不能使用 rsyslog,可以这样做: ExecStart=/bin/bash -ce "exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"

如果您的发行版更新 systemd (),您可以将 StandardOutputStandardError 的值设置为 file:YOUR_ABSPATH_FILENAME .


长话短说:

systemd 的较新版本中有一个相对较新的选项 (the github request is from 2016 ish and the enhancement is merged/closed 2017 ish) where you can set the values of StandardOutput or StandardError to file:YOUR_ABSPATH_FILENAME. The file:path option is documented in the most recent systemd.exec man page

这项新功能相对较新,因此不适用于 centos-7(或之前的任何 centos)等较旧的发行版。

假设日志已经被放入 stdout/stderr,并且系统单元的登录 /var/log/syslog

journalctl -u unitxxx.service

Jun 30 13:51:46 host unitxxx[1437]: time="2018-06-30T11:51:46Z" level=info msg="127.0.0.1
Jun 30 15:02:15 host unitxxx[1437]: time="2018-06-30T13:02:15Z" level=info msg="127.0.0.1
Jun 30 15:33:02 host unitxxx[1437]: time="2018-06-30T13:33:02Z" level=info msg="127.0.0.1
Jun 30 15:56:31 host unitxxx[1437]: time="2018-06-30T13:56:31Z" level=info msg="127.0.0.1

配置 rsyslog(系统日志服务)

# Create directory for log file
mkdir /var/log/unitxxx

# Then add config file /etc/rsyslog.d/unitxxx.conf

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

重启 rsyslog

systemctl restart rsyslog.service

我建议在 systemd service 文件本身中添加 stdoutstderr 文件。

参考:https://www.freedesktop.org/software/systemd/man/systemd.exec.html#StandardOutput=

按照您的配置,它应该不会像:

StandardOutput=/home/user/log1.log
StandardError=/home/user/log2.log

应该是:

StandardOutput=file:/home/user/log1.log
StandardError=file:/home/user/log2.log

当您不想一次又一次地重新启动服务时,这会起作用

这将创建一个新文件并且不会附加到现有文件。

改用:

StandardOutput=append:/home/user/log1.log
StandardError=append:/home/user/log2.log

注意:确保您已经创建了目录。估计是不支持创建目录吧

我们正在使用 Centos7,spring 使用 systemd 启动应用程序。我是 运行 java 如下。并将 StandardOutput 设置为文件对我不起作用。

ExecStart=/bin/java -jar xxx.jar  -Xmx512-Xms32M

以下变通解决方案无需设置 StandardOutput 即可工作。 运行 java 通过 sh 如下。


ExecStart=/bin/sh -c 'exec /bin/java -jar xxx.jar -Xmx512M -Xms32M >> /data/logs/xxx.log 2>&1'

简答:

StandardOutput=file:/var/log1.log
StandardError=file:/var/log2.log

如果您不希望每次服务 运行 时都清除文件,请改用追加:

StandardOutput=append:/var/log1.log
StandardError=append:/var/log2.log