我正在尝试将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提供的信息
-
在Ubuntu 16.04上不适用于我。 journalctl -u仍然有效,但是没有任何内容发送到指定的文件。
-
这在Debian上很有效,但是它抱怨不赞成使用~,而应该改用stop。另请注意,如果第二行彼此紧接,则第二行可以缩短为& stop。
-
对于systemd 236或更高版本,您还可以使用StandardOutput = file:/ some / path github.com/systemd/systemd/pull/7198直接写入文件
-
@leezu仅供参考,我写的答案与您的评论相似。在看到您的评论之前,我已经写了答案。
-
在第1行或之前,在解析文件/etc/rsyslog.d/project.conf时发生错误:令牌上的语法错误== [v8.32.0 try rsyslog.com/e/2207]
-
来源不再可用。
-
我通过将etcrsyslog.d<newfile>.conf内容更改为::programname, isequal,"<your program identifier>" varlogsomelog.log此处有关rsyslog过滤器的文档来工作:rsyslog.com/doc/v8-stable/configuration/filters.html以及此处有关programname属性的文档:rsyslog。 com / doc / master / configuration / properties.html
-
在使用rsyslog拥有自己的用户syslog且必须具有对日志位置的写权限之前,我在使用此配置时遇到了问题。因此,请相应地使用chown。希望这对某人有帮助。
-
在ubuntu 16.04上,此日志记录到/path/to/log/file.log和/ var / log / syslog
-
是否可以使用此方法将stdout与stderr分开?
-
@Imaskar谢谢!这对我来说是Xenial上的硬道理。
-
Ubuntu在其默认配置文件中使用ReinerScript。因此,将/etc/rsyslog.d/<new_file>.conf的内容更改为if $programname == program_identifier then { action (type="omfile" file="varlogmy_program.log") }的结果是开箱即用的,而无需更改/var/log/my_program.log的权限
-
谢谢,在Centos 7.5上进行测试-日志同时出现在journalctl -u SERVICE和varlogFILE.log上
-
以下rsyslog配置对我有用::programname, isequal,"xxx" varlogxxxxxx.log
-
答案可能会提供有用的替代解决方案,但它并未说明OPs方法为何行不通的原因。我个人想知道,因为我自己尝试过他的方法,但这对我也不起作用。但为什么?
-
在撰写本文时,@ GregWoods的StandardOutput设置只是没有使用文件描述符。现在,有一种方法可以通过提供" file:<path> "值来实现。只需阅读手册:man7.org/linux/man-pages/man5/systemd.exec.5.html
-
systy和stderr是systyemd中的默认syslog和进程名称,因此您根本不需要弄乱配置。
-
第2步讨论/path/to/log/file.log,然后第3步讨论chown那个文件-但是它不存在,因为没有任何步骤创建它
如果您的发行版具有更新的systemd(systemd版本236或更高版本),则可以将StandardOutput或StandardError的值设置为file:YOUR_ABSPATH_FILENAME。
长话:
在systemd的较新版本中,有一个相对较新的选项(github请求来自2016 ish,增强功能已合并/关闭2017 ish),您可以在其中将StandardOutput或StandardError的值设置为file:YOUR_ABSPATH_FILENAME。 file:path选项记录在最新的systemd.exec手册页中。
此新功能相对较新,因此不适用于较旧的发行版,如centos-7(或之前的任何centos)。
-
在2018-03-20中无法在ubuntu 1604中工作。 ubuntu 1604中的systemd版本只有229。
-
谢谢,你说的很清楚。我只是不敢相信ubuntu 1604中的systemd不能仅通过config将输出重定向到文件。我必须使用sh方法来解决此问题。
-
@bronzeman的功能请求直到2017年才关闭,而Ubuntu 16.04于2016年问世。在给定的主要Ubuntu版本(例如16.04、16.10、17.04等)中,Ubuntu在其核心系统软件包中保持ABI兼容性。因此,除非systemd(或Linux内核,glibc或其他任何东西)保持与首次发布Ubuntu版本时相同的ABI,否则他们不会升级systemd。
-
FWIW:Ive进行了一些搜索,但是此功能似乎没有日志轮换的规定,例如重新打开日志文件的功能,其中一个必须使用logrotate中的copytruncate。
-
问题是,无论单位用户和组是什么,该文件总是以root:root身份创建...
您可能会收到此错误:
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日志。您可以使用journalctl -u your-unit-name在日记中仅查看过程的日志。
-
要指定文件,有另一个更清洁的选项,如文档所示:The fd option connects the output stream to a single file descriptor provided by a socket unit. A custom named file descriptor can be specified as part of this option, after a":" (e.g."fd:foobar").
-
可怕的答案,它解决了我的问题。我只想扩展一下,因为当前如果服务重新启动会覆盖旧日志,则必须将以下部分替换为:2>&1 > varlog.log。谢谢
-
坦白说,在ExecStart中使用命令字符串调用Shell听起来像是"错误方式"。
-
/ bin / sh -c看起来不对,但是可以工作。它也可以与Restart = always一起使用。我还建议您将StandardOutput = null添加到配置中,以避免一些垃圾日志进入/ var / syslog
-
/ bin / sh -c对我不起作用,我认为由于systemd中存在奇怪的引用规则。参见例如stackoverflow.com/questions/23935637/systemd-string-escaping。有人有这个工作吗?
-
" / bin / sh "是一个很好的解决方法,但是您必须使用" exec ",否则该服务将无法正确重启,因为SIGTERM不会传递给子进程。参见veithen.io/2014/11/16/sigterm-propagation.html
-
/ bin / sh -c由于不起作用" systemctl stop service"命令而产生一种不希望的结果。它只会杀死sh进程,而不会触及服务
-
journalctl -u很荒谬,并且有许多缺点。需要重新设计时考虑实际的工作流程和简单的命令。每个QA团队成员都讨厌它(与systemctrl一样不提供输出)。从一开始就没有想到文件输出,这只是犯罪行为;而且,许多企业用户仍然没有它。这是一个错误,并且尚未得到改进。这是公司接管而使用户苦苦挣扎的一种情况。
-
要正确重定向stderr,必须使用>varlog.log 2>&1,而不是相反。
我建议在systemd service文件本身中添加stdout和stderr文件。
引荐: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 |
注意:确保已经创建目录。我猜它不支持创建目录。
-
该答案重复,但细节较少
-
我认为,这使其更直接\\\\\\\\\\易于理解。
-
对我来说,file:路由在服务的第一次加载时起作用,但是在随后的重新启动时,它不再写入文件。我从文档中尝试了append:,但根本没有用。
-
请注意,文档明确指出file:每次都写入文件的开头,并且不会截断...进一步地,append:似乎是一个新添加(即,在Ubuntu的man systemd.exec页面中不存在) 18.04)。
-
append:已在系统版本240中引入。要变通解决file:,将新的日志输出放置在目标文件的开头,可能会有所帮助:ExecStartPre=binbash -c mv varlogmylogs.log varlogmy$$(date +%%T)-logs.log。保持日志干净并以某种方式模拟日志轮换效果
如果由于某种原因无法使用rsyslog,则可以这样做:
ExecStart=/bin/bash -ce"exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"
-
bash的-e选项有什么作用?
-
不幸的是,在我的情况下,唯一有效的解决方案是在每次服务重启时都不会丢失日志文件,因为append在我当前的systemd版本中不可用。
简短答案:
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 |
-
该答案重复,但细节较少
-
超级有帮助。我使用此技术将Ubuntu 18.04和20.04的日志记录恢复到/var/log/tomcatX/catalina.out。
我们正在使用带有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' |
-
-1用于以错误的顺序定义jvm参数。 -Xmx512M必须在-jar之前定义。另外,您的体验也值得期待。 Systemd不使用Shell调用服务
-
@SamiKorhonen,我在测试此功能后添加了我的评论。甚至我在想-Xmx512M的命令对您来说都是一个笑柄。添加盲注之前,请先进行测试。
假设日志已经放入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 |