进程中调用子进程时出现IOError: [Errno 9] Bad file descriptor错误。

4
if args.daemon:
    pid = os.fork()
    if pid > 0:
        sys.exit(0)

    os.close(0)
    os.close(1)
    os.close(2)

main()


def main():
    # some code
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

当我将主程序作为守护进程调用时(即分叉出的进程并关闭stdin / stdout / stderr),我会收到IOError:[Errno 9]。 我怀疑是由于关闭这些管道,但如果我不这样做,我的程序就不会返回。 有没有办法在守护进程中执行子进程?


你说的“我的程序不会返回”的意思是什么?你关闭了标准输出和标准错误输出。根据定义,它不应该返回。 - Jakob Lovern
如果你在shell中运行它,除非我关闭0、1、2,否则它不会返回。所以这就是我想做的。但我认为这就是导致IOError的原因。所以我希望能够关闭并仍然调用子进程。 - ealeon
你说过那句话。但是你所说的“return”是什么意思呢?是指将控制权交还给你吗? - Jakob Lovern
@JakobLovern 是的,即在后台运行。 - ealeon
两个进程中,哪一个在使用控制台,是父进程还是子进程?应该是父进程。当您调用os.fork时,它应该将子进程独立推出,只有针对其PID的信号才能触及它。没有必要关闭stdin/stdout/stderr,因为它(子进程)从一开始就没有打开它们。 - Jakob Lovern
很抱歉,我很难理解你在说什么以及你的意图。我告诉你我运行程序时看到的行为。请自己尝试一下。如果您不关闭,则提示不会返回。进程在前台运行,而不是后台。 - ealeon
1个回答

0

我修改了代码:

if args.daemon:
    pid = os.fork()
    if pid > 0:
        sys.exit(0)
    os.close(0)
    os.close(1)
    os.close(2)

至:

 if args.daemon:
    stdin = '/dev/null'
    stdout = '/dev/null'
    stderr = '/dev/null'

    try:
        pid = os.fork()
        if pid > 0:
            # exit first parent
            sys.exit(0)
    except OSError, e:
        sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
        sys.exit(1)

    # decouple from parent environment
    os.chdir("/")
    os.setsid()
    os.umask(0)

    # do second fork
    try:
        pid = os.fork()
        if pid > 0:
            # exit from second parent
            sys.exit(0)
    except OSError, e:
        sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
        sys.exit(1)

    # redirect standard file descriptors
    sys.stdout.flush()
    sys.stderr.flush()
    si = file(stdin, 'r')
    so = file(stdout, 'a+')
    se = file(stderr, 'a+', 0)
    os.dup2(si.fileno(), sys.stdin.fileno())
    os.dup2(so.fileno(), sys.stdout.fileno())
    os.dup2(se.fileno(), sys.stderr.fileno())

并且 subprocess 不再引发 IOError 异常


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接