【发布时间】:2022-11-02 21:57:35
【问题描述】:
我们发现了有趣的问题。我们的环境是使用 ansible 配置的,它反过来安装 gems。
一些宝石,我们想要比某些东西更新的版本。例如,aws-sdk-core 版本 >= 3.104。
这个ansible任务运行:
gem install -v '>= 3.104' aws-sdk-core
然后,我们有一个 cronjob,它每 5 分钟(但跨越几千台服务器)运行一个“需要 aws-sdk-core”的脚本。
而且,每隔一段时间,它就会中断:
/var/lib/gems/2.5.0/gems/aws-sdk-core-3.166.0/lib/seahorse.rb:3:in `require_relative': cannot load such file -- /var/lib/gems/2.5.0/gems/aws-sdk-core-3.166.0/lib/seahorse/util (LoadError)
...
我制作了一个简单的脚本,在另一个小得多的 gem 上显示了问题:
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'progressbar'
puts 1
如果你将它保存为 z.rb,然后在 shell 中运行:while true; do ./z.rb; done,然后在另一个 shell 中:while true; do gem install -v '>= 1.0.0' progressbar; done,最终(一两分钟后)你会在运行 z 的 shell 中得到。 RB:
1
1
<internal:/usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- progressbar (LoadError)
from <internal:/usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb>:85:in `require'
from ./z.rb:3:in `<main>'
1
1
1
除了开始/救援并在 1 秒睡眠后重试(我可以这样做,但它太丑了),有什么办法可以避免这个问题?
对我们来说,问题是我们需要至少安装某个特定版本(如果我们提供 version = SOMETHING,ansible 会完全避免调用 gem install,但我们也希望安装新版本),而比赛的窗口条件很小,有数千台服务器,并且每 5 分钟运行一次的 cronjob(ansible 每 4 小时运行一次),我们每天会收到大约十几封 cronjob 失败的邮件。
【问题讨论】:
标签: ruby rubygems race-condition