使用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
相关产品推荐
相关产品推荐

