Category Archives: Ruby

Compiling Ruby from source and building an RPM from it using FPM

We all love Ruby here at Squirrel5. We love everything about it … except installing it.

What’s the big deal with installing Ruby you’ll ask? Well, let’s start from the top.

If you are using CentOS for pretty much everything like we do, you probably know that the most recent version of Ruby you
can find in the repositories is 1.8.7.374 for CentOS 6.x.

Things are better with CentOS 7.x as you can get Ruby 2.0.0.598 directly from the repositories.

Ruby 2.0.0 is probably good enough for most cases, but 1.8.7 is not. How do we go about installing a newer version of Ruby on CentOS 6.x then?

There’s a few ways to install a more modern version of Ruby – you can use RVM, Rbenv, or even the RedHat Software Collections.

Our preferred way is to compile Ruby from source once and then make an RPM package out of it.

Just like installing Ruby, there’s more than one ways to build an RPM package. We like using FPM to create a Ruby RPM, which of course requires Ruby, so we have a chicken and egg situation going.

For this guide we fired up a test VPS using Atlantic.net – we recommend using a VPS/server with at least 2 CPU cores so that the compiling goes much faster.

1. Install Ruby 1.9.3 or newer so that FPM can work – I’m going to use RVM to install it:

gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
curl -sSL https://get.rvm.io | bash -s stable --ruby
source /usr/local/rvm/scripts/rvm

2. Check what version of Ruby did RVM install:

rvm list 

rvm rubies

=* ruby-2.3.0 [ x86_64 ]

# => - current
# =* - current && default
#  * - default

3. Also check by asking Ruby itself:

ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]

4. Let’s install some other dependencies so we don’t run into trouble later:

yum groupinstall Development tools -y
yum -y install openssl-devel libffi-devel readline-devel gdbm-devel libyaml-devel tcl-devel tk-devel

5. All good – now let’s install the FPM gem:

gem install fpm --no-ri --no-rdoc

6. Now visit https://www.ruby-lang.org/en/downloads/ and get the source of Ruby that you like – in our case we’re going to download Ruby 2.3.1:

cd /tmp
wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz

7. Untar it:

tar -xzf ruby-2.3.1.tar.gz

8. Enter the directory of the source code:

cd ruby-2.3.1

9. Now let’s configure Ruby:

./configure --prefix=/usr

Note the –prefix=/usr — this means that the compiled ruby will expect to live under /usr (which is the standard Ruby location)

This one should only take a couple of minutes.

10. Compile Ruby:

time make -j2

In the above command, replace the -j2 with the number of cores your system has – in our case, we got 2:

The above took just under 4 minutes on our test server.

11. Now the tricky part – we’re going to install the version of Ruby we just compiled in a different directory, so that we can package it up with ease:

make install DESTDIR=/ruby-compiled-from-source

12. Test that the install worked:

/ruby-compiled-from-source/usr/bin/ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]

Important note: although Ruby seems to be working, if you try to do any actual work you might get a dependency warning. This is because we have compiled ruby by telling it to live under /usr but thrn we installed it under /ruby-compiled-from-source 🙂

13. Package it up with FPM:

cd /ruby-compiled-from-source/usr/
fpm --verbose -v 2.3.1 -n ruby-squirrel5 -d 'libyaml' -s dir -t rpm .=/usr

What the above command does is:

  • It will create an RPM type package from the files in the current directory (/ruby-compiled-from-source/usr)
  • It will set the package version to 2.3.1
  • It will set the RPM name to ruby-squirrel5 and append the version – so you’ll get ruby-squirrel5-2.3.1-1.x86_64.rpm
  • It will set the package ‘libyaml’ as an RPM dependency

When this is done you should see output like this:

Wrote: /tmp/package-rpm-build20160816-9601-1dz4ld2/RPMS/x86_64/ruby-squirrel5-2.3.1-1.x86_64.rpm {:level=>:info}
Executing(%clean): /bin/sh -e /tmp/rpm-tmp.Ybvumo {:level=>:info}
Created package {:path=>"ruby-squirrel5-2.3.1-1.x86_64.rpm"}

14. Now let’s uninstall the previous versions of Ruby and install the new one:

rvm remove ruby-2.3.0
rvm implode #this will remove RVM!

15. Now install the new one:

yum install /ruby-compiled-from-source/usr/ruby-squirrel5-2.3.1-1.x86_64.rpm

16. Test it:

[root@rubytest usr]# ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
[root@rubytest usr]# which ruby
/usr/bin/ruby

So now you can create a yum repository and distribute the Ruby RPM to servers through yum or any other way you like!

Sources:

Sending notifications to Jabber through Ruby – a simple example

Hello Squirrels,

We were recently investigating possible solutions to notify our team members when an alert from our monitoring system comes in.

Most of our team was already using Skype so that seemed like the most natural solution. Unfortunately it turns out, that the most “robust” way of sending messages programmatically to Skype in 2016 is via Sevabot but it requires quite an indirect approach to send those messages. We ended up not even testing this solution as having a dependency to software that requires a graphical environment running seems like overkill for us.

We then looked into using Jabber. A disadvantage with Jabber is of course that we’d need to setup our own Jabber server and maintain it, but this turned out to be trivial in comparison to making Skype work for us (We’ll discuss the Jabber setup in a future post).

The next problem was actually sending the messages. We sure found a lot of ready scripts out there claiming of being able to do the job, but once we tested them they simply would not work.

This prompted us to write our own script to get this done using Ruby. The script uses the xmpp4r gem to interface with Jabber.

Here’s what the script looks like:

#!/bin/env ruby
# Install the gem with:
# gem install xmpp4r --no-ri --no-rdoc

require 'timeout'
require 'xmpp4r'
include Jabber

Timeout::timeout(3) {
 username="username@your-server.com"
 password = "the_supa_password"
 message = (STDIN.read).strip
 destination = ARGV[0]
 Jabber::debug = true

 client = Client.new(JID::new(username))
 client.connect
 client.auth(password)

 msg = Message::new(destination, message)
 msg.type=:chat
 client.send(msg)
}

The above will send a notification from “username@your-server.com” to whoever you specify on the terminal. Example:

echo "hey did you see those squirrels across the street?!?" | /usr/local/bin/jabber_send.rb somebody@some-server.com

The above example will send the message “hey did you see those squirrels across the street?!?” to the user somebody@some-server.com.

Voila!

Sources: