From 788886450c3219163d096dc7101b5670b054878b Mon Sep 17 00:00:00 2001 From: Daniel Gibbs Date: Sun, 30 Oct 2016 22:14:36 +0000 Subject: [PATCH] Backup function improvements (#1161) * Added no of days since last backup Allows the number of days since last backup to be displayed * Added last backup x days ago Added a bracket in the last backup date stating how many days ago the last backup took place * Added lock file creation to logs * corrected trap display ... * Updated comment * updated log message * Lockfile * downloading ${filename}... * Improvements up command_backup.sh Changes to the messages displayed on screen added trap and improved lockfile support renamed some functions other misc changes --- lgsm/functions/check_tmuxception.sh | 4 +- lgsm/functions/command_backup.sh | 255 ++++++++++++++-------------- lgsm/functions/command_debug.sh | 6 +- lgsm/functions/command_details.sh | 8 +- lgsm/functions/command_monitor.sh | 4 +- lgsm/functions/command_start.sh | 4 +- lgsm/functions/command_stop.sh | 6 +- lgsm/functions/core_dl.sh | 8 +- lgsm/functions/info_distro.sh | 2 + 9 files changed, 156 insertions(+), 141 deletions(-) diff --git a/lgsm/functions/check_tmuxception.sh b/lgsm/functions/check_tmuxception.sh index 31e7b81d7..5b906f53e 100644 --- a/lgsm/functions/check_tmuxception.sh +++ b/lgsm/functions/check_tmuxception.sh @@ -10,7 +10,7 @@ local commandname="check" fn_check_is_in_tmux(){ if [ -n "${TMUX}" ];then fn_print_fail_nl "tmuxception error: Sorry Cobb you cannot start a tmux session inside of a tmux session." - fn_script_log_fatal "tmuxception error: Attempted to start a tmux session inside of a tmux session." + fn_script_log_fatal "Tmuxception error: Attempted to start a tmux session inside of a tmux session." fn_print_information_nl "LGSM creates a tmux session when starting the server." echo "It is not possible to run a tmux session inside another tmux session" echo "https://github.com/GameServerManagers/LinuxGSM/wiki/Tmux#tmuxception" @@ -20,7 +20,7 @@ fn_check_is_in_tmux(){ fn_check_is_in_screen(){ if [ -n "${STY}" ];then fn_print_fail_nl "tmuxception error: Sorry Cobb you cannot start a tmux session inside of a screen session." - fn_script_log_fatal "tmuxception error: Attempted to start a tmux session inside of a screen session." + fn_script_log_fatal "Tmuxception error: Attempted to start a tmux session inside of a screen session." fn_print_information_nl "LGSM creates a tmux session when starting the server." echo "It is not possible to run a tmux session inside screen session" echo "https://github.com/GameServerManagers/LinuxGSM/wiki/Tmux#tmuxception" diff --git a/lgsm/functions/command_backup.sh b/lgsm/functions/command_backup.sh index 489e0a8f4..34d014c42 100644 --- a/lgsm/functions/command_backup.sh +++ b/lgsm/functions/command_backup.sh @@ -10,31 +10,57 @@ local commandaction="Backup" local function_selfname="$(basename $(readlink -f "${BASH_SOURCE[0]}"))" check.sh -fn_script_log "Entering backup" + +# Trap to remove lockfile on quit. +fn_backup_trap(){ + echo "" + echo -ne "backup ${backupname}.tar.gz..." + fn_print_canceled_eol_nl + fn_script_log_info "backup ${backupname}.tar.gz: CANCELED" + sleep 1 + rm -f "${backupdir}/${backupname}.tar.gz" | tee -a "${scriptlog}" + echo -ne "backup ${backupname}.tar.gz..." + fn_print_removed_eol_nl + fn_script_log_info "backup ${backupname}.tar.gz: REMOVED" + # Remove lock file + rm -f "${tmpdir}/.backup.lock" + core_exit.sh +} # Check if a backup is pending or has been aborted using .backup.lock -fn_check_pending_backup(){ +fn_backup_check_lockfile(){ if [ -f "${tmpdir}/.backup.lock" ]; then - fn_print_error "A backup is currently running or has been aborted." - fn_print_info_nl "If you keep seing this message, remove the following file:" - echo "${tmpdir}/.backup.lock" - fn_script_log_fatal "A backup is currently running or has been aborted." - fin_script_log_info "If you keep seing this message, remove the following file: ${tmpdir}/.backup.lock" + fn_print_info_nl "Lock file found: Backup is currently running" + fn_script_log_error "Lock file found: Backup is currently running: ${tmpdir}/.backup.lock" core_exit.sh fi } -# Initialization +# Initialisation fn_backup_init(){ - fn_print_dots "" - sleep 0.5 - # Prepare backup file name with servicename current date + # Backup file name with servicename and current date backupname="${servicename}-$(date '+%Y-%m-%d-%H%M%S')" - # Tells how much will be compressed using rootdirduexbackup value from info_distro and prompt for continue + info_distro.sh - fn_print_info_nl "A total of ${rootdirduexbackup} will be compressed into the following backup:" - fn_script_log "A total of ${rootdirduexbackup} will be compressed into the following backup: ${backupdir}/${backupname}.tar.gz" - echo "${backupdir}/${backupname}.tar.gz" + fn_print_dots "Backup starting" + fn_script_log_info "Backup starting" + sleep 1 + fn_print_ok "Backup starting" + sleep 1 + echo -ne "\n" + if [ ! -d "${backupdir}" ]||[ "${backupcount}" == "0" ]; then + fn_print_info_nl "There are no previous backups" + else + if [ "${lastbackupdaysago}" == "0" ]; then + daysago="less than 1 day ago" + elif [ "${lastbackupdaysago}" == "1" ]; then + daysago="1 day ago" + else + daysago="${lastbackupdaysago} days ago" + fi + echo " * Previous backup was created ${daysago}, total size ${lastbackupsize}" + sleep 1 + fi } @@ -44,16 +70,16 @@ fn_backup_stop_server(){ # Server is stopped if [ "${status}" == "0" ]; then serverstopped="no" - # Server is up and stoponbackup is off + # Server is running and stoponbackup=off elif [ "${stoponbackup}" == "off" ]; then serverstopped="no" - fn_print_info_nl "${servicename} is started and will not be stopped." - fn_print_information_nl "It is advised to stop the server to prevent a file changes and tar errors." - fn_script_log_info "${servicename} is started during the backup" - fn_script_log_info "It is advised to stop the server to prevent a file changes and tar errors." - # Server is up and will be stopped if stoponbackup has no value or anything else than "off" + fn_print_warn_nl "${servicename} is currently running" + echo " * Although unlikely; creating a backup while ${servicename} is running might corrupt the backup." + fn_script_log_warn "${servicename} is currently running" + fn_script_log_warn "Although unlikely; creating a backup while ${servicename} is running might corrupt the backup" + # Server is running and will be stopped if stoponbackup=on or unset else - fn_print_warning_nl "${servicename} will be stopped during the backup." + fn_print_warn_nl "${servicename} will be stopped during the backup" fn_script_log_warn "${servicename} will be stopped during the backup" sleep 4 serverstopped="yes" @@ -63,117 +89,97 @@ fn_backup_stop_server(){ } # Create required folders -fn_backup_directories(){ -fn_print_dots "Backup in progress, please wait..." -fn_script_log_info "Initiating backup" -sleep 0.5 - -# Directories creation -# Create backupdir if it doesn't exist -if [ ! -d "${backupdir}" ]; then - fn_print_info_nl "Creating ${backupdir}" - fn_script_log_info "Creating ${backupdir}" - mkdir "${backupdir}" -fi -# Create tmpdir if it doesn't exist -if [ -n "${tmpdir}" ]&&[ ! -d "${tmpdir}" ]; then - fn_print_info_nl "Creating ${tmpdir}" - fn_script_log "Creating ${tmpdir}" - mkdir -p "${tmpdir}" -fi +fn_backup_dir(){ + # Create backupdir if it doesn't exist + if [ ! -d "${backupdir}" ]; then + mkdir -p "${backupdir}" + fi } -# Create lockfile fn_backup_create_lockfile(){ -if [ -d "${tmpdir}" ]; then - touch "${tmpdir}/.backup.lock" - fn_script_log "Lockfile created" -fi + # Create lockfile + date > "${tmpdir}/.backup.lock" + fn_script_log_info "Lockfile generated" + fn_script_log_info "${tmpdir}/.backup.lock" + # trap to remove lockfile on quit. + trap fn_backup_trap INT } # Compressing files fn_backup_compression(){ -fn_script_log "Compressing ${rootdirduexbackup}" -tar -czf "${backupdir}/${backupname}.tar.gz" -C "${rootdir}" --exclude "backups" ./* -fn_script_log "Compression over" -} - -# Check tar exit code and set the result -fn_check_tar_exit(){ -if [ $? == 0 ]; then - backupresult="PASS" -else - backupresult="FAIL" -fi -} - -# Remove lockfile -fn_backup_remove_lockfile(){ -if [ -d "${tmpdir}" ]&&[ -f "${tmpdir}/.backup.lock" ]; then - rm "${tmpdir}/.backup.lock" - fn_script_log "Lockfile removed" -fi -} - -fn_backup_summary(){ - # when backupresult="PASS" - if [ "${backupresult}" == "PASS" ]; then - fn_print_ok_nl "Backup created: ${backupname}.tar.gz is $(du -sh "${backupdir}/${backupname}.tar.gz" | awk '{print $1}') size" - fn_script_log_pass "Backup created: ${backupdir}/${backupname}.tar.gz is $(du -sh "${backupdir}/${backupname}.tar.gz" | awk '{print $1}') size" - # When backupresult="FAIL" - elif [ "${backupresult}" == "FAIL" ]; then - fn_print_error_nl "Backup failed: ${backupname}.tar.gz" - fn_script_log_error "Backup failed: ${backupname}.tar.gz" - core_exit.sh + # Tells how much will be compressed using rootdirduexbackup value from info_distro and prompt for continue + fn_print_info "A total of ${rootdirduexbackup} will be compressed." + fn_script_log_info "A total of ${rootdirduexbackup} will be compressed: ${backupdir}/${backupname}.tar.gz" + sleep 2 + fn_print_dots "Backup (${rootdirduexbackup}) ${backupname}.tar.gz, in progress..." + fn_script_log_info "backup ${rootdirduexbackup} ${backupname}.tar.gz, in progress" + tar -czf "${backupdir}/${backupname}.tar.gz" -C "${rootdir}" --exclude "backups" ./* + local exitcode=$? + if [ ${exitcode} -ne 0 ]; then + fn_print_fail_eol + fn_script_log_fatal "Backup in progress: FAIL" + echo "${tarcmd}" | tee -a "${scriptlog}" + fn_print_fail_nl "Starting backup" + fn_script_log_fatal "Starting backup" else - fn_print_error_nl "Could not determine compression result." - fn_script_log_error "Could not determine compression result." - core_exit.sh + fn_print_ok_eol + sleep 1 + fn_print_ok_nl "Completed: ${backupname}.tar.gz, total size $(du -sh "${backupdir}/${backupname}.tar.gz" | awk '{print $1}')" + fn_script_log_pass "Backup created: ${backupname}.tar.gz, total size $(du -sh "${backupdir}/${backupname}.tar.gz" | awk '{print $1}')" fi } - # Clear old backups according to maxbackups and maxbackupdays variables -fn_backup_clearing(){ -# How many backups there are -backupscount=$(find "${backupdir}/" -type f -name "*.tar.gz"|wc -l) -# How many backups exceed maxbackups -backupquotadiff=$((backupscount-maxbackups)) -# How many backups exceed maxbackupdays -backupsoudatedcount=$(find "${backupdir}"/ -type f -name "*.tar.gz" -mtime +"${maxbackupdays}"|wc -l) -# If backup variables are set -if [ -n "${maxbackupdays}" ]&&[ -n "${maxbackups}" ]; then - # If anything can be cleared - if [ "${backupquotadiff}" -gt "0" ]||[ "${backupsoudatedcount}" -gt "0" ]; then - # If maxbackups greater or equal than backupsoutdatedcount, then it is used over maxbackupdays - if [ "${backupquotadiff}" -gt "${backupsoudatedcount}" ]||[ "${backupquotadiff}" -eq "${backupsoudatedcount}" ]; then - # Display how many backups will be cleared - fn_print_info_nl "${backupquotadiff} backup(s) exceed max ${maxbackups} and will be cleared." - fn_script_log "${backupquotadiff} backup(s) exceed max ${maxbackups} and will be cleared" - sleep 2 - # Clear over quota backups - find "${backupdir}"/ -type f -name "*.tar.gz" -printf '%T@ %p\n' | sort -rn | tail -${backupquotadiff} | cut -f2- -d" " | xargs rm - fn_print_ok_nl "Cleared ${backupquotadiff} backup(s)." - fn_script_log "Cleared ${backupquotadiff} backup(s)" - # If maxbackupdays is used over maxbackups - elif [ "${backupquotadiff}" -lt "${backupsoudatedcount}" ]; then - # Display how many backups will be cleared - fn_print_info_nl "${backupsoudatedcount} backup(s) older than ${maxbackupdays} days will be cleared." - fn_script_log "${backupsoudatedcount} backup(s) older than ${maxbackupdays} days will be cleared" - find "${backupdir}"/ -type f -mtime +"${maxbackupdays}" -exec rm -f {} \; - fn_print_ok_nl "Cleared ${backupsoudatedcount} backup(s)." - fn_script_log_pass "Cleared ${backupsoudatedcount} backup(s)" - else - fn_script_log "No backups older than ${maxbackupdays} days were found" +fn_backup_prune(){ + # How many backups there are + info_distro.sh + # How many backups exceed maxbackups + backupquotadiff=$((backupcount-maxbackups)) + # How many backups exceed maxbackupdays + backupsoudatedcount=$(find "${backupdir}"/ -type f -name "*.tar.gz" -mtime +"${maxbackupdays}"|wc -l) + # If backup variables are set + if [ -n "${maxbackupdays}" ]&&[ -n "${maxbackups}" ]; then + # If anything can be cleared + if [ "${backupquotadiff}" -gt "0" ]||[ "${backupsoudatedcount}" -gt "0" ]; then + fn_print_dots "Pruning" + fn_script_log_info "Backup pruning activated" + sleep 1 + fn_print_ok_nl "Pruning" + sleep 1 + # If maxbackups greater or equal to backupsoutdatedcount, then it is over maxbackupdays + if [ "${backupquotadiff}" -ge "${backupsoudatedcount}" ]; then + # Display how many backups will be cleared + echo " * Pruning: ${backupquotadiff} backup(s) has exceeded the ${maxbackups} backups limit" + fn_script_log_info "Pruning: ${backupquotadiff} backup(s) has exceeded the ${maxbackups} backups limit" + sleep 1 + fn_print_dots "Pruning: Clearing ${backupquotadiff} backup(s)" + fn_script_log_info "Pruning: Clearing ${backupquotadiff} backup(s)" + sleep 1 + # Clear backups over quota + find "${backupdir}"/ -type f -name "*.tar.gz" -printf '%T@ %p\n' | sort -rn | tail -${backupquotadiff} | cut -f2- -d" " | xargs rm + fn_print_ok_nl "Pruning: Clearing ${backupquotadiff} backup(s)" + fn_script_log_pass "Pruning: Cleared ${backupquotadiff} backup(s)" + # If maxbackupdays is used over maxbackups + elif [ "${backupquotadiff}" -lt "${backupsoudatedcount}" ]; then + # Display how many backups will be cleared + echo " * Pruning: ${backupsoudatedcount} backup(s) are older than ${maxbackupdays} days." + fn_script_log_info "Pruning: ${backupsoudatedcount} backup(s) older than ${maxbackupdays} days." + sleep 1 + fn_print_dots "Pruning: Clearing ${backupquotadiff} backup(s)." + fn_script_log_info "Pruning: Clearing ${backupquotadiff} backup(s)" + sleep 1 + # Clear backups over quota + find "${backupdir}"/ -type f -mtime +"${maxbackupdays}" -exec rm -f {} \; + fn_print_ok_nl "Pruning: Clearing ${backupquotadiff} backup(s)" + fn_script_log_pass "Pruning: Cleared ${backupquotadiff} backup(s)" + fi + sleep 1 fi fi -else - fn_script_log "No backups to clear since maxbackupdays and maxbackups variables are not set" -fi } # Restart the server if it was stopped for the backup -fn_backup_start_back(){ +fn_backup_start_server(){ if [ "${serverstopped}" == "yes" ]; then exitbypass=1 command_start.sh @@ -181,17 +187,16 @@ fn_backup_start_back(){ } # Run functions -fn_check_pending_backup +fn_backup_check_lockfile +fn_backup_create_lockfile fn_backup_init fn_backup_stop_server -fn_backup_directories -fn_backup_create_lockfile +fn_backup_dir fn_backup_compression -fn_check_tar_exit -fn_backup_remove_lockfile -fn_backup_summary -fn_backup_clearing -fn_backup_start_back +fn_backup_prune +fn_backup_start_server + +# Remove lock file +rm -f "${tmpdir}/.backup.lock" -sleep 0.5 core_exit.sh diff --git a/lgsm/functions/command_debug.sh b/lgsm/functions/command_debug.sh index 98bd3082c..ac1d0add8 100644 --- a/lgsm/functions/command_debug.sh +++ b/lgsm/functions/command_debug.sh @@ -10,7 +10,7 @@ local function_selfname="$(basename $(readlink -f "${BASH_SOURCE[0]}"))" # Trap to remove lockfile on quit. fn_lockfile_trap(){ - # Remove lock file + # Remove lockfile rm -f "${rootdir}/${lockselfname}" # resets terminal. Servers can sometimes mess up the terminal on exit. reset @@ -87,8 +87,10 @@ fn_script_log_info "Starting debug" sleep 1 fn_print_ok_nl "Starting debug" -# create lock file. +# Create lockfile date > "${rootdir}/${lockselfname}" +fn_script_log_info "Lockfile generated" +fn_script_log_info "${rootdir}/${lockselfname}" # trap to remove lockfile on quit. trap fn_lockfile_trap INT diff --git a/lgsm/functions/command_details.sh b/lgsm/functions/command_details.sh index 22f8e2a5f..5743e17b0 100644 --- a/lgsm/functions/command_details.sh +++ b/lgsm/functions/command_details.sh @@ -262,7 +262,13 @@ fn_details_backup(){ { echo -e "${blue}No. of backups:\t${default}${backupcount}" echo -e "${blue}Latest backup:${default}" - echo -e "${blue} date:\t${default}${lastbackupdate}" + if [ "${lastbackupdaysago}" == "0" ]; then + echo -e "${blue} date:\t${default}${lastbackupdate} (less than 1 day ago)" + elif [ "${lastbackupdaysago}" == "1" ]; then + echo -e "${blue} date:\t${default}${lastbackupdate} (1 day ago)" + else + echo -e "${blue} date:\t${default}${lastbackupdate} (${lastbackupdaysago} days ago)" + fi echo -e "${blue} file:\t${default}${lastbackup}" echo -e "${blue} size:\t${default}${lastbackupsize}" } | column -s $'\t' -t diff --git a/lgsm/functions/command_monitor.sh b/lgsm/functions/command_monitor.sh index b11015e40..3c6d7fad4 100644 --- a/lgsm/functions/command_monitor.sh +++ b/lgsm/functions/command_monitor.sh @@ -13,8 +13,8 @@ local function_selfname="$(basename $(readlink -f "${BASH_SOURCE[0]}"))" fn_monitor_check_lockfile(){ # Monitor does not run it lockfile is not found if [ ! -f "${rootdir}/${lockselfname}" ]; then - fn_print_error_nl "Disabled: No lock file found" - fn_script_log_error "Disabled: No lock file found" + fn_print_error_nl "Disabled: No lockfile found" + fn_script_log_error "Disabled: No lockfile found" echo " * To enable monitor run ./${selfname} start" core_exit.sh fi diff --git a/lgsm/functions/command_start.sh b/lgsm/functions/command_start.sh index f7f324bf1..57dcbfa60 100644 --- a/lgsm/functions/command_start.sh +++ b/lgsm/functions/command_start.sh @@ -33,7 +33,7 @@ fn_start_teamspeak3(){ fi mv "${scriptlog}" "${scriptlogdate}" - # Create lock file + # Create lockfile date > "${rootdir}/${lockselfname}" cd "${executabledir}" if [ "${ts3serverpass}" == "1" ];then @@ -78,7 +78,7 @@ fn_start_tmux(){ core_exit.sh fi - # Create lock file + # Create lockfile date > "${rootdir}/${lockselfname}" cd "${executabledir}" tmux new-session -d -s "${servicename}" "${executable} ${parms}" 2> "${scriptlogdir}/.${servicename}-tmux-error.tmp" diff --git a/lgsm/functions/command_stop.sh b/lgsm/functions/command_stop.sh index 489013e3d..95aa10536 100644 --- a/lgsm/functions/command_stop.sh +++ b/lgsm/functions/command_stop.sh @@ -234,7 +234,7 @@ fn_stop_teamspeak3(){ ${filesdir}/ts3server_startscript.sh stop > /dev/null 2>&1 check_status.sh if [ "${status}" == "0" ]; then - # Remove lock file + # Remove lockfile rm -f "${rootdir}/${lockselfname}" fn_print_ok_nl "${servername}" fn_script_log_pass "Stopped ${servername}" @@ -253,7 +253,7 @@ fn_stop_mumble(){ sleep 1 check_status.sh if [ "${status}" == "0" ]; then - # Remove lock file + # Remove lockfile rm -f "${rootdir}/${lockselfname}" fn_stop_tmux fn_script_log_pass "Stopped ${servername}" @@ -272,7 +272,7 @@ fn_stop_tmux(){ sleep 0.5 check_status.sh if [ "${status}" == "0" ]; then - # Remove lock file + # Remove lockfile rm -f "${rootdir}/${lockselfname}" # ARK doesn't clean up immediately after tmux is killed. # Make certain the ports are cleared before continuing. diff --git a/lgsm/functions/core_dl.sh b/lgsm/functions/core_dl.sh index e6e563fc7..6d971b997 100644 --- a/lgsm/functions/core_dl.sh +++ b/lgsm/functions/core_dl.sh @@ -78,14 +78,14 @@ fn_dl_extract(){ # Trap to remove file download if canceled before completed fn_fetch_trap(){ echo "" - echo -ne "downloading ${filename}: " + echo -ne "downloading ${filename}..." fn_print_canceled_eol_nl - fn_script_log_info "downloading ${filename}: CANCELED" + fn_script_log_info "downloading ${filename}...CANCELED" sleep 1 rm -f "${filedir}/${filename}" | tee -a "${scriptlog}" - echo -ne "downloading ${filename}: " + echo -ne "downloading ${filename}..." fn_print_removed_eol_nl - fn_script_log_info "downloading ${filename}: REMOVED" + fn_script_log_info "downloading ${filename}...REMOVED" core_exit.sh } diff --git a/lgsm/functions/info_distro.sh b/lgsm/functions/info_distro.sh index f526b4328..cc4037d72 100644 --- a/lgsm/functions/info_distro.sh +++ b/lgsm/functions/info_distro.sh @@ -122,6 +122,8 @@ if [ -d "${backupdir}" ]; then lastbackup=$(ls -t "${backupdir}"/*.tar.gz | head -1) # date of most recent backup. lastbackupdate=$(date -r "${lastbackup}") + # no of days since last backup. + lastbackupdaysago=$(( ( $(date +'%s') - $(date -r "${lastbackup}" +'%s') )/60/60/24 )) # size of most recent backup. lastbackupsize=$(du -h "${lastbackup}" | awk '{print $1}') fi