TOMODACHI SHELL
Free Palestine !! - Free Gaza !!
Current File : //../opt/managed_servers/scripts/free_memory.sh |
readonly FREE_MEMORY_CHECK_DATA="${BACKGROUND_DATA}/free_memory_check.data";
readonly FREE_MEMORY_CHECK_ERRORS="${BACKGROUND_DATA}/free_memory_check.errors";
readonly INNODB_VALS_TOO_LOW=2;
set_new_innodb_vars(){
declare -A human_multipliers;
human_multipliers=([K]=1000 [M]=1000000 [G]=1000000000);
local innodb_vars="$@";
local mysql_config="/etc/my.cnf";
local mysql_config_backup="${mysql_config}_$(date +%s)";
rsync -q $mysql_config $mysql_config_backup;
/scripts/restartsrv_mysql --status &>/dev/null || return 1;
for i_var in $innodb_vars; do
local var_name=$(cut -d= -f1 <<< $i_var);
local multiplier=$(cut -d= -f2 <<< $i_var | grep -oP "[a-zA-Z]$" | tr [:lower:] [:upper:]);
local i_value=$(cut -d= -f2 <<< $i_var | grep -oP "[0-9]+");
local i_value_min;
if [[ $multiplier && ${human_multipliers[$multiplier]} ]]; then
i_value=$(( $i_value * ${human_multipliers[$multiplier]} ));
fi;
if [[ $var_name == "innodb_buffer_pool_size" ]]; then
i_value_min=20000000;
elif [[ $var_name == "innodb_log_file_size" ]]; then
i_value_min=5000000;
fi;
if [[ $i_value -lt $i_value_min ]]; then
return $INNODB_VALS_TOO_LOW;
fi;
local i_value_new=$(( $i_value / 2 ));
sed -i "s/$i_var/$var_name=$i_value_new/" $mysql_config;
# Restore the mysql config backup if a value wasn't set in the mysql config file
if [[ -z $(grep "^$var_name=$i_value_new$" $mysql_config) ]]; then
rsync -q $mysql_config_backup $mysql_config;
rm -f $mysql_config_backup;
return 1;
fi;
done;
/scripts/restartsrv_mysql &>/dev/null && {
rm -f $mysql_config_backup;
return 0;
} || {
rsync -q $mysql_config_backup $mysql_config;
rm -f $mysql_config_backup;
return 1;
}
}
innodb_vars_optimization(){
local innodb_buffer_pool_size=$(grep innodb_buffer_pool_size <<< "$innodb_vars" | tail -1);
local innodb_log_file_size=$(grep innodb_log_file_size <<< "$innodb_vars" | tail -1);
local cur_cpu_utilization=$(top -bn1 | head -5 | grep "^%Cpu(s)" | grep -oP "(?<=ni, ).+(?= id)" | tr -d ' ' |
awk '{printf "%d", (100 - $1)}');
local cpu_utilization_threshold=80; # percentage
if [[ $cur_cpu_utilization -lt $cpu_utilization_threshold ]]; then
set_new_innodb_vars "$innodb_buffer_pool_size $innodb_log_file_size" && {
ram_usage_data[service_status]=$SERVICE_ACTIVE;
ram_usage_data[auto_fix_status]=$AUTO_FIX_SUCCESS;
} || {
if [[ $? -eq $INNODB_VALS_TOO_LOW ]]; then
# optimization unavailable due to minimal innodb values limits
ram_usage_data[recommendations]=$(printf "%s\n\n%s\n\n%s" \
"$(memory_recommendation_mysql_optimization_unavailable_minimal_innodb_vals)"\
"$(memory_recommendation_generic)"\
"$(plan_upgrade_recommendation_as_alternative)" | json_escape);
else
ram_usage_data[service_status]=$SERVICE_DOWN;
ram_usage_data[auto_fix_status]=$AUTO_FIX_FAIL;
fi;
};
else
# innodb values cannot be optimized due to high CPU usage
ram_usage_data[recommendations]=$(printf "%s\n\n%s\n\n%s" \
"$(memory_recommendation_mysql_optimization_unavailable_high_cpu_usage)"\
"$(memory_recommendation_generic)"\
"$(plan_upgrade_recommendation_as_alternative)" | json_escape);
fi;
}
memory_recommendation_mysql(){
local mysql_config="/etc/my.cnf";
local innodb_vars=$(grep -e ^innodb_buffer_pool_size -e ^innodb_log_file_size $mysql_config 2>/dev/null);
if [[ $(management_type_check) == $COMPLETE && -n $innodb_vars ]]; then
# If ram_usage_data[auto_fix_status] is unset, notifications will not be sent automatically.
#unset ram_usage_data[auto_fix_status]; # Currently disabled, to sent notifications automatically.
innodb_vars_optimization;
elif [[ $(management_type_check) == $BASIC && -n $innodb_vars ]]; then
ram_usage_data[recommendations]=$(printf "%s\n\n%s\n\n%s" "$(memory_recommendation_mysql_body)"\
"$(memory_recommendation_generic)" "$(plan_upgrade_recommendation_as_alternative)" |
json_escape);
fi;
}
memory_check_recommendation(){
declare -a proc;
readarray -t proc <<< "$(ps -eo user,pid,%mem,rss,command)";
local ps_head=$(head -1 <<< "${proc[0]}");
# Processes under %1 ram usage will be filtered out
local processes_sorted=$(process_filter proc);
local top_proc=$(head -1 <<< "$processes_sorted");
local mysql_match="mysql|maria";
# Tickets will not be sent automatically for servers with Complete management when the memory load is unclear
if [[ $(management_type_check) == $COMPLETE ]]; then
unset ram_usage_data[auto_fix_status];
fi;
# Check if mysql is the top ram usage process
if [[ -n $(grep -iE "$mysql_match" <<< "$top_proc") ]]; then
memory_recommendation_mysql;
else
ram_usage_data[recommendations]=$(printf "%s\n\n%s" "$(memory_recommendation_generic)"\
"$(plan_upgrade_recommendation_as_alternative)" | json_escape);
fi;
ram_usage_data[details]=$(echo -e "${ps_head}\n${processes_sorted}" | json_escape);
}
process_filter(){
local name=$1[@];
shift;
local arr=("${!name}");
local usage_threshold=1;
for (( i = 1; $i < ${#arr[@]}; ((++i)) )); do
if [[ $(tr -s ' ' <<< "${arr[$i]}" | cut -d' ' -f3 | cut -d. -f1) -ge $usage_threshold ]]; then
echo "${arr[$i]}";
fi;
done | sort -rnk3;
}
bytes_to_human_readable(){
awk 'function bytes_to_hread(bytes){
mult_c=split("K M G", mult)
c=0
while(bytes > 1000 && c < mult_c){
bytes=(bytes / 1000)
++c
}
printf "%.2f %s", bytes, mult[c]
}
bytes_to_hread($1)
' <<< "$1";
}
memory_check_main(){
local critical_threshold=10;
#local warning_threshold=15;
declare -A ram_usage_data;
local free_cmd_bytes=$(free -b);
local ram_total_bytes=$(grep Mem: <<< "$free_cmd_bytes" | awk {'print $2'});
local ram_free_bytes=$(grep Mem: <<< "$free_cmd_bytes" | awk {'print $7'});
ram_usage_data[ram_total]=$(bytes_to_human_readable "$(grep Mem: <<< "$free_cmd_bytes" | awk {'print $2'})");
ram_usage_data[ram_free]=$(bytes_to_human_readable "$(grep Mem: <<< "$free_cmd_bytes" | awk {'print $7'})");
local free_ram_percentage=$(( $ram_free_bytes * 100 / $ram_total_bytes ));
ram_usage_data[free_percent]="$free_ram_percentage";
ram_usage_data[auto_fix_status]=$AUTO_FIX_NOPE;
if [[ $free_ram_percentage -lt $critical_threshold ]]; then
ram_usage_data[service_status]=$SERVICE_DOWN;
memory_check_recommendation;
#elif [[ $free_ram_percentage -lt $warning_threshold ]]; then
# ram_usage_data[service_status]=$SERVICE_WARNING;
# memory_check_recommendation;
else
ram_usage_data[service_status]=$SERVICE_ACTIVE;
fi;
bash_arr_to_json ram_usage_data ${!ram_usage_data[@]} > "$FREE_MEMORY_CHECK_DATA";
}
memory_check(){
run_check_in_background "memory_check_main" "$FREE_MEMORY_CHECK_DATA" "$FREE_MEMORY_CHECK_ERRORS"\
"${CHECK_LOCKS_DIR}/${FUNCNAME}.lock";
}
TOMODACHI | Tempest Hacker