os.setsid 操作不被允许

4 投票
1 回答
4712 浏览
提问于 2025-04-20 04:18

好的,请耐心听我说,网上似乎有一些关于这个问题的答案,但我就是搞不明白。

我是在一个Django Celery环境中运行它的,经过了两次分叉。我不知道这些是否会改变什么,但我猜应该没有。

代码不多,留给大家的也不算太复杂。

if __name__ == '__main__':
    os.setsid()

但是我遇到了一个很麻烦的错误,提示“操作不允许”。

我正在使用最新稳定版的Django、Debian、Celery和Python。

1 个回答

3

Python中的 os.setsid() 可能会调用底层的库函数 setsid(3)

man 3 setsid 中,完整的错误信息部分是:

ERRORS
   EPERM  The  process group ID of any process equals the PID of the call-
          ing process.  Thus, in particular, setsid() fails if the calling
          process is already a process group leader.

换句话说,setsid() 失败的唯一原因是调用这个函数的进程已经是一个进程组的领导者。所以:你可以忽略这个失败。要确认这一点,可以比较在 os.setsid() 失败时从 getpid()getpgid() 得到的结果:

#!/usr/bin/env python

import os
import errno

if __name__ == '__main__':
    try:
        os.setsid()
    except OSError, (err_no, err_message):
        print "os.setsid failed: errno=%d: %s" % (err_no, err_message)
        print "pid=%d  pgid=%d" % (os.getpid(), os.getpgid(0))

当我运行上面的代码时,我得到:

os.setsid failed: errno=1: Operation not permitted
pid=17025  pgid=17025

注意,进程ID(pid)等于进程组ID(pgid),这意味着这个进程确实已经是一个进程组的领导者。

附注:是的,Python在遇到错误时抛出异常,这确实让人困惑,因为有时候只需要一个简单的错误返回码就能区分成功和失败(就像我们熟悉的Unix libc API那样)。不幸的是,这就是Python系统调用接口的实现方式,所以你需要用 try: except ...: 的结构来包裹许多系统调用,以防止Python中断你的代码。

撰写回答