Tidyfy code

This commit is contained in:
root 2016-08-31 10:30:20 +02:00
parent 746f5d3a4d
commit a067eddb20

View file

@ -185,7 +185,7 @@ my $basic_password_files =
: abs_path( $opt{passwordfile} ); : abs_path( $opt{passwordfile} );
# Related to password option # Related to password option
$opt{pass}=$opt{password} if ($opt{pass} eq 0 and $opt{password} ne 0); $opt{pass} = $opt{password} if ( $opt{pass} eq 0 and $opt{password} ne 0 );
# for RPM distributions # for RPM distributions
$basic_password_files = "/usr/share/mysqltuner/basic_passwords.txt" $basic_password_files = "/usr/share/mysqltuner/basic_passwords.txt"
@ -202,7 +202,8 @@ if ( $opt{verbose} ) {
} }
# for RPM distributions # for RPM distributions
$opt{cvefile} = "/usr/share/mysqltuner/vulnerabilities.csv" unless ( defined $opt{cvefile} and -f "$opt{cvefile}" ); $opt{cvefile} = "/usr/share/mysqltuner/vulnerabilities.csv"
unless ( defined $opt{cvefile} and -f "$opt{cvefile}" );
$opt{cvefile} = '' unless -f "$opt{cvefile}"; $opt{cvefile} = '' unless -f "$opt{cvefile}";
$opt{cvefile} = './vulnerabilities.csv' if -f './vulnerabilities.csv'; $opt{cvefile} = './vulnerabilities.csv' if -f './vulnerabilities.csv';
@ -236,8 +237,9 @@ my ( $mysqlvermajor, $mysqlverminor, $mysqlvermicro );
# Super structure containing all information # Super structure containing all information
my %result; my %result;
$result{'MySQLTuner'}{'version'}=$tunerversion; $result{'MySQLTuner'}{'version'} = $tunerversion;
$result{'MySQLTuner'}{'options'}=\%opt; $result{'MySQLTuner'}{'options'} = \%opt;
# Functions that handle the print styles # Functions that handle the print styles
sub prettyprint { sub prettyprint {
print $_[0] . "\n" unless ( $opt{'silent'} or $opt{'json'} ); print $_[0] . "\n" unless ( $opt{'silent'} or $opt{'json'} );
@ -367,7 +369,8 @@ sub pretty_uptime {
my ( $physical_memory, $swap_memory, $duflags ); my ( $physical_memory, $swap_memory, $duflags );
sub memerror { sub memerror {
badprint "Unable to determine total memory/swap; use '--forcemem' and '--forceswap'"; badprint
"Unable to determine total memory/swap; use '--forcemem' and '--forceswap'";
exit 1; exit 1;
} }
@ -455,8 +458,9 @@ sub os_setup {
$result{'OS'}{'Physical Memory'}{'pretty'} = hr_bytes($physical_memory); $result{'OS'}{'Physical Memory'}{'pretty'} = hr_bytes($physical_memory);
$result{'OS'}{'Swap Memory'}{'bytes'} = $swap_memory; $result{'OS'}{'Swap Memory'}{'bytes'} = $swap_memory;
$result{'OS'}{'Swap Memory'}{'pretty'} = hr_bytes($swap_memory); $result{'OS'}{'Swap Memory'}{'pretty'} = hr_bytes($swap_memory);
$result{'OS'}{'Other Processes'}{'bytes'} = get_other_process_memory(); $result{'OS'}{'Other Processes'}{'bytes'} = get_other_process_memory();
$result{'OS'}{'Other Processes'}{'pretty'} = hr_bytes(get_other_process_memory()); $result{'OS'}{'Other Processes'}{'pretty'} =
hr_bytes( get_other_process_memory() );
} }
sub get_http_cli { sub get_http_cli {
@ -801,16 +805,19 @@ sub mysql_setup {
debugprint "$mysqladmincmd $remotestring ping 2>&1"; debugprint "$mysqladmincmd $remotestring ping 2>&1";
my $loginstatus = `$mysqladmincmd $remotestring ping 2>&1`; my $loginstatus = `$mysqladmincmd $remotestring ping 2>&1`;
if ( $loginstatus =~ /mysqld is alive/ ) { if ( $loginstatus =~ /mysqld is alive/ ) {
# Login went just fine # Login went just fine
$mysqllogin = " $remotestring "; $mysqllogin = " $remotestring ";
# Did this go well because of a .my.cnf file or is there no password set?
# Did this go well because of a .my.cnf file or is there no password set?
my $userpath = `printenv HOME`; my $userpath = `printenv HOME`;
if ( length($userpath) > 0 ) { if ( length($userpath) > 0 ) {
chomp($userpath); chomp($userpath);
} }
unless ( -e "${userpath}/.my.cnf" or -e "${userpath}/.mylogin.cnf" ) unless ( -e "${userpath}/.my.cnf" or -e "${userpath}/.mylogin.cnf" )
{ {
badprint "Successfully authenticated with no password - SECURITY RISK!"; badprint
"Successfully authenticated with no password - SECURITY RISK!";
} }
return 1; return 1;
} }
@ -944,7 +951,7 @@ sub arr2hash {
my $sep = shift; my $sep = shift;
$sep = '\s' unless defined($sep); $sep = '\s' unless defined($sep);
foreach my $line (@$harr) { foreach my $line (@$harr) {
next if ($line =~ m/^\*\*\*\*\*\*\*/); next if ( $line =~ m/^\*\*\*\*\*\*\*/ );
$line =~ /([a-zA-Z_]*)\s*$sep\s*(.*)/; $line =~ /([a-zA-Z_]*)\s*$sep\s*(.*)/;
$$href{$1} = $2; $$href{$1} = $2;
debugprint "V: $1 = $2"; debugprint "V: $1 = $2";
@ -952,11 +959,13 @@ sub arr2hash {
} }
sub get_all_vars { sub get_all_vars {
# We need to initiate at least one query so that our data is useable # We need to initiate at least one query so that our data is useable
$dummyselect = select_one "SELECT VERSION()"; $dummyselect = select_one "SELECT VERSION()";
if (not defined($dummyselect) or $dummyselect eq "") { if ( not defined($dummyselect) or $dummyselect eq "" ) {
badprint "You probably doesn't get enough privileges for running MySQLTuner ..."; badprint
exit(256); "You probably doesn't get enough privileges for running MySQLTuner ...";
exit(256);
} }
$dummyselect =~ s/(.*?)\-.*/$1/; $dummyselect =~ s/(.*?)\-.*/$1/;
debugprint "VERSION: " . $dummyselect . ""; debugprint "VERSION: " . $dummyselect . "";
@ -1040,7 +1049,7 @@ sub remove_empty {
sub get_file_contents { sub get_file_contents {
my $file = shift; my $file = shift;
open(my $fh, "<", $file) or die "Can't open $file for read: $!"; open( my $fh, "<", $file ) or die "Can't open $file for read: $!";
my @lines = <$fh>; my @lines = <$fh>;
close $fh or die "Cannot close $file: $!"; close $fh or die "Cannot close $file: $!";
@lines = remove_cr @lines; @lines = remove_cr @lines;
@ -1058,32 +1067,39 @@ sub cve_recommendations {
return; return;
} }
#prettyprint "Look for related CVE for $myvar{'version'} or lower in $opt{cvefile}"; #prettyprint "Look for related CVE for $myvar{'version'} or lower in $opt{cvefile}";
my $cvefound = 0; my $cvefound = 0;
open(my $fh, "<", $opt{cvefile}) or die "Can't open $opt{cvefile} for read: $!"; open( my $fh, "<", $opt{cvefile} )
or die "Can't open $opt{cvefile} for read: $!";
while ( my $cveline = <$fh> ) { while ( my $cveline = <$fh> ) {
my @cve = split( ';', $cveline ); my @cve = split( ';', $cveline );
debugprint "Comparing $mysqlvermajor\.$mysqlverminor\.$mysqlvermicro with $cve[1]\.$cve[2]\.$cve[3] : ".(mysql_version_le( $cve[1], $cve[2], $cve[3] )?'<=':'>'); debugprint
"Comparing $mysqlvermajor\.$mysqlverminor\.$mysqlvermicro with $cve[1]\.$cve[2]\.$cve[3] : "
. ( mysql_version_le( $cve[1], $cve[2], $cve[3] ) ? '<=' : '>' );
# Avoid not major/minor version corresponding CVEs # Avoid not major/minor version corresponding CVEs
next unless (int($cve[1])==$mysqlvermajor && int($cve[2])==$mysqlverminor); next
if ( int($cve[3]) >= $mysqlvermicro ) { unless ( int( $cve[1] ) == $mysqlvermajor
&& int( $cve[2] ) == $mysqlverminor );
if ( int( $cve[3] ) >= $mysqlvermicro ) {
badprint "$cve[4](<= $cve[1]\.$cve[2]\.$cve[3]) : $cve[6]"; badprint "$cve[4](<= $cve[1]\.$cve[2]\.$cve[3]) : $cve[6]";
$result{'CVE'}{'List'}{$cvefound}="$cve[4](<= $cve[1]\.$cve[2]\.$cve[3]) : $cve[6]"; $result{'CVE'}{'List'}{$cvefound} =
"$cve[4](<= $cve[1]\.$cve[2]\.$cve[3]) : $cve[6]";
$cvefound++; $cvefound++;
} }
} }
close $fh or die "Cannot close $opt{cvefile}: $!"; close $fh or die "Cannot close $opt{cvefile}: $!";
$result{'CVE'}{'nb'}=$cvefound; $result{'CVE'}{'nb'} = $cvefound;
my $cve_warning_notes=""; my $cve_warning_notes = "";
if ( $cvefound == 0 ) { if ( $cvefound == 0 ) {
goodprint "NO SECURITY CVE FOUND FOR YOUR VERSION"; goodprint "NO SECURITY CVE FOUND FOR YOUR VERSION";
return; return;
} }
if ($mysqlvermajor eq 5 and $mysqlverminor eq 5) { if ( $mysqlvermajor eq 5 and $mysqlverminor eq 5 ) {
infoprint "False positive CVE(s) for MySQL and MariaDB 5.5.x can be found."; infoprint
infoprint "Check careful each CVE for those particular versions"; "False positive CVE(s) for MySQL and MariaDB 5.5.x can be found.";
infoprint "Check careful each CVE for those particular versions";
} }
badprint $cvefound . " CVE(s) found for your MySQL release."; badprint $cvefound . " CVE(s) found for your MySQL release.";
push( @generalrec, push( @generalrec,
@ -1102,7 +1118,7 @@ sub get_opened_ports {
} @opened_ports; } @opened_ports;
@opened_ports = sort { $a <=> $b } grep { !/^$/ } @opened_ports; @opened_ports = sort { $a <=> $b } grep { !/^$/ } @opened_ports;
debugprint Dumper \@opened_ports; debugprint Dumper \@opened_ports;
$result{'Network'}{'TCP Opened'}=\@opened_ports; $result{'Network'}{'TCP Opened'} = \@opened_ports;
return @opened_ports; return @opened_ports;
} }
@ -1118,7 +1134,7 @@ sub get_process_memory {
my $pid = shift; my $pid = shift;
my @mem = `ps -p $pid -o rss`; my @mem = `ps -p $pid -o rss`;
return 0 if scalar @mem != 2; return 0 if scalar @mem != 2;
return $mem[1]*1024; return $mem[1] * 1024;
} }
sub get_other_process_memory { sub get_other_process_memory {
@ -1144,7 +1160,7 @@ sub get_other_process_memory {
sub get_os_release { sub get_os_release {
if ( -f "/etc/lsb-release" ) { if ( -f "/etc/lsb-release" ) {
my @info_release = get_file_contents "/etc/lsb-release"; my @info_release = get_file_contents "/etc/lsb-release";
my $os_relase = $info_release[3]; my $os_relase = $info_release[3];
$os_relase =~ s/.*="//; $os_relase =~ s/.*="//;
$os_relase =~ s/"$//; $os_relase =~ s/"$//;
return $os_relase; return $os_relase;
@ -1157,7 +1173,7 @@ sub get_os_release {
if ( -f "/etc/os-release" ) { if ( -f "/etc/os-release" ) {
my @info_release = get_file_contents "/etc/os-release"; my @info_release = get_file_contents "/etc/os-release";
my $os_relase = $info_release[0]; my $os_relase = $info_release[0];
$os_relase =~ s/.*="//; $os_relase =~ s/.*="//;
$os_relase =~ s/"$//; $os_relase =~ s/"$//;
return $os_relase; return $os_relase;
@ -1165,7 +1181,7 @@ sub get_os_release {
if ( -f "/etc/issue" ) { if ( -f "/etc/issue" ) {
my @info_release = get_file_contents "/etc/issue"; my @info_release = get_file_contents "/etc/issue";
my $os_relase = $info_release[0]; my $os_relase = $info_release[0];
$os_relase =~ s/\s+\\n.*//; $os_relase =~ s/\s+\\n.*//;
return $os_relase; return $os_relase;
} }
@ -1177,7 +1193,7 @@ sub get_fs_info() {
my @iinfo = `df -Pi| grep '%'`; my @iinfo = `df -Pi| grep '%'`;
shift @iinfo; shift @iinfo;
@sinfo = map { @sinfo = map {
my $v= $_; my $v = $_;
$v =~ s/.*\s(\d+)%\s+(.*)/$1\t$2/g; $v =~ s/.*\s(\d+)%\s+(.*)/$1\t$2/g;
$v; $v;
} @sinfo; } @sinfo;
@ -1191,7 +1207,7 @@ sub get_fs_info() {
else { else {
infoprint "mount point $2 is using $1 % of total space"; infoprint "mount point $2 is using $1 % of total space";
} }
$result{'Filesystem'}{'Space Pct'}{$2}=$1; $result{'Filesystem'}{'Space Pct'}{$2} = $1;
} }
} }
@ -1212,7 +1228,7 @@ sub get_fs_info() {
else { else {
infoprint "mount point $2 is using $1 % of max allowed inodes"; infoprint "mount point $2 is using $1 % of max allowed inodes";
} }
$result{'Filesystem'}{'Inode Pct'}{$2}=$1; $result{'Filesystem'}{'Inode Pct'}{$2} = $1;
} }
} }
} }
@ -1272,7 +1288,7 @@ sub get_kernel_info() {
infoprint "Information about kernel tuning:"; infoprint "Information about kernel tuning:";
foreach my $param (@params) { foreach my $param (@params) {
infocmd_tab("sysctl $param 2>/dev/null"); infocmd_tab("sysctl $param 2>/dev/null");
$result{'OS'}{'Config'}{$param}=`sysctl -n $param 2>/dev/null`; $result{'OS'}{'Config'}{$param} = `sysctl -n $param 2>/dev/null`;
} }
if ( `sysctl -n vm.swappiness` > 10 ) { if ( `sysctl -n vm.swappiness` > 10 ) {
badprint badprint
@ -1285,8 +1301,11 @@ sub get_kernel_info() {
} }
# only if /proc/sys/sunrpc exists # only if /proc/sys/sunrpc exists
my $tcp_slot_entries=`sysctl -n sunrpc.tcp_slot_table_entries 2>/dev/null`; my $tcp_slot_entries =
if ( -f "/proc/sys/sunrpc" and ($tcp_slot_entries eq '' or $tcp_slot_entries < 100) ) { `sysctl -n sunrpc.tcp_slot_table_entries 2>/dev/null`;
if ( -f "/proc/sys/sunrpc"
and ( $tcp_slot_entries eq '' or $tcp_slot_entries < 100 ) )
{
badprint badprint
"Initial TCP slot entries is < 1M, please consider having a value greater than 100"; "Initial TCP slot entries is < 1M, please consider having a value greater than 100";
push @generalrec, "setup Initial TCP slot entries greater than 100"; push @generalrec, "setup Initial TCP slot entries greater than 100";
@ -1311,33 +1330,33 @@ sub get_kernel_info() {
} }
sub get_system_info() { sub get_system_info() {
$result{'OS'}{'Release'}=get_os_release(); $result{'OS'}{'Release'} = get_os_release();
infoprint get_os_release; infoprint get_os_release;
if (is_virtual_machine) { if (is_virtual_machine) {
infoprint "Machine type : Virtual machine"; infoprint "Machine type : Virtual machine";
$result{'OS'}{'Virtual Machine'}='YES'; $result{'OS'}{'Virtual Machine'} = 'YES';
} }
else { else {
infoprint "Machine type : Physical machine"; infoprint "Machine type : Physical machine";
$result{'OS'}{'Virtual Machine'}='NO'; $result{'OS'}{'Virtual Machine'} = 'NO';
} }
$result{'Network'}{'Connected'}='NO'; $result{'Network'}{'Connected'} = 'NO';
`ping -c 1 ipecho.net &>/dev/null`; `ping -c 1 ipecho.net &>/dev/null`;
my $isConnected = $?; my $isConnected = $?;
if ( $? == 0 ) { if ( $? == 0 ) {
infoprint "Internet : Connected"; infoprint "Internet : Connected";
$result{'Network'}{'Connected'}='YES'; $result{'Network'}{'Connected'} = 'YES';
} }
else { else {
badprint "Internet : Disconnected"; badprint "Internet : Disconnected";
} }
$result{'OS'}{'Type'}=`uname -o`; $result{'OS'}{'Type'} = `uname -o`;
infoprint "Operating System Type : " . infocmd_one "uname -o"; infoprint "Operating System Type : " . infocmd_one "uname -o";
$result{'OS'}{'Kernel'}=`uname -r`; $result{'OS'}{'Kernel'} = `uname -r`;
infoprint "Kernel Release : " . infocmd_one "uname -r"; infoprint "Kernel Release : " . infocmd_one "uname -r";
$result{'OS'}{'Hostname'}=`hostname`; $result{'OS'}{'Hostname'} = `hostname`;
$result{'Network'}{'Internal Ip'}=`hostname -I`; $result{'Network'}{'Internal Ip'} = `hostname -I`;
infoprint "Hostname : " . infocmd_one "hostname"; infoprint "Hostname : " . infocmd_one "hostname";
infoprint "Network Cards : "; infoprint "Network Cards : ";
infocmd_tab "ifconfig| grep -A1 mtu"; infocmd_tab "ifconfig| grep -A1 mtu";
@ -1345,16 +1364,16 @@ sub get_system_info() {
my $httpcli = get_http_cli(); my $httpcli = get_http_cli();
infoprint "HTTP client found: $httpcli" if defined $httpcli; infoprint "HTTP client found: $httpcli" if defined $httpcli;
my $ext_ip=""; my $ext_ip = "";
if ( $httpcli =~ /curl$/ ) { if ( $httpcli =~ /curl$/ ) {
$ext_ip=infocmd_one "$httpcli ipecho.net/plain"; $ext_ip = infocmd_one "$httpcli ipecho.net/plain";
} }
elsif ( $httpcli =~ /wget$/ ) { elsif ( $httpcli =~ /wget$/ ) {
$ext_ip=infocmd_one "$httpcli -q -O - ipecho.net/plain"; $ext_ip = infocmd_one "$httpcli -q -O - ipecho.net/plain";
} }
infoprint "External IP : ".$ext_ip; infoprint "External IP : " . $ext_ip;
$result{'Network'}{'External Ip'}=$ext_ip; $result{'Network'}{'External Ip'} = $ext_ip;
badprint badprint
"External IP : Can't check because of Internet connectivity" "External IP : Can't check because of Internet connectivity"
unless defined($httpcli); unless defined($httpcli);
@ -1362,13 +1381,14 @@ sub get_system_info() {
. infocmd_one "grep 'nameserver' /etc/resolv.conf \| awk '{print \$2}'"; . infocmd_one "grep 'nameserver' /etc/resolv.conf \| awk '{print \$2}'";
infoprint "Logged In users : "; infoprint "Logged In users : ";
infocmd_tab "who"; infocmd_tab "who";
$result{'OS'}{'Logged users'}=`who`; $result{'OS'}{'Logged users'} = `who`;
infoprint "Ram Usages in Mb : "; infoprint "Ram Usages in Mb : ";
infocmd_tab "free -m | grep -v +"; infocmd_tab "free -m | grep -v +";
$result{'OS'}{'Free Memory RAM'}=`free -m | grep -v +`; $result{'OS'}{'Free Memory RAM'} = `free -m | grep -v +`;
infoprint "Load Average : "; infoprint "Load Average : ";
infocmd_tab "top -n 1 -b | grep 'load average:'"; infocmd_tab "top -n 1 -b | grep 'load average:'";
$result{'OS'}{'Load Average'}=`top -n 1 -b | grep 'load average:'`; $result{'OS'}{'Load Average'} = `top -n 1 -b | grep 'load average:'`;
#infoprint "System Uptime Days/(HH:MM) : `uptime | awk '{print $3,$4}' | cut -f1 -d,`"; #infoprint "System Uptime Days/(HH:MM) : `uptime | awk '{print $3,$4}' | cut -f1 -d,`";
} }
@ -1479,10 +1499,11 @@ sub security_recommendations {
goodprint "There are no anonymous accounts for any database users"; goodprint "There are no anonymous accounts for any database users";
} }
if ( mysql_version_le( 5, 1 ) ) { if ( mysql_version_le( 5, 1 ) ) {
badprint "No more password checks for MySQL version <=5.1"; badprint "No more password checks for MySQL version <=5.1";
badprint "MySQL version <=5.1 are deprecated and end of support."; badprint "MySQL version <=5.1 are deprecated and end of support.";
return; return;
} }
# Looking for Empty Password # Looking for Empty Password
@mysqlstatlist = select_array @mysqlstatlist = select_array
"SELECT CONCAT(user, '\@', host) FROM mysql.user WHERE ($PASS_COLUMN_NAME = '' OR $PASS_COLUMN_NAME IS NULL) AND plugin NOT IN ('unix_socket', 'win_socket')"; "SELECT CONCAT(user, '\@', host) FROM mysql.user WHERE ($PASS_COLUMN_NAME = '' OR $PASS_COLUMN_NAME IS NULL) AND plugin NOT IN ('unix_socket', 'win_socket')";
@ -1599,7 +1620,7 @@ sub get_replication_status {
infoprint "No replication setup for this server."; infoprint "No replication setup for this server.";
return; return;
} }
$result{'Replication'}{'status'}= \%myrepl; $result{'Replication'}{'status'} = \%myrepl;
my ($io_running) = $myrepl{'Slave_IO_Running'}; my ($io_running) = $myrepl{'Slave_IO_Running'};
debugprint "IO RUNNING: $io_running "; debugprint "IO RUNNING: $io_running ";
my ($sql_running) = $myrepl{'Slave_SQL_Running'}; my ($sql_running) = $myrepl{'Slave_SQL_Running'};
@ -1662,9 +1683,11 @@ sub mysql_version_ge {
my ( $maj, $min, $mic ) = @_; my ( $maj, $min, $mic ) = @_;
$min ||= 0; $min ||= 0;
$mic ||= 0; $mic ||= 0;
return int($mysqlvermajor) > int($maj) return
|| ( int($mysqlvermajor) == int($maj) && int($mysqlverminor) > int($min) ) int($mysqlvermajor) > int($maj)
|| ( int($mysqlverminor) == int($min) && int($mysqlvermicro) >= int($mic) ); || ( int($mysqlvermajor) == int($maj) && int($mysqlverminor) > int($min) )
|| ( int($mysqlverminor) == int($min)
&& int($mysqlvermicro) >= int($mic) );
} }
# Checks if MySQL version is lower than equal to (major, minor, micro) # Checks if MySQL version is lower than equal to (major, minor, micro)
@ -1672,9 +1695,11 @@ sub mysql_version_le {
my ( $maj, $min, $mic ) = @_; my ( $maj, $min, $mic ) = @_;
$min ||= 0; $min ||= 0;
$mic ||= 0; $mic ||= 0;
return int($mysqlvermajor) < int($maj) return
|| ( int($mysqlvermajor) == int($maj) && int($mysqlverminor) < int($min) ) int($mysqlvermajor) < int($maj)
|| ( int($mysqlverminor) == int($min) && int($mysqlvermicro) <= int($mic) ); || ( int($mysqlvermajor) == int($maj) && int($mysqlverminor) < int($min) )
|| ( int($mysqlverminor) == int($min)
&& int($mysqlvermicro) <= int($mic) );
} }
# Checks if MySQL micro version is lower than equal to (major, minor, micro) # Checks if MySQL micro version is lower than equal to (major, minor, micro)
@ -1818,11 +1843,11 @@ sub check_storage_engines {
( $engine, $size, $count, $dsize, $isize ) = ( $engine, $size, $count, $dsize, $isize ) =
$line =~ /([a-zA-Z_]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/; $line =~ /([a-zA-Z_]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
debugprint "Engine Found: $engine"; debugprint "Engine Found: $engine";
next unless (defined($engine)); next unless ( defined($engine) );
$size=0 unless defined($size); $size = 0 unless defined($size);
$isize=0 unless defined($isize); $isize = 0 unless defined($isize);
$dsize=0 unless defined($dsize); $dsize = 0 unless defined($dsize);
$count=0 unless defined($count); $count = 0 unless defined($count);
$enginestats{$engine} = $size; $enginestats{$engine} = $size;
$enginecount{$engine} = $count; $enginecount{$engine} = $count;
$result{'Engine'}{$engine}{'Table Number'} = $count; $result{'Engine'}{$engine}{'Table Number'} = $count;
@ -1830,15 +1855,15 @@ sub check_storage_engines {
$result{'Engine'}{$engine}{'Data Size'} = $dsize; $result{'Engine'}{$engine}{'Data Size'} = $dsize;
$result{'Engine'}{$engine}{'Index Size'} = $isize; $result{'Engine'}{$engine}{'Index Size'} = $isize;
} }
my $not_innodb=''; my $not_innodb = '';
if ($result{'Variables'}{'innodb_file_per_table'} eq 'OFF') { if ( $result{'Variables'}{'innodb_file_per_table'} eq 'OFF' ) {
$not_innodb="AND NOT ENGINE='InnoDB'"; $not_innodb = "AND NOT ENGINE='InnoDB'";
} }
$result{'Tables'}{'Fragmented tables'} = $result{'Tables'}{'Fragmented tables'} =
[ select_array [ select_array
"SELECT CONCAT(CONCAT(TABLE_SCHEMA, '.'), TABLE_NAME),DATA_FREE FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','performance_schema', 'mysql') AND DATA_LENGTH/1024/1024>100 AND DATA_FREE*100/(DATA_LENGTH+INDEX_LENGTH+DATA_FREE) > 10 AND NOT ENGINE='MEMORY' $not_innodb" "SELECT CONCAT(CONCAT(TABLE_SCHEMA, '.'), TABLE_NAME),DATA_FREE FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','performance_schema', 'mysql') AND DATA_LENGTH/1024/1024>100 AND DATA_FREE*100/(DATA_LENGTH+INDEX_LENGTH+DATA_FREE) > 10 AND NOT ENGINE='MEMORY' $not_innodb"
]; ];
$fragtables = scalar @{$result{'Tables'}{'Fragmented tables'}}; $fragtables = scalar @{ $result{'Tables'}{'Fragmented tables'} };
} }
else { else {
@ -1927,14 +1952,14 @@ sub check_storage_engines {
badprint "Total fragmented tables: $fragtables"; badprint "Total fragmented tables: $fragtables";
push( @generalrec, push( @generalrec,
"Run OPTIMIZE TABLE to defragment tables for better performance" ); "Run OPTIMIZE TABLE to defragment tables for better performance" );
my $total_free=0; my $total_free = 0;
foreach my $table_line (@{$result{'Tables'}{'Fragmented tables'}}) { foreach my $table_line ( @{ $result{'Tables'}{'Fragmented tables'} } ) {
my ($table_name,$data_free)=split(/\s+/,$table_line); my ( $table_name, $data_free ) = split( /\s+/, $table_line );
$data_free=0 if (!defined($data_free) or $data_free eq ''); $data_free = 0 if ( !defined($data_free) or $data_free eq '' );
$data_free=$data_free/1024/1024; $data_free = $data_free / 1024 / 1024;
$total_free+=$data_free; $total_free += $data_free;
push( @generalrec, push( @generalrec,
" OPTIMIZE TABLE $table_name; -- can free $data_free MB"); " OPTIMIZE TABLE $table_name; -- can free $data_free MB" );
} }
push( @generalrec, push( @generalrec,
"Total freed space after theses OPTIMIZE TABLE : $total_free Mb" ); "Total freed space after theses OPTIMIZE TABLE : $total_free Mb" );
@ -2417,12 +2442,14 @@ sub mysql_stats {
. hr_bytes( $mycalc{'per_thread_buffers'} ) . hr_bytes( $mycalc{'per_thread_buffers'} )
. " per thread ($myvar{'max_connections'} max threads)"; . " per thread ($myvar{'max_connections'} max threads)";
infoprint "P_S Max memory usage: " . hr_bytes_rnd( get_pf_memory() ); infoprint "P_S Max memory usage: " . hr_bytes_rnd( get_pf_memory() );
$result{'P_S'}{'memory'}=get_other_process_memory(); $result{'P_S'}{'memory'} = get_other_process_memory();
$result{'P_S'}{'pretty_memory'}=hr_bytes_rnd(get_other_process_memory()); $result{'P_S'}{'pretty_memory'} =
hr_bytes_rnd( get_other_process_memory() );
infoprint "Galera GCache Max memory usage: " infoprint "Galera GCache Max memory usage: "
. hr_bytes_rnd( get_gcache_memory() ); . hr_bytes_rnd( get_gcache_memory() );
$result{'Galera'}{'GCache'}{'memory'}=get_gcache_memory(); $result{'Galera'}{'GCache'}{'memory'} = get_gcache_memory();
$result{'Galera'}{'GCache'}{'pretty_memory'}=hr_bytes_rnd(get_gcache_memory()); $result{'Galera'}{'GCache'}{'pretty_memory'} =
hr_bytes_rnd( get_gcache_memory() );
if ( $opt{buffers} ne 0 ) { if ( $opt{buffers} ne 0 ) {
infoprint "Global Buffers"; infoprint "Global Buffers";
@ -2564,13 +2591,16 @@ sub mysql_stats {
} }
# name resolution # name resolution
if (not defined($result{'Variables'}{'skip_name_resolve'})) { if ( not defined( $result{'Variables'}{'skip_name_resolve'} ) ) {
infoprint "Skipped name resolution test due to missing skip_name_resolve in system variables. ?More info?"; infoprint
} elsif( $result{'Variables'}{'skip_name_resolve'} eq 'OFF') { "Skipped name resolution test due to missing skip_name_resolve in system variables. ?More info?";
}
elsif ( $result{'Variables'}{'skip_name_resolve'} eq 'OFF' ) {
badprint badprint
"name resolution is active : a reverse name resolution is made for each new connection and can reduce performance"; "name resolution is active : a reverse name resolution is made for each new connection and can reduce performance";
push( @generalrec, push( @generalrec,
"Configure your accounts with ip or subnets only, then update your configuration with skip-name-resolve=1" ); "Configure your accounts with ip or subnets only, then update your configuration with skip-name-resolve=1"
);
} }
# Query cache # Query cache
@ -2580,15 +2610,15 @@ sub mysql_stats {
push( @generalrec, push( @generalrec,
"Upgrade MySQL to version 4+ to utilize query caching" ); "Upgrade MySQL to version 4+ to utilize query caching" );
} }
elsif ( mysql_version_ge( 5, 5 ) and !mysql_version_ge( 10, 1 ) ) { elsif ( mysql_version_ge( 5, 5 ) and !mysql_version_ge( 10, 1 ) ) {
if ( $myvar{'query_cache_type'} ne "OFF" ) { if ( $myvar{'query_cache_type'} ne "OFF" ) {
badprint badprint
"Query cache may be disabled by default due to mutex contention."; "Query cache may be disabled by default due to mutex contention.";
push( @adjvars, "query_cache_type (=0)" ); push( @adjvars, "query_cache_type (=0)" );
} }
else { else {
goodprint goodprint
"Query cache is disabled by default due to mutex contention on multiprocessor machines."; "Query cache is disabled by default due to mutex contention on multiprocessor machines.";
} }
} }
elsif ( $myvar{'query_cache_size'} < 1 ) { elsif ( $myvar{'query_cache_size'} < 1 ) {
@ -2754,28 +2784,33 @@ sub mysql_stats {
badprint "Thread cache is disabled"; badprint "Thread cache is disabled";
push( @generalrec, "Set thread_cache_size to 4 as a starting value" ); push( @generalrec, "Set thread_cache_size to 4 as a starting value" );
push( @adjvars, "thread_cache_size (start at 4)" ); push( @adjvars, "thread_cache_size (start at 4)" );
} else { }
if ( defined($myvar{'thread_handling'}) and $myvar{'thread_handling'} eq 'pools-of-threads') { else {
infoprint "Thread cache hit rate: not used with pool-of-threads"; if ( defined( $myvar{'thread_handling'} )
} else { and $myvar{'thread_handling'} eq 'pools-of-threads' )
if ( $mycalc{'thread_cache_hit_rate'} <= 50 ) { {
badprint infoprint "Thread cache hit rate: not used with pool-of-threads";
"Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% (" }
. hr_num( $mystat{'Threads_created'} ) else {
. " created / " if ( $mycalc{'thread_cache_hit_rate'} <= 50 ) {
. hr_num( $mystat{'Connections'} ) badprint
. " connections)"; "Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% ("
push( @adjvars, . hr_num( $mystat{'Threads_created'} )
"thread_cache_size (> $myvar{'thread_cache_size'})" ); . " created / "
} else { . hr_num( $mystat{'Connections'} )
goodprint . " connections)";
"Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% (" push( @adjvars,
. hr_num( $mystat{'Threads_created'} ) "thread_cache_size (> $myvar{'thread_cache_size'})" );
. " created / " }
. hr_num( $mystat{'Connections'} ) else {
. " connections)"; goodprint
"Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% ("
. hr_num( $mystat{'Threads_created'} )
. " created / "
. hr_num( $mystat{'Connections'} )
. " connections)";
}
} }
}
} }
# Table cache # Table cache
@ -3113,9 +3148,10 @@ sub mysqsl_pfs {
infoprint "Performance schema is enabled."; infoprint "Performance schema is enabled.";
infoprint "Memory used by P_S: " . hr_bytes( get_pf_memory() ); infoprint "Memory used by P_S: " . hr_bytes( get_pf_memory() );
if (grep /^sys$/, select_array("SHOW DATABASES")) { if ( grep /^sys$/, select_array("SHOW DATABASES") ) {
infoprint "Sys schema is installed."; infoprint "Sys schema is installed.";
} else { }
else {
infoprint "Sys schema isn't installed."; infoprint "Sys schema isn't installed.";
return; return;
} }
@ -3260,12 +3296,12 @@ sub mariadb_galera {
next unless $gvar =~ /^wsrep.*/; next unless $gvar =~ /^wsrep.*/;
next if $gvar eq 'wsrep_provider_options'; next if $gvar eq 'wsrep_provider_options';
debugprint "\t" . trim($gvar) . " = " . $myvar{$gvar}; debugprint "\t" . trim($gvar) . " = " . $myvar{$gvar};
$result{'Galera'}{'variables'}{$gvar}= $myvar{$gvar}; $result{'Galera'}{'variables'}{$gvar} = $myvar{$gvar};
} }
debugprint "Galera wsrep provider Options:"; debugprint "Galera wsrep provider Options:";
my @galera_options = get_wsrep_options; my @galera_options = get_wsrep_options;
$result{'Galera'}{'wsrep options'}=get_wsrep_options(); $result{'Galera'}{'wsrep options'} = get_wsrep_options();
foreach my $gparam (@galera_options) { foreach my $gparam (@galera_options) {
debugprint "\t" . trim($gparam); debugprint "\t" . trim($gparam);
} }
@ -3273,25 +3309,25 @@ sub mariadb_galera {
foreach my $gstatus ( keys %mystat ) { foreach my $gstatus ( keys %mystat ) {
next unless $gstatus =~ /^wsrep.*/; next unless $gstatus =~ /^wsrep.*/;
debugprint "\t" . trim($gstatus) . " = " . $mystat{$gstatus}; debugprint "\t" . trim($gstatus) . " = " . $mystat{$gstatus};
$result{'Galera'}{'status'}{$gstatus}= $myvar{$gstatus}; $result{'Galera'}{'status'}{$gstatus} = $myvar{$gstatus};
} }
infoprint "GCache is using " infoprint "GCache is using "
. hr_bytes_rnd( get_wsrep_option('gcache.mem_size') ); . hr_bytes_rnd( get_wsrep_option('gcache.mem_size') );
my @primaryKeysNbTables = select_array( my @primaryKeysNbTables = select_array(
"Select CONCAT(c.table_schema,CONCAT('.', c.table_name)) "Select CONCAT(c.table_schema,CONCAT('.', c.table_name))
from information_schema.columns c from information_schema.columns c
join information_schema.tables t using (TABLE_SCHEMA, TABLE_NAME) join information_schema.tables t using (TABLE_SCHEMA, TABLE_NAME)
where c.table_schema not in ('mysql', 'information_schema', 'performance_schema') where c.table_schema not in ('mysql', 'information_schema', 'performance_schema')
and t.table_type != 'VIEW' and t.table_type != 'VIEW'
group by c.table_schema,c.table_name group by c.table_schema,c.table_name
having sum(if(c.column_key in ('PRI','UNI'), 1,0)) = 0" having sum(if(c.column_key in ('PRI','UNI'), 1,0)) = 0"
); );
if ( scalar(@primaryKeysNbTables) > 0 ) { if ( scalar(@primaryKeysNbTables) > 0 ) {
badprint "Following table(s) don't have primary key:"; badprint "Following table(s) don't have primary key:";
foreach my $badtable (@primaryKeysNbTables) { foreach my $badtable (@primaryKeysNbTables) {
badprint "\t$badtable"; badprint "\t$badtable";
push @{$result{'Tables without PK'}}, $badtable; push @{ $result{'Tables without PK'} }, $badtable;
} }
} }
else { else {
@ -3348,6 +3384,7 @@ having sum(if(c.column_key in ('PRI','UNI'), 1,0)) = 0"
badprint badprint
"There are $nbNodesSize nodes in wsrep_cluster_size. Prefer 3 or 5 nodes architecture."; "There are $nbNodesSize nodes in wsrep_cluster_size. Prefer 3 or 5 nodes architecture.";
} }
# wsrep_cluster_address doesn't include garbd nodes # wsrep_cluster_address doesn't include garbd nodes
if ( $nbNodes > $nbNodesSize ) { if ( $nbNodes > $nbNodesSize ) {
badprint badprint
@ -3393,13 +3430,22 @@ having sum(if(c.column_key in ('PRI','UNI'), 1,0)) = 0"
} }
if ( trim( $myvar{'wsrep_sst_method'} ) !~ "^xtrabackup.*" ) { if ( trim( $myvar{'wsrep_sst_method'} ) !~ "^xtrabackup.*" ) {
badprint "Galera SST method is not xtrabackup based."; badprint "Galera SST method is not xtrabackup based.";
push( @adjvars, "set up parameter wsrep_sst_method to xtrabackup based parameter" ); push( @adjvars,
"set up parameter wsrep_sst_method to xtrabackup based parameter"
);
} }
else { else {
goodprint "SST Method is based on xtrabackup."; goodprint "SST Method is based on xtrabackup.";
} }
if ( (defined($myvar{'wsrep_OSU_method'}) && trim( $myvar{'wsrep_OSU_method'} ) eq "TOI") || if (
(defined($myvar{'wsrep_osu_method'}) && trim( $myvar{'wsrep_osu_method'} ) eq "TOI") ) { (
defined( $myvar{'wsrep_OSU_method'} )
&& trim( $myvar{'wsrep_OSU_method'} ) eq "TOI"
)
|| ( defined( $myvar{'wsrep_osu_method'} )
&& trim( $myvar{'wsrep_osu_method'} ) eq "TOI" )
)
{
goodprint "TOI is default mode for upgrade."; goodprint "TOI is default mode for upgrade.";
} }
else { else {
@ -3591,20 +3637,38 @@ sub mysql_innodb {
} }
# InnoDB Used Buffer Pool Size vs CHUNK size # InnoDB Used Buffer Pool Size vs CHUNK size
if ( ! defined ($myvar{'innodb_buffer_pool_chunk_size'}) ) { if ( !defined( $myvar{'innodb_buffer_pool_chunk_size'} ) ) {
infoprint "InnoDB Buffer Pool Chunk Size not used or defined in your version"; infoprint
} else { "InnoDB Buffer Pool Chunk Size not used or defined in your version";
infoprint "Number of InnoDB Buffer Pool Chunk : ". int($myvar{'innodb_buffer_pool_size'}) / int( $myvar{'innodb_buffer_pool_chunk_size'}) .
" for ". $myvar{'innodb_buffer_pool_instances'}. " Buffer Pool Instance(s)";
if ( int($myvar{'innodb_buffer_pool_size'}) % ( int( $myvar{'innodb_buffer_pool_chunk_size'}) * int($myvar{'innodb_buffer_pool_instances'})) eq 0 ) {
goodprint "innodb_buffer_pool_size is aligned with value innodb_buffer_pool_chunk_size and innodb_buffer_pool_instances";
} else {
badprint "innodb_buffer_pool_size is not aligned with value innodb_buffer_pool_chunk_size and innodb_buffer_pool_instances";
#push( @adjvars, "Adjust innodb_buffer_pool_instances, innodb_buffer_pool_chunk_size with innodb_buffer_pool_size" );
push( @adjvars, "innodb_buffer_pool_size must always be equal to or a multiple of innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances" );
}
} }
else {
infoprint "Number of InnoDB Buffer Pool Chunk : "
. int( $myvar{'innodb_buffer_pool_size'} ) /
int( $myvar{'innodb_buffer_pool_chunk_size'} ) . " for "
. $myvar{'innodb_buffer_pool_instances'}
. " Buffer Pool Instance(s)";
if (
int( $myvar{'innodb_buffer_pool_size'} ) % (
int( $myvar{'innodb_buffer_pool_chunk_size'} ) *
int( $myvar{'innodb_buffer_pool_instances'} )
) eq 0
)
{
goodprint
"innodb_buffer_pool_size is aligned with value innodb_buffer_pool_chunk_size and innodb_buffer_pool_instances";
}
else {
badprint
"innodb_buffer_pool_size is not aligned with value innodb_buffer_pool_chunk_size and innodb_buffer_pool_instances";
#push( @adjvars, "Adjust innodb_buffer_pool_instances, innodb_buffer_pool_chunk_size with innodb_buffer_pool_size" );
push( @adjvars,
"innodb_buffer_pool_size must always be equal to or a multiple of innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances"
);
}
}
# InnoDB Read efficency # InnoDB Read efficency
if ( defined $mycalc{'pct_read_efficiency'} if ( defined $mycalc{'pct_read_efficiency'}
&& $mycalc{'pct_read_efficiency'} < 90 ) && $mycalc{'pct_read_efficiency'} < 90 )
@ -3965,8 +4029,8 @@ ENDSQL
# Take the two recommendation arrays and display them at the end of the output # Take the two recommendation arrays and display them at the end of the output
sub make_recommendations { sub make_recommendations {
$result{'Recommendations'}=\@generalrec; $result{'Recommendations'} = \@generalrec;
$result{'Adjust variables'}=\@adjvars; $result{'Adjust variables'} = \@adjvars;
subheaderprint "Recommendations"; subheaderprint "Recommendations";
if ( @generalrec > 0 ) { if ( @generalrec > 0 ) {
prettyprint "General recommendations:"; prettyprint "General recommendations:";
@ -4056,7 +4120,7 @@ sub dump_result {
debugprint "HTML REPORT: $opt{'reportfile'}"; debugprint "HTML REPORT: $opt{'reportfile'}";
if ( $opt{'reportfile'} ne 0 ) { if ( $opt{'reportfile'} ne 0 ) {
eval {require Text::Template}; eval { require Text::Template };
if ($@) { if ($@) {
badprint "Text::Template Module is needed."; badprint "Text::Template Module is needed.";
exit 1; exit 1;
@ -4080,7 +4144,7 @@ sub dump_result {
close $fh; close $fh;
} }
if ( $opt{'json'} ne 0 ) { if ( $opt{'json'} ne 0 ) {
eval {require JSON}; eval { require JSON };
if ($@) { if ($@) {
print "$bad JSON Module is needed.\n"; print "$bad JSON Module is needed.\n";
exit 1; exit 1;
@ -4108,35 +4172,34 @@ sub which {
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# BEGIN 'MAIN' # BEGIN 'MAIN'
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
headerprint; # Header Print headerprint; # Header Print
validate_tuner_version; # Check last version validate_tuner_version; # Check last version
mysql_setup; # Gotta login first mysql_setup; # Gotta login first
os_setup; # Set up some OS variables os_setup; # Set up some OS variables
get_all_vars; # Toss variables/status into hashes get_all_vars; # Toss variables/status into hashes
get_tuning_info; # Get information about the tuning connexion get_tuning_info; # Get information about the tuning connexion
validate_mysql_version; # Check current MySQL version validate_mysql_version; # Check current MySQL version
check_architecture; # Suggest 64-bit upgrade
check_architecture; # Suggest 64-bit upgrade system_recommendations; # avoid to many service on the same host
system_recommendations; # avoid to many service on the same host check_storage_engines; # Show enabled storage engines
check_storage_engines; # Show enabled storage engines mysql_databases; # Show informations about databases
mysql_databases; # Show informations about databases mysql_indexes; # Show informations about indexes
mysql_indexes; # Show informations about indexes security_recommendations; # Display some security recommendations
security_recommendations; # Display some security recommendations cve_recommendations; # Display related CVE
cve_recommendations; # Display related CVE calculations; # Calculate everything we need
calculations; # Calculate everything we need mysql_stats; # Print the server stats
mysql_stats; # Print the server stats mysqsl_pfs; # Print Performance schema info
mysqsl_pfs; # Print Performance schema info mariadb_threadpool; # Print MaraiDB ThreadPool stats
mariadb_threadpool; # Print MaraiDB ThreadPool stats mysql_myisam; # Print MyISAM stats
mysql_myisam; # Print MyISAM stats mariadb_ariadb; # Print MaraiDB AriaDB stats
mariadb_ariadb; # Print MaraiDB AriaDB stats mysql_innodb; # Print InnoDB stats
mysql_innodb; # Print InnoDB stats mariadb_tokudb; # Print MaraiDB TokuDB stats
mariadb_tokudb; # Print MaraiDB TokuDB stats mariadb_galera; # Print MaraiDB Galera Cluster stats
mariadb_galera; # Print MaraiDB Galera Cluster stats get_replication_status; # Print replication info
get_replication_status; # Print replication info make_recommendations; # Make recommendations based on stats
make_recommendations; # Make recommendations based on stats dump_result; # Dump result if debug is on
dump_result; # Dump result if debug is on close_outputfile; # Close reportfile if needed
close_outputfile; # Close reportfile if needed
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# END 'MAIN' # END 'MAIN'