25

I want to be able to read a currently open file. The test.rb is sending its output to test.log which I want to be able to read and ultimately send via email.

I am running this using cron:

*/5 * * * /tmp/test.rb > /tmp/log/test.log 2>&1 

I have something like this in test.rb:

#!/usr/bin/ruby def read_file(file_name) file = File.open(file_name, "r") data = file.read file.close return data end puts "Start" puts read_file("/tmp/log/test.log") puts "End" 

When I run this code, it only gives me this output:

Start End 

I would expect the output to be something like this:

Start Start (from the reading of the test.log since it should have the word start already) End 
2
  • 1
    I hate to say it, but there are a lot of things wrong with this whole application. Can you rephrase what you want to do? Reading an open file isn't what you are doing nor does it make a lot of sense, so explaining your goal carefully will probably help you understand the steps needed to get there. Commented Dec 18, 2010 at 8:51
  • My goal is to log the script (its output and any errors it occurs) and at the end of the script, I want it to send this log to me via email. Commented Dec 18, 2010 at 17:23

5 Answers 5

46

Ok, you're trying to do several things at once, and I suspect you didn't systematically test before moving from one step to the next.

First we're going to clean up your code:

def read_file(file_name) file = File.open(file_name, "r") data = file.read file.close return data end puts "Start" puts read_file("/tmp/log/test.log") puts "End" 

can be replaced with:

puts "Start" puts File.read("./test.log") puts "End" 

It's plain and simple; There's no need for a method or anything complicated... yet.

Note that for ease of testing I'm working with a file in the current directory. To put some content in it I'll simply do:

echo "foo" > ./test.log 

Running the test code gives me...

Greg:Desktop greg$ ruby test.rb Start foo End 

so I know the code is reading and printing correctly.

Now we can test what would go into the crontab, before we deal with its madness:

Greg:Desktop greg$ ruby test.rb > ./test.log Greg:Desktop greg$ 

Hmm. No output. Something is broken with that. We knew there was content in the file previously, so what happened?

Greg:Desktop greg$ cat ./test.log Start End 

Cat'ing the file shows it has the "Start" and "End" output of the code, but the part that should have been read and output is now missing.

What happening is that the shell truncated "test.log" just before it passed control to Ruby, which then opened and executed the code, which opened the now empty file to print it. In other words, you're asking the shell to truncate (empty) it just before you read it.

The fix is to read from a different file than you're going to write to, if you're trying to do something with the contents of it. If you're not trying to do something with its contents then there's no point in reading it with Ruby just to write it to a different file: We have cp and/or mv to do those things for us witout Ruby being involved. So, this makes more sense if we're going to do something with the contents:

ruby test.rb > ./test.log.out 

I'll reset the file contents using echo "foo" > ./test.log, and cat'ing it showed 'foo', so I'm ready to try the redirection test again:

Greg:Desktop greg$ ruby test.rb > ./test.log.out Greg:Desktop greg$ cat test.log.out Start foo End 

That time it worked. Trying it again has the same result, so I won't show the results here.

If you're going to email the file you could add that code at this point. Replacing the puts in the puts File.read('./test.log') line with an assignment to a variable will store the file's content:

contents = File.read('./test.log') 

Then you can use contents as the body of a email. (And, rather than use Ruby for all of this I'd probably do it using mail or mailx or pipe it directly to sendmail, using the command-line and shell, but that's your call.)

At this point things are in a good position to add the command to crontab, using the same command as used on the command-line. Because it's running in cron, and errors can happen that we'd want to know about, we'd add the 2>&1 redirect to capture STDERR also, just as you did before. Just remember that you can NOT write to the same file you're going to read from or you'll have an empty file to read.

That's enough to get your app working.

Sign up to request clarification or add additional context in comments.

Comments

20
class FileLineRead File.open("file_line_read.txt") do |file| file.each do |line| phone_number = line.gsub(/\n/,'') user = User.find_by_phone_number(line) user.destroy unless user.nil? end end end 
  1. open file
  2. read line
  3. DB Select
  4. DB Update

Comments

5

In the cron job you have already opened and cleared test.log (via redirection) before you have read it in the Ruby script.

Why not do both the read and write in Ruby?

1 Comment

Please be patient since I am really a newbie on this. But how can I do what you suggested on reading and writing it in Ruby?
5

It may be a permissions issue or the file may not exist.

f = File.open("test","r") puts f.read() f.close() 

The above will read the file test. If the file exists in the current directory

1 Comment

It's not a permissions issue or file existence problem. It's a problem with timing and the shell truncating the file immediately before reading it.
4

The problem is, as I can see, already solved by Slomojo. I'll only add:
to read and print a text file in Ruby, just:

puts File.read("/tmp/log/test.log") 

3 Comments

So, I tried this but I am still getting the same output. Is it because the output is sort of buffered so nothing is still in the log file when the file is being read?
@Carmen, I'm Windows adept, sorry, I don't know nothing about your cron )
@Carmen, there is no buffering involved. The cronjob fires off and the file is truncated by the OS when the STDOUT and STDERR redirections are set up, which occurs just before the OS starts your application.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.