Wie behebe ich ein Problem mit einem Bundler, der die neueste Version von gem benötigt, wenn ich eine andere Version benötige?

8

Ich kratzte mir seit fast 2 Wochen am Kopf. Ich habe einen Ubuntu 14.04-Server mit rbenv installiert, auf dem verschiedene Rails-Websites ausgeführt werden, einige davon auf älteren Versionen von Rails, einige auf der neuesten Version.

Ich habe insbesondere 2 Websites, für die beide eine andere Version von puma_worker_killer benötigen, für eine Version 0.1.0 und für die andere Version 0.1.1. Beide Websites verwenden Ruby 2.5.3.

Wenn ich den Server mit RAILS_ENV=dev3 bundle exec pumactl -F ./config/puma.rb startstarte, wird in den Protokollen der folgende Fehler angezeigt und die Website hängt:

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)

Zuerst dachte ich, dass es ein Problem mit rbenv gewesen sein könnte, da ich die Edelsteine ​​in ~ / .gem anstatt in ~ / .rbenv installiert hatte, also habe ich alle Rubine in ~ / .gem zerstört und sie frisch in die richtige installiert rbenv Ordner mit bundle installund ich bekomme immer noch das gleiche Problem.

An dieser Stelle möchte ich klarstellen, dass ich online umfangreiche Recherchen zu diesem Thema durchgeführt habe und weiß, dass ich viele Dinge tun kann, um dies zu lösen.

Ich weiß, ich kann einfach die Version ändern und bundle update puma_worker_killer.

Ich weiß auch, dass ich die neueste Version entfernen kann, indem ich gem uninstall puma_worker_killer0.1.1 auswähle, aber dies würde bedeuten, dass die Abhängigkeiten von der anderen Website nicht erfüllt werden.

Ich habe mich ein wenig mit dem Quellcode von Bundler befasst und kann feststellen, dass dies durch die folgende Codezeile verursacht wird:

return if activated_spec.version == spec.version

Wenn Sie im Kontext des Bundlers bundle execsowohl mit als auch activated_specmit specmatch ausführen, bedeutet dies, dass der folgende Code in dieser Methode ( check_for_activated_spec!) nicht ausgeführt wird. Wenn Sie den obigen Befehl activated_specausführen , um den Server zu starten, ist (das aktivierte Gem) aus irgendeinem Grund die neueste Version (0.1.1) und nicht die in der Gemfile (0.1.0) aufgeführte, was bedeutet, dass es nicht zurückkehrt und wirft der Fehler oben.

Ich sollte auch erwähnen, dass es anscheinend auch das gleiche Problem mit get_process_mem gibt, das eine der Abhängigkeiten von puma_worker_killer ist. Es beschwert sich über die Aktivierung von 0.2.5, aber mein Gemfile möchte 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)

Nach meinem Verständnis von Bundler sollte es die in der Gemfile aufgeführte Version laden, wenn es verwendet wird bundle exec, um genau diesem Problem entgegenzuwirken, dass mehrere Versionen desselben Gems vorhanden sind.

Ich weiß, dass ich auch ein separates Gemset erstellen könnte (was anscheinend mit rbenv möglich ist), das verschiedene Versionen von puma_worker_killer enthält und dann innerhalb des Projekts ausgeführt wird rbenv local 2.5.3-pwk0.1.0oder rbenv local 2.5.3-pwk0.1.1je nach gewünschter Version ausgeführt wird, aber das scheint übertrieben für das, was ich möchte leisten.

Bei dieser Geschwindigkeit bin ich versucht, einfach alle Websites mit der neuesten Version von puma_worker_killer und get_process_mem zu aktualisieren und sie dann zu sperren und alle älteren Versionen auf dem Server zu entfernen, aber ich denke nicht, dass ich das tun muss.

Weiß jemand, was hier passiert oder ob ich etwas krass Falsches mache?

Unten ist der Code, mit dem ich puma_worker_killer in meiner puma-Konfiguration verwende.

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
Arran Scott
quelle
1
Normalerweise stelle ich meine Umgebung für jedes Projekt im Docker ein, damit sich das Setup nicht gegenseitig stört. Es ist auch nicht so schwer, ein Verzeichnis vom Host-Computer in die Docker-Instanz zu mounten, obwohl das Verwalten des Images manchmal etwas schwierig sein kann. In diesem Fall richte ich normalerweise ein neues Docker ein und mounte erneut aus dem Host-Verzeichnis, um von vorne zu beginnen.
Darkash
Es lohnt sich, Ihre Gemfile.lock-Datei zu löschen und dann die Bundle-Installation erneut auszuführen. Dadurch werden alle nicht angegebenen Versionsnummern entfernt und versucht, eine Reihe von Gems zu erstellen, die alle miteinander kompatibel sind. Dabei wird ein Fehler ausgegeben und die Konflikte erklärt wenn es nicht möglich ist
Mark
@darkash yeah docker wäre der ideale weg dazu. Das ist in der Pipeline für zukünftige Verbesserungen, aber ich versuche nur, dieses unmittelbare Problem zu überwinden, damit ich alle Websites dazu bringen kann, sich auf demselben Server gut miteinander zu verhalten
Arran Scott
1
@ Mark ja, ich weiß, dass ich das auch tun könnte, aber das ist nur ähnlich wie beim Laufen, bundle update puma_worker_killernicht wahr, da es nur die neueste Version von puma_worker_killer verwendet, die auf dem Server installiert ist
Arran Scott

Antworten:

1

Was hier passiert, ist, dass Sie im Grunde mehrere Versionen des Edelsteins in Ihrem System haben.

Meistens verursachte es keine Probleme, da bundle execdie erforderlichen Versionen für Ihre Anwendung dynamisch geladen werden.

In einigen Fällen enthalten Edelsteine ​​Binärdateien. Ein solcher Fall bundle exechilft nicht, da Sie nur eine Version in einem Moment verknüpfen können.

Wenn Sie die Binärdatei als Alias ​​aufrufen möchten, müssen Sie grundsätzlich für jede Anwendung ein separates Gemset verwenden.

Wenn Sie alle Edelsteine ​​an einem Ort aufbewahren möchten, können Sie Binärdateien direkt aufrufen.

In Ihrem Fall wird es sein:

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

Mit der _<version>_Konstruktion können Sie die Version der Binärdatei angeben, die Sie ausführen möchten.

Sie können auch Ihre benutzerdefinierte Binärdatei erstellen, z. B. fake_pumactlinnerhalb des Projekts. Dadurch wird der Gemfile.lockAufruf der Bibliothek überprüft und automatisch weitergeleitet, und die Version wird automatisch für Sie angegeben. Eine andere Möglichkeit besteht darin, die Gem-Version nach Shell-Skript zu analysieren und dieses Skript anstelle _<version>_Ihres Aufrufs einzufügen.

Hier ist das kurze Beispiel

$ 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_versionDie Variable kann aus dem Ergebnis eines Bash-Befehls definiert werden, aus dem die Gem-Version extrahiert wird Gemfile.lock.

Achempion
quelle
Danke für deine Antwort. Ich weiß, dass ich den Weg gehen könnte, ein separates Gemset zu erstellen, aber das wollte ich eigentlich nicht. Ich mag die Art und Weise, wie Sie erwähnt haben, eine bestimmte Binärdatei mit der Version anzugeben. Ich habe es jedoch gerade versucht und es scheint nicht zu funktionieren. Auf dieser einen speziellen App habe ich Puma 3.7.0 als die in Gemfile angegebene Version, aber auch 4.1.0 installiert. Ich führe den folgenden Befehl aus: RAILS_ENV=dev3 bundle exec pumactl _4.1.0_ -F ./config/puma.rb startund es startet stattdessen 3.7.0 und nicht 4.1.0 ( Version 3.7.0 (ruby 2.5.3-p105), codename: Snowy Sagebrush)
Arran Scott
Können Sie mir bitte auch erklären, wie Sie das machen würden? 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.
Arran Scott
Ich habe die Antwort erweitert
Achempion
Vielen Dank. Seltsamerweise funktioniert dies, wenn ich mich außerhalb der Wurzel eines Rails-Projekts befinde, aber wenn ich dann in eines der Verzeichnisse cd, funktioniert es nicht ... ➜ 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 Ich muss herausfinden, warum das so ist, aber Sie haben meine Frage tatsächlich beantwortet. Also danke und ich werde es als beantwortet markieren
Arran Scott
Sie könnten ersetzen pumactl ${puma_version} -vmit ${pumactl_path} -vals auch, sollte in Projektverzeichnis arbeiten , wo pumactl_pathwird in einem binären innerhalb gem forlder als Pfad definiert werden. Gemfile.lockBeeinflussen Sie möglicherweise das Ergebnis Ihres Befehls, da dieser eine ältere Version enthält.
Achempion