別のバージョンが必要な場合に、最新バージョンのgemを必要とするバンドルの問題を修正するにはどうすればよいですか?


8

私はこれで2週間近く頭を悩ませてきました。rbenvがインストールされたUbuntu 14.04サーバーを使用して、いくつかの異なるRails Webサイトを実行しています。それらの一部は古いバージョンのRailsにあり、一部は最新バージョンにあります。

特に2つのWebサイトがあり、どちらも異なるバージョンのpuma_worker_killerが必要です。1つは0.1.0が必要で、もう1つは0.1.1が必要です。これらのWebサイトは両方ともRuby 2.5.3を使用しています。

サーバーを起動するとRAILS_ENV=dev3 bundle exec pumactl -F ./config/puma.rb start、ログに次のエラーが表示され、Webサイトがハングします。

You have already activated puma_worker_killer 0.1.1, but your Gemfile requires puma_worker_killer 0.1.0. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)

最初に〜/ .rbenvではなく〜/ .gemにgemをインストールしていたため、rbenvに問題があるのではないかと思ったので、すべてのルビーを〜/ .gemに入れて、正しい場所に新しくインストールしましたrbenvフォルダーを使用bundle installしても、同じ問題が引き続き発生します。

この時点で、私はこの問題についてオンラインで広範な調査を行ったことを明確にしたいと思います。これを解決するために私は多くのことができることを知っています。

バージョンとを変更するだけで十分bundle update puma_worker_killerです。

また、gem uninstall puma_worker_killer0.1.1を実行して選択することで最新バージョンを削除できることも知っていますが、これは他のWebサイトへの依存関係が満たされないことを意味します。

バンドラーのソースコードを掘り下げて調べたところ、次のコード行が原因であることがわかります。

return if activated_spec.version == spec.version

とmatchのbundle exec両方を使用してバンドラーのコンテキストで実行する場合、そのメソッド()の次のコードは実行されません。何らかの理由で、上記のコマンドを実行してサーバーを起動すると、(アクティブ化されたgem)は最新バージョン(0.1.1)であり、Gemfile(0.1.0)にリストされているものではないため、返されずにスローされます上記のエラー。activated_specspeccheck_for_activated_spec!activated_spec

また、puma_worker_killerの依存関係の1つであるget_process_memにも同じ問題があるようです。それはすでに0.2.5をアクティブ化していると不平を言っていますが、私のGemfileは0.2.4を望んでいます:

You have already activated get_process_mem 0.2.5, but your Gemfile requires get_process_mem 0.2.4. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)

bundle exec同じgemに複数のバージョンがあるというこの非常に問題を解決するために使用する場合は、gemfileにリストされているバージョンをロードする必要があるというのが、bundleの私の理解です。

プロジェクト内に異なるバージョンのpuma_worker_killerが含まれる別のgemset(明らかにrbenvを使用して実行できます)を作成し、実行するrbenv local 2.5.3-pwk0.1.0か、または目的のバージョンにrbenv local 2.5.3-pwk0.1.1応じて、プロジェクト内で実行することもできますが、それはやりたいことにはやり過ぎのようです成し遂げる。

このレートでは、puma_worker_killerとget_process_memの両方の最新バージョンですべてのWebサイトを更新し、それらをロックしてサーバー上のすべての古いバージョンを削除したくなりますが、そうする必要はないと思います。

ここで何が起こっているのか、または私が目立って間違っていることをしているのか誰か知っていますか?

以下は、私のpuma構成でpuma_worker_killerを使用するために使用するコードです。

before_fork do
  require 'puma_worker_killer'

  PumaWorkerKiller.config do |config|
    config.ram           = 1024 # mb
    config.frequency     = 5 # seconds
    config.percent_usage = 0.98
    config.rolling_restart_frequency = 12 * 3600 # 12 hours in seconds
  end

  PumaWorkerKiller.start
end

1
私は通常、プロジェクトごとに環境をDocker内に設定するので、セットアップが互いに干渉することはありません。ホストマシンからDockerインスタンスにディレクトリをマウントすることもそれほど難しくありませんが、イメージの維持は少し難しい場合があります。その場合、私は通常、新しいdockerをセットアップし、ホストディレクトリから再度マウントしてやり直します。
darkash

Gemfile.lockファイルを削除してから、bundle installを再度実行する価値があります。指定されていないすべてのバージョン番号が削除され、互いに互換性のあるgemのセットが作成され、エラーが発生し、クラッシュが説明されます。それが不可能な場合
マーク

@darkashええDockerはこれを行うのに理想的な方法です。これは、将来の改善のためのパイプラインでだが、私はちょうど私が同じサーバ上でお互いにうまく動作するすべてのウェブサイトを得ることができるので、この即時の問題を克服しようとしている
アラン・スコット

1
@Markええ、私もそれができることを知っていますがbundle update puma_worker_killer、サーバーにインストールされている最新バージョンのpuma_worker_killerを使用するだけなので、それは実行に似ているだけではありません
Arran Scott

回答:


1

ここで起こっているのは、基本的にシステムにいくつかのバージョンのgemがあることです。

bundle execアプリケーションに必要なバージョンを動的にロードするため、ほとんどの場合、問題は発生しませんでした。

場合によっては、gemにバイナリファイルが含まれます。bundle exec一度にリンクできるバージョンは1つだけなので、このような場合は役に立ちません。

基本的に、エイリアスでバイナリを呼び出す場合は、アプリケーションごとに個別のgemsetを使用する必要があります。

すべての宝石を1か所に保管したい場合は、バイナリファイルを直接呼び出すことができます。

あなたの場合それは次のようになります:

RAILS_ENV=dev3 bundle exec pumactl _0.1.0_ -F ./config/puma.rb

_<version>_建設はあなたが実行したいバイナリファイルのバージョンを指定することができます。

fake_pumactlをチェックGemfile.lockしてライブラリへの呼び出しを自動的にプロキシし、バージョンを自動的に指定するプロジェクト内のように、カスタムバイナリを作成することもできます。もう1つの方法は、シェルスクリプトでgemバージョンを解析し、このスクリプトを_<version>_呼び出しの代わりに配置することです。

ここに簡単な例があります

$ gem install puma
Fetching puma-4.3.3.gem

$ gem install puma -v 4.3.0
Fetching puma-4.3.0.gem

$ pumactl -v
4.3.3

$ pumactl _4.3.0_ -v
4.3.0

$ ruby -v
ruby 2.6.3p62

$ export puma_version=_4.3.0_
$ pumactl ${puma_version} -v
4.3.0

puma_version変数は、gemバージョンをから抽出するbashコマンドの結果から定義できますGemfile.lock


ご回答有難うございます。別のGemsetを作成する道を進むことができることはわかっていますが、実際にはそれを実行したくありませんでした。バージョンで特定のバイナリファイルを指定する方法について説明しました。しかし、私はそれを試してみましたが、うまくいかないようです。この特定のアプリでは、Gemfileで指定されたバージョンとしてPuma 3.7.0を使用していますが、4.1.0もインストールしています。次のコマンドを実行します。 RAILS_ENV=dev3 bundle exec pumactl _4.1.0_ -F ./config/puma.rb start代わりに、4.1.0ではなく3.7.0を起動します(Version 3.7.0 (ruby 2.5.3-p105), codename: Snowy Sagebrush
Arran Scott

これをどのように行うかについても説明していただけますか? You can create your custom binary as well, like fake_pumactl inside the project which will check the Gemfile.lock and automatically proxy your call to the library and specify version automatically for you.
アランスコット

私は答えを拡張しました
achempion

ありがとう。奇妙なことに、これは私がRailsプロジェクトのルートの外にいるときに機能しますが、dirsの1つにcdすると機能しません... ➜ app_root git:(develop) ✗ gem install puma -v 3.12.0 Building native extensions. This could take a while... Successfully installed puma-3.12.0 Done installing documentation for puma after 1 seconds 1 gem installed ➜ app_root git:(develop) ✗ pumactl _3.12.0_ -v 3.7.0 理由を理解する必要がありますが、実際に私の質問に答えましたありがとうございます。回答済みとしてマークします
Arran Scott

あなたは置き換えることができpumactl ${puma_version} -v${pumactl_path} -vも、プロジェクトディレクトリ内で動作するはずpumactl_pathバイナリ内部の宝石forlderへのパスとして定義されます。多分Gemfile.lockそれは古いバージョンが含まれているため、コマンドの結果に影響を与えます。
achempion
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.