Guest User

Untitled

a guest
Feb 19th, 2018
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.48 KB | None | 0 0
  1. require 'rubygems'
  2. require 'mailfactory'
  3. require 'term/ansicolor'
  4.  
  5. class String
  6. include Term::ANSIColor
  7. end
  8.  
  9. class Abyss
  10. attr_accessor :daemons, :daemons_alive, :daemons_dead, :interval
  11.  
  12. DAEMON_PATH = '/etc/rc.d'
  13. STATUS_PATH = '/var/run'
  14.  
  15. def initialize all_daemons = {}
  16. @daemons = []
  17. @interval = 60 * 15 # 15 minutes
  18.  
  19. special_cases = {
  20. 'courier-imap' => ['imapd', 'imapd-ssl', 'courier', 'pop3d', 'pop3d-ssl']
  21. }
  22.  
  23. if all_daemons.empty?
  24. # fetch the list of started daemons from rc.conf
  25. daemons = File.readlines('/etc/rc.conf').find{|l| l =~ /^DAEMONS/}.chomp
  26. # get the daemons out of there
  27. daemons = daemons.scan(/DAEMONS=\((.*?)\)/).first.first
  28. # get all the daemons and split them into dead and alive ones
  29. # remove @ if it's there - background-started-processes
  30. dead, alive = daemons.split.map{|d| d.gsub('@', '')}.partition{|d| d =~ /!/}
  31. alive = alive.map { |d| special_cases[d].nil? ? d : special_cases[d] }.flatten
  32. all_daemons = {:alive => alive, :dead => dead}
  33. end
  34.  
  35. all_daemons.each do |state, daemons|
  36. status = state.to_s.send(state == :dead ? :red : :green)
  37.  
  38. daemons.each do |daemon|
  39. puts "adding daemon [#{status}] #{daemon.inspect}"
  40. add daemon, state
  41. end
  42. end
  43.  
  44. puts "#{@daemons.size} Daemons registered:"
  45. puts "Starting up - Interval every #{@interval} seconds"
  46. startup
  47. end
  48.  
  49. def startup
  50. loop do
  51. Thread.new do
  52. @daemons.each do |daemon|
  53. case daemon.should_be
  54. when :alive
  55. # puts "#{daemon.name} is #{daemon.is} and should be #{daemon.should_be} [#{daemon.alive?}]"
  56. daemon.start if daemon.dead?
  57. when :dead
  58. daemon.stop if daemon.alive?
  59. end
  60. end
  61. failures = @daemons.find_all { |d| d.failures >= 1 }
  62. p failures unless failures.empty?
  63. failures.each do |daemon|
  64. puts "Found #{daemon} erronous..."
  65. sendmail daemon
  66. end
  67. end
  68. sleep @interval
  69. end
  70. end
  71.  
  72. def [](daemon)
  73. @daemons.find{|d| d.name == daemon.to_sym} || @daemons[daemon]
  74. end
  75.  
  76. def add daemon, state = :alive
  77. remove daemon
  78. @daemons << Daemon.new(daemon, state)
  79. end
  80.  
  81. def remove daemon
  82. @daemons.delete_if{|d| d.name == daemon.to_sym}
  83. end
  84.  
  85. def sendmail daemon
  86. daemon_inspect = %{
  87. }
  88. mail = MailFactory.new
  89. mail.to = 'm.fellinger@gmail.com'
  90. mail.from = 'abyss@weez-int.com'
  91. mail.subject = "[Abyss] Failure - #{daemon.name} - #{daemon.failures} failures"
  92. mail.text = %{
  93. Houston, we've got a problem
  94.  
  95. #{daemon.name} is #{daemon.is} and should be #{daemon.should_be} [#{daemon.should_be daemon.should_be}]
  96.  
  97. The Daemon:
  98. Name: #{daemon.name}
  99. is: #{daemon.is}
  100. should be: #{daemon.should_be}
  101. failures: #{daemon.failures}
  102. command: #{daemon.error[:cmd]}
  103. the error: #{daemon.error[:returned]}
  104. }
  105. sendmail = IO.popen "sendmail #{mail.to}", 'w+'
  106. sendmail.puts mail.to_s
  107. sendmail.close
  108. end
  109. end
  110.  
  111. class Daemon
  112. attr_accessor :name, :should_be, :failures, :error
  113.  
  114. def initialize name, state = :alive
  115. @name = name.to_sym
  116. @should_be = state
  117. @failures = 0
  118. @error = nil
  119. end
  120.  
  121. def is
  122. alive? ? :alive : :dead
  123. end
  124.  
  125. def should_be sym = nil
  126. sym ? (@should_be == sym) : @should_be
  127. end
  128.  
  129. def alive?
  130. File.exist? "#{Abyss::STATUS_PATH}/daemons/#{name}"
  131. end
  132.  
  133. def should_be_alive?
  134. should_be :alive
  135. end
  136.  
  137. def dead?
  138. !alive?
  139. end
  140.  
  141. def should_be_dead?
  142. should_be :dead
  143. end
  144.  
  145. def pid
  146. File.read("#{Abyss::STATUS_PATH}/#{name}.pid").to_i
  147. end
  148.  
  149. def start
  150. handle :start
  151. end
  152.  
  153. def stop
  154. handle :stop
  155. end
  156.  
  157. def restart
  158. handle :restart
  159. end
  160.  
  161. def handle demand
  162. if [:start, :stop, :restart].include? demand
  163. puts "#{demand} #{name}"
  164. cmd = "sudo #{Abyss::DAEMON_PATH}/#{name} #{demand}"
  165. action = `#{cmd}`.uncolored
  166. demand_fulfilled = lambda{ demand == :stop ? dead? : alive? }
  167. if demand_fulfilled.call
  168. @failures = 0
  169. else
  170. @failures += 1
  171. @error = {:cmd => cmd, :returned => action}
  172. unless @failures > 3
  173. puts "#{demand} failed, trying to restart"
  174. handle :restart
  175. end
  176. end
  177. else
  178. puts "unknown demand '#{demand}'"
  179. end
  180. demand_fulfilled.call
  181. end
  182. end
  183.  
  184. Abyss.new
Add Comment
Please, Sign In to add comment