可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In a rake task if I use puts command then I see the output on console. However I will not see that message in log file when app is deployed on production.
However if I say Rails.logger.info then in development mode I see nothing on console. I need to go to log file and tail that.
I would ideally like to use Rails.logger.info and in development mode inside the rake task, the output from logger should also be sent to console.
Is there a way to achieve that?
回答1:
Put this in application.rb
, or in a rake task initialize code
if defined?(Rails) && (Rails.env == 'development')
Rails.logger = Logger.new(STDOUT)
end
This is Rails 3 code. Note that this will override logging to development.log
. If you want both STDOUT
and development.log
you'll need a wrapper function.
If you'd like this behaviour only in the Rails console, place the same block of code in your ~/.irbrc
.
回答2:
You could create a new rake task to get this to work.
desc "switch logger to stdout"
task :to_stdout => [:environment] do
Rails.logger = Logger.new(STDOUT)
end
This way when you execute your rake task you can add to_stdout first to get stdout log messages or don't include it to have messages sent to the default log file
rake to_stdout some_task
回答3:
Rake tasks are run by a user, on a command-line. Anything they need to know right away ("processed 5 rows") should be output on the terminal with puts
.
Anything that needs to be kept for posterity ("sent warning email to jsmith@example.com") should be sent to the Rails.logger
.
回答4:
I'd say that using Rails.logger.info
is the way to go.
You won't be able to see it in the server console because it won't run via the server. Just open up a new console and tail -f
the log file, it'll do the trick.
Many users are aware of the UNIX®
command 'tail', which can be used to
display the last few lines of a large
file. This can be useful for viewing
log files, etc.
Even more useful in some situations,
is the '-f' parameter to the 'tail'
command. This causes tail to 'follow'
the output of the file. Initially, the
response will be the same as for
'tail' on its own - the last few lines
of the file will be displayed.
However, the command does not return
to the prompt, and instead, continues
to 'follow' the file. When additional
lines are added to the file, they will
be displayed on the terminal. This is
very useful for watching log files, or
any other file which may be appended
over time. Type 'man tail' for more
details on this and other tail
options.
(via)
回答5:
Code
For Rails 4 and newer, you can use Logger broadcast.
If you want to get both STDOUT and file logging for rake tasks in development mode, you can add this code into config/environments/development.rb
:
if File.basename($0) == 'rake'
# http://stackoverflow.com/questions/2246141/puts-vs-logger-in-rails-rake-tasks
log_file = Rails.root.join("log", "#{Rails.env}.log")
Rails.logger = ActiveSupport::Logger.new(log_file)
Rails.logger.extend(ActiveSupport::Logger.broadcast(ActiveSupport::Logger.new(STDOUT)))
end
Test
Here's a small Rake task to test the above code :
# lib/tasks/stdout_and_log.rake
namespace :stdout_and_log do
desc "Test if Rails.logger outputs to STDOUT and log file"
task :test => :environment do
puts "HELLO FROM PUTS"
Rails.logger.info "HELLO FROM LOGGER"
end
end
Running rake stdout_and_log:test
outputs
HELLO FROM PUTS
HELLO FROM LOGGER
while
HELLO FROM LOGGER
has been added to log/development.log
.
Running rake stdout_and_log:test RAILS_ENV=production
outputs
HELLO FROM PUTS
while
HELLO FROM LOGGER
has been added to log/production.log
.
回答6:
How about creating an application helper which detects which environment is running and does the right thing?
def output_debug(info)
if RAILS_ENV == "development"
puts info
else
logger.info info
end
end
Then call output_debug instead of puts or logger.info
回答7:
In Rails 2.X to redirect the logger to STDOUT in models:
ActiveRecord::Base.logger = Logger.new(STDOUT)
To redirect logger in controllers:
ActionController::Base.logger = Logger.new(STDOUT)
回答8:
Execute a background job with '&' and open script/console or whatever..
That way you can run multiple commands in the same window.
tail -f log/development.log &
script/console
Loading development environment (Rails 2.3.5)
>> Product.all
2011-03-10 11:56:00 18062 DEBUG Product Load (6.0ms) SELECT * FROM "products"
[<Product.1>,<Product.2>]
note Can get sloppy quickly when there is a lot of logging output.