为什么Process.setsid在ruby中需要root特权?

Gur*_*ngh 5 ruby daemon process root

在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>'
Run Code Online (Sandbox Code Playgroud)

或者,如果我更改uid或使用Process.uid=method 的进程,它将失败,并显示相同的错误。如果我以root身份运行Ruby程序,则效果很好,并且在运行时不更改进程的UID。

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

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

因此,我很好奇为什么Process.setsid需要上述特权,而setsid大多数UNIX(如OS)上的程序却不需要。

dbe*_*hur 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
Run Code Online (Sandbox Code Playgroud)

查看Rexecunicorn以获取 Ruby 中 POSIX 守护进程的示例。

setsid(1) 程序不会出现 EPERM 错误,因为它在调用 setsid(2) 之前就进行了分叉。请参阅此处的第 31 行