web-dev-qa-db-ja.com

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ソケットはデプロイヤーユーザーが所有しているため、これも問題にはなりません。

誰かがどこを見るべきか手がかりを持っていますか?

更新:

少し掘り下げた後、私はそれがEPERMをスローするProcess.initgroupsへの呼び出しに要約されることを発見しました。私はこれをirbで確認しました。エラーの原因がわかりません。ユーザーは/etc/groupを読み取ることができます。

5
fiskeben

私はついにそれを理解しました。問題は、デプロイヤーユーザーのプライマリグループが間違っていたことでした。 'staff'である必要がありますが、代わりに 'deployer'でした。つまり、Unicornは、新しいワーカープロセスの所有権を、使用することになっているグループに引き渡そうとしますが、それを実行できるのはrootだけです。

他の誰かが知る必要がある場合に備えて、次のように/etc/passwdを編集してプライマリグループを変更しました。

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

「50」は「スタッフ」のギッドです。そもそも1002年でした。 'staff'グループのgidを取得するには、次のようにします。

cat /etc/group | grep staff

それは次の線に沿って何かを言うでしょう:

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

Gidは、「x」の後の番号です。

2
fiskeben

私があなたをよく理解しているなら、あなたは通常のユーザーの下でSudoなしでサービスを開始しようとしています。これは機能せず、受け取ったようなエラーが発生します操作は許可されていません。これは、すべてではないにしてもほとんどの場合に当てはまります。これは、サービスがそのジョブを実行するために次の1つ以上を必要とするためです。

  1. 1024未満のポートでのバインド/リスニング。
  2. ルート以外で読み取れないファイルを読み取っています。
  3. ルート以外では書き込みできないファイルを書き込んでいます。
  4. そしておそらくもっと(私は思い出せません)。
4
Khaled

私は最近これで男の日を失いました。コンテキストは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行目の周りにprintステートメントを使用してコードベースをインストルメント化すると、次のデバッグ情報が得られました。

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の違いにたどり着きました。問題は、アプリユーザーが別のプライマリグループ(admin)に属していることでした。アプリユーザーをプライマリとしてアプリグループに移動すると、機能しました。これは、ボックスのユーザーアカウントを定義した/ etc/passwdファイルを編集することによって行われました。

これをテストする別の方法は、sgを使用して、次のようなsgコマンドを使用して正しいグループでUnicornを手動で実行することです。

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

注:上記のフック後のユニコーンは私には機能しませんでした。これ以外は何も機能しませんでした。

0
fuzzygroup

同じ問題が発生しました。最終的に私のために働いたのは、after_fork do |server, worker|ブロックのUnicorn構成で次のように設定することでした:(これはgithubUnicorn構成からのものです)

  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
0
trans1t