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/share/perl5/DBMon/Daemon.pm
package DBMon::Daemon;

use POSIX qw(setsid);
use DBMon::Log qw(say);
use DBMon::DB;
use DBMon::Ini;
use strict;
use FindBin qw($Bin);


# настройки по-умолчанию
my $DEF_SETTINGS = {
                        INI_FILE => "dbmon.ini",
                   };


sub new
{
    my $proto = shift;
    my $setting = shift;
    my $class = ref $proto || $proto;
    my $self = $DEF_SETTINGS;

    foreach(keys %$setting)
    {
        $self->{$_} = $setting->{$_};
    }

    $self->{INI} = new DBMon::Ini;
    
    $self->{INI}->read( $self->{INI_FILE} );
	
    $self->{PID_FILE} = '/var/run/'.$self->{INI}->{Settings}->{pid_file};
    $self->{LOG_FILE} = $self->{INI}->{Settings}->{log_file};
    $self->{WRITE_LOG_TO_FILE} = $self->{INI}->{Settings}->{write_log_to_file};
    $self->{WRITE_LOG_TO_SYSLOG} = $self->{INI}->{Settings}->{write_log_to_syslog};
    $self->{LOG_LEVEL} = $self->{INI}->{Settings}->{log_level};

    $self->{DB} = [];
    
    if (open (FD, $self->{PID_FILE})) {
    	$self->{PID} = <FD>;
    	close (FD);
    }

    DBMon::Log::init($self->{WRITE_LOG_TO_FILE}, $self->{LOG_FILE},
		     $self->{WRITE_LOG_TO_SYSLOG}, $self->{LOG_LEVEL});
    $self = bless $self, $class;
	
    return $self;
}


sub writepid
{
    my $self = shift;

    if (open (FD, '>'.$self->{PID_FILE})) {
	print FD $$;
	close FD;
	chmod 0600, $self->{PID_FILE};
	return 1;
    } else {
    	say ("Can't write pid file: ".$!, "err");
	return 0;
    }
}

sub init
{
    my $self = shift;

    $self->{HOST_DEFAULT} = $self->{INI}->{'default:host'};
    $self->{RULE_DEFAULT} = $self->{INI}->{'default:rule'};
    $self->{CON_TIME} = $self->{INI}->{Settings}->{connection_interval};
    $self->{MON_TIME} = $self->{INI}->{Settings}->{monitoring_interval};

    my @list = keys %{$self->{INI}};


    # считываем из конфига данные по все правилам
    foreach(@list)
    {
        if(/^rule\:(.*)/)
        {
            my $rule_ini = $self->{INI}->{$_};
            $rule_ini->{name} = $1;

            my ($k, $v);
            while(($k,$v) = each(%{$self->{RULE_DEFAULT}}))
            {
                 unless(defined($rule_ini->{$k}))
                 {
                    $rule_ini->{$k} = $v;
                 }
            }

            $self->{RULE}->{$1} = $rule_ini;
        }
    }


    # считываем из конфига данные по хостам
    # и пробуем коннектиться
    foreach(@list)
    {
        if(/^host\:(.*)/)
        {
            my $db_ini = $self->{INI}->{$_};
            $db_ini->{name} = $1;

            my ($k, $v);
            while(($k,$v) = each(%{$self->{HOST_DEFAULT}}))
            {
                 unless(defined($db_ini->{$k}))
                 {
                    $db_ini->{$k} = $v;
                 }
            }

            # расчитываем правила доступные на этом хосту
            my %rules = ();
            # подгружаем доступные правила
            if(my $ar = $db_ini->{allow_rule})
            {
                if($ar eq '*')
                {
                    %rules = %{$self->{RULE}};
                }
                else
                {
                    foreach(split /;/, $ar)
                    {
                        $rules{$_} = $self->{RULE}->{$_};
                    }
                }
            }
            # удаляем запрещенные правила
            if(my $dr = $db_ini->{deny_rule})
            {
                if($dr eq '*')
                {
                    %rules = ();
                }
                else
                {
                    foreach(split /;/, $dr)
                    {
                        delete $rules{$_};
                    }
                }
            }

            my $db = new DBMon::DB($db_ini);
            $db->{RULE} = \%rules;
	    $db->connect;
            push @{$self->{HOST}}, $db;
        }
    }
    return 1;
}


sub run
{
    my $self = shift;

    if($self->{PID} && kill 0=>$self->{PID})
    {
    	#say "DBMon is already running (pid ".$self->{PID}.")", "warn";
        exit;
    }
    $self->{PID} = $$;

    umask 0;
    open STDIN, '/dev/null';
    open STDOUT, '>/dev/null';
    open STDERR, '>/dev/null';
    my $pid = fork;
    unless (defined($pid)) {
    	say "Can't fork: ".$!, "err";
	exit;
    }
    exit if $pid;
    setsid;
	
    $|=1;                      # отключаем буферизацию

    say 'DBMon started', 'notice';

    $self->writepid || exit;
    $self->init || exit;

    my $last_mon_time = time;
    my $last_con_time = time;
    my $split = q/;/;

    for(;;)
    {
        my $wait = 1;

	# Проверяем process list'ы и убиваем то, что надо убить
        if( time - $last_mon_time >= $self->{MON_TIME} )
        {
            # выполняем мониторинг
            # say 'Checking queries on all servers', 'debug';
            foreach my $db (@{$self->{HOST}})
            {
		next unless( $db->{conn} );
       
       		my $prlist = $db->monitor;
				
		unless( $prlist )
		{
		    $db->{conn} = 0;
		    next;
		}
				
		foreach my $one_proc(@{$prlist})
                {
                    foreach(keys %{$db->{RULE}})
                    {
                   	my $rule = $db->{RULE}->{$_};
                        next if($rule->{status} ne $one_proc->{State});
                        next if($rule->{killtime} > $one_proc->{Time});

                       say "$one_proc->{User}: killtime: $rule->{killtime} > $one_proc->{Time}", 'debug';
                       say "allow deny checks : Status:$rule->{status}, allow_to_kill:$rule->{allow_to_kill} , deny_to_kill:$rule->{deny_to_kill}", 'debug';
                        my $user_check = 0;
			# проверка по allow
                        if(my $ak = $rule->{allow_to_kill})
                        {
                            if($ak eq '*')
                            {
                            	$user_check = 1;
                            }
                            else
                            {
                            	foreach(split /$split/,$ak)
                                {
				    chomp;
				    if($one_proc->{User}=~/$_/)
                                    {
                                        say "allow to kill: $one_proc->{User} --> $_ found, kill him", 'debug';
                                    	$user_check = 1;
                                        last;
                                    }
				    else 
				    {
					say "user $one_proc->{User} is not found in allow_t_kill rule ... ok", 'debug';
				    }
                                }
                            }
                        }
			# проверка на deny
                        if(my $dk = $rule->{deny_to_kill})
                        {
                            if($dk eq '*')
                            {
                            	$user_check = 0;
                            }
                            else
                            {
                            	foreach(split /$split/,$dk)
                                {
				    chomp;
                                    if($one_proc->{User}=~/$_/)
				    {
                                        say "deny to kill: $one_proc->{User} --> $_", 'debug';
                                    	$user_check = 0;
                                        last;
                                    }
                                }
                            }
                        }

                        if ($user_check)
                        {
				say "sorry I want to kill $one_proc->{User}", 'debug';
                            # убиваем
                            if ($db->killproc($one_proc->{Id}))
			    {
                                say "Killed query at \"$db->{name}\":".
				    "id $one_proc->{Id}, state: \"$one_proc->{State}\",".
				    "time: $one_proc->{Time} (user $one_proc->{User}, db $one_proc->{Db})",
				    'debug';
			    }
		    	    else
			    {
				say "Can't kill thread $one_proc->{Id} at $db->{name}", 'warn';
			    }
                            last; #cut
                        }

                    }
                }
            }
            $last_mon_time = time;
            $wait = 0;
        }
		

	# Восстанавливаем соединения с серверами, с которыми его нет
	if( time - $last_con_time >= $self->{CON_TIME} )
	{
	    foreach my $db (@{$self->{HOST}})
	    {
		unless( $db->{conn} )
		{
		    $db->connect;
		}
	    }
	    $last_con_time = time;			
	    $wait = 0;
	}

        sleep 1 if $wait;
    }
}

sub kill
{
    my $self = shift;
    if($self->{PID} && kill 0=>$self->{PID})
    {
	say 'DBMon stopped', 'notice';
        kill HUP=>$self->{PID}; #proc killed
    }
    else
    {
        say 'Can\'t stop DBMon: daemon is not running', 'err';
    }
    unlink $self->{PID_FILE};
    return 1;
}




1;