2

What I'm trying to achieve is a capistrano3 task that does a log file grep on all servers - this would save a lot of time as we have a lot of servers so doing it manually or even scripted but sequentially takes ages.

I have a rough at the edges task that actually works except when one of the servers returns nothing for the grep. In this case the whole command falls over.

Hence wondering if there is a way to set capture to accept empty returns.

namespace :admin do
  task :log_grep, :command, :file do |t,args|
    command = args[:command] || 'ask for a command'
    file = args[:file] || 'log_grep_results'
    outs = {}
    on roles(:app), in: :parallel do
      outs[host.hostname] = capture(:zgrep, "#{command}")
    end

    File.open(file, 'w') do |fh|
      outs.each do |host,out|
        fh.write(out)
      end
    end
  end
end

2 Answers2

4

Should anyone else come to this question, here's solution - raise_on_non_zero_exit: false

i wanted:

resp = capture %([ -f /var/run/xxx/xxx.pid ] && echo "ok")

error:

SSHKit::Command::Failed: [ -f /var/run/xxx/xxx.pid ] && echo "ok" exit status: 1
[ -f /var/run/xxx/xxx.pid ] && echo "ok" stdout: Nothing written
[ -f /var/run/xxx/xxx.pid ] && echo "ok" stderr: Nothing written

solution:

resp = capture %([ -f /var/run/xxx/xxx.pid ] && echo "ok"), raise_on_non_zero_exit: false
# resp => ""
Ondřej Želazko
  • 648
  • 7
  • 16
0

So the work around I did was to start adding what I'm calling Capistrano utility scripts in the repo. Then capistrano runs these scripts. All the scripts are is a wrapper around a grep and some logic to output something if the return is empty.

Capistrano code:

namespace :utils do
  task :log_grep, :str, :file, :save_to do |t,args|
    command_args = "#{args[:str]} #{args[:file]}"
    outs = {}
    on roles(:app), in: :parallel do
      outs[host.hostname] = capture(:ruby, "#{fetch(:deploy_to)}/current/bin/log_grep.rb #{args[:str]} #{args[:file]}")
    end

    file = args[:save_to]
    file ||= 'log_grep_output'
    File.open(file, 'w') do |fh|
      outs.each do |host,out|
        s = "#{host} -- #{out}\n"
        fh.write(s)
      end
    end
  end
end

Ruby script log_grep.rb:

a = `zgrep #{ARGV[0]} #{ARGV[1]}`
if a.empty?
  puts 'Nothing Found'
else
  puts a
end