I just got my Pickaxe v2 book in the mail today and have already put it to good use writing a script to check that the services for a host are up and responding. It uses many of the libraries included with Ruby but also another library ‘net-ping’ which you can get with a gem install net-ping
. To use it all you have to do is to call the script with one to four parameers:
- First is the host you want to check, i.e. theadmin.org
- Second is the username to login to for FTP, i.e. user-bob (this will default to guest is not defined)
- Third is the password to login to for FTP, i.e. bobpassword (this will default to guest is not defined)
- Fourth is where to place the logfile, i.e. /home/bob/server.log (this will default to /tmp/server_up.log)
Here is a link to the code, and here is it for viewing:
#!/usr/bin/env ruby # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Program to check that certin services are running on a host # # Copyright (c) 2006 Eric Davis # Released under the MIT License # Details: http://dropbox.www.freelancingdigest.com/bin/server_up/LICENSE.txt # # Last Revision: [2006/04/27] # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # require 'rubygems' require 'net/ping' require 'net/http' require 'net/smtp' require 'net/ftp' require 'time' def log_error(error) File.open(@log_file, 'a') do |log| log.puts Time.now.rfc2822.to_s + ": " + error end end def check_ping(host) if not Net::PingExternal.new(host).ping log_error("Error: #{host} is not responding to a ping") end end def check_mail(host, port=25, ehlo=host) begin Net::SMTP.start(host, port, ehlo) do |smtp| log_error("Mail Server down") unless smtp.started? end rescue SocketError => socket_error log_error("Error Connecting To SMTP: #{socket_error}") rescue TimeoutError => timeout_error log_error("SMTP connection timed out: #{timeout_error}") end end def check_web(host, file='/') begin Net::HTTP.start(host) do |http| response = http.get(file) if not response.code.match(/200/) log_error("Web Server down or not resonding: #{response.code} #{response.message}") end end rescue SocketError => socket_error log_error("Error Connecting To Web: #{socket_error}") rescue TimeoutError => timeout_error log_error("Web connection timed out: #{timeout_error}") end end def check_ftp(host, login, password) begin Net::FTP.open(host) do |ftp| log_error("FTP Server down or not responding #{ftp.last_response_code}") unless ftp.last_response_code.match(/220/) if password.empty? ftp.login(login) else ftp.login(login, password) end end rescue Net::FTPPermError => login_error log_error("FTP Server not allowing logins for '#{login}' using '#{password}': #{login_error}") rescue SocketError => socket_error log_error("Error Connecting To FTP: #{socket_error}") rescue TimeoutError => timeout_error log_error("FTP connection timed out: #{timeout_error}") end end ftp_user = ARGV[1] || 'guest' ftp_password = ARGV[2] || 'guest' @log_file = ARGV[3] || '/tmp/server_up.log' check_ping(ARGV[0]) check_mail(ARGV[0]) check_web(ARGV[0]) check_ftp(ARGV[0], ftp_user, ftp_password)
Eric Davis
Aieee! It’s pretty clear you’re just starting Ruby–you’ve ignored one of its most powerful features (blocks), and duplicated a ton of code in the process.
Instead of having a ton of places where you rescue Socket/Timeout errors and present a generic message, do something like this:
This is just a rough idea, but I’m sure you get the picture.
Seems that my pretty Ruby formatting was trashed : Ah well, copy/paste it into a text editor and you should be able to recreate it in its original form. Let me know if you end up implementing my suggestion–it would be interesting to hear about.
Yep, Ruby is still new to me (this is one of the larger scripts I have written that is actually useful). That definitely makes cleaner, I will have to try it out. I also planned to add some unit tests to it also.
(I also adjusted your formatting so it should come out correct now)