Reputation: 311
Is there a way to pipe every output to a file, like monitoring the terminal to make a history of everything that is printed?
Also, when I use tee
it seems to stop the output of the actual program. How can I change this? I want to maintain the normal output and just use a copy of it to save in the file.
Just as an example, I have this ruby script:
100.times do |i|
puts i
end
And running $ruby script.rb | tee output.txt
will save the output just fine, but it will only be printed after the whole thing runs.
Upvotes: 3
Views: 753
Reputation: 513
If you're using bash (which you are according to your tags), you could run script -a -c "ruby your_script.rb" -f your_file.out
.
So, for example, if you wrote the following script, saved it as test.rb
:
# test.rb
i = 0
while true do
i += 1
puts i
sleep 1
end
And then ran script -a -c "ruby test.rb" -f test.out
, you'd be able to refresh the file every time and see that it is incrementing one by one each second, even though the script is in media res; that is, still running. This is because it is "flushing" every output.
DRAWBACKS: You can only do this using the script
command in bash. In this regard, you create a dependency; if script
is not there, or it does not work as the script
on my machine does, then this approach might not work at all. Always be wary of dependencies.
Sometimes, you might not be running your script on bash and script
may not be available. What then? Well, you can just create a method that prints to a file and then to the stdout, regardless of operating system. It will then flush the file every time to make sure it's up-to-date.
# print_to_file.rb
class PrintOutputToFile
def self.file
@@file ||= File.open("my_output.log", "w")
end
def self.puts! some_data
file.write "#{some_data}\n"
file.flush
puts some_data
end
end
i = 0
while true do
i += 1
PrintOutputToFile.puts! i
sleep 1
end
DRAWBACKS: This will clear the file every time you run it. You might need to modify this little script if you want to keep a long-term log that saves over many runs. Also, this script will crash outright if you do not have file permissions. This is not meant to be used for production, but merely as a proof-of-concept for those interested in implementing a system like this.
You can also do this by copying the old puts method into a proc, and then overriding the core puts method to write to the log file, but ending it with an invocation of the original puts method.
@@old_puts = method(:puts).to_proc
def puts(output)
@@file ||= File.open("your_log.txt", "w")
@@file.write "#{output}\n"
@@old_puts.call output
@@file.flush
end
DRAWBACKS: This is a step beyond hacky and I frankly would not recommend actually doing this unless you really, really know what you're doing and absolutely have to.
Upvotes: 3