Capistrano 3: Running a command on all servers

This Capistrano task runs a command on all servers.

bundle exec cap production app:run cmd='zgrep -P "..." RAILS_ROOT/log/production.log'

Code

# lib/capistrano/tasks/app.rake

namespace :app do

  # Use e.g. to grep logs on all servers:
  #   b cap production app:run_cmd cmd='zgrep -P "..." RAILS_ROOT/log/production.log' 
  #
  # * Use RAILS_ROOT as a placeholder for the remote Rails root directory.
  # * Append ` || test $? =1;` to grep calls in order to avoid exit code 1 (= "nothing found")
  # * To be able to process the output with a pipe, prepend `yes | ` to confirm the prompt
  desc 'Run a command on all servers'
  task :run do
    cmd = ENV['cmd'].to_s
    raise 'Please specify the command with CMD=…' if cmd == ''

    cmd = cmd.gsub /RAILS_ROOT/, shared_path.to_s
    puts '> RAILS_ROOT in your command has been replaced with the remote Rails root directory.'

    puts "Prepared command: #{cmd}"
    print '> Run this on all servers? [n] '
    if $stdin.gets =~ /y/
      on roles :app do
        execute cmd
      end
    else
      puts 'x Canceled.'
    end
  end

Make sure you require custom Capistrano task files:

# Capfile

Dir.glob('lib/capistrano/tasks/*.rake').each do |r|
  # `import r` calls Rake.application.add_import(r), which imports the file only
  # *after* this file has been processed, so the imported tasks would not be
  # available to the hooks below.
  Rake.load_rakefile r
end
Dominik Schöler 4 months ago