【问题标题】:Python script that spawns processes fails to start under systemd生成进程的 Python 脚本无法在 systemd 下启动
【发布时间】:2020-08-26 10:54:57
【问题描述】:

我有一个 python 脚本,它定期扫描文件夹以供 ffmpeg 处理。我决定把它变成一个系统服务。该脚本在命令行上运行良好,但当我尝试将其作为服务运行时会引发 BlockingIOError。为了解决这个问题,我将脚本归结为一个几乎是 hello world 的示例,但我仍然得到相同的结果。这是我所拥有的:

foobar.py

import subprocess 

result = subprocess.run(['/usr/bin/ffmpeg', '-h'])

print(result)

foobar.service

[Unit]
Description=foobar

[Service]
Type=simple
TasksMax=1
User=root
Environment="PATH=/usr/bin:/root/24-7"
ExecStart=/usr/bin/python3.8 /root/24-7/foobar.py

例外

Aug 26 12:47:55 Ubuntu-1804-bionic-64-minimal systemd[1]: Started foobar.
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]: Traceback (most recent call last):
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]:   File "/root/24-7/foobar.py", line 6, in <module>
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]:     result = subprocess.run(['/usr/bin/ffmpeg', '-h'])
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]:   File "/usr/lib/python3.8/subprocess.py", line 489, in run
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]:     with Popen(*popenargs, **kwargs) as process:
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]:   File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]:     self._execute_child(args, executable, preexec_fn, close_fds,
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]:   File "/usr/lib/python3.8/subprocess.py", line 1637, in _execute_child
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]:     self.pid = _posixsubprocess.fork_exec(
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal python3.8[4539]: BlockingIOError: [Errno 11] Resource temporarily unavailable
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal systemd[1]: foobar.service: Main process exited, code=exited, status=1/FAILURE
Aug 26 12:48:15 Ubuntu-1804-bionic-64-minimal systemd[1]: foobar.service: Failed with result 'exit-code'.

不知道还有什么可以尝试的。我做到了,我什至尝试用 sleep() 延迟通话,看看是否可能等待几秒钟会打开任何阻塞的东西。我不知道该尝试什么。有人知道吗?

【问题讨论】:

  • “我将脚本归结为一个几乎是 hello world 的示例” -- 谢谢。很少有人真正做到这一点,看到一个这样做的问题令人耳目一新。我已经相应地投票赞成这个问题。

标签: python systemd


【解决方案1】:

问题是你的TasksMax=1。这会阻止子进程的分叉,并且效果并不特定于 subprocess.run —— 诸如 subprocess.Popenos.systemos.fork 之类的任何东西,甚至尝试分叉的非 Python 应用程序都会遇到类似的问题。

这里是os.fork在受到TasksMax=1影响时表现出类似的症状:

foobar.py

import os

pid = os.fork()
if pid == 0:
    print("child")
    os._exit(0)
else:
    print(os.waitpid(pid, 0))
Aug 26 12:25:57 moon systemd[1]: Started foobar.
Aug 26 12:25:57 moon python3.8[9477]: Traceback (most recent call last):
Aug 26 12:25:57 moon python3.8[9477]:   File "/root/24-7/foobar.py", line 3, in <module>
Aug 26 12:25:57 moon python3.8[9477]:     pid = os.fork()
Aug 26 12:25:57 moon python3.8[9477]: BlockingIOError: [Errno 11] Resource temporarily unavailable
Aug 26 12:25:57 moon systemd[1]: foobar.service: Main process exited, code=exited, status=1/FAILURE
Aug 26 12:25:57 moon systemd[1]: foobar.service: Failed with result 'exit-code'.

如果您删除该行或增加限制,那么它将起作用。

使用您的简单 ffmpeg -h 示例,即使将其增加到 2 对我也有效,尽管使用您想要运行的真实选项,您可能希望将其增加一点,以防万一 ffmpeg 需要分叉它自己的子进程。

【讨论】:

  • 就是这样!谢谢!从示例中复制和粘贴我的原始 .service 并且从未注意 TasksMax 设置的症状。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-16
  • 2020-08-21
  • 1970-01-01
  • 2020-04-22
相关资源
最近更新 更多