如何从Raspbian上的systemd服务正确重定向stdout / stderr?

时间:2017-04-25 05:45:08

标签: python python-3.x raspberry-pi raspbian systemd

我使用systemd在Raspbian(Jessie)上设置了一个服务,使其在启动后启动。守护程序配置如下所示:

[Unit]
After=multi-user.target

[Service]
Type=idle
User=root
ExecStart=/bin/sh -c "exec /home/pi/sources/mydaemon.py >> /home/pi/mydaemon.log 2>&1"

[Install]
WantedBy=multi-user.target

重定向>>不起作用。我已经尝试了StandardOutputStandardError可用的大多数选项,但是他们从未将我的脚本输出打印到/var/log/daemon.log,而journalctl -u mydaemon.service只显示有关服务正在启动和停止。

我目前没有对脚本中的文件描述符做任何有趣的事情。我只想让我的print()logging.info()语句出现在我可以阅读的地方。有什么想法吗?

(为了清楚起见,守护进程必须以root身份运行。这可能与我的打印问题有关吗?)

3 个答案:

答案 0 :(得分:5)

我需要使用-u参数运行python以确保消息不被缓冲。

使用这些行,打印行会立即添加到日记中:

StandardOutput=journal+console
ExecStart=/home/pengman/scripts/mqtt_monitor/venv/bin/python -u home/pengman/scripts/mqtt_monitor/src/mqtt_monitor.py

(我在virtualenv中运行,但这无关紧要)

答案 1 :(得分:3)

通常你只是直接运行一个服务(确保它的可执行文件有一个shebang行):

 ExecStart=/home/pi/sources/mydaemon.py

使用StandardOutput=的默认重定向到systemd日志,这样您就可以使用journalctl -u mydaemon.service读取日志。

Systemd很好地控制了日志的文件增长和文件轮换。

您的服务以root用户身份运行是无关紧要的。

如果您没有看到上述任何日志输出,请检查整个日志中是否有可能归因于您的服务的附近日志:

 journalctl

这是必要的,因为当脚本存在之前的某些最后一行日志记录可能不会归因于脚本时,会出现一个已知问题。对于在退出之前只运行一小段时间的脚本,这一点尤其明显。

答案 2 :(得分:2)

@ mark-stosberg接受的答案是金钱和正确的答案。我想扩大他的答案,而评论太短。

systemd-journald.service手册页在“流记录”部分中提到了这一点:

  

默认情况下,systemd服务管理器使用标准输出和标准错误连接到日志来调用所有服务进程。可以通过StandardOutput= / StandardError=单位文件设置来更改此行为,有关详细信息,请参见systemd.exec(5)。

因此,在@eric的原始单位文件中,为了将输出发送到/home/pi/mydaemon.log,您可以在单位文件中完成

ExecStart=/usr/bin/python -u /home/pi/sources/mydaemon.py
StandardOutput=file:/home/pi/mydaemon.log
StandardError=inherit

请注意StandardError的值。这来自systemd.exec(5)联机帮助页,它意味着将 stderr 钩接到与 stdout 相同的句柄,就像在外壳中2>&1语法。

此外,如果您想立即更新日志,则必须告诉Python不要缓冲输出(使用-u开关)。这就是为什么我也更改了ExecStart=的原因。在流式传输python输出(whether in systemd or from the shell)时,output is buffered by default和文件将不会更新,直到缓冲区刷新或进程结束。


UPDATE 20190411-Raspbian的较早版本的systemd不接受file:/的{​​{1}}目标(感谢@nak指出这一点),因此我的回答实际上不适用于OP问题,因为关于Raspbian(我在openSUSE Tumbleweed 中进行了测试)。 This SO question "How to redirect output of systemd service to a file"详细介绍了使用旧systemd的替代方法。