Skip to content

Instantly share code, notes, and snippets.

@cPLevey
Created June 10, 2016 07:24
Show Gist options
  • Save cPLevey/1614b6f207bd4fb52d8f3d999a507162 to your computer and use it in GitHub Desktop.
Save cPLevey/1614b6f207bd4fb52d8f3d999a507162 to your computer and use it in GitHub Desktop.
Site5 cPanel Update "Slowdown" Hook
#!/bin/bash
# Pre-upcp hook which will deny upcp in case the server already has IO,
# chef-client, cdp etc. are running..!
# Story: https://wwwhosting.atlassian.net/browse/SH-222
# Set limit load avg. for VPS/hardware
# Defaults to 6 for VPS and 10 for hardware ones
if [[ $(/sbin/lspci | wc -l) -eq 0 ]]; then
limit_load=6
else
limit_load=10
fi
limit_iowait=40
# Maximum retries
max_wait=6
# Log
log="/var/log/upcp/slowdown-upcp-hook.log"
_log() {
echo "$(date '+%m-%d-%Y_%H:%M') $1" >> $log
}
# Failed update tracker
tracker="/usr/local/cpanel/logs/failed.upcp"
# Alert e-mail
alert_email="[email protected]"
# Failure points
failure_points=""
# Force run
force="/etc/force_upcp"
## Functions ##
# Check if hcp is doing its thing
_check_hcp() {
if [ -x /usr/sbin/hcp ] && /usr/sbin/hcp -l | grep -q "Virtual Device:" ; then
failure_points="CDP $failure_points"
fi
}
# See if load avg. is above what's set
_check_loadavg() {
load=$(cut -f1 -d. /proc/loadavg)
io_wait=$(/usr/bin/iostat | awk '{print $5}' | grep -A1 '%iowait' | tail -1 | cut -f1 -d.)
if [[ $load -gt $limit_load || $io_wait -gt $limit_iowait ]]; then
failure_points="LOAD $failure_points"
fi
}
# Check if chef is running
_check_chef() {
if pgrep -u root chef-client &>/dev/null ; then
failure_points="CHEF $failure_points"
fi
}
# Check if it's peak hour
_peak_hours() {
cur_time_hour=$(date +"%H" | sed 's/^0*//')
cur_time_min=$(date +"%M" | sed 's/^0*//')
if seq 6 11 | grep -w $cur_time_hour ; then
sleep_hours=$(( 11 - cur_time_hour ))
sleep_mins=$(( 60 - cur_time_min ))
sleep_for=$(( sleep_hours * 3600 + sleep_mins * 60 ))
echo "$(date '+%m-%d-%Y_%H:%M') Stalling upcp for $sleep_for seconds due to: Peak Hours detected." >> $log
sleep $sleep_for
fi
}
# Upcp killer script
_upcp_killer() {
if [ ! -f $tracker ]; then
touch $tracker
else
if find $tracker -mtime +3 1>/dev/null 2>&1; then
mail_subject="Forcing upcp run on server $(hostname)"
mail_body="Forcing upcp. \n\n Last 20 lines of $log: \n\n $(tail -20 $log)"
_log "Forcing upcp run"
echo -e "$mail_body" | mail -s "$mail_subject" "$alert_email"
exit 0
fi
fi
pgrep -u root "cPanel Update" | while read -r pid ; do
kill -15 $pid
done
_log "Update denied"
}
## Start ##
_log "Hook triggered"
if [ -f $force ]; then
_log "Forcing upcp run"
exit 0
else
for ((try=1; try<=max_wait; try++)) ; do
failure_points=""
# _peak_hours should be always called first before any other failure points
# as calling it after might lead to false positives
_peak_hours
_check_hcp
_check_loadavg
_check_chef
if [ ! "$failure_points" ]; then
_log "Update allowed to run"
exit 0
else
# Sleep 30 mins on the first try, 60 on the next, 90, 120 ..
wait_for=$((1800*$try))
_log "Stalling upcp for $wait_for seconds due to: $failure_points"
sleep $wait_for
fi
done
fi
_upcp_killer && exit 1
@EvilBash0r
Copy link

EvilBash0r commented Aug 8, 2018

You shouldn't be taking the cPanel client's custom scripts from their servers and putting them to public Git repos...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment