Capistrano task to tail remote application logs of multiple servers

When your application is running on a multi-server setup, application logs are stored per server (unless you choose a centralized logging solution).
Here is a Capistrano task that connects to all servers and prints logs to your terminal like this:

$ cap production app:logs
00:00 app:logs
      01 tail -n0 -F /var/www/your-application/shared/log/production.log | while read line; do echo "$(hostname): $line"; done
      01 app01-prod: Started GET "/sign_in" for 1.2.3.4 at 2018-04-26 11:28:19 +0200
      01 app01-prod: Processing by Users::SessionsController#new as HTML
      01 app01-prod:   Rendering devise/sessions/new.haml within layouts/signed_out
      01 app01-prod:   Rendered devise/sessions/new.haml within layouts/signed_out (4.8ms)
      01 app01-prod:   Rendered layouts/shared/_head.haml (0.5ms)
      01 app01-prod: Completed 200 OK in 8ms (Views: 6.1ms | ActiveRecord: 0.0ms)
      01 app02-prod: Started GET "/messages/number_of_new" for 5.6.7.8 at 2018-04-26 11:28:20 +0200
      01 app02-prod: Processing by MessagesController#number_of_new as */*
      01 app02-prod:   Rendering text template
      01 app02-prod:   Rendered text template (0.0ms)
      01 app02-prod: Completed 200 OK in 23ms (Views: 1.0ms | ActiveRecord: 7.2ms)

Store the following task in a file like lib/capistrano/tasks/app.rake.

namespace :app do

  desc 'Tail remote log files'
  task :logs do
    on roles :app do
      logfile = ENV['LOG'] || fetch(:rails_env)
      execute %(tail -n0 -F #{shared_path}/log/#{logfile}.log | while read line; do echo "$(hostname): $line"; done)
    end
  end

end

If you have some other log file that you want to tail, use the LOG env variable, like LOG=sidekiq cap production app:logs.

Note that Capistrano truncates lines that are longer than your terminal. This can be painful when looking at logs, and we recommend you disable truncation entirely.

Arne Hartherz Almost 6 years ago