#!/usr/bin/env bash ########################################################################### # Script: zoneminder-event-cleanup.sh # Purpose: Clean up old Zoneminder events but exclude archived events # Authors: Claudio Kuenzler (2018,2021,2023) # Guenter Bailey (2020) # Carlos Milan Figueredo (2021) # Doc: https://www.claudiokuenzler.com/blog/814/how-to-manually-clean-up-delete-zoneminder-events # History: # 2018-12-14 First version # 2018-12-18 DB Name variable in first query # 2020-07-24 added Docker Mysql (@Brawn1) # 2020-08-06 changed for zoneminder 1.24+ (@Brawn1) # 2020-08-07 remove complexity and docker parts (@Brawn1) # 2021-03-08 Export MYSQL_PWD (fix issue #6) # 2021-08-28 Added transactional processing, progress indicator and truncate log option (@cmilanf) # 2021-09-08 Catch MySQL Error # 2023-06-09 Delete empty cache directories ########################################################################### # User variables olderthan=60 # Defines the minimum age in days of the events to be deleted zmcache=/var/cache/zoneminder/events # Defines the path where zm stores events mysqlhost=localhost # Defines the MySQL host for the zm database mysqldb=zm # Defines the MySQL database name used by zm mysqluser=zoneminder # Defines a MySQL user to connect to the database mysqlpass=zm-mysql-password # Defines the password for the MySQL user export MYSQL_PWD=${mysqlpass} zm_linked_version="" # set "true" if using zoneminder pre 1.24 (old version with symlinks instead directories by events) truncate_logs="true" # set "true" if you want to truncate Log table # Spin progress spin='-\|/' # Fixed variables tmpfile=/tmp/$RANDOM # Get archived events from database declare -a archived=( $(mysql -N -h ${mysqlhost} -u ${mysqluser} -e "select Id from ${mysqldb}.Events where Archived = 1;") ) # Catch MySQL errors if [[ -n $(echo ${archived[*]} | grep "ERROR") ]]; then echo "Error while connecting to database. Error was: ${archived[*]}" exit 1 fi # Define find exceptions based on archived events i=0 for id in $(echo ${archived[*]}); do findexception[$i]=" ! -name .${id}" let i++ done # Find events according to our filter if [[ ! -z ${zm_linked_version} ]]; then find ${zmcache}/ -mindepth 2 -type l -mtime +${olderthan} ${findexception[*]} -exec ls -la {} + > $tmpfile else find ${zmcache}/ -mindepth 3 -maxdepth 3 -type d -mtime +${olderthan} ${findexception[*]} -exec ls -ld {} + > $tmpfile fi num_events=$(wc -l < $tmpfile) # For each found event... i=0 j=0 while read line; do i=$(( (i+1) %4 )) j=$((j+1)) printf "\r[${spin:$i:1}] ($j/$num_events) " # Get the event ID eventid=$(echo $line | awk '{print $9}' | awk -F'/' '{print $NF}' | sed "s/\.//g") realpath=$(echo $line | awk '{print $9"/"$11}' | sed "s/\.[0-9]*\///g") echo -n "Deleting Event Id=$eventid" if [[ ! -z ${zm_linked_version} ]]; then symlink=$(echo $line | awk '{print $9}') rm -f ${symlink} fi # delete events from disk and check if absolute path is similar to zmcache path (prevent to delete /) if [[ ${realpath} == ${zmcache}* ]]; then rm -rf ${realpath} fi # delete eventid from database mysql_query="START TRANSACTION; DELETE FROM ${mysqldb}.Events where Id = $eventid; DELETE FROM ${mysqldb}.Frames where EventId = $eventid; DELETE FROM ${mysqldb}.Stats where EventId = $eventid; COMMIT;" mysql -h ${mysqlhost} -N -u ${mysqluser} -e "${mysql_query}" done < $tmpfile echo "Event clean-up finished!" # Delete empty directories inside zmcache find ${zmcache}/ -empty -type d -delete # truncate log table if [[ ! -z ${truncate_logs} ]]; then echo "Truncating Logs table..." mysql -h ${mysqlhost} -N -u ${mysqluser} -e "TRUNCATE TABLE ${mysqldb}.Logs" echo "Logs clean-up finished!" fi exit 0