#!/bin/bash
##
## This util reads /proc/user_beancounters directly if run by root user.
## Unprivileged users may use beanc.c from http://www.labradordata.ca/home/35
## to pipe beancounter data into stdin.
## Primary reference: http://wiki.openvz.org/Proc/user_beancounters
## Also http://forum.swsoft.com/showthread.php?s=d03fd7e49b67dfb1f45f4f453e019a73&threadid=26770
Default_Args=""
## Default_Args="+a -e"
## Without Default_Args, options must be given as command line parameters.
## With Default_Args, options may be overridden by command line parameters.
## Revisions:
##
## V0.01: - released 11 Nov 2006 by grummund and yager on irc.chatspike.net#RapidVPS
## V0.02: - improve syntax checking for command line arguments, reject incorrect options.
## - add 'B' option, for all beancounters
## - general tarting up of the code
## V0.03: - incorporate direct reading of /proc/user_beancounters by root user
## - incorporate Default_Args variable; set option defaults to 'n'
## - fix MB reporting for kmemsize
## TODO list, bugs, idea proposals...
##
## - improve quoting of variables, a good defensive measure otherwise
## things break too easily.
## - demarcation lines printed even when not required with -H
## - add some example command line usage
## Output option defaults to everything off
option_date=n; option_datehost=n; option_uptime=n
option_limits=n; option_usage=n
option_memory=n; option_kernel=n
option_others=n; option_failcnts=n
option_demarcations=n; option_info=n
option_help=n; option_veid=n
exp0="******" # preceeds the information text
## Array field constants:
param_name=0; held=1; maxheld=2; barrier=3; limit=4; failcnt=5
declare -a FailCounts
FailCounts[0]=0
fails=0
print_usage () {
cat <<EOF >&2
Usage: $0 [(+|-)(option)[option]...] ...]
[+|-] turns output options on or off
Options:
a) for all options (use first)
d) demarcation lines ------
H) Header Elements:
v) VEID
i) ID : date and hostname
s) status : uptime
B) BeanCounters:
l) limits set by host
u) usage by VE
m) memory pages
k) kernel (low) memory
o) other, non-memory, parameters
f) fail counts
Informational:
e) explanations
EOF
}
demarcate () {
echo '-----------------------------------------------'
}
read_params () {
case $# in
2) UBC_version="$2"; return;;
7) UBC_veid="${1%:}"; shift;;
6) ;;
*) print_usage; exit 1;;
esac
PARAM=$1
let UBC_$PARAM[1]=$2
let UBC_$PARAM[2]=$3
let UBC_$PARAM[3]=$4
let UBC_$PARAM[4]=$5
let UBC_$PARAM[5]=$6
# eval echo "debug: $PARAM= \${UBC_$PARAM[@]}"
let fails=UBC_$PARAM[5]
if [ $fails -gt 0 ] && [ $6 != "failcnt" ]; then
let "FailCounts[0] += 1"
FailCounts[${FailCounts[0]}]="$*"
fi
}
## A couple handy functions:
Kilobytes= # Global variable to hold oversize return value of function.
kilos () {
Kilobytes=$(($1 / 1024))
return
}
Megabytes= # Global variable to hold oversize return value of function.
megas () {
kilos $1
Megabytes=$(($Kilobytes / 1024))
# let "Megabytes /= 1024"
return
}
print_bytes () {
if [ "$2" -gt 1048576 ]; then
printf "$1" "$(($2 / 1048576))" "MB"
elif [ "$2" -gt 1024 ]; then
printf "$1" "$(($2 / 1024))" "KB"
else
printf "$1" "$2" "B"
fi
}
## Parse the option arguments:
parse_args () {
#echo debug-parse:"$@"
for arg in "$@"; do
#echo debug-arg:$arg
case "${arg:0:1}" in
+) option_state=y;;
-) option_state=n;;
*) print_usage; exit 1;;
esac
char=1
while [ "$char" -lt "${#arg}" ]; do
case "${arg:$char:1}" in
v) option_veid=$option_state;;
i) option_datehost=$option_state;;
s) option_uptime=$option_state;;
l) option_limits=$option_state;;
u) option_usage=$option_state;;
m) option_memory=$option_state;;
k) option_kernel=$option_state;;
o) option_others=$option_state;;
f) option_failcnts=$option_state;;
d) option_demarcations=$option_state;;
e) option_info=$option_state;;
B) option_limits=$option_state
option_usage=$option_state
option_memory=$option_state
option_kernel=$option_state
option_others=$option_state
option_failcnts=$option_state;;
H) option_veid=$option_state
option_datehost=$option_state
option_uptime=$option_state;;
a) option_datehost=$option_state
option_uptime=$option_state
option_limits=$option_state
option_usage=$option_state
option_memory=$option_state
option_kernel=$option_state
option_others=$option_state
option_failcnts=$option_state
option_demarcations=$option_state
option_info=$option_state
option_veid=$option_state;;
*) print_usage; exit 1;;
esac
char=$[$char+1]
done # while
case "$arg" in
-h|+h|--h|--help)
print_usage; exit 0;;
esac
done
}
## Test for no options
if [ -z "$Default_Args" ] && [ -z "$*" ] ; then
print_usage
echo "You must edit $0 Default_Args variable and/or put option arguments on command line"
exit 1
fi
#echo "debug-options:$Default_Args:$*"
## Read the default arguments
[ "$Default_Args" ] && parse_args $Default_Args
## Read the command line arguments
[ "$*" ] && parse_args "$@"
## Sane usage of command line options
if [ "$option_memory" = y -o "$option_kernel" = y ] && \
[ "$option_limits$option_usage" = "nn" ]; then
option_limits=y
option_usage=y
fi
if [ "$option_limits" = y -o "$option_usage" = y ] && \
[ "$option_memory$option_kernel" = "nn" ]; then
option_memory=y
option_kernel=y
fi
## Read the UBC data:
if [ -O /proc/user_beancounters ] ; then
while read LINE; do
# echo "debug:$LINE:"
read_params $LINE
done < /proc/user_beancounters
else # read via stdin
echo -n "/proc/user_beancounters required in stdin"
while read LINE; do
read_params $LINE
echo -e "\r"
done
fi
#printf "\r"
## Output whatever interests you:
[ $option_demarcations = y ] && demarcate
[ $option_veid = y ] && echo "Processing UBC version $UBC_version for VEID: $UBC_veid"
[ $option_datehost = y ] && echo "$(date) $(hostname)"
[ $option_uptime = y ] && echo "$(uptime)"
if [ $option_memory = y ] ; then
[ $option_demarcations = y ] && demarcate
if [ $option_limits = y ] ; then
[ $option_info = y ] && \
echo "$exp0 vmguarpages and oomguarpages limits are unspecified"
[ $option_info = y ] && \
echo "$exp0 each VE privvmpages limit should be <= 0.6 * RAM (=1228 MB), probably [much] lower."
printf "%4d MB Allocation Limit [privvmpages limit]\n" \
$((${UBC_privvmpages[limit]} / 256))
[ $option_info = y ] && \
echo "$exp0 only high value processes have a chance in this range"
[ $option_info = y ] && \
echo "$exp0 having this safety range is important to permit critical processes"
printf "%4d MB Allocation Barrier [privvmpages barrier]\n" \
$((${UBC_privvmpages[barrier]} / 256))
[ $option_info = y ] && \
echo "$exp0 allocation requests in this range have a chance"
printf "%4d MB Allocation Guarantee [vmguarpages barrier]\n" \
$((${UBC_vmguarpages[barrier]} / 256))
[ $option_info = y ] && \
echo "$exp0 allocation will succeed in this range"
printf "%4d MB Memory Guarantee [oomguarpages barrier]\n" \
$((${UBC_oomguarpages[barrier]} / 256))
fi # limits
if [ $option_usage = y ] ; then
printf "%4d MB" $((${UBC_privvmpages[held]} / 256))
printf " (%4d MB Max) page memory allocated [privvmpages held]\n" \
$((${UBC_privvmpages[$maxheld]} / 256))
printf "%4d MB" $((${UBC_oomguarpages[held]} / 256))
printf " (%4d MB Max) memory + swap used [oomguarpages held]\n" \
$((${UBC_oomguarpages[$maxheld]} / 256))
printf "%4d MB" $((${UBC_physpages[held]} / 256))
printf " (%4d MB Max) page memory used [physpages held]\n" \
$((${UBC_physpages[$maxheld]} / 256))
fi # usage
fi # memory
#[ $option_info = y ] && \
#echo "$exp0 host system swap size should be double the physical RAM size"
if [ $option_kernel = y ] ; then
if [ $option_limits = y ] ; then
megas "${UBC_kmemsize[limit]}"
kilos "${UBC_kmemsize[limit]}"
printf "%4d MB (%6d KB) kernel memory limit [kmemsize limit]\n" \
"$Megabytes" "$Kilobytes"
[ $option_info = y ] && \
echo "$exp0 a safety range here, between limit and barrier, is important"
megas "${UBC_kmemsize[barrier]}"
kilos "${UBC_kmemsize[barrier]}"
printf "%4d MB (%6d KB) kernel memory barrier [kmemsize barrier]\n" \
"$Megabytes" "$Kilobytes"
fi # limits
if [ $option_usage = y ] ; then
# print_bytes "%4d %s kernel memory used [kmemsize held]\n" ${UBC_kmemsize[held]}
megas "${UBC_kmemsize[$held]}"
kilos "${UBC_kmemsize[$held]}"
# printf "%4d MB kernel memory used [kmemsize held] (%6d KB)\n" \
printf "%4d MB (%6d KB) kernel memory used [kmemsize held]\n" \
"$Megabytes" "$Kilobytes"
BUFMEM=$(( \
${UBC_tcpsndbuf[held]} + ${UBC_tcprcvbuf[held]} + \
${UBC_othersockbuf[held]} + ${UBC_dgramrcvbuf[held]}))
# print_bytes "%4d %s buffer memory used [*buf held]\n" $BUFMEM
megas "$BUFMEM"
kilos "$BUFMEM"
# printf "%4d MB buffer memory used [*buf held] (%6d KB)\n" \
printf "%4d MB (%6d KB) buffer memory used [*buf held]\n" \
"$Megabytes" "$Kilobytes"
fi # usage
fi #kernel
if [ $option_others = y ] ; then
[ $option_demarcations = y ] && demarcate
echo ' Used : Max_Used : Limit for Other Resources'
for X in "${!UBC_num@}"; do
eval printf '"%6d %6d %6d %s\n"' \
"\${$X[held]}" "\${$X[maxheld]}" "\${$X[limit]} ${X#*_}"
done
fi # other
if [ $option_failcnts = y ] ; then
[ $option_demarcations = y ] && demarcate
# look at failcnts ....
# declare -p FailCounts
echo "Fail Count conditions: ${FailCounts[0]}"
if [ ${FailCounts[0]} -gt 0 ]; then
for i in ${FailCounts[0]}; do
echo ${FailCounts[$i]}
done
fi
fi # failcnts
exit 0