Official website for Linux User & Developer
FOLLOW US ON:
Jul
19

Ruby development for system administrators

by Koen Vervloesem

Koen Vervloesem doesn’t like shell scripts that are difficult to maintain, therefore he uses Ruby for his sysadmin tasks. Do the same with his four-page guide…

In our previous scripts, we already used the method File.open to read a file. We can also create a new file and write text to it:

file = File.new(“temp.txt”, “w”)
file.puts(“foobar”)
file.close

We can also do a lot with file metadata:

puts File.open(“temp.txt”).atime
File.open(“temp.txt”).chmod(0600)
File.open(“temp.txt”).chown(1000, 1000)

But most of the interesting methods are class methods, which take the filename as an argument…

File.dirname(“/home/koan/temp.txt”)
File.basename(“/home/koan/temp.txt”)
File.size(“/home/koan/temp.txt”)
File.delete(“/home/koan/temp.txt”)
File.exists?(“/home/koan/temp.txt”)
File.directory?(“/home/koan/temp.txt”)
File.executable?(“/home/koan/temp.txt”)

There’s also a Dir class for directories, a module FileUtils for copying, moving, removing files and so on, and a module Find to make it easier to recursively search for files under a directory. We’ll illustrate this in a script that searches for backup files (*~) in a directory (recursively) and zips them for archival. The original files can then be deleted safely, but we leave this as an exercise to the reader.

#!/usr/bin/env ruby
require ‘rubygems’
gem ‘rubyzip’
require ‘find’
require ‘zip/zip’

directory = ARGV[0]
pattern = “*~”
Zip::ZipFile.open(“backup.zip”, Zip::ZipFile::CREATE) do |zipfile|
   Find.find(directory) do |path|
      filename = File.basename(path)
      if File.directory?(path)
         if filename == ‘.’ or filename == ‘..’
            Find.prune
         end
      else
         if File.fnmatch(pattern, filename)
            puts path
            zipfile.add(path.sub(directory, “”), path)
         end
      end
   end
end

Here we see another way to install a non-standard Ruby library: using Ruby gems, the programming language’s own package manager. The directory that we want to search in is the first argument to the script, and the search pattern is ‘*~’. Then we create a zip file and start searching in the directory with the Find.find method.

This will iterate through each file recursively. If the file is ‘.’ (the current directory) or ‘..’ (the parent directory), we don’t look any further into this directory. If it’s another directory we don’t do anything with the directory itself, which means that next it’s the turn of the files in this directory. In the other case (the current file is a regular file), the filename is matched to the pattern – if it matches, the file is added to the zip file, with its relative path to the directory we searched in as the zip index.

Advanced usage
Of course, Ruby is not the holy grail for sysadmins. There are a lot of cases where Perl or even shell scripts are better. For example, the number of Ruby libraries can’t beat the breadth of Perl modules in CPAN. So if your task requires such functionality, it’s probably better to use Perl. However, Ruby catches on quickly, and recently some powerful system administration tools have been written in Ruby, such as the configuration management tool Puppet, which we’ll talk about in another article.

The examples we have shown are of course rather basic, but you get the picture. If you want to do some serious sysadmin tasks in Ruby scripts, you have to take care of error handling and a robust command-line interface instead of just using ARGV[0]. The GetoptLong module can parse the command’s arguments and options in a structured way.
When your Ruby sysadmin scripts begin to grow in complexity, it’s also a good idea to restructure them as Rake tasks. Rake originated as a simple Ruby build program with capabilities similar to the UNIX make command, but it’s also very usable to do deployment tasks or migrate database schemas.

Click here to see what else was in issue 89 of Linux User & Developer…

twitter follow us
Pages: 1 2 3 4
  • Tell a Friend
  • Follow our Twitter to find out about all the latest Linux news, reviews, previews, interviews, features and a whole more.

    5 Comments »

    • Dummy00001 said:

      The guide is quite informative.

      But since your site engine does not support proper code formatting, examples require tweaking before use.

      Or Ruby’s really capable of interpreting the WinWord-style single quotes – “require ‘csv’”?

    • Ruben Espadas said:

      Nice introduction, the said “when men were men….” is forgotten, but the tools help more than “prestige”. Thanks for this article.

    • Matthew Closson said:

      @Dummy00001 Ruby can use single or double quoted strings. Double quoted strings give you some extra functionality when it comes to string interpolation but it is a fairly standard Ruby practice to use single quoted otherwise.

    Trackbacks

    What's your opinion?

    Add your comment below, or trackback from your own site. You can also subscribe to these comments via RSS.

    Be nice. Keep it clean. Stay on topic. No spam.

    * Required fields