启动 Unicorn 时不允许操作

启动 Unicorn 时不允许操作

我在 Ubuntu(Amazon EC2)上创建了一个 nginx/unicorn/capistrato 设置,主要遵循以下方法本指南。我想一切都设置好了,但是当我启动 Unicorn 时,我在日志中收到(很多)这个错误:

E, [2012-09-08T08:57:20.658092 #12356] ERROR -- : Operation not permitted (Errno::EPERM)
/home/deployer/apps/bridgekalenderen.no/shared/bundle/ruby/1.9.1/gems/unicorn-4.3.1/lib/unicorn/worker.rb:82:in `initgroups'

我看到它与用户的权限有关,但我就是搞不清楚我遗漏了什么。如果我使用 sudo(或者,实际上是 rvmsudo)启动服务器,服务器就会顺利启动。

用户具有 sudo 权限,我已多次修改应用程序的 chmod,因此那里的文件权限应该没问题。/tmp 中的 unicorn 套接字归 deployer 用户所有,因此这也不是什么问题。

有人知道该看哪儿吗?

更新:

经过一番挖掘,我发现它归结为一个Process.initgroups引发 EPERM 的调用。我已经在 irb 中验证了这一点。我不明白是什么导致了错误。用户可以读取/etc/group

答案1

如果我理解正确的话,您正在尝试在非普通用户的情况下启动服务sudo。这将不起作用,并会出现您收到的错误不允许操作在大多数情况下(如果不是全部)情况都是如此,因为任何服务都需要以下一项或多项才能完成其工作:

  1. 绑定/监听端口 < 1024。
  2. 正在读取非 root 无法读取的文件。
  3. 正在写入非 root 无法写入的文件。
  4. 甚至可能更多(我不记得了)。

答案2

我终于搞明白了。问题在于部署者用户的主组是错误的。它应该是“staff”,但却是“deployer”。这意味着 unicorn 试图将新工作进程的所有权移交给它应该使用的组,但只有 root 才能做到这一点。

/etc/passwd为了防止其他人需要知道,我通过如下编辑更改了主要组:

deployer:x:1002:50:,,,:/home/deployer:/bin/bash

'50' 是 'staff' 的 gid。它一开始是 1002。要获取 'staff' 组的 gid,请执行以下操作:

cat /etc/group | grep staff

它会说类似这样的话:

staff:x:50:<comma separated list of users in this group>

gid 是“x”后面的数字。

答案3

我遇到了同样的问题。最终对我有用的是在我的 unicorn 配置中的块中设置以下内容after_fork do |server, worker|:(它来自 github unicorn 配置)

  begin
    uid, gid = Process.euid, Process.egid
    user, group = 'deployer', 'staff'
    target_uid = Etc.getpwnam(user).uid
    target_gid = Etc.getgrnam(group).gid
    worker.tmp.chown(target_uid, target_gid)
    if uid != target_uid || gid != target_gid
      Process.initgroups(user, target_gid)
      Process::GID.change_privilege(target_gid)
      Process::UID.change_privilege(target_uid)
    end
  rescue => e
    if RAILS_ENV == 'development'
      STDERR.puts "couldn't change user, oh well"
    else
      raise e
    end
  end

答案4

最近我为此损失了一天时间。上下文试图在名为 apps 的用户上运行 Unicorn,但 Errno::EPERM 错误一直困扰着我们。以下是堆栈跟踪:

E, [2018-04-12T20:45:07.277588 #2048] ERROR -- : Operation not permitted (Errno::EPERM)
/apps/cas-seas3/shared/bundle/ruby/2.2.0/gems/unicorn-5.4.0/lib/unicorn/worker.rb:143:in `initgroups'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/gems/unicorn-5.4.0/lib/unicorn/worker.rb:143:in `user'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/gems/unicorn-5.4.0/lib/unicorn/http_server.rb:657:in `init_worker_process'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/gems/unicorn-5.4.0/lib/unicorn/http_server.rb:682:in `worker_loop'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/gems/unicorn-5.4.0/lib/unicorn/http_server.rb:549:in `spawn_missing_workers'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/gems/unicorn-5.4.0/lib/unicorn/http_server.rb:563:in `maintain_worker_count'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/gems/unicorn-5.4.0/lib/unicorn/http_server.rb:293:in `join'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/gems/unicorn-5.4.0/bin/unicorn:126:in `<top (required)>'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/bin/unicorn:23:in `load'
/apps/cas-seas3/shared/bundle/ruby/2.2.0/bin/unicorn:23:in `<top (required)>'

在第 143 行左右使用打印语句对代码库进行检测,得到了以下调试信息:

user = apps
group=apps
uid=1040
gid=110
whoami=apps
Process.egid = 1001

gid 和 Process.egid 之间的差异导致此代码块失败:

if gid && Process.egid != gid
  Process.initgroups(user, gid)
  Process::GID.change_privilege(gid)
end

这就是导致失败的原因。

我最终将其归结为 GID / EGID 之间的差异,问题在于应用程序用户属于不同的主要组(管理员)。当我将应用程序用户移至应用程序组作为主要用户时,它就起作用了。这是通过编辑定义框的用户帐户的 /etc/passwd 文件来完成的。

另一种测试方法是使用 sg 手动运行具有正确组的 unicorn,使用 sg 命令如下:

bundle exec sg apps -c unicorn -c /apps/cas-seas3/current/config/unicorn.rb -E deployment -D

如果您发现它有效,那么这是一个非常好的信号,表明您需要查看您的用户/组设置。

Unicorn 似乎对用户/组设置非常敏感,会检查 /etc/passwd 和 /etc/group,还会使用此 ps 行检查执行 Unicorn 进程时的 UID 和 GID 差异:

ps -eo uid,gid,egid,args | grep unicorn

注意:上面的钩子后的独角兽对我来说不起作用。除了这个之外什么都不起作用。

相关内容