| 1 |
#!/bin/ksh |
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
PATH="" |
|---|
| 31 |
PROG_NAME=top_http_users |
|---|
| 32 |
PROG_VERSION=0.1.0 |
|---|
| 33 |
ALTERNC_ROOT=/var/alternc |
|---|
| 34 |
ALTERNC_ETC=/etc/alternc |
|---|
| 35 |
ALTERNC_LIB=/usr/lib/alternc |
|---|
| 36 |
ALTERNC_CONF_FILE=$ALTERNC_ETC/local.sh |
|---|
| 37 |
LOG_DIR=/var/log/apache |
|---|
| 38 |
TMP_ROOT=$ALTERNC_ROOT/tmp |
|---|
| 39 |
RES_FILE=$TMP_ROOT/$PROG_NAME.res.$$ |
|---|
| 40 |
INTERMEDIATE_FILE=$TMP_ROOT/$PROG_NAME.int.$$ |
|---|
| 41 |
LOCK_FILE=/var/run/$PROG_NAME |
|---|
| 42 |
export TEXTDOMAIN=alternc-admintools |
|---|
| 43 |
YES=yes |
|---|
| 44 |
NO=no |
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
awk=/usr/bin/awk |
|---|
| 49 |
grep=/bin/grep |
|---|
| 50 |
cat=/bin/cat |
|---|
| 51 |
zcat=/bin/zcat |
|---|
| 52 |
head=/usr/bin/head |
|---|
| 53 |
id=/usr/bin/id |
|---|
| 54 |
sort=/usr/bin/sort |
|---|
| 55 |
rm=/bin/rm |
|---|
| 56 |
mysql=/usr/bin/mysql |
|---|
| 57 |
sed=/bin/sed |
|---|
| 58 |
cut=/usr/bin/cut |
|---|
| 59 |
tail=/usr/bin/tail |
|---|
| 60 |
ls=/bin/ls |
|---|
| 61 |
gettext=/usr/bin/gettext |
|---|
| 62 |
printf=/usr/bin/printf |
|---|
| 63 |
lockfileremove=/usr/bin/lockfile-remove |
|---|
| 64 |
lockfilecreate=/usr/bin/lockfile-create |
|---|
| 65 |
lockfiletouch=/usr/bin/lockfile-touch |
|---|
| 66 |
|
|---|
| 67 |
|
|---|
| 68 |
[ -x "$gettext" ] || { echo "Cannot execute $gettext"; exit 1 ; } |
|---|
| 69 |
|
|---|
| 70 |
for i in $awk $grep $cat $zcat $head $id $sort $rm $mysql $sed $cut $tail $ls $printf $lockfileremove $lockfilecreate $lockfiletouch |
|---|
| 71 |
do |
|---|
| 72 |
[ -x "$i" ] || { echo "$($gettext "Unable to execute") ${i}."; exit 1 ; } |
|---|
| 73 |
done |
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 |
|
|---|
| 77 |
function set_messages |
|---|
| 78 |
|
|---|
| 79 |
{ |
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
USAGE=$($gettext -e "Usage: top_http_users [ options ] number\n\ntop_http_users is a program that gives brief statistics\non apache usage by parsing the apache logs.\n\nOptions:\n -h, --help This help text.\n -v, --version Show version.\n -z, --use-gz-logs Parse gzipped and .1, ...n apache logs instead of just parsing the current log.\n -s, --ssl Parse the apache-ssl logs instead of parsing the non-ssl apache logs.\n -n, --number=NUMBER parse the NUMBER last lines of the current log.\n This option is not compatible with the --use-gz-logs option.\nSee the top_http_users(8) manual page for more information.") |
|---|
| 85 |
NOT_FOUND_MSG=$($gettext "does not exist.") |
|---|
| 86 |
NON_NUM_MSG=$($gettext "The \"number\" argument must be a number.") |
|---|
| 87 |
NON_COMPATIBLE_MSG=$($gettext "The -n and -z options are not compatible.") |
|---|
| 88 |
NON_NUM_MSG_FOR_N=$($gettext "The -n option requieres a number as argument.") |
|---|
| 89 |
LOCKFILE_CREATION_FAILED=`$printf "$($gettext "%s is allready beeing executed.")" $PROG_NAME` |
|---|
| 90 |
NON_ROOT_MSG=$($gettext "You have to be root (uid 0) to execute this program.") |
|---|
| 91 |
MISSING_PROG=$($gettext "Unable to execute") |
|---|
| 92 |
HIT_RES_MSG=`$printf "$($gettext "Top %s domains served by apache, sorted by number of lines in log (using gzipped logs: %s):")" $NB_USERS $($gettext "$USE_GZ_LOGS")` |
|---|
| 93 |
SIZE_RES_MSG=`$printf "$($gettext "Top %s domains served by apache, sorted by size (using gzipped logs: %s):")" $NB_USERS $($gettext "$USE_GZ_LOGS")` |
|---|
| 94 |
TIME_RES_MSG=`$printf "$($gettext "Top %s domains served by apache, sorted by execution time in seconds (using gzipped logs: %s):")" $NB_USERS $($gettext "$USE_GZ_LOGS")` |
|---|
| 95 |
ACCOUNT_HIT_RES_MSG=`$printf "$($gettext "Top %s AlternC accounts served by apache, sorted by number of lines in logs (using gzipped logs: %s):")" $NB_USERS $($gettext "$USE_GZ_LOGS")` |
|---|
| 96 |
ACCOUNT_SIZE_RES_MSG=`$printf "$($gettext "Top %s AlternC accounts served by apache, sorted by size (using gzipped logs: %s):")" $NB_USERS $($gettext "$USE_GZ_LOGS")` |
|---|
| 97 |
ACCOUNT_TIME_RES_MSG=`$printf "$($gettext "Top %s AlternC accounts served by apache, sorted by execution time in seconds (using gzipped logs: %s):")" $NB_USERS $($gettext "$USE_GZ_LOGS")` |
|---|
| 98 |
DEBUG_1_MSG=$($gettext "Parsing") |
|---|
| 99 |
DEBUG_2_MSG=$($gettext "Getting account for each domain") |
|---|
| 100 |
DEBUG_3_MSG=$($gettext "Printing results") |
|---|
| 101 |
MISSING_CONF_FILE=`$printf "$($gettext "Can't find %s. Are you sure AlterncC is properly installed?")" $ALTERNC_CONF_FILE` |
|---|
| 102 |
MYSQL_UNREACHABLE_DATABASE=`$printf "$($gettext "Cannot access accounts database. Please check either %s or Mysql state.")" $ALTERNC_CONF_FILE` |
|---|
| 103 |
SQL_ERROR_MSG=$($gettext -e "Sorry, an sql error appeared. The error message is:\n%s") |
|---|
| 104 |
UNKNOWN_OPTION=$($gettext "Unknown %s option.") |
|---|
| 105 |
} |
|---|
| 106 |
|
|---|
| 107 |
|
|---|
| 108 |
|
|---|
| 109 |
function trap_EXIT |
|---|
| 110 |
|
|---|
| 111 |
{ |
|---|
| 112 |
|
|---|
| 113 |
$rm -f $RES_FILE |
|---|
| 114 |
$rm -f $INTERMEDIATE_FILE |
|---|
| 115 |
$lockfileremove $LOCK_FILE |
|---|
| 116 |
exit |
|---|
| 117 |
} |
|---|
| 118 |
trap trap_EXIT INT KILL TERM QUIT ABRT STOP HUP |
|---|
| 119 |
|
|---|
| 120 |
|
|---|
| 121 |
|
|---|
| 122 |
|
|---|
| 123 |
|
|---|
| 124 |
set_messages |
|---|
| 125 |
|
|---|
| 126 |
[ "`$id -u`" -ne 0 ] && { echo $NON_ROOT_MSG ; exit 1 ; } |
|---|
| 127 |
|
|---|
| 128 |
|
|---|
| 129 |
IS_N_PARAM=false |
|---|
| 130 |
USE_GZ_LOGS="$NO" |
|---|
| 131 |
N_PARAM="" |
|---|
| 132 |
COMMAND=$cat |
|---|
| 133 |
for ARG in "$@" ; do |
|---|
| 134 |
[ "$IS_N_PARAM" = "true" ] && { shift ; IS_N_PARAM=false ; continue ; } |
|---|
| 135 |
[ "`$printf "$ARG\n" | $cut -c1`" != "-" ] && [ "$IS_N_PARAM" = "false" ] && break |
|---|
| 136 |
|
|---|
| 137 |
case $ARG in |
|---|
| 138 |
-h | --help ) echo $PROG_NAME version $PROG_VERSION ; $printf "$USAGE\n" ; exit ;; |
|---|
| 139 |
-v | --version ) echo $PROG_NAME version $PROG_VERSION ; exit ;; |
|---|
| 140 |
-s | --ssl ) LOG_DIR=/var/log/apache-ssl ;; |
|---|
| 141 |
-z | --use-gz-logs ) USE_GZ_LOGS="$YES" ;; |
|---|
| 142 |
-n | --number=* ) |
|---|
| 143 |
if [ "$ARG" != "-n" ] ; then |
|---|
| 144 |
N_PARAM=`echo $ARG | $cut -d"=" -f2` |
|---|
| 145 |
else |
|---|
| 146 |
N_PARAM=$2 |
|---|
| 147 |
IS_N_PARAM=true |
|---|
| 148 |
fi |
|---|
| 149 |
[ `echo "$N_PARAM" | $grep -c [^0-9]` != 0 ] && { echo "$NON_NUM_MSG_FOR_N" ; exit 1 ; } |
|---|
| 150 |
COMMAND="$tail -n $N_PARAM" |
|---|
| 151 |
;; |
|---|
| 152 |
*) $printf "${UNKNOWN_OPTION}\n" $ARG ; exit 1 ;; |
|---|
| 153 |
esac |
|---|
| 154 |
shift |
|---|
| 155 |
done |
|---|
| 156 |
LOG_FILE=$LOG_DIR/access.log |
|---|
| 157 |
|
|---|
| 158 |
|
|---|
| 159 |
[ "$USE_GZ_LOGS" = "$YES" ] && ! [ -z "$N_PARAM" ] && { echo $NON_COMPATIBLE_MSG ; exit 1 ; } |
|---|
| 160 |
|
|---|
| 161 |
[ -z "$1" ] || [ "$#" -gt 1 ] && { $printf "$USAGE\n" ; exit 1 ; } |
|---|
| 162 |
|
|---|
| 163 |
[ `echo "$1" | $grep -c [^0-9]` != 0 ] && { echo "$NON_NUM_MSG" ; exit 1 ; } || NB_USERS=$1 |
|---|
| 164 |
|
|---|
| 165 |
[ -d "$LOG_DIR" ] || { echo "$LOG_DIR $NOT_FOUND_MSG" ; exit 1 ; } |
|---|
| 166 |
[ -d "$TMP_ROOT" ] || { echo "$TMP_ROOT $NOT_FOUND_MSG" ; exit 1 ; } |
|---|
| 167 |
[ -f "$LOG_FILE" ] || { echo "$LOG_FILE $NOT_FOUND_MSG" ; exit 1 ; } |
|---|
| 168 |
|
|---|
| 169 |
[ -f "$ALTERNC_CONF_FILE" ] || { echo $MISSING_CONF_FILE ; exit 1 ; } && . $ALTERNC_CONF_FILE |
|---|
| 170 |
|
|---|
| 171 |
[ -z "$MYSQL_HOST" ] && MYSQL_HOST=localhost |
|---|
| 172 |
$mysql -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASS -D$MYSQL_DATABASE -e "select count(*) from domaines_standby;" > /dev/null 2>&1 |
|---|
| 173 |
[ "$?" != 0 ] && { echo "$MYSQL_UNREACHABLE_DATABASE" ; exit 1 ; } || mysql="$mysql -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASS -D$MYSQL_DATABASE -B -N -e " |
|---|
| 174 |
|
|---|
| 175 |
|
|---|
| 176 |
$lockfilecreate --retry 1 $LOCK_FILE |
|---|
| 177 |
if [ $? != 0 ] |
|---|
| 178 |
then |
|---|
| 179 |
echo $LOCKFILE_CREATION_FAILED |
|---|
| 180 |
exit 1 |
|---|
| 181 |
fi |
|---|
| 182 |
$lockfiletouch $LOCK_FILE & |
|---|
| 183 |
BADGER="$!" |
|---|
| 184 |
|
|---|
| 185 |
|
|---|
| 186 |
|
|---|
| 187 |
set_messages |
|---|
| 188 |
|
|---|
| 189 |
[ "$DEBUG" ] && echo "$DEBUG_1_MSG $LOG_FILE" ; $COMMAND $LOG_FILE | $awk '{z=NF-1 ; domaine[$NF]++ ; if ($10 != "-") size[$NF]+=$10 ; time[$NF]+=$z} END {for (item in domaine) print item" "domaine[item]" "size[item]" "time[item]}' > $RES_FILE |
|---|
| 190 |
for FILE in `$ls -1 $LOG_FILE.* | $grep -v "\.gz$"`; do |
|---|
| 191 |
[ "$USE_GZ_LOGS" = "$YES" ] && [ -f $FILE ] && { [ "$DEBUG" ] && echo "$DEBUG_1_MSG $FILE" ; $cat $FILE | $awk '{z=NF-1 ; domaine[$NF]++ ; if ($10 != "-") size[$NF]+=$10 ; time[$NF]+=$z} END {for (item in domaine) print item" "domaine[item]" "size[item]" "time[item]}' >> $RES_FILE ; } |
|---|
| 192 |
done |
|---|
| 193 |
if [ "$USE_GZ_LOGS" = "$YES" ] |
|---|
| 194 |
then |
|---|
| 195 |
for GZLOG in $LOG_FILE.*.gz |
|---|
| 196 |
do |
|---|
| 197 |
[ "$DEBUG" ] && echo "$DEBUG_1_MSG $GZLOG" |
|---|
| 198 |
$zcat $GZLOG | $awk '{z=NF-1 ; domaine[$NF]++ ; if ($10 != "-") size[$NF]+=$10 ; time[$NF]+=$z} END {for (item in domaine) print item" "domaine[item]" "size[item]" "time[item]}' >> $RES_FILE |
|---|
| 199 |
done |
|---|
| 200 |
fi |
|---|
| 201 |
|
|---|
| 202 |
|
|---|
| 203 |
|
|---|
| 204 |
$cat $RES_FILE | $awk '{domaine[$1]+=$2 ; size[$1]+=$3 ; time[$1]+=$4} END {for (item in domaine) print item" "domaine[item]" "size[item]" "time[item]}' > $INTERMEDIATE_FILE |
|---|
| 205 |
|
|---|
| 206 |
[ "$DEBUG" ] && echo $DEBUG_2_MSG |
|---|
| 207 |
> $RES_FILE |
|---|
| 208 |
for i in `$cat $INTERMEDIATE_FILE | $sed s/" "/"@@@@"/g` |
|---|
| 209 |
do |
|---|
| 210 |
TMP=`echo $i | $sed s/"@@@@"/" "/g` |
|---|
| 211 |
DOMAIN=`echo $TMP | $cut -d " " -f1 | $sed s/\"//g | $sed s/"\\\\\\\\"/""/g` |
|---|
| 212 |
[ "$DEBUG" ] && echo DOMAIN : $DOMAIN |
|---|
| 213 |
ACCOUNT=`$mysql "select a.login, a.mail from membres a, sub_domaines b where a.uid = b.compte and concat(if(sub=\"\", \"\", concat(sub, \".\")), domaine) = \"${DOMAIN}\";" 2>&1` |
|---|
| 214 |
[ "$?" != 0 ] && { $printf "$SQL_ERROR_MSG\n" " $ACCOUNT" ; kill "${BADGER}" ; trap_EXIT ; } |
|---|
| 215 |
! [ -z "$ACCOUNT" ] && [ `echo $ACCOUNT | $grep -c "^ERROR"` = 0 ] && echo "$ACCOUNT $TMP" >> $RES_FILE |
|---|
| 216 |
done |
|---|
| 217 |
|
|---|
| 218 |
|
|---|
| 219 |
[ "$DEBUG" ] && echo $DEBUG_3_MSG |
|---|
| 220 |
echo $HIT_RES_MSG |
|---|
| 221 |
$cat $INTERMEDIATE_FILE | $awk {'printf ("%20.0f %s\n", $2, $1)'} | $sort -gr | $head -n$NB_USERS |
|---|
| 222 |
echo "" |
|---|
| 223 |
echo $SIZE_RES_MSG |
|---|
| 224 |
$cat $INTERMEDIATE_FILE | $awk {'printf ("%20.0f %s\n", $3, $1)'} | $sort -gr | $head -n$NB_USERS |
|---|
| 225 |
echo "" |
|---|
| 226 |
echo $TIME_RES_MSG |
|---|
| 227 |
$cat $INTERMEDIATE_FILE | $awk {'printf ("%20.0f %s\n", $4, $1)'} | $sort -gr | $head -n$NB_USERS |
|---|
| 228 |
|
|---|
| 229 |
$cat $RES_FILE | $awk '{size[$1]+=$5 ; time[$1]+=$6 ; hit[$1]+=$4 ; mail[$1]=$2} END {for (item in size) print size[item]" "time[item]" "hit[item]" "item" "mail[item]}' > $INTERMEDIATE_FILE |
|---|
| 230 |
|
|---|
| 231 |
echo "" |
|---|
| 232 |
echo $ACCOUNT_HIT_RES_MSG |
|---|
| 233 |
$cat $INTERMEDIATE_FILE | $awk {'printf ("%20.0f %s (%s)\n", $3, $4, $5)'} | $sort -gr | $head -n$NB_USERS |
|---|
| 234 |
echo "" |
|---|
| 235 |
echo $ACCOUNT_SIZE_RES_MSG |
|---|
| 236 |
$cat $INTERMEDIATE_FILE | $awk {'printf ("%20.0f %s (%s)\n", $1, $4, $5)'} | $sort -gr | $head -n$NB_USERS |
|---|
| 237 |
echo "" |
|---|
| 238 |
echo $ACCOUNT_TIME_RES_MSG |
|---|
| 239 |
$cat $INTERMEDIATE_FILE | $awk {'printf ("%20.0f %s (%s)\n", $2, $4, $5)'} | $sort -gr | $head -n$NB_USERS |
|---|
| 240 |
|
|---|
| 241 |
|
|---|
| 242 |
|
|---|
| 243 |
kill "${BADGER}" |
|---|
| 244 |
trap_EXIT |
|---|
| 245 |
|
|---|
| 246 |
|
|---|