242

我正在尝试将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

请纠正我的做法。

4

8 回答 8

322

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

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

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

然后,假设您的发行版使用 rsyslog 来管理 syslog,请在其中创建一个包含/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>) 使用,但它们也可以在您选择的文件中使用。

来源:archive.org

于 2017-05-07T09:58:00.783 回答
108

如果您有更新的发行版systemdsystemd版本 236 或更新StandardOutput),您可以将或的值设置StandardErrorfile:YOUR_ABSPATH_FILENAME


很长的故事:

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

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

于 2018-01-01T18:23:26.683 回答
79

我建议在 systemd文件本身中添加stdout和归档。stderrservice

参考: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

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

于 2019-01-17T09:16:53.570 回答
56

您可能会收到此错误:

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

systemd.exec(5)手册页:

StandardOutput=

控制已执行进程的文件描述符 1 (STDOUT) 连接到的位置。取inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console,kmsg+console或之一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' 
于 2016-06-02T15:11:20.650 回答
23

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

于 2017-09-11T20:44:31.953 回答
17

简短的回答:

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

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

StandardOutput=append:/var/log1.log
StandardError=append:/var/log2.log
于 2020-01-05T14:53:20.313 回答
4

我们正在使用 Centos7,带有 systemd 的 spring boot 应用程序。我正在运行java,如下所示。并将 StandardOutput 设置为文件对我不起作用。

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

下面的解决方案在不设置 StandardOutput 的情况下工作。通过 sh 运行 java,如下所示。


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

在此处输入图像描述

于 2019-11-26T05:29:24.713 回答
4

假设日志已经放到stdout/stderr,并且有 systemd 单元的登录/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
于 2018-06-30T16:21:39.453 回答