Skip to content

Instantly share code, notes, and snippets.

@mzpqnxow
Created January 26, 2022 15:40
Show Gist options
  • Save mzpqnxow/88761eaaecc393ea3e75ab8040465eca to your computer and use it in GitHub Desktop.
Save mzpqnxow/88761eaaecc393ea3e75ab8040465eca to your computer and use it in GitHub Desktop.
Bash function to roll log files (or any other file) with a maximum keep
#!/bin/bash
#
# Function to roll files in the way that logrotate rolls log files
# Keeps up to the specified amount of files
#
#
# (C) 2022, AG
#
set -eu
# Globals, optional
declare -r SAVE_COUNT=10
declare COMPRESS=xz
declare EXT=".xz"
#
# roll_file()
# Description
# -----------
# Roll a file up to a maximum keep count in the way that logrotate
# rolls and keeps log file
#
# Arguments
# ---------
# basefile: The filename that should be rolled
# compressor: Optional; The name of the compression program (e.g. xz)
# ext: Optional; The extension added by the compression program, including the dot (e.g. .xz)
# maxkeep: Optional; The total number of rolled files to keep
#
# Caveats
# -------
# This will not clean up files that are above the keep count. For example, if
# your keep count is 5 and you basefile.8 exists, it will not be cleaned up. It
# will properly clean up basefile.5. If you're consistent in how you use this it
# should not be an issue
#
# Notes
# -----
# There must be a simpler and more elegant way to do this, but this works
# reliably so it's good enough :>
#
roll_file() {
local ext="${EXT:-}"
local -r basefile="$1"
local -r compressor="${2:-${COMPRESS:-}}"
local -r ext="${3:-${EXT:-}}"
local -r maxkeep="${4:-$SAVE_COUNT}"
if [ -e "$basefile" ]; then
for i in $(seq $maxkeep -1 1); do
nextfile="$basefile.$i$ext"
next_keep_file="$basefile.$((i + 1))$ext"
[[ ! -e "$nextfile" ]] && continue
if [ $i -eq $maxkeep ]; then
# Reached maximum keep count, remove it; it will be replaced
rm -f "$nextfile"
continue
fi
mv "$nextfile" "$next_keep_file"
done
# Finally, roll the base file and compress it if necessary
local -r roll_to="$basefile.1"
mv "$basefile" "$roll_to"
if [ "$compressor" != "" ]; then
# compress the rolled file if compressor is set and it exists
if [ ! $(command -v "$compressor") ]; then
echo "$compressor does not exist; file $basefile was rolled to file $roll_to but *not* compressed!"
echo "Exiting ..."
exit
fi
# Remove if it already exists
rm -f "$roll_to$ext"
# Compress it
"$compressor" "$roll_to"
fi
fi
}
# Roll the file "somefile", using the global defaults
roll_file somefile
# Roll the file "somefile" using bzip2 to compress
roll_file somefile bzip2 .bz2
# Roll the file "somefile" using bzip2 to compress; keep only the latest 5 copies
roll_file somefile bzip2 .bz2 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment