Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I copy STDOUT to a file without stopping it showing onscreen using Ruby

Tags:

ruby

I'm attempting to copy stdout to a file for logging purposes. I also want it to display in the Ruby console of the IDE I'm using.

I inserted this code into my script and it redirects $stdout to the my.log file:

$stdout.reopen("my.log", "w")

Does anyone know of a gem or technique to copy the contents of $stdout to a file and not redirect it to a file? Also, I am not using Rails just Ruby.

like image 963
Conner Avatar asked Feb 24 '12 16:02

Conner


People also ask

How to fix a hard to read stdout in Linux?

A good solution is saving the hard-to-read stdout into a separate file and checking that file. Based on different use scenarios, there are 3 different requirements: Record all input and output of the terminal and save it to a file This article will introduce 3 methods for the above 3 tasks. 1. Angle brackets: Save Standard Output (stdout) to a File

How to redirect stdout to a file in Linux?

If stderr is redirected to stdout first, use the below-given command to redirect the stdout to a file. “&>” is also used for the same functionality which“2>&1” performs. All of the shells do not support this form redirection, but bash and Zsh support it. Stdout and stderr can be redirected by utilizing the following syntax.

How do I copy or redirect command prompt output to a file?

This post explains how to copy or redirect Command Prompt output to a file or the clipboard. To open a Command Prompt window, press WinKey + R to launch the Run dialog. Type in cmd.exe and press Ok. In Windows 8.1 and Windows 10, you can right-click Start and click Command Prompt. There are several other ways to open Command Prompt.

How do I copy console output to the clipboard?

This tool copies the data redirected or passed to it, into the clipboard. You can redirect the output of your console tool or command to the clipboard using the built-in Clip.exe tool by piping the output. The command you’d run is: That would copy the output of the systeminfo command to the Windows Clipboard.


1 Answers

Something like this might help you:

class TeeIO < IO
  
  def initialize orig, file
    @orig = orig
    @file = file
  end
  
  def write string
    @file.write string
    @orig.write string
  end
  
end

Most of the methods in IO that do output ultimately use write, so you only have to override this one method. You can use it like this:

#setup
tee = TeeIO.new $stdout, File.new('out.txt', 'w')
$stdout = tee

# Now lots of example uses:
puts "Hello"
$stdout.puts "Extending IO allows us to expicitly use $stdout"
print "heres", :an, :example, "using", 'print', "\n"
48.upto(57) do |i|
  putc i
end
putc 10 #newline
printf "%s works as well - %d\n", "printf", 42
$stdout.write "Goodbye\n"

After this example, the following is written identically to both the console and to the file:

Hello
Extending IO allows us to expicitly use $stdout
heresanexampleusingprint
0123456789
printf works as well - 42
Goodbye

I won't claim this technique is fail proof, but it should work for simple uses of stdout. Test it for your use.

Note that you don't have to use reopen on $stdout unless you want to redirect output from a child process or an uncooperative extension. Simply assigning a different IO object to it will work for most uses.


RSpec

The RSpec command line takes a reference to $stdout before you can get any code to run to reassign it, so this doesn't work. reopen still works in this case as you're changing the actual object pointed to by both $stdout and the reference that RSpec has, but this doesn't give you output to both.

One solution is to monkey-patch $stdout like this:

$out_file = File.new('out.txt', 'w')

def $stdout.write string
  $out_file.write string
  super
end

This works, but as with all monkey patching, be careful. It would be safer to use your OS's tee command.

like image 102
matt Avatar answered Oct 25 '22 04:10

matt