Skip to content

Instantly share code, notes, and snippets.

@weldpua2008
Created May 11, 2017 17:43
Show Gist options
  • Select an option

  • Save weldpua2008/44e6884ac2bc6d0c129ddf03a9336656 to your computer and use it in GitHub Desktop.

Select an option

Save weldpua2008/44e6884ac2bc6d0c129ddf03a9336656 to your computer and use it in GitHub Desktop.
#!/bin/bash
#################################################################################
# This tool can sample backtraces for memory allocations based on glibc's builtins
# (malloc, calloc, realloc) that have not been freed (via free) in the sampling time period.
#################################################################################
# Author Valeriy Soloviov <weldpua2008@gmail.com>
ZABBIX_SCHED_PERIOD=600
PROFILE_FILENAME=/tlvmedia/code/www/sample-bt-leaks_current.svg
PROFILE_FILENAME_HOURLY=/tlvmedia/code/www/sample-bt-leaks_hourly.svg
PROFILE_FILENAME_DAYLY=/tlvmedia/code/www/sample-bt-leaks_dayly.svg
PROFILE_FILENAME_WEEKLY=/tlvmedia/code/www/sample-bt-leaks_weekly.svg
PROFILE_FILENAME_HTML=/tlvmedia/code/www/sample-bt-leaks.html
PROFILE_FILENAME_HTML_BCK=/tlvmedia/code/www/sample-bt-leaks.html.back
TMP_PROFILE_FILENAME=/tmp/sample-bt-leaks_current.svg
TMP_PROFILE_FILENAME_RAW=/tmp/sample-bt-leaks_result.cbt
TMP_FILES_BT=/tmp/sample-bt-leaks_result-fix1.bt
TMP_FILES_CDB=/tmp/sample-bt-leaks.cbt
IMG_HOSTNAME=$(hostname)
MOVEBACK_HTML="no"
ps -o pid= -C $(basename "$0")|grep -v $$|tr -d ' '| grep -E '[[:digit:]]'
if [ $? -eq 0 ];then
echo "Job is already running"
exit 1
fi
set -oe pipefail
if [ ! -e "/tlvmedia/code/www/" ];then
echo "/tlvmedia/code/www is not exist"
exit 1
fi
function on_exit()
{
local _exit_code=${1:-1}
if [[ $_exit_code -eq 0 ]]; then
echo "SUCCESSFULLY"
# [ -e "$LOCK_ERROR" ] && $SUDO rm -f $LOCK_ERROR &> /dev/null
else
echo "FAILED"
if [ "${MOVEBACK_HTML:-no}" = "yes" ];then
echo "moved back $PROFILE_FILENAME_HTML_BCK -> $PROFILE_FILENAME_HTML"
if [ -e "$PROFILE_FILENAME_HTML_BCK" ];then
[ -e "$PROFILE_FILENAME_HTML" ] && $SUDO rm -f "$PROFILE_FILENAME_HTML"
$SUDO mv "$PROFILE_FILENAME_HTML_BCK" "$PROFILE_FILENAME_HTML" || true
fi
fi
fi
exit $_exit_code
}
trap 'on_exit $?' EXIT HUP TERM INT
[ "$(id -u)" != "0" ] && SUDO=$(which sudo 2> /dev/null||echo "sudo")|| SUDO=""
# Zabbix checks
if [[ "$1" = "debug" ]]; then
set -x
elif [ "$1" = "zabbix" ];then
if [ -e "${PROFILE_FILENAME}" ];then
if [ $(($(date +%s) - $(stat -c %Y "${PROFILE_FILENAME}" || echo 0) )) -lt ${ZABBIX_SCHED_PERIOD:-3600} ];then
echo "No need updates"
exit 0;
fi
fi
fi
# getting pid of nginx/openresty
nginx_pid=$($SUDO ps -o pid,ppid= --no-headers --sort=-pcpu -C nginx|awk '$2!=1 {print $1;exit}')
[[ "${nginx_pid:-}" = "" ]] && exit 1
# checking if somebody is running the strapxx
$SUDO ps -Af|grep -E 'stap|lj-lua-stacks|lj-vm-states'|grep -v grep -q && sleep 5 || true
OUTPUT=$( { $SUDO /usr/src/stapxx/stap++ /usr/src/stapxx/samples/sample-bt-leaks.sxx -x ${nginx_pid:-} --arg time=5 -D STP_NO_OVERLOAD -D MAXMAPENTRIES=10000 > ${TMP_FILES_BT} ;} 2>&1 )
n=$( wc -l < $TMP_FILES_BT )
if [ $n -lt 1 ];then
sleep 6
OUTPUT=$( { $SUDO /usr/src/stapxx/stap++ /usr/src/stapxx/samples/sample-bt-leaks.sxx -x ${nginx_pid:-} --arg time=5 -D STP_NO_OVERLOAD -D MAXMAPENTRIES=10000 > ${TMP_FILES_BT} ;} 2>&1 )
n=$( wc -l < $TMP_FILES_BT )
if [ $n -lt 1 ];then
echo "Error stap++: ${OUTPUT}"
exit 1
fi
fi
$SUDO /usr/src/FlameGraph/stackcollapse-stap.pl $TMP_FILES_BT > $TMP_FILES_CDB
$SUDO /usr/src/FlameGraph/flamegraph.pl --countname=bytes --title="Memory Leak Flame Graph for (${IMG_HOSTNAME}) at `date`" $TMP_PROFILE_FILENAME_RAW $TMP_FILES_CDB| $SUDO tee ${TMP_PROFILE_FILENAME} > /dev/null
$SUDO /bin/cp $TMP_PROFILE_FILENAME ${PROFILE_FILENAME}
function html_header(){
local htmlfile=${1:-}
[ "$htmlfile" = "" ] && exit 1
cat <<EOF | $SUDO tee $htmlfile > /dev/null
<!DOCTYPE html>
<html>
<head>
<style>
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
li {
float: left;
}
li a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover:not(.active) {
background-color: #111;
}
.active {
background-color: #4CAF50;
}
</style>
</head>
<body>
<ul>
EOF
}
# adds a file to a html report
function html_add_file(){
local htmlfile=${1:-}
local filepath=${2:-current.svg}
local class_active="${4:-no}"
local li_class=""
[ "$class_active" = "yes" ] && li_class='class="active"'
[ "$htmlfile" = "" ] && exit 1
local descr="Current"
local filename=$(basename ${filepath:-current.svg})
case $filename in
hour*) descr="An hour ago";;
day*) descr="An day ago";;
week*) descr="An week ago";;
month*) descr="An month ago";;
esac
local description=${3:-$descr}
cat <<EOF | $SUDO tee -a $htmlfile > /dev/null
<li><a $li_class onclick="document.getElementById('graph').data='/${filename}'">$description</a></li>
EOF
}
# adds footer for html report
function html_footer(){
local htmlfile=${1:-}
local result_filename=$(basename "${PROFILE_FILENAME}")
[ "$htmlfile" = "" ] && exit 1
cat <<EOF | $SUDO tee -a $htmlfile > /dev/null
</ul>
<object id="graph" data="/${result_filename:-current.svg}" style="width:100%"></object>
</body>
</html>
EOF
}
# updates file and adds it to html report
function replace_file(){
local src_file=${1:-}
local dest_file=${2:-}
local time_differense=${3:-3600}
local html_file=${4:-$PROFILE_FILENAME_HTML}
if [ -e "$src_file" ];then
if [ $(($(date +%s) - $(stat -c %Y "$dest_file" || echo 0) )) -gt ${time_differense:-1} ];then
$SUDO /bin/cp $src_file $dest_file
fi
fi
if [ -e "$dest_file" ];then
html_add_file "${html_file}" "${dest_file}"
fi
}
############################# execution
# backup changes
if [ -e "$PROFILE_FILENAME_HTML" ];then
$SUDO mv "$PROFILE_FILENAME_HTML" "$PROFILE_FILENAME_HTML_BCK" || true
MOVEBACK_HTML="yes"
fi
# adding html report header
html_header "$PROFILE_FILENAME_HTML"
# adding current(last) image
html_add_file "$PROFILE_FILENAME_HTML" "${PROFILE_FILENAME}" "Current" "yes"
# update hourly,dayly and weekly graphs
replace_file "$TMP_PROFILE_FILENAME" "$PROFILE_FILENAME_HOURLY" 3600 "$PROFILE_FILENAME_HTML"
replace_file "$TMP_PROFILE_FILENAME" "$PROFILE_FILENAME_DAYLY" 86400 "$PROFILE_FILENAME_HTML"
replace_file "$TMP_PROFILE_FILENAME" "$PROFILE_FILENAME_WEEKLY" 604800 "$PROFILE_FILENAME_HTML"
# adding html report footer
html_footer "$PROFILE_FILENAME_HTML"
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment