tags:

views:

106

answers:

3

Having problems with a Ruby script that uses File.Open

Here is the code that I am speaking of...

f = File.open(Socket.gethostname().gsub!(/[[:space:].]/,"")+".log","a")

The issue is the + inside of .open, it is returning a error message saying its a undefined method.

Anyone able to help?

Edit: Here is some code from the class which is causing the problem.

Not sure if this will help though.

def logExecution()
  f = File.open(Socket.gethostname().gsub!(/[[:space:].]/,"")+".log","a")
  f.puts(" [" + Time.new().to_s() + "] " +\
         File.basename($0) + " " + $*.join(" "))
  f.close
end
+3  A: 

What is the error message you're getting: NoMethodError: undefined method +' for nil:NilClass` ?

If yes, then Socket.gethostname().gsub!(/[[:space:].]/,"") is returning nil

How do you create your Socket ? You could try with a fully qualified domain name, i.e. "myhost.mydomain.com" instead of "myhost".

What name should your log file have ?

philippe
Am guessing this mean its something to do with the way am trying to run the application?
Aran
Could be, or an issue in the application code. Can you come with more details, perhaps more code ?
philippe
+1  A: 

First of all, there's no really compelling reason to strip dots from hostnames. "www.example.com.log" is a better filename than "wwwexamplecom.log". So my recommendation would be to use this:

def log_execution
  hostname = (Socket.gethostname() || "localhost")
  File.open(hostname + ".log", "a") do |f|
    f.puts(
      " [" + Time.new.to_s + "] " +
      File.basename($0) + " " + $*.join(" ")
    )
  end
end

But if you really must, then use this:

def log_execution
  hostname = (Socket.gethostname() || "localhost")
  File.open(hostname.gsub(".", "") + ".log", "a") do |f|
    f.puts(
      " [" + Time.new.to_s + "] " +
      File.basename($0) + " " + $*.join(" ")
    )
  end
end

Essentially, this block of code just logs the name of the command being run and the command line arguments used to invoke it. Also note, I renamed and reformatted the method to use standard Ruby coding style. The original was really awful.

Bob Aman
A: 

There is more than the ruby code style that you can improve:

  • use gethostbyname, and rescue to a default
  • open the file using a block, ensures that if something throws, the file is closed

The result would be:

require 'socket'

def log_execution()
  logname = Socket.gethostbyname(Socket.gethostname).first rescue "localhost"
  File.open("#{logname}.log", 'a') do |f|
    f.puts(" [" + Time.new().to_s() + "] " + File.basename($0) + " " + $*.join(" "))
  end
end

And then you can improve further, by not reinventing the stdlib:

require 'socket'
require 'logger'

# do only once in your program
logname = Socket.gethostbyname(Socket.gethostname).first rescue "localhost"
log = Logger.new(logname)
log.level = Logger::WARN

Then just log using the standard api:

log.info("hello!")
log.warn("message!")

If you don't like the format which looks like:

W, [2009-12-05T03:05:48.764552 #22759]  WARN -- : message!

You can use log4r, which is api compatible but has more options...

duncan