You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用FIFO时守护进程内的进程立即退出问题排查

在Python守护进程中保持FIFO转发Shell的运行

问题根源:
当使用daemon.DaemonContext时,默认行为会关闭所有非标准文件描述符(即除了stdin、stdout、stderr之外的所有fd)。你在守护进程上下文之外打开的FIFO和日志文件的文件描述符会被关闭,导致启动的sh进程因为没有有效的输入输出流而立即退出。

解决方案:
需要在初始化DaemonContext时,通过files_preserve参数明确指定需要保留的文件描述符,同时配置守护进程的工作目录、标准流重定向等参数避免潜在问题。

修改后的完整代码:

from contextlib import contextmanager
import subprocess
import os
from pathlib import Path
import daemon


@contextmanager
def tmp_fifo(path: Path):
    try:
        # 可选:指定FIFO权限,确保外部可写入
        os.mkfifo(path, 0o666)
        file = os.open(path, os.O_RDWR | os.O_NONBLOCK)
        yield file
    finally:
        os.unlink(path)


fifo_path = Path.home() / "sh.fifo"
with tmp_fifo(fifo_path) as fifo, open("dout.log", "w+") as outfile:
    context = daemon.DaemonContext(
        # 强制保留FIFO和日志文件的文件描述符
        files_preserve=[fifo, outfile.fileno()],
        # 设置守护进程工作目录,避免相对路径失效
        working_directory=str(Path.cwd()),
        # 重定向标准流到/dev/null,避免终端依赖
        stdin=open(os.devnull, 'r'),
        stdout=open(os.devnull, 'w'),
        stderr=open(os.devnull, 'w'),
    )
    with context:
        with subprocess.Popen(["sh"], stdin=fifo, stdout=outfile) as popen:
            popen.wait()

关键修改说明:

  • files_preserve=[fifo, outfile.fileno()]:明确告知守护进程不要关闭这两个文件描述符,保证sh进程能正常读取FIFO输入、写入日志文件。
  • working_directory:守护进程默认会切换到根目录,设置为当前工作目录可避免相对路径的日志文件找不到。
  • 标准流重定向:将stdin/stdout/stderr指向/dev/null,消除守护进程对原终端的依赖,防止终端关闭导致进程异常退出。

额外注意:
如果需要其他用户或进程访问FIFO,创建时一定要指定合适的权限(如示例中的0o666),避免权限不足导致写入失败。

内容的提问来源于stack exchange,提问作者Schottky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 05:43:12