关于linux:如何将systemd服务的输出重定向到文件

How to redirect output of systemd service to a file

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

1
2
3
4
5
6
7
8
9
10
11
12
13
[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

请更正我的方法。


我认为有一种解决问题的更优雅的方法:将stdout / stderr发送给具有标识符的syslog,并指示syslog管理器按程序名称拆分其输出。

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

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

然后,假设您的发行版使用rsyslog来管理syslog,请在/etc/rsyslog.d/<new_file>.conf中创建一个文件,其内容如下:

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

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

1
2
3
# 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>)获得,但也将在您选择的文件中提供。

通过archive.org提供的信息


如果您的发行版具有更新的systemd(systemd版本236或更高版本),则可以将StandardOutputStandardError的值设置为file:YOUR_ABSPATH_FILENAME

长话:

systemd的较新版本中,有一个相对较新的选项(github请求来自2016 ish,增强功能已合并/关闭2017 ish),您可以在其中将StandardOutputStandardError的值设置为file:YOUR_ABSPATH_FILENAMEfile:path选项记录在最新的systemd.exec手册页中。

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


您可能会收到此错误:

1
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)手册页。

或者也许您可以尝试这样的操作(全部都在一行中):

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


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

引荐:https://www.freedesktop.org/software/systemd/man/systemd.exec.html#StandardOutput=

配置后,它应该不会:

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

应为:

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

当您不想一次又一次地重新启动服务时,此方法有效。

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

改为使用:

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

注意:确保已经创建目录。我猜它不支持创建目录。


如果由于某种原因无法使用rsyslog,则可以这样做:

ExecStart=/bin/bash -ce"exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"


简短答案:

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

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

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


我们正在使用带有systemd的Spring Boot应用程序Centos7。我正在如下运行Java。并将StandardOutput设置为file对我不起作用。

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

以下解决方法在未设置StandardOutput的情况下工作。通过sh如下运行java。

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

enter image description here


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

1
2
3
4
5
6
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(系统日志记录服务)

1
2
3
4
5
6
7
# 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

1
systemctl restart rsyslog.service