rails - Redirecting console output to a file
You can use override $stdout
to redirect the console output:
$stdout = File.new('console.out', 'w')
You may also need to call this once:
$stdout.sync = true
To restore:
$stdout = STDOUT
Redirect the puts command output to a log file
I should recommend to use ruby logger, it is better than puts, you can have multiple log levels that you can turn on/off: debug, warn, info,error, etc.
logger = Logger.new(STDOUT)
logger = Logger.new("/var/log/my-daemon.log")
I use runit package to manage ruby services, it has svlogd than will redirect daemon output to log file, here is run script for logger process:
#!/bin/sh
set -e
LOG=/var/log/my-daemon
test -d "$LOG" || mkdir -p -m2750 "$LOG" && chown nobody:adm "$LOG"
exec chpst -unobody svlogd -tt "$LOG"
Ruby redirect output to file
You either can write to a file explicitly (open file and write to it)
file = File.open('target.file', 'w') do |file|
File.foreach('links.txt') do |li|
file.puts(li) if li['PersonNight']
end
end
Or redirect from outside your script, using regular unix machinery
ruby my_script.rb > target.file
How to redirect tracepoint output to a file in Ruby?
As a comment said, the p
prints to stdout. To redirect the output to another TTY (or another file), the file needs to be opened and the .print
method can be used. The following code gets the desired functionality:
def start_trace
file = File.open("/dev/ttys007", "w")
trace =
TracePoint.new(:call) { |tp|
file.print [tp.path, tp.lineno, tp.event, tp.method_id]
file.puts()
}
trace.enable
yield
trace.disable
file.close
end
def fun1
puts("This is fun1")
end
def fun2
puts("This is fun2")
end
def fun3(num)
puts("This is fun3: " + num)
fun2
end
start_trace { fun3("bye") }
Log rails console always to file in production env
Here's a solution with only one file for a whole system, no modification to your Rails projects and no modification to your console command.
You can put this in your ~/.irbrc, I tested it with Ruby 2.1.5 and Rails 3.2/4.0/4.2 :
# ~/.irbrc for http://stackoverflow.com/questions/39411783/log-rails-console-always-to-file-in-production-env
if defined? Rails
puts "Loading configuration for Rails console from #{__FILE__}"
time = Time.now.strftime('%Y_%m_%d__%H_%M_%S')
log_file = File.join(Rails.root, "log", "rails_console_#{Rails.env}_#{time}.log")
#log_file = "/home/sshuser/myproject/console_sessions/#{time}.txt"
puts " logging to #{log_file}"
logger = Logger.new(log_file)
Rails.logger = logger
ActiveRecord::Base.logger = logger if defined? ActiveRecord
# Intercepts STDIN from IRB
module Readline
module History
def self.write_log(line)
Rails.logger.info(line)
end
def self.start_session_log
write_log("# session start: #{Time.now}")
at_exit { write_log(" # session stop: #{Time.now}") }
end
end
alias :old_readline :readline
def readline(*args)
ln = old_readline(*args)
begin
History.write_log("STDIN : #{ln}")
rescue
end
ln
end
end
# $stdout writes to STDOUT and Rails.logger
# $stderr writes to STDERR and Rails.logger
class MultiLog
def initialize(io)
@io = io
@desc = io.inspect[/STD\w+/]
end
def write(str)
Rails.logger.info("#{@desc} : #{str}")
@io.write(str)
end
def close
@io.close
end
end
$stdout = MultiLog.new(STDOUT)
$stderr = MultiLog.new(STDERR)
Readline::History.start_session_log
end
For Pry, you should use this ~/.pryrc :
# ~/.pryrc for http://stackoverflow.com/questions/39411783/log-rails-console-always-to-file-in-production-env
if defined? Rails
puts "Loading configuration for Rails console from #{__FILE__}"
time = Time.now.strftime('%Y_%m_%d__%H_%M_%S')
log_file = File.join(Rails.root, "log", "rails_console_#{Rails.env}_#{time}.log")
#log_file = "/home/sshuser/myproject/console_sessions/#{time}.txt"
puts " logging to #{log_file}"
logger = Logger.new(log_file)
Rails.logger = logger
ActiveRecord::Base.logger = logger if defined? ActiveRecord
# Intercepts STDIN from pry (from http://www.hardscrabble.net/2015/how-to-log-all-input-in-your-pry-rails-console)
class LoggingReadline
delegate :completion_proc, :completion_proc=, to: Readline
def readline(prompt)
Readline.readline(prompt).tap do |user_input|
Rails.logger.info("STDIN : #{user_input}")
end
end
end
Pry.config.input = LoggingReadline.new
# $stdout writes to STDOUT and Rails.logger
# $stderr writes to STDERR and Rails.logger
class MultiLog
# Needed for #tty?, #flush : https://github.com/pry/pry/issues/1464
def method_missing(sym,*p)
@io.send(sym,*p)
end
def initialize(io)
@io = io
@desc = io.inspect[/STD\w+/]
end
def write(str)
Rails.logger.info("#{@desc} : #{str}")
@io.write(str)
end
alias_method :print, :write
end
$stdout = MultiLog.new(STDOUT)
$stderr = MultiLog.new(STDERR)
end
It saves console input, output and errors, as well as database queries into the specified file.
For example :
~/www/my_movies> bundle exec rails console -e development
Loading development environment (Rails 4.0.4)
Loading configuration for Rails console from /home/ricou/.irbrc
logging to /home/ricou/www/my_movies/log/rails_console_development_2016_10_28__11_58_41.log
2.1.5 :001 > Movie.first
=> Est - Ouest
2.1.5 :002 > puts 2+2
4
=> nil
2.1.5 :003 > exit
outputs this log file :
# Logfile created on 2016-10-28 11:58:41 +0200 by logger.rb/44203
I, [2016-10-28T11:58:41.062811 #3860] INFO -- : # session start: 2016-10-28 11:58:41 +0200
I, [2016-10-28T11:58:46.822753 #3860] INFO -- : STDIN : Movie.first
D, [2016-10-28T11:58:46.883974 #3860] DEBUG -- : Movie Load (0.7ms) SELECT "movies".* FROM "movies" ORDER BY "movies"."id" ASC LIMIT 1
I, [2016-10-28T11:58:46.896787 #3860] INFO -- : STDOUT : => Est - Ouest
I, [2016-10-28T11:58:48.922083 #3860] INFO -- : STDIN : puts 2+2
I, [2016-10-28T11:58:48.922486 #3860] INFO -- : STDOUT : 4
I, [2016-10-28T11:58:48.922524 #3860] INFO -- : STDOUT :
I, [2016-10-28T11:58:48.922584 #3860] INFO -- : STDOUT : => nil
I, [2016-10-28T11:58:50.341326 #3860] INFO -- : STDIN : exit
I, [2016-10-28T11:58:50.342142 #3860] INFO -- : # session stop: 2016-10-28 11:58:50 +0200
How do I dump Pry output to a file or Vim?
I have a hash, with nested hashes/objects, which I need to send over to a 3rd party for work with an API. They need a dump of the data so they can set up the receiving end of my call. I'm just going to do this in Ruby now, but it would have made more sense to dump the data through PRY, rather than edit my ruby object to dump the data, which I only need once.
If you can start the server from a local command-line, or SSH to the host and run an instance there, you can use Pry for this. Basically you need to add these lines to your code at the appropriate place:
require 'pry-debugger'; binding.pry
which will stop your code and put you at the Pry prompt. At that point you can enter something like:
require 'json'
File.write('test.data', hash.to_json)
Read the Pry.debugger documentation for information about using Pry with remote Rails sessions, which might work better for you.
How replicate rails console output style in runner script?
This formatting is a result of PrettyPrint module - PP
:
u = User.first
pp u #=> Which is basically a shortcut for: PP.pp(u)
Note however, that by default this will not generate a colourful output. Pry additionally process the formatted string through another gem - coderay, which is responsible for ruby syntax highlighting. If you want to print in colour, then:
u = User.first
Pry::ColorPrinter.pp(u)
Related Topics
Rack::Request - How to Get All Headers
Rails Put Validation in a Module Mixin
Nested Forms in Rails - Accessing Attribute in Has_Many Relation
How to Traverse Symlinked Directories in Ruby with a "**" Glob
How to Use Rspec to Mock Stdin/Stdout to Test Console Reads & Writes
Using Rbenv Doesn't Work with Sudo
Generate an HTML Table from an Array of Hashes in Ruby
Redirect User After Log in Only If It's on Root_Path
How to Get the Last SQL Query Performed by Activerecord in Ruby on Rails
How to Check If a Ruby Array Includes One of Several Values
Putting the Results of Pp (Or Anything Outputted to Console) into a String
Use of Caret Symbol (^) in Ruby
Ruby Timeouts and System Commands
How to Round a Time Down to the Nearest 15 Minutes in Ruby
Returning Data from Forked Processes
Breaking Up Long Strings on Multiple Lines in Ruby Without Stripping Newlines