HEX

Warning: set_time_limit() [function.set-time-limit]: Cannot set time limit - prohibited by configuration in /home/u547966/brikov.ru/www/wp-content/plugins/admin-menu-editor/menu-editor.php on line 745
Server: Apache
System: Linux 4.19.0-0.bpo.9-amd64 x86_64 at red40
User: u547966 (5490)
PHP: 5.3.29-mh2
Disabled: syslog, dl, popen, proc_open, proc_nice, proc_get_status, proc_close, proc_terminate, posix_mkfifo, chown, chgrp, accelerator_reset, opcache_reset, accelerator_get_status, opcache_get_status, pcntl_alarm, pcntl_fork, pcntl_waitpid, pcntl_wait, pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wifcontinued, pcntl_wexitstatus, pcntl_wtermsig, pcntl_wstopsig, pcntl_signal, pcntl_signal_dispatch, pcntl_get_last_error, pcntl_strerror, pcntl_sigprocmask, pcntl_sigwaitinfo, pcntl_sigtimedwait, pcntl_exec, pcntl_getpriority, pcntl_setpriority
Upload Files
File: //usr/lib/ruby/vendor_ruby/mh/checkservice.rb
# vim: ts=2 sts=2 sw=2 et si
# $Id: checkservice.rb 2153 2012-12-29 13:10:58Z aremizov $

require 'yaml'

module MH
  module CheckService
    attr_reader :cfg, :service_state

    class PerfData
      attr_reader :value

      def initialize(data)
        if data.kind_of? Hash
          @label = data[:label]
          @value = %w{value warning critical min max}.map { |k| data[k.to_sym] }.join ';'
        else
          @label = 'data'
          @value = data
        end
        @as_string = "'#{@label.to_s.gsub(/'=/, '')}'=#{@value}"
      end

      def to_s
        @as_string
      end
    end

    class ServiceStatus < Exception
      EXIT_CODE = {
        :ok       => 0,
        :warning  => 1,
        :critical => 2,
        :unknown  => 3
      }

      WEIGHT = {
        :ok       => 0,
        :unknown  => 1,
        :warning  => 2,
        :critical => 3
      }

      attr_reader :status, :perf_data, :exit_code

      def initialize(status, message, perf_data = nil)
        if EXIT_CODE.include? status
          @status, @message = status, message
        elsif EXIT_CODE.index(status)
          @status, @message = EXIT_CODE.index(status), message
        else
          @status, @message = :unknown, "Unknown status #{status} (original message is \"#{message}\")"
        end
        @exit_code = EXIT_CODE[@status]
        @perf_data = if perf_data and not perf_data.empty?
          if perf_data.kind_of? Array
            perf_data.flatten
          else
            PerfData.new perf_data
          end
        end
      end

      def <=>(service_status)
        WEIGHT[service_status.status] <=> WEIGHT[@status]
      end

      def message
        if @perf_data.respond_to? :value
          @message % [@perf_data.value]
        else
          @message
        end
      end

      def to_s
        final_message = if @perf_data
          perf_data = if @perf_data.kind_of? Array
            @perf_data.map { |d| d.to_s }.join ' '
          else
            @perf_data.to_s
          end
          "#{message}|#{perf_data}"
        else
          message
        end

        "#{status.to_s.upcase} #{final_message}"
      end
    end

    class State
      def initialize(filename)
        @filename = filename
        @current_state = Hash.new
      end

      def load
        @common_config = {
          'history_length' => 10
        }
        if not File.zero? @filename and File.readable? @filename
          @all_states = YAML.load_file @filename
          unless @all_states.kind_of? Array
            raise ServiceStatus.new :unknown, "Can't parse state file #{@filename}"
          end
        else
          @all_states = []
        end
      end

      def <<(current_state)
        @all_states.unshift({ :time => Time.new, :state => current_state})
        save 
      end

      def save
        while @all_states.size > @common_config['history_length'] do
          @all_states.pop
        end
        File.open(@filename, 'w', 0700) { |f| YAML.dump(@all_states, f) }
      end

      def get(n = 1)
        @all_states[n]
      end

      def set(k,v)
        self << {k => v}
      end
    
      def current_state
        @all_states.first[:state]
      end

      def difference(axis, item = nil)
        return if @all_states.length < 2
        if item
          @all_states[0][:state][item][axis] - @all_states[1][:state][item][axis]
        else
          @all_states[0][:state][axis] - @all_states[1][:state][axis]
        end
      end
    
      def derivative(axis, item = nil)
        return if @all_states.length < 2
        timedelta = @all_states[0][:time] - @all_states[1][:time]
        return if timedelta == 0
        difference(axis, item) / timedelta
      end
      
    end 

    def check_service(service_name)
      read_config service_name
      @service_state = State.new File.join(@common_config['statedir'], "#{service_name}.state.yaml")

      lock_file = File.join @common_config['lockdir'], "#{service_name}.lock"
      service_status = if lock_script(lock_file)
        begin
          @service_state.load

          states = [yield].flatten.compact.sort
          status :unknown, 'no data collected' if states.empty?

          general_status = states.first.status
          general_message = states .
            select { |state| state.status == general_status } .
            map { |state| state.message } .
            join ', '
          general_perf_data = states.map { |state| state.perf_data }.compact

          status general_status, general_message, general_perf_data
        rescue ServiceStatus => service_status
          service_status
        ensure
          unlock_script(lock_file)
        end
      else
        ServiceStatus.new :unknown, 'script execution is locked'
      end
      puts service_status.to_s
      exit service_status.exit_code
    end

    def status_message(message, perf_data = nil)
      @status_message = message
      @perf_data = perf_data
    end

    def status(status, message = nil, perf_data = nil)
      status_message(message, perf_data) if message
      raise ServiceStatus.new status, @status_message, @perf_data
    end

    def status_from_external_command(command)
      message = %x{#{command}}.to_s.strip
      status $?.exitstatus, message
    end

    def status_from_file(filename, max_age)
      unless File.readable? filename
        status :unknown, "Can't read file #{filename}"
      end
      if Time.now - File.stat(filename).ctime > max_age
        status :unknown, "Status file #{filename} is older than #{max_age} seconds"
      end

      status_code, message = File.open(filename).read.split(' ', 2)
      unless status_code.kind_of? String
        status_code = 'unknown'
        message = "Can't recognize status from '#{filename}'"
      end
      status status_code.downcase.to_sym, message
    end

    def qx(commandline)
      result = %x{#{commandline}}
      status :unknown, "'#{commandline}' invocation error" unless $?.exitstatus == 0
      result
    end

    def defaults(hash)
      @defaults = hash
    end

    def read_config(service_name)
      def locate_config(filename)
        ['/usr/local/etc', '/etc'].each do |path|
          config_file = File.join(path, filename)
          return config_file if File.exists? config_file
        end
        nil
      end

      @common_config = {
        'lockdir'   => '/tmp',
        'statedir' => '/tmp',
      }
      @cfg = @defaults.clone

      config_file = locate_config('checkservice.conf')
      return unless config_file

      sections = File.open(config_file) { |f| YAML::load(f) }
      if sections.kind_of? Hash
        @common_config.update sections['common'] if sections.include? 'common'
        @cfg.update sections[service_name] if sections.include? service_name
      end
    end

    def lock_script(lock_file)
      if File.exists? lock_file
        %x{pgrep -F#{lock_file} -f #{$0}}
        if $?.exitstatus == 0
          puts "Lock file #{lock_file} found. Abort execution."
          throw :lock_found
        end
      end

      File.open(lock_file, 'w') { |f| f.write $$ }
    end

    def unlock_script(lock_file)
      begin
        File.unlink lock_file
      rescue Errno::ENOENT
      end
    end
  end
end

class Array
  def check_each
    self.map do |item|
      begin
        yield item
        status :unknown, "no status for \"#{item}\""
      rescue MH::CheckService::ServiceStatus => service_status
      end
      service_status
    end
  end
end