diff --git a/production/download_site/backup-drupal.sh b/production/download_site/backup-drupal.sh new file mode 100644 index 0000000..48583cd --- /dev/null +++ b/production/download_site/backup-drupal.sh @@ -0,0 +1,185 @@ +#!/bin/bash + +DIR_PATH="$(echo ${1} | sed 's:/*$::')" +DIR=$(basename ${DIR_PATH}) +LOG="${DIR}.log" +TIMESTAMP=`date +%Y/%m/%d' '%H:%M:%S` +echo + +# +# show to screen and also write to log +# +function log() { + echo -e "\e[96m`date +'%d/%m/%Y %H:%M:%S'`\e[39m $1" + echo -e "`date +'%d/%m/%Y %H:%M:%S'` $1" >> $LOG +} + +# +# database - get credentials from settings.php +# +function get_credentials() { + SETTINGS=$(find ${DIR_PATH} -name settings.php | grep default) + DATABASE=$(cat $SETTINGS | tr -d ' ' | grep "^'database'" | awk -F\' '{print $4}') + USERNAME=$(cat $SETTINGS | tr -d ' ' | grep "^'username'" | awk -F\' '{print $4}') + PASSWORD=$(cat $SETTINGS | tr -d ' ' | grep "^'password'" | awk -F\' '{print $4}') + DOMAIN=$(echo ${DIR_PATH} | awk -F/ '{print $5}') + + [[ -z "${SETTINGS}" ]] && log "Empty variable SETTINGS" && return 1 + [[ -z "${DATABASE}" ]] && log "Empty variable DATABASE" && return 1 + [[ -z "${USERNAME}" ]] && log "Empty variable USERNAME" && return 1 + [[ -z "${PASSWORD}" ]] && log "Empty variable PASSWORD" && return 1 + [[ -z "${DOMAIN}" ]] && log "Empty variable DOMAIN" && return 1 + + log "DIR : ${DIR}" + log "SETTINGS : $(basename ${SETTINGS})" + log "DATABASE : ${DATABASE}" + log "USERNAME : ${USERNAME}" + + return 0 +} + +# +# database - verify credentials +# +function verify_credentials() { + mysql -u"${USERNAME}" -p"${PASSWORD}" --batch --skip-column-names -e "SHOW DATABASES;" | grep "^${DATABASE}$" > /dev/null; + + if [ $? -ne 0 ];then + log "Verify database credentials [FAIL]" + return 1 + fi + + log "Verify database credentials [ OK ]" + return 0 +} + +# +# database - export data +# +function export_databse() { + mysqldump -u"${USERNAME}" -p"${PASSWORD}" ${DATABASE} > ${DATABASE}.sql + if [ $? -ne 0 ];then + log "Export database [FAIL]" + return 1 + fi + log "Export database [ OK ]" + return 0 +} + +# +# Create TarBall +# +function create_tarball() { + TARBALL="$(echo $RANDOM | md5sum | head -c 32; echo;)-${DIR}.tar.gz" + tar -czpf ${TARBALL} ${DIR_PATH} ${DATABASE}.sql &> /dev/null + + if [ $? -ne 0 ];then + log "Create tarball [FAIL]" + return 1 + fi + + log "Create tarball [ OK ]" + rm -f "${DATABASE}.sql" + + + # move to download path + DOWNLOAD_PATH=${DIR_PATH} + + if [ -d "${DIR_PATH}/web" ];then + DOWNLOAD_PATH="${DIR_PATH}/web" + fi + + mv ${TARBALL} ${DOWNLOAD_PATH} + + # calculate download time and add 2 minutes for the user to click the download link + INTERNET_Mbps=50000000 # 50Mbps + SIZE=$( du -sh ${DOWNLOAD_PATH}/${TARBALL} | awk '{print $1}' ) + SIZE_BITS=$( du -s ${DOWNLOAD_PATH}/${TARBALL} | awk '{print $1}' ) + DOWNLOAD_SECS=$(( ${SIZE_BITS} / ${INTERNET_Mbps} )) + AVAILABLE_SECS=$(( ${DOWNLOAD_SECS} + 120 )) + AVAILABLE_MINS=$(( ${AVAILABLE_SECS} / 60 )) + + # create download link + log "" + log " 🍓 DOWNLOAD" + log "" + log "URL : https://${DOMAIN}/${TARBALL}" + log "Size : ${SIZE}" + log "Available for : ${AVAILABLE_MINS} minutes" + log "" + + return 0 +} + +# +# Delete tarball +# +function delete_tarball() { + if [ -f ${DOWNLOAD_PATH}/${TARBALL} ];then + log "Start ${AVAILABLE_SECS} seconds timer for deleting ${TARBALL}" + ./safeDelete.sh "${DOWNLOAD_PATH}/${TARBALL}" ${AVAILABLE_SECS} & + else + log "Cannot find "${DOWNLOAD_PATH}/${TARBALL}" for deleting" + fi +} + +function add_server_stats() { + log "" + log " 🍓 SERVER STATUS" + log "" + + log "Users and Uptime" + echo "$(w)" >> ${LOG} + echo "" >> ${LOG} + + log "Disk Usage" + echo "$(df -h)" >> ${LOG} + echo "" >> ${LOG} + + log "Memory Usage" + echo "$(free -g)" >> ${LOG} + echo "" >> ${LOG} + + log "Network Interface" + echo "$(ifconfig eth0)" >> ${LOG} + echo "" >> ${LOG} + + log "System TOP 10 resources" + echo "$(ps -eo pid,%cpu,%mem,user,comm --sort=-%cpu | head -n 11)" >> ${LOG} + echo "" >> ${LOG} +} + +# +# Send mail +# +function send_mail_log() { + SUBJECT="Backup ${DIR}" + RECIPIENTS="stefanos@dotsoft.gr" + cat ${LOG} | mailx -a 'Content-Type: text/html' -s ${SUBJECT} ${RECIPIENTS} +} + +# dont start if you dont have a valid drupal directory +[ $# -lt 1 ] && echo "${TIMESTAMP} Directory argument is missing" > backup.log && exit +[ $# -gt 1 ] && echo "${TIMESTAMP} Too many arguments" > backup.log && exit +[ ! -d ${DIR_PATH} ] && echo "${TIMESTAMP} ${DIR} does not exist" > backup.log && exit + +# Start +function main () { + echo -e "
" > ${LOG}
+  if get_credentials; then
+    if verify_credentials; then
+      if export_databse; then
+        if create_tarball; then
+	  delete_tarball
+	fi
+      fi
+    fi
+  fi
+  add_server_stats
+  echo -e "
" >> ${LOG} + send_mail_log +} + +main + + diff --git a/production/download_site/safeDelete.sh b/production/download_site/safeDelete.sh new file mode 100644 index 0000000..b69b7cc --- /dev/null +++ b/production/download_site/safeDelete.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# Before deleting a file ensure that + +# 1. The filename has the right FORMAT +# 2. The file is a TYPE of compressed file +# 3. The file has an EXTENSION of compresed file + +[ ${#} -ne 2 ] && echo "safedelete.sh: Some Argument is missing" && exit +[ ! -f ${1} ] && echo "safedelete.sh: Argument is not a file: ${1}" && exit +[ ${2} -gt 3600 ] && echo "safedelete.sh: Waiting time is more that one hour" && exit + +# +# 1. Check the filename FORMAT +# +FORMAT=$(basename ${1} | grep -E "^[a-zA-Z0-9]{32}-.*\.(zip|gz|7zip|tar|tar\.gz|tar\.bz2)$" ) +if [ "${FORMAT}" != "" ];then + + # + # 2. Check the file TYPE + # + TYPE=$(file --mime-type ${1} | awk '{print $2}' | awk -F/ '{print $2}' ) + if [ "${TYPE}" == "zip" ] || + [ "${TYPE}" == "x-tar" ] || + [ "${TYPE}" == "x-bz2" ] || + [ "${TYPE}" == "gzip" ] || + [ "${TYPE}" == "7zip" ];then + + # + # 3. Check the file EXTENSION + # + EXTENSION=$(echo ${1} | awk -F\. '{print $NF}') + if [ "${EXTENSION}" == "zip" ] || + [ "${EXTENSION}" == "tar" ] || + [ "${EXTENSION}" == "bz2" ] || + [ "${EXTENSION}" == "gz" ] || + [ "${EXTENSION}" == "7zip" ];then + sleep ${2} && rm -f "${1}" + else + echo "Wrong file extension" && exit + fi + else + echo "Wrong file type" && exit + fi +else + echo "Wrong filename format" && exit +fi + diff --git a/production/download_site/select.sh b/production/download_site/select.sh new file mode 100644 index 0000000..d22f86b --- /dev/null +++ b/production/download_site/select.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +IFS=$'\n' +ROOT_PATH="/var/www/vhosts" + +# +# get directories +# +if [ -f "./vhosts.du" ]; then + du_output=$(cat "./vhosts.du") +else + echo + echo -e "Reading disk usage for every directory in ${ROOT_PATH}. Please wait..." + echo + cd ${ROOT_PATH} + du_output=$(du -sh */ | column --table -R1) +fi + +# +# convert directorires into menu items +# +index=0 +menu_items=() +for dir in $du_output; do + menu_items+=("$index $dir" "") + index=$(expr $index + 1) +done + +# +# show menu +# +dialog --no-lines --menu "Choose a directory from ${ROOT_PATH}:" 0 0 0 "${menu_items[@]}" 2> /tmp/menu_choice +menu_choice=$(cat /tmp/menu_choice) +rm -f /tmp/menu_choice +echo +# +# Find the site root directory +# +SELECTED_DIR=$(echo ${menu_choice} | awk '{print $3}') +[ "${SELECTED_DIR}" == "" ] && echo "No directory selected" && exit +echo "SELECTED_DIR :" $SELECTED_DIR + +VHOST_DIR=${ROOT_PATH}/$SELECTED_DIR +[ ! -d "${ROOT_PATH}/${SELECTED_DIR}" ] && echo "Cannot find selected vhost directory ${VHOST_DIR}" && exit +echo -e "VHOST_DIR :" $VHOST_DIR + +# +# Find the index.php or index.html, the full path and the dir name +# +SITE_INDEX=$(find ${VHOST_DIR} -name index.php -printf "%d %p\n"|sort -n|perl -pe 's/^\d+\s//;' | head -n1) +if [ "${SITE_INDEX}" == "" ];then + SITE_INDEX=$(find ${VHOST_DIR} -name index.html -printf "%d %p\n"|sort -n|perl -pe 's/^\d+\s//;' | head -n1) +fi + +echo -e "INDEX :" $SITE_INDEX + +INDEX_PATH=$(dirname $SITE_INDEX) +echo -e "INDEX_PATH :" $INDEX_PATH + +INDEX_DIR=$(echo $INDEX_PATH | awk -F/ '{print $NF}') +echo -e "INDEX_DIR :" $INDEX_DIR + +TARGET_DIR=${INDEX_PATH} + +# +# Determine the type of the site +# +SITE_TYPE="unknown" +[ -d "${INDEX_PATH}/core" ] && [ -d "${INDEX_PATH}/sites" ] && SITE_TYPE="drupal" +[ -d "${INDEX_PATH}/admin" ] && [ -d "${INDEX_PATH}/mod" ] && SITE_TYPE="moodle" + +# +# If its composer site get the parent directory of web/ +# +if [ ${INDEX_DIR} == "web" ]; then + TARGET_DIR=$(dirname ${INDEX_PATH}) +fi + +echo -e "TARGET_DIR :" $TARGET_DIR +echo +cd /root + +# +# Confirm this is the right type of site +# +read -p "This is a ${SITE_TYPE} site. Continue to backup?" -n 1 -r +if [[ $REPLY =~ ^[Yy]$ ]]; then + echo + # + # Send path to back script + # + [ ${SITE_TYPE} == 'drupal' ] && bash ./backup-${SITE_TYPE}.sh ${TARGET_DIR} & + [ ${SITE_TYPE} == 'moodle' ] && echo "Backup for type ${SITE_TYPE} not implemented yet!" && exit + [ ${SITE_TYPE} == 'unknown' ] && echo "Backup for ${SITE_TYPE} types has not yet implemented!" && exit +fi +echo + +