Viewing: remove_changelog
#!/usr/bin/bash
# remove_changelog: emergency remove changelog files from server.
#
# This is emergency tool to cleanup changelogs in server if changelog
# records cannot be removed by regular means, e.g. due to llog corruptions
#
# Tool goes through changelog_catalog and removes all plain llogs listed
# then removes changelog_catalog itself and changelog_users
# Script accept single parameter which is mount point of server FS mounted
# locally, script accepts also --dry-run option to emulate files removal
#
# Steps to cleanup problematic llogs:
#
# 1. mount MDT filesystem locally on server as ldiskfs/ZFS mount
# 2. run script first in dry-run mode to make sure it parses llogs as needed:
# # bash remove_changelog -n <local_mount>
# 3. save all llogs for analysis:
# # bash remove_changelog -n -z /tmp/llogs_saved <local_mount>
# 4. check that /tmp/llogs_saved.tar.gz exists and has all llogs inside:
# # ls -ali /tmp/llogs_saved.tar.gz
# # tar -tf /tmp/llog_saved.tar.gz
# 5. finally run script to delete all llogs:
# # bash remove_changelog <local_mount>
#
# For better llogs compression xz can be used as well, pass it to the script
# via GZIP env variable:
# # GZIP=xz bash remove_changelog -n -z /tmp/llogs_saved <local_mount>
# Archive name will ends with .xz in that case instead of .gz
ECHO=echo
PROG=$(basename $0)
LLOG_READER=${LLOG_READER:-llog_reader}
GZIP=${GZIP:-gzip}
usage() {
cat -- <<USAGE 1>&2
usage: remove_changelog [--dry-run|-n] [--help|-h] [--quiet|-q]
[--zip}-z] <archive> <localmount>
--help|-h show this usage message
--dry-run|-n only print the names of files to be removed
--quiet|-q run quietly (don't print filenames or status)
--zip|-z <name_prefix>
save all llogs into compressed tar archive with given
name prefix using gzip by default. Other compression
tools can be used via GZIP env variable.
The 'localmount' argument should be an locally mounted MDT device mountpoint.
Examples:
remove_changelog /mnt/mdt0
remove_changelog --dry-run /mnt/mdt0
remove_changelog -z /tmp/llogs /mnt/mdt0
USAGE
exit 1
}
OPT_DRYRUN=false
OPT_ARCH=""
OPT_MOUNT=""
# Examine any long options and arguments
while [ -n "$*" ]; do
arg="$1"
case "$arg" in
-h|--help) usage;;
-n|--dry-run) OPT_DRYRUN=true;;
-q|--quiet) ECHO=:;;
-z|--zip) OPT_ARCH="$2.tar"; shift;;
*)
[ -d "$arg" ] && OPT_MOUNT="$arg";;
esac
shift
done
remove_changelog() {
local mntpoint=$OPT_MOUNT
local catalog=${mntpoint}/changelog_catalog
local users=${mntpoint}/changelog_users
local arch=$OPT_ARCH
if $OPT_DRYRUN; then
$ECHO "Dry run was requested, no changes will be applied"
fi
$ECHO "Scan changelog_catalog at '$mntpoint':"
if [[ ! -f $catalog ]] ; then
echo "$PROG: $catalog doesn't exist already."
else
if [[ ! $(which $LLOG_READER 2>/dev/null) ]] ; then
echo "$PROG: $LLOG_READER is missing."
exit 1
fi
[[ -z $arch ]] || tar -cf $arch $catalog 2>/dev/null
if (( $(stat -c %s $catalog) >= 8192 )) ; then
while read -r path ; do
[[ -z $arch ]] ||
tar -rf $arch ${mntpoint}/$path 2>/dev/null
$ECHO "rm ${mntpoint}/$path"
$OPT_DRYRUN || rm -f ${mntpoint}/$path
done < <($LLOG_READER $catalog |
awk -F "path=" '/path=/ { print $2 }')
else
echo "$PROG: $catalog is too small."
fi
$ECHO "> $catalog"
$OPT_DRYRUN || > $catalog
fi
if [[ -f $users ]] ; then
[[ -z $arch ]] || tar -rf $arch $users 2>/dev/null
$ECHO "> $users"
$OPT_DRYRUN || > $users
else
echo "$PROG: $user doesn't exist."
fi
if [[ "$arch" ]] ; then
$GZIP -3 $arch
$ECHO "llog archive was created by $GZIP"
fi
}
if [ -z $OPT_MOUNT ] ; then
echo "Mount is not specified, exiting"
exit 1
fi
remove_changelog