This commit is contained in:
tuend-work
2025-11-12 23:24:15 +07:00
parent 525acd79e4
commit 0b28a76e20
954 changed files with 57051 additions and 49 deletions

View File

@@ -0,0 +1,541 @@
#!/bin/sh
# This script is written by Martynas Bendorius and DirectAdmin
# It is used to process AWstats for a domain
# Official AWstats webpage: http://www.awstats.org
# Usage:
# ./awstats_process.sh <user> <domain>
VERSION=2.9
ADD_CGI=1
ADD_HTML=1
#set this to 1 if you need the script to reset the awstats link for each domain to root (when harden symlinks patch is enabled in apache)
#this should only need to be enabled once, and can be disabled after that one run.
ENSURE_ROOT_LINKS=0
#Set this to 1 if you have extra awstats.old folders you want to get rid of.
#DA will automatically clear them during the conversion, but this is here in case you had issues and need to try again.
CLEAR_AWSTATS_OLD=0
OS=`uname`
ROOTGRP=root
SU_BIN=/bin/su
if [ "$OS" = "FreeBSD" ]; then
ROOTGRP=wheel
SU_BIN=/usr/bin/su
fi
if [ "${ADD_CGI}" -eq 0 ] && [ "${ADD_HTML}" -eq 0 ]; then
echo "One of ADD_CGI and ADD_HTML must be set to 1";
exit 10;
fi
AUID=`/usr/bin/id -u`
if [ "$AUID" != 0 ]; then
echo "You require Root Access to run this script";
exit 1;
fi
if [ $# != 2 ] && [ $# != 3 ]; then
echo "$0 version $VERSION"
echo "Usage:";
echo "$0 <user> <domain> (<subdomain>)";
echo "you gave #$#: $0 $1 $2";
exit 2;
fi
#AWSTATS_MODE=1 hard link log files, readble by User
#AWSTATS_MODE=2 full copies of logs, readble by User
AWSTATS_MODE=`/usr/local/directadmin/directadmin c | grep '^awstats=' | cut -d= -f2`
if [ "${AWSTATS_MODE}" = "0" ] || [ "${AWSTATS_MODE}" = "" ] || [ "${AWSTATS_MODE}" -gt 2 ]; then
echo "awstats not enabled from:";
echo "/usr/local/directadmin/directadmin c | grep '^awstats='";
echo "awstats=${AWSTATS_MODE}";
exit 17
fi
id ${1} >/dev/null 2>&1
RET=$?
if [ "${RET}" -ne 0 ]; then
echo "User ${1} does not exist";
exit 3;
fi
SUB="";
if [ $# = 3 ]; then
SUB=$3
fi
USER=$1
DOMAIN=$2
UHOME=`grep -e "^${USER}:" /etc/passwd | head -n 1 | cut -d: -f6`
TOP_DOMAIN=$2
if [ "$UHOME" = "" ]; then
echo "Could not find a home path for user $USER in /etc/passwd";
exit 4;
fi
HTTPD=httpd
if [ "`/usr/local/directadmin/directadmin c | grep ^nginx= | cut -d= -f2`" -eq 1 ]; then
HTTPD=nginx
fi
if [ "`/usr/local/directadmin/directadmin c | grep ^nginx_proxy= | cut -d= -f2`" -eq 1 ]; then
HTTPD=nginx
fi
AWSTATS=/usr/local/awstats
MODEL=${AWSTATS}/wwwroot/cgi-bin/awstats.model.conf
STATS_DIR=${UHOME}/domains/${DOMAIN}/awstats
DATA=.data
DATA_DIR=${STATS_DIR}/${DATA}
LOGDIR=/var/log/${HTTPD}/domains
IS_CAGEFS=0
CAGEFSCTL=/usr/sbin/cagefsctl
if [ -x ${CAGEFSCTL} ]; then
C=`${CAGEFSCTL} --list-enabled | grep -c ${USER}`
if [ "${C}" -gt 0 ]; then
IS_CAGEFS=1
fi
fi
USER_LOGS=/var/log/user_logs
if [ ! -d ${USER_LOGS} ]; then
if [ -d /var/user_logs ]; then
echo "Moving /var/user_logs to ${USER_LOGS}"
mv /var/user_logs ${USER_LOGS}
else
mkdir ${USER_LOGS}
chmod 711 ${USER_LOGS}
echo "This folder is for temporary http log hard-links or copies, for awstats processing as the User.\nIt should usually be empty, less this file, unless awstats is running for a domain." > ${USER_LOGS}/.readme.txt
chmod 644 ${USER_LOGS}/.readme.txt
fi
fi
if [ "${SUB}" != "" ]; then
STATS_DIR=$STATS_DIR/${SUB}
DATA_DIR=${STATS_DIR}/${DATA}
CONFIG=${DATA_DIR}/awstats.${SUB}.${DOMAIN}.conf
LOG=${LOGDIR}/${DOMAIN}.${SUB}.log
READ_LOG=${USER_LOGS}/${USER}/${DOMAIN}.${SUB}.log
#we change the domain name at the last possible moment, after we're done with DOMAIN.
#all calls to DOMAIN from this point onwards will see sub.domain.com
DOMAIN=${SUB}.${DOMAIN}
else
CONFIG=${DATA_DIR}/awstats.${DOMAIN}.conf
LOG=${LOGDIR}/${DOMAIN}.log
READ_LOG=${USER_LOGS}/${USER}/${DOMAIN}.log
fi
if [ ! -e ${AWSTATS} ]; then
echo "${AWSTATS} does not exist!";
exit 5;
fi
#####################################################
# Script now runs core commands as the User.
# actions and conversions below.
run_as_user()
{
if [ "$OS" = "FreeBSD" ]; then
${SU_BIN} -l -m ${USER} -c "umask 022; $1"
else
${SU_BIN} -l -s /bin/sh -c "umask 022; $1" ${USER}
fi
return $?
}
get_dir_owner()
{
D=$1
if [ ! -d ${D} ]; then
echo "";
return;
fi
U=`ls -ld ${D} | awk '{print $3}'`
echo $U
}
#1 for false
#0 for true
should_convert_to_user()
{
if [ "`get_dir_owner $DATA_DIR`" != "root" ]; then
return 1;
fi
return 0;
}
ensure_awstats_in_cagefs()
{
if [ "${IS_CAGEFS}" != "1" ]; then
return;
fi
#Ensure awstats is in the skeleton.
DA_CFG=/etc/cagefs/conf.d/directadmin.cfg
C=`grep ^paths= ${DA_CFG} | grep -c /usr/local/awstats/`
if [ "${C}" = "0" ]; then
echo "Adding /usr/local/awstats/ to ${DA_CFG} paths";
perl -pi -e 's#^paths=#paths=/usr/local/awstats/, #' ${DA_CFG}
${CAGEFSCTL} --update
CHECK=`run_as_user "if [ -e /usr/local/awstats/tools/awstats_buildstaticpages.pl ]; then echo 0; else echo 1; fi"`
if [ "${CHECK}" != "0" ]; then
${CAGEFSCTL} --force-update
fi
fi
}
convert_awstast_to_user()
{
# As the User, copy awstats to awstats.user
# Ensure copy was successful. If not, abort everything.
# rename awstats to awstats.old, and awstats.user to awstats
STATS_DIR_USER=${STATS_DIR}.user
if [ -e ${STATS_DIR_USER} ]; then
echo "${STATS_DIR_USER} already exist. Removing it before we proceed."
run_as_user "/bin/rm -rf ${STATS_DIR_USER}"
fi
if [ "${IS_CAGEFS}" = "1" ]; then
#CloudLinux doesnt let Users copy links pointing to root files,
#so we'll remove those links first, since they're not important.
echo "Removing symbolic links..."
run_as_user "find ${STATS_DIR}/ -type l -delete"
echo "Done removing symbolic links."
fi
run_as_user "/bin/cp -RPp ${STATS_DIR} ${STATS_DIR_USER}"
diff -rq ${STATS_DIR} ${STATS_DIR_USER} > /dev/null
DIFF_RET=$?
if [ "${DIFF_RET}" != "0" ]; then
echo "awstats.user vs awstats folder do not match:";
diff -rq ${STATS_DIR} ${STATS_DIR_USER}
echo "";
echo "aborting conversion."
exit 14;
fi
echo "All checks passed. Swapping folders";
run_as_user "/bin/mv ${STATS_DIR} ${STATS_DIR}.old"
if [ ! -d ${STATS_DIR}.old ]; then
echo "Rename to ${STATS_DIR}.old must have failed. Cannot find that directory after move as User."
exit 16;
fi
#re-link root owned links.
run_as_user "rm -f ${STATS_DIR_USER}/icon"
run_as_user "rm -f ${STATS_DIR_USER}/lang"
run_as_user "rm -f ${STATS_DIR_USER}/lib"
run_as_user "rm -f ${STATS_DIR_USER}/plugins"
ln -s /usr/local/awstats/wwwroot/icon ${STATS_DIR_USER}/icon
ln -s /usr/local/awstats/wwwroot/cgi-bin/lang ${STATS_DIR_USER}/lang
ln -s /usr/local/awstats/wwwroot/cgi-bin/lib ${STATS_DIR_USER}/lib
ln -s /usr/local/awstats/wwwroot/cgi-bin/plugins ${STATS_DIR_USER}/plugins
run_as_user "/bin/mv ${STATS_DIR_USER} ${STATS_DIR}"
echo "action=delete&value=secure_disposal&user=${USER}&path=${STATS_DIR}.old" >> /usr/local/directadmin/data/task.queue
}
#####################################################
ensure_awstats_in_cagefs;
if [ ! -e ${STATS_DIR} ]; then
run_as_user "mkdir ${STATS_DIR}";
run_as_user "chmod 755 ${STATS_DIR}"
else
if [ -h ${STATS_DIR} ]; then
echo "${STATS_DIR} is a symbolic link. Aborting.";
exit 8;
fi
#directory does exist. Should we convert it?
if should_convert_to_user; then
echo "Converting contents of ${STATS_DIR} to the User ${USER}"
convert_awstast_to_user;
else
echo "Conversion not required. Continuing normally";
fi
fi
if [ ! -e ${DATA_DIR} ]; then
run_as_user "mkdir ${DATA_DIR}"
run_as_user "chmod 755 ${DATA_DIR}"
else
if [ -h ${DATA_DIR} ]; then
echo "${DATA_DIR} is a symbolic link. Aborting.";
exit 9;
fi
fi
#this bit is to fix the 700 that backups cannot see. (bug)
#http://www.directadmin.com/features.php?id=915
run_as_user "chmod 755 ${DATA_DIR}"
#do it every time. Users must not be able to edit the config directly.
#chown -R root:${ROOTGRP} ${DATA_DIR} #never do this again
if [ ! -s ${CONFIG} ]; then
if [ ! -s ${MODEL} ]; then
echo "${MODEL} does not exist or is empty.";
exit 6;
fi
run_as_user "cp -f ${MODEL} ${CONFIG}"
run_as_user "chmod 644 ${CONFIG}"
run_as_user "perl -pi -e 's#LogFile=\\\"/var/log/httpd/mylog.log\\\"#LogFile=\\\"${READ_LOG}\\\"#' ${CONFIG}"
run_as_user "perl -pi -e 's#SiteDomain=\\\"\\\"#SiteDomain=\"${DOMAIN}\"#' ${CONFIG}"
run_as_user "perl -pi -e 's#DirData=\\\".\\\"#DirData=\\\"${DATA_DIR}\\\"#' ${CONFIG}"
run_as_user "perl -pi -e 's#DirCgi=\\\"/cgi-bin\\\"#DirCgi=\\/awstats\\\"#' ${CONFIG}"
run_as_user "perl -pi -e 's#ValidHTTPCodes=\\\"200 304\\\"#ValidHTTPCodes=\\\"200 304 206\\\"#' ${CONFIG}"
#Oct 24, 2010
run_as_user "perl -pi -e 's#DirIcons=\\\"/icon\\\"#DirIcons=\\\"icon\\\"#' ${CONFIG}"
else
run_as_user "perl -pi -e 's#DirIcons=\\\"${STATS_DIR}\\\"#DirIcons=\\\"icon\\\"#' ${CONFIG}"
#run_as_user "perl -pi -e 's#^LogFile=\\\".*\\\"\$#LogFile=\\\"${READ_LOG}\\\"#' ${CONFIG}"
run_as_user "perl -pi -e 's#^LogFile=.*\$#LogFile=\\\"${READ_LOG}\\\"#' ${CONFIG}"
fi
ensure_root()
{
if [ "$ENSURE_ROOT_LINKS" != 1 ]; then
return;
fi
F=$1
TARGET=$2
if [ ! -h $F ]; then
return;
fi
FOWNER=`ls -la $F | awk '{print $3}'`
if [ "$FOWNER" = "$USER" ]; then
echo "Setting link $F to root";
run_as_user "rm '$F'"
ln -s "$TARGET" "$F"
fi
}
ICON=${STATS_DIR}/icon
#only create it during conversion. Never reset, which could be predicted.
#if [ ! -h $ICON ]; then
# run_as_user "rm -rf $ICON"
# ln -s ${AWSTATS}/wwwroot/icon $ICON
#fi
ensure_root $ICON ${AWSTATS}/wwwroot/icon
if [ ! -e "${ICON}" ]; then
ln -s ${AWSTATS}/wwwroot/icon $ICON
fi
#Oct 24, 2010
if [ "${ADD_CGI}" -eq 1 ]; then
#copy cgi-bin bits to awstats directory.
NEEDS_UPDATING=0
AS_PL=${AWSTATS}/wwwroot/cgi-bin/awstats.pl
if [ ! -e "${STATS_DIR}/awstats.pl" ]; then
NEEDS_UPDATING=1
else
#ensure it's current
CURRENT_REV=`grep '$REVISION = ' ${STATS_DIR}/awstats.pl | cut -d\' -f2`
echo "Current REVISION from ${STATS_DIR}/awstats.pl: ${CURRENT_REV}";
if [ "${CURRENT_REV}" = "" ]; then
echo "${STATS_DIR}/awstats.pl does not have REVISION set, updating from ${AS_PL}"
NEED_UPDATING=1
elif [ "${CURRENT_REV}" -lt 20180105 ]; then
echo "${STATS_DIR}/awstats.pl is old, updating from ${AS_PL}"
NEEDS_UPDATING=1
fi
fi
if [ "${NEEDS_UPDATING}" -eq 1 ]; then
run_as_user "/bin/cp -v ${AS_PL} ${STATS_DIR}/awstats.pl"
#make a few changes so it can find the config.
run_as_user "perl -pi -e 's#\\\"\$DIR\\\",\s+\\\"/etc/awstats\\\",#\\\"\$DIR\\\",\t\\\"${DATA_DIR}\\\",#' ${STATS_DIR}/awstats.pl"
#repeat for variations of the awstats.pl files
run_as_user "perl -pi -e 's#\\\"/etc/awstats\\\"#\\\"${DATA_DIR}\\\"#' ${STATS_DIR}/awstats.pl"
fi
run_as_user "chmod 755 ${STATS_DIR}/awstats.pl"
if [ ! -e "${STATS_DIR}/lang" ]; then
ln -s ${AWSTATS}/wwwroot/cgi-bin/lang ${STATS_DIR}/lang
fi
ensure_root ${STATS_DIR}/lang ${AWSTATS}/wwwroot/cgi-bin/lang
if [ ! -e "${STATS_DIR}/lib" ]; then
ln -s ${AWSTATS}/wwwroot/cgi-bin/lib ${STATS_DIR}/lib
fi
ensure_root ${STATS_DIR}/lib ${AWSTATS}/wwwroot/cgi-bin/lib
if [ ! -e "${STATS_DIR}/plugins" ]; then
ln -s ${AWSTATS}/wwwroot/cgi-bin/plugins ${STATS_DIR}/plugins
fi
ensure_root ${STATS_DIR}/plugins ${AWSTATS}/wwwroot/cgi-bin/plugins
WWWCONFIG=${DATA_DIR}/awstats.www.${DOMAIN}.conf
if [ ! -e ${WWWCONFIG} ]; then
run_as_user "ln -s awstats.${DOMAIN}.conf ${WWWCONFIG}"
fi
EXECCGI=1;
DC=/usr/local/directadmin/data/users/${USER}/domains/${TOP_DOMAIN}.conf
if [ -s ${DC} ]; then
C=`grep -c "^cgi=OFF" $DC`
if [ "${C}" -gt 0 ]; then
EXECCGI=0;
fi
fi
HTACCESS=${STATS_DIR}/.htaccess
ADD_HTA=0
if [ ! -e ${HTACCESS} ]; then
ADD_HTA=1
else
#check it's contents
COUNT=`run_as_user "grep -c 'DirectoryIndex awstats.pl' ${HTACCESS}"`
if [ "${COUNT}" -eq 0 ] && [ "${EXECCGI}" -eq 1 ]; then
ADD_HTA=1
fi
if [ "${COUNT}" -eq 1 ] && [ "${EXECCGI}" -eq 0 ]; then
ADD_HTA=1
fi
fi
if [ -h ${HTACCESS} ]; then
echo "${HTACCESS} is a symbolic link. Aborting.";
exit 11;
fi
if [ "${ADD_HTA}" -eq 1 ]; then
if [ "${EXECCGI}" -eq 1 ]; then
run_as_user "echo 'Options -Indexes +ExecCGI' > ${HTACCESS}"
run_as_user "echo 'AddHandler cgi-script .pl' >> ${HTACCESS}"
run_as_user "echo 'DirectoryIndex awstats.pl' >> ${HTACCESS}"
else
run_as_user "echo 'Options -Indexes' > ${HTACCESS}"
fi
run_as_user "echo '' >> ${HTACCESS}"
run_as_user "echo 'RewriteEngine On' >> ${HTACCESS}"
run_as_user "echo 'RewriteCond %{HTTP_HOST} ^www.${DOMAIN}\$ [NC]' >> ${HTACCESS}"
run_as_user "echo 'RewriteRule ^(.*)\$ http://${DOMAIN}/awstats/\$1 [R=301,L]' >> ${HTACCESS}"
fi
fi
#Setup logs to be readable.
mkdir $USER_LOGS/$USER
chmod 750 $USER_LOGS/$USER
if [ "${AWSTATS_MODE}" = "1" ]; then
ln $LOG $READ_LOG
elif [ "${AWSTATS_MODE}" = "2" ]; then
/bin/cp $LOG $READ_LOG
else
echo "UNKNOWN AWSTATS MODE!!"
fi
chown root:$USER $USER_LOGS/$USER
if [ "${IS_CAGEFS}" = "1" ]; then
# need to have user_logs visible to the user, in the skeleton.
# Use the split method on user_logs
C=`grep -c "^%${USER_LOGS}" /etc/cagefs/cagefs.mp`
if [ "${C}" = "0" ]; then
echo "Adding %${USER_LOGS} to /etc/cagefs/cagefs.mp";
echo "%${USER_LOGS}" >> /etc/cagefs/cagefs.mp
${CAGEFSCTL} --remount ${USER}
fi
# can we see the log?
CHECK=`run_as_user "if [ -r ${READ_LOG} ]; then echo 1; else echo 0; fi"`
if [ "${CHECK}" = "0" ]; then
${CAGEFSCTL} --remount ${USER}
fi
CHECK=`run_as_user "if [ -r ${READ_LOG} ]; then echo 1; else echo 0; fi"`
if [ "${CHECK}" = "0" ]; then
echo "Cannot read log ${READ_LOG} as user ${USER} after:"
echo "${CAGEFSCTL} --remount ${USER}"
run_as_user "ls -la ${USER_LOGS}"
fi
fi
if [ "${ADD_HTML}" -eq 1 ]; then
BD='-builddate=%YY%MM'
#this doesn't work because there are 4 hours of the next month in the logs on the first day.
#They empty the stats from the old html for last month.
#DAY=`date +%e`
#if [ "$DAY" -eq 1 ]; then
# YYMM=`date --date='yesterday' +%y%m`
# BD="-builddate=$YYMM"
#fi
#-lang=en
run_as_user "/usr/bin/perl ${AWSTATS}/tools/awstats_buildstaticpages.pl -config=${DOMAIN} -configdir=${DATA_DIR} -update -diricons=icon -awstatsprog=${AWSTATS}/cgi-bin/awstats.pl -dir=${STATS_DIR} $BD"
RET=$?
#we stil need to set a value though:
MAIN_FILE=awstats.${DOMAIN}.`date +%y%m`.html
MAIN_HTML=${STATS_DIR}/${MAIN_FILE}
INDEX_HTML=${STATS_DIR}/index.html
#changes per month
run_as_user "ln -sf ${MAIN_FILE} ${INDEX_HTML}"
#ensure_root ${INDEX_HTML}
#ensure_root ${MAIN_HTML}
else
#this is for the case where we dont want to waste time with static html files (ADD_HTML=0) but ADD_CGI is still on.
#due to the check check for !ADD_HTML&&!ADD_CGI above, ADD_CGI must be 1 at this point.
run_as_user "/usr/bin/perl ${AWSTATS}/tools/awstats_updateall.pl now -configdir=${DATA_DIR} -awstatsprog=${AWSTATS}/cgi-bin/awstats.pl"
# -excludeconf=awstats.www.${DOMAIN}.conf we're using mod_rewrite to change www.domain.com/awstast to domain.com/awstats, since only domain.com/awstats works unless we link every single data file (ugly).
RET=$?
fi
echo "Cleanup..."
rm -f $READ_LOG
if [ "${IS_CAGEFS}" != "1" ]; then
rm -rf $USER_LOGS/$USER
fi
if [ "${CLEAR_AWSTATS_OLD}" = "1" ]; then
echo "Clearing ${STATS_DIR} via task.queue. This will run in the background.";
echo "action=delete&value=secure_disposal&user=${USER}&path=${STATS_DIR}.old" >> /usr/local/directadmin/data/task.queue
fi
exit $RET;