fpm fails under ruby 1.8.5 (missing Object#instance_variable_defined?) #214

jordansissel opened this Issue Apr 26, 2012 · 15 comments

7 participants


Looks like the backports gem doesn't define Object#instance_variable_defined?

The following is from ruby 1.8.5

# fpm
/usr/lib/ruby/gems/1.8/gems/clamp-0.3.1/lib/clamp/attribute_declaration.rb:15:in `input_type': undefined method `instance_variable_defined?' for #<FPM::Command:0xb7e77914> (NoMethodError)
        from /usr/lib/ruby/gems/1.8/gems/fpm-0.4.9/lib/fpm/command.rb:190:in `execute'
        from /usr/lib/ruby/gems/1.8/gems/clamp-0.3.1/lib/clamp/command.rb:64:in `run'
        from /usr/lib/ruby/gems/1.8/gems/cl amp-0.3.1/lib/clamp/command.rb:126:in `run'
        from /usr/lib/ruby/gems/1.8/gems/fpm-0.4.9/bin/fpm:8
        from /usr/bin/fpm:19:in `load'
        from /usr/bin/fpm:19

It might be fun to just sublcass Hash and use #key? instead.


well, I think this is in clamp, not fpm. Implementing the missing method should be easy.


I expected the backports gem to provide it, but it doesn't at this time. I"ll file a bug there separately :)

pjr commented Aug 8, 2012

Can't see the issue open in backports, would be great to get this working with 1.8.5 (standard in el5)


I don't have any centos5 systems at this time so I can't test any fix - I'll have a go getting vagrant up with centos 5.


I can't even install fpm on centos5/ruby1.8.5:

[vagrant@vagrant-centos-56-64 rubygems-1.3.5]$ sudo gem install fpm
*** buffer overflow detected ***: /usr/bin/ruby terminated

How do you even install this?

pjr commented Aug 9, 2012

Yeh, CentOS 5 is OLD as is ruby 1.8.5. I nearly forgot I fixed this bug. This is fixed upstream in el5, but awaiting next minor release before we'll actually see it. You basically need a patched version of ruby.


You need a monkeypatched shellwords.Shellwords

  def shellescape(str)
    str = str.to_s

    # An empty argument will be skipped, so return empty quotes.
    return "''" if str.empty?

    str = str.dup

    # Treat multibyte characters as is.  It is caller's responsibility
    # to encode the string in the right encoding for the shell
    # environment.
    str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1")

    # A LF cannot be escaped with a backslash because a backslash + LF
    # combo is regarded as line continuation and simply ignored.
    str.gsub!(/\n/, "'\n'")

    return str

  module_function :shellescape

  class << self
    alias escape shellescape

Then you need instance_variable_defined for clamp.

unless Object.respond_to?("instance_variable_defined?")
    class Object
        def instance_variable_defined?(meth)

Then fpm works.

$ sudo /usr/bin/fpm -s dir -t rpm -n "slashbin" -v 1.0 /bin /sbin
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.90047
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.90047
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.90047
Processing files: slashbin-1.0-1
Wrote: /tmp/package-rpm-build20120805-4842-12qmgu1/RPMS/i686/slashbin-1.0-1.i686.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.91598
Created rpm {"path":"slashbin-1.0-1.i686.rpm"}

@pjr I'm a Ruby newbie, how do I patch Ruby 1.8.6 with this shellwords.Shellwords method? I'm using CentOS 5.5.


Hey deserodio,
The monkey patch involves taking the method wholesale from the latest ruby source code, and dropping it into shellwords.rb in the Ruby installation directory.
You can see the method source needed here:
, and using the "Click to toggle source" option.
Copy and paste the source for that method alone into your local copy of shellwords.rb
You'll also need to add one single line after the method definition:

module_function :shellescape

, somewhere after the class definition you've just added for shellescape.


For what it's worth I found I had to carry out two additional hacks not mentioned here already to get FPM working for me on CentOS 5.8

FPM package.rb has to be patched with the same fix already applied to command.rb in clamp above for the "instance_variable_defined?" issue

JSON 1.6.6 has a dependency on some Ruby symbols not present in Ruby 1.8.5 (namely RSTRING_LEN), so I needed to do the following:
Add the following to ruby.h

#define RSTRING_PTR(s) (RSTRING(s)->ptr)
#define RSTRING_LEN(s) (RSTRING(s)->len)

,then run "gem uninstall json" and "gem install json" to ensure the native extensions are rebuilt with the new header information


Thanks @heavydawson I ended doing exactly this. In case anyone stuck with CentOS 5.5 needs to do the same, I've described the steps to intstall fpm on CentOS 5.5 here.


Neither am I a ruby programmer so it took me a while to figure out what and where exactly to patch to resolve the instance_variable_defined issue. So here it is for those with similarly limited ruby knowledge:

  1. Edit the file /usr/lib64/ruby/gems/1.8/gems/fpm-0.4.29/lib/fpm/command.rb (change the path implicitly)
  2. Paste the missing codepart before the line class FPM::Command < Clamp::command (above the comment if there is)
  3. The missing codepart to paste is:
unless Object.respond_to?("instance_variable_defined?")
    class Object
        def instance_variable_defined?(meth)

Good luck :)


I think my solution here is going to be to start providing fpm as a omnibussed package you can 'apt-get install' or whatever; like Vagrant or Chef is these days.

Trying to chase down bugs in ancient versions of Ruby isn't a good use for anyone's time, and doing omnibus packaging will solve this for good!


You can also upgrade to a non-broken version of Ruby 1.8; here's what I use on CentOS 5:

#!/bin/bash -ex

cd /tmp/build

# There are a bunch of things that are terribly broken in Ruby 1.8.5, which is
# what CentOS 5 ships with.  So, to get things working, we upgrade to 1.8.7,
# which is the latest in the 1.8 branch.  We don't want to go all the way to
# 1.9 because RightScale uses a lot of Ruby in their scripts, and that
# transition would be much more likely to break things.

wget --no-verbose 'ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p370.tar.gz'
tar zxf ruby-1.8.7-p370.tar.gz
cd ruby-1.8.7-p370
./configure --prefix=/usr --libdir=/usr/lib64 --without-X11
make install
cd ../

wget --no-verbose 'http://production.cf.rubygems.org/rubygems/rubygems-1.8.24.tgz'
tar zxf rubygems-1.8.24.tgz
cd rubygems-1.8.24
ruby setup.rb

Last time I tried to fix this on CentOS 5 / Ruby 1.8.5, Ruby kept segfaulting due to bugs. I don't think there's anything to do here given Ruby 1.8.5 crashes so much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment