6

在 Ruby 中,如果以非超级用户身份运行,则调用Process.setsid失败并显示“不允许操作”错误。尝试:

$ irb
irb(main):001:0> Process.setsid
Errno::EPERM: Operation not permitted
    from (irb):1:in `setsid'
    from (irb):1
    from ~/.rbenv/versions/1.9.2-p290/bin/irb:12:in `<main>'

或者,如果我更改 uid 或使用Process.uid=方法的进程,它会失败并出现相同的错误。如果我以 root 身份运行 Ruby 程序,它可以正常工作,并且我不会在运行时更改进程的 UID。

但是,在 Ubuntu 或其他发行版的 shell 中,setsid(参考: http: //linux.die.net/man/2/setsid)程序不需要超级用户权限。

我知道这会stdsid重置程序的会话,这在守护进程时也很有用。在我的代码中,我试图更改 UID 并对其进行守护,同时还重置会话。

因此,我很好奇为什么Process.setsid需要上述权限,而setsid大多数 UNIX 等操作系统上的程序却不需要。

4

1 回答 1

5

Process.setsid是对 POSIX setsid(2)的精简包装,其手册页显示:

错误

EPERM

任何进程的进程组 ID 等于调用进程的 PID。因此,特别是,如果调用进程已经是进程组领导,则 setsid() 会失败。

当你的程序运行时,它已经是组长了。在去恶魔化时,您应该为您的守护进程派生一个新进程。Process.setsid分叉后没有 EPERM 错误的情况下工作:

$ irb
irb> Process.setsid
Errno::EPERM: Operation not permitted
    from (irb):1:in `setsid'
    from (irb):1
    from /Users/dbenhur/.rbenv/versions/1.9.3-p194/bin/irb:12:in `<main>'
irb> fork { Process.setsid }
=> 3359

查看Rexecunicorn以了解 Ruby 中的 POSIX 守护进程的示例。

setsid(1) 程序没有收到 EPERM 错误,因为它在调用 setsid(2) 之前分叉。请参见此处的第 31 行

于 2012-06-21T20:38:35.800 回答