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

mea*_*our 136 linux rhel systemd centos7 rhel7

我试图将系统服务的o/p重定向到文件但它似乎不起作用.我这样做如下:

[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
Run Code Online (Sandbox Code Playgroud)

请建议将o/p重定向到文件的正确方法

Val*_*ace 190

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

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

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=<your program identifier> # without any quote
Run Code Online (Sandbox Code Playgroud)

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

if $programname == '<your program identifier>' then /path/to/log/file.log
& stop
Run Code Online (Sandbox Code Playgroud)

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

资料来源:http://wiki.rsyslog.com/index.php/Filtering_by_program_name(已损坏的链接,存档可在Archive.org上获得)

  • 使用systemd 236或更新版本,您还可以使用StandardOutput = file直接写入文件:/ some/path https://github.com/systemd/systemd/pull/7198 (40认同)
  • 在Ubuntu 16.04上不适合我.`journalctl -u`仍然有效但没有任何内容被发送到指定的文件. (7认同)
  • 我在使用此配置时遇到了问题,直到我发现“rsyslog”有自己的用户“syslog”并且它必须具有对日志位置的写访问权限。因此请相应地使用“chown”。希望这对某人有帮助。 (5认同)
  • 这在 Debian Stretch 上效果很好,但它抱怨“~”已被弃用,而应该使用“stop”。另请注意,如果第二行紧随其后,则可以将第二行缩短为“&amp; stop”。 (2认同)
  • 我通过将`/etc/rsyslog.d/ &lt;newfile&gt; .conf`内容更改为:`:programname,isequal,“ &lt;您的程序标识符&gt;” / var / log / somelog.log`来工作。这是rsyslog上的文档。过滤器:https://www.rsyslog.com/doc/v8-stable/configuration/filters.html这是有关“程序名”之类的属性的文档:https://www.rsyslog.com/doc/master/configuration/ properties.html (2认同)
  • @GregWoods 在撰写本文时,StandardOutput 设置根本没有采用文件描述符。现在有一种方法可以通过提供“file:&lt;path&gt;”值来做到这一点。只需阅读手册:https://man7.org/linux/man-pages/man5/systemd.exec.5.html (2认同)

Tre*_*ith 57

如果你有一个较新的一个较新的发行版systemd(systemd236或更新版本),你可以设置的值,StandardOutputStandardErrorfile:YOUR_ABSPATH_FILENAME.


很长的故事:

在新版本systemd有一个比较新的选项(GitHub的请求是自2016年ISH和提高合并/关闭2017年ISH),在这里可以设置的值,StandardOutputStandardErrorfile:YOUR_ABSPATH_FILENAME.该file:path选项记录在最新的systemd.exec手册页中.

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

  • 在2018-03-20不在ubuntu 1604中工作.ubuntu 1604中的systemd版本仅为229. (8认同)
  • FWIW:我进行了一些搜索,但此功能似乎没有提供日志轮换功能,例如重新打开日志文件的功能,必须在“logrotate”中使用“copytruncate”之类的功能。 (2认同)
  • 问题是,该文件始终创建为 root:root,无论设备的用户和组如何...... (2认同)

Shu*_*tan 41

您可能会收到此错误:

Failed to parse output specifier, ignoring: /var/log1.log
Run Code Online (Sandbox Code Playgroud)

systemd.exec(5)手册页:

StandardOutput=

控制已执行进程的文件描述符1(STDOUT)所连接的位置.注意到之一inherit,null,tty,journal,syslog,kmsg,journal+console,syslog+console,kmsg+consolesocket.

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' 
Run Code Online (Sandbox Code Playgroud)

  • 坦率地说,在ExecStart中使用命令字符串调用shell听起来像是真正错误的方法. (9认同)
  • 在这些选项中,建议登录systemd日志.您可以使用`journalctl -u your-unit-name`在日志中查看流程的日志. (7认同)
  • 要指定文件,还有另一个清除选项,如文档所示:`fd选项将输出流连接到套接字单元提供的单个文件描述符.可以在":"之后将自定义命名文件描述符指定为此选项的一部分(例如"fd:foobar"). (6认同)
  • Awsome回答,它解决了我的问题.我只是想扩展,因为目前如果服务重新启动覆盖旧日志,必须将此部分替换为:`2>&1>/var/log.log`:"2>&1 >> /var/log.log `.谢谢 (5认同)
  • @orion:请把它作为一个单独的答案.:-) (3认同)
  • “/bin/sh”是一个很好的解决方法,但您必须使用“exec”,否则服务将无法正确重新启动,因为 SIGTERM 不会传递给子进程。请参阅http://veithen.io/2014/11/16/sigterm-propagation.html (2认同)

Raj*_*ain 16

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

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

如您所配置,它不应该:

StandardOutput=/home/user/log1.log
StandardError=/home/user/log2.log
Run Code Online (Sandbox Code Playgroud)

它应该是:

StandardOutput=file:/home/user/log1.log
StandardError=file:/home/user/log2.log
Run Code Online (Sandbox Code Playgroud)

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

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

使用代替:

StandardOutput=append:/home/user/log1.log
StandardError=append:/home/user/log2.log
Run Code Online (Sandbox Code Playgroud)

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

  • systemd 版本 240 中引入了 `append:`。要解决 `file:` 将新日志输出放置在目标文件开头的问题,类似以下内容可能会有所帮助:`ExecStartPre=/bin/bash -c 'mv /var /log/my/logs.log /var/log/my/$$(date +%%T)-logs.log'`。保持干净的日志并以某种方式模拟日志轮换效果 (5认同)
  • [此答案](/sf/answers/3363650671/)的副本,详细信息较少 (4认同)
  • 请注意,文档明确指出“file:”每次都会写入文件的开头,并且不会截断...此外,“append:”似乎是一个新添加的内容(即不存在于“man systemd.conf”中)。 Ubuntu 18.04 上的 exec` 页面)。 (4认同)
  • 对于任何好奇的人来说,Ubuntu 20.04 目前的 systemd 版本为 245,而 Ubuntu 18.04 则为 237。因此不幸的是,您必须有 20.04 才能使用 `append:`。 (3认同)
  • 我认为,这使其更直接\更易于理解。 (2认同)

Tig*_*gra 15

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


小智 10

简短的回答:

StandardOutput=file:/var/log1.log
StandardError=file:/var/log2.log
Run Code Online (Sandbox Code Playgroud)

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

StandardOutput=append:/var/log1.log
StandardError=append:/var/log2.log
Run Code Online (Sandbox Code Playgroud)

  • [此答案](/sf/answers/3796277201/)的重复项,详细信息较少 (3认同)
  • 超级有帮助。我使用此技术将 Ubuntu 18.04 和 20.04 的日志记录恢复到 /var/log/tomcatX/catalina.out。 (2认同)

San*_*rur 7

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

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

Run Code Online (Sandbox Code Playgroud)

以下解决方案无需设置标准输出即可工作。通过 sh 运行 java 如下。


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

Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • @SamiKorhonen,我在测试这是否有效后添加了我的评论。即使我在想 -Xmx512M 的顺序也与你相似。请在添加盲目评论之前进行测试。 (4认同)