我们发现了一个有趣的问题。我们的环境是通过使用ansible配置的,而ansible又会安装gem。
一些gem,我们希望版本比什么都新。例如,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.rb的shell中,您将得到:
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,但是我们也希望安装新的版本),虽然竞争条件的窗口很小,但是有成千上万的服务器,并且cronjob每5分钟运行一次,(ansible每4小时运行一次),我们每天都会收到~打邮件,cronjob失败。
2条答案
按热度按时间a6b3iqyw1#
也许不是答案,但仍然...:)我认为没有比以某种方式同步任务更好的方法了。
Rubygems安装程序似乎在安装新的之前删除了现有的gem文件(如果要安装的版本存在的话,我猜)。
这很容易确认。例如,安装了两个
pry
版本-- 0.14.0和0.14 1 --我执行以下操作:1.运行
while true; do gem install --no-document -f -v '0.14.1' pry; done
1.在另一个shell中运行
while true; do gem which pry; done
2的结果如下所示:
正如人们所期望的那样--各种各样的意外(从将gem解析为以前的版本到由于我们在中间的不完整状态中捕获gem安装过程而发生的几个异常)。
除了你提到的重试之外,还可以这样做:
Gem
API从cron作业检查gem状态,如果所需的gem不存在,则关闭LoadError
并正常关闭dhxwm5r42#
在与其他人交谈时,我们想出了一个解决方案。似乎增加了这两个选项:
--conservative --minimal-deps
到gem安装解决了这个问题。