如何从 Raspbian 上的 systemd 服务正确重定向 stdout/stderr?
How do I properly redirect stdout/stderr from a systemd service on Raspbian?
我使用 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
重定向 >>
无效。我已经尝试了 StandardOutput
和 StandardError
可用的大部分选项,但它们永远不会最终将我的脚本输出打印到 /var/log/daemon.log 并且 journalctl -u mydaemon.service
仅显示有关服务的消息正在启动和停止。
目前我没有对脚本中的文件描述符做任何有趣的事情。我只希望我的 print()
或 logging.info()
语句出现在我可以阅读的地方。有什么想法吗?
(需要说明的是,守护进程确实必须 运行 作为 root。这可能与我的打印问题有关吗?)
通常你只是直接 运行 一个服务(确保它的可执行文件有一个 shebang 行):
ExecStart=/home/pi/sources/mydaemon.py
并使用 StandardOutput=
的默认重定向到 systemd 日志,因此您可以使用 journalctl -u mydaemon.service
阅读日志。
Systemd 很好地为您控制日志的文件增长和文件轮换。
您的服务 运行 与 root 无关。
如果您没有看到上述任何日志输出,还请检查整个日志以查找附近可能归因于您的服务的日志:
journalctl
这是必要的,因为存在一个已知问题,即脚本存在之前的最后几行日志记录可能不归因于该脚本。这对于在退出前仅 运行s 几分之一秒的脚本尤其明显。
我需要 运行 python 使用 -u 参数来确保消息没有被缓冲。
使用这些行,打印行会立即添加到日志中:
StandardOutput=journal+console
ExecStart=/home/pengman/scripts/mqtt_monitor/venv/bin/python -u home/pengman/scripts/mqtt_monitor/src/mqtt_monitor.py
(我在 virtualenv 中 运行ning,但这不重要)
@mark-stosberg 接受的答案是正确的。我想稍微扩展他的答案,但评论太短了。
systemd-journald.service
手册页在 STREAM LOGGING 部分提到了这一点:
The systemd service manager invokes all service processes with standard output and standard error connected to the journal by default. This behaviour may be altered via the StandardOutput=
/StandardError=
unit file settings, see systemd.exec
(5) for details.
所以在@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
在 shell 语法中。
此外,如果您希望日志立即更新,您必须告诉 Python 不要缓冲输出(使用它的 -u
开关)。这也是我更改 ExecStart=
的原因。流式传输 python 输出时 (whether in systemd or from the shell) the output is buffered by default 并且在缓冲区刷新或进程结束之前不会更新文件。
更新 20190411 - Raspbian 的早期版本的 systemd 不接受 StandardOutput
的 file:/
目标(感谢@nak 指出这一点),所以我的回答没有关于 Raspbian(我在 openSUSE Tumbleweed 中测试过)对于 OP 问题并没有真正起作用。 详细介绍了使用旧版 systemd 执行此操作的替代方法。
我遇到了同样的问题。
使用 StandardOutput=journal+console
解决。
我使用 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
重定向 >>
无效。我已经尝试了 StandardOutput
和 StandardError
可用的大部分选项,但它们永远不会最终将我的脚本输出打印到 /var/log/daemon.log 并且 journalctl -u mydaemon.service
仅显示有关服务的消息正在启动和停止。
目前我没有对脚本中的文件描述符做任何有趣的事情。我只希望我的 print()
或 logging.info()
语句出现在我可以阅读的地方。有什么想法吗?
(需要说明的是,守护进程确实必须 运行 作为 root。这可能与我的打印问题有关吗?)
通常你只是直接 运行 一个服务(确保它的可执行文件有一个 shebang 行):
ExecStart=/home/pi/sources/mydaemon.py
并使用 StandardOutput=
的默认重定向到 systemd 日志,因此您可以使用 journalctl -u mydaemon.service
阅读日志。
Systemd 很好地为您控制日志的文件增长和文件轮换。
您的服务 运行 与 root 无关。
如果您没有看到上述任何日志输出,还请检查整个日志以查找附近可能归因于您的服务的日志:
journalctl
这是必要的,因为存在一个已知问题,即脚本存在之前的最后几行日志记录可能不归因于该脚本。这对于在退出前仅 运行s 几分之一秒的脚本尤其明显。
我需要 运行 python 使用 -u 参数来确保消息没有被缓冲。
使用这些行,打印行会立即添加到日志中:
StandardOutput=journal+console
ExecStart=/home/pengman/scripts/mqtt_monitor/venv/bin/python -u home/pengman/scripts/mqtt_monitor/src/mqtt_monitor.py
(我在 virtualenv 中 运行ning,但这不重要)
@mark-stosberg 接受的答案是正确的。我想稍微扩展他的答案,但评论太短了。
systemd-journald.service
手册页在 STREAM LOGGING 部分提到了这一点:
The systemd service manager invokes all service processes with standard output and standard error connected to the journal by default. This behaviour may be altered via the
StandardOutput=
/StandardError=
unit file settings, seesystemd.exec
(5) for details.
所以在@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
在 shell 语法中。
此外,如果您希望日志立即更新,您必须告诉 Python 不要缓冲输出(使用它的 -u
开关)。这也是我更改 ExecStart=
的原因。流式传输 python 输出时 (whether in systemd or from the shell) the output is buffered by default 并且在缓冲区刷新或进程结束之前不会更新文件。
更新 20190411 - Raspbian 的早期版本的 systemd 不接受 StandardOutput
的 file:/
目标(感谢@nak 指出这一点),所以我的回答没有关于 Raspbian(我在 openSUSE Tumbleweed 中测试过)对于 OP 问题并没有真正起作用。
我遇到了同样的问题。
使用 StandardOutput=journal+console
解决。