mirror of
https://oauth2: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@github.com/m1ngsama/TNT.git
synced 2026-06-26 05:44:38 +08:00
174 lines
3.9 KiB
Bash
Executable file
174 lines
3.9 KiB
Bash
Executable file
#!/bin/sh
|
|
# Compact and archive a TNT messages.log file.
|
|
#
|
|
# This is an operator-run maintenance tool. For strict consistency, stop TNT
|
|
# or run it during a quiet maintenance window before compacting the active log.
|
|
|
|
set -eu
|
|
|
|
DRY_RUN=0
|
|
KEEP_ARCHIVES=5
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: scripts/logrotate.sh [--dry-run] [--keep-archives N] [LOG_FILE [MAX_SIZE_MB [KEEP_LINES]]]
|
|
|
|
Defaults:
|
|
LOG_FILE /var/lib/tnt/messages.log
|
|
MAX_SIZE_MB 100
|
|
KEEP_LINES 10000
|
|
|
|
Exit status:
|
|
0 success, including missing log file
|
|
1 runtime error
|
|
64 invalid arguments
|
|
USAGE
|
|
}
|
|
|
|
fail_usage() {
|
|
echo "logrotate: $*" >&2
|
|
usage >&2
|
|
exit 64
|
|
}
|
|
|
|
fail() {
|
|
echo "logrotate: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
is_uint() {
|
|
case "${1:-}" in
|
|
''|*[!0-9]*)
|
|
return 1
|
|
;;
|
|
*)
|
|
return 0
|
|
;;
|
|
esac
|
|
}
|
|
|
|
is_positive_uint() {
|
|
is_uint "$1" && [ "$1" -gt 0 ]
|
|
}
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--dry-run)
|
|
DRY_RUN=1
|
|
shift
|
|
;;
|
|
--keep-archives)
|
|
[ "$#" -ge 2 ] || fail_usage "missing value for --keep-archives"
|
|
is_uint "$2" || fail_usage "invalid archive count: $2"
|
|
KEEP_ARCHIVES=$2
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
-*)
|
|
fail_usage "unknown option: $1"
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[ "$#" -le 3 ] || fail_usage "too many arguments"
|
|
|
|
LOG_FILE=${1:-/var/lib/tnt/messages.log}
|
|
MAX_SIZE_MB=${2:-100}
|
|
KEEP_LINES=${3:-10000}
|
|
|
|
case "$LOG_FILE" in
|
|
''|-*)
|
|
fail_usage "invalid log path"
|
|
;;
|
|
esac
|
|
is_uint "$MAX_SIZE_MB" || fail_usage "invalid max size: $MAX_SIZE_MB"
|
|
is_positive_uint "$KEEP_LINES" || fail_usage "invalid keep lines: $KEEP_LINES"
|
|
|
|
if [ ! -e "$LOG_FILE" ]; then
|
|
echo "logrotate: $LOG_FILE does not exist"
|
|
exit 0
|
|
fi
|
|
[ -f "$LOG_FILE" ] || fail "$LOG_FILE is not a regular file"
|
|
|
|
MAX_BYTES=$((MAX_SIZE_MB * 1024 * 1024))
|
|
FILE_SIZE=$(wc -c < "$LOG_FILE" | tr -d ' ')
|
|
[ -n "$FILE_SIZE" ] || fail "could not read log size"
|
|
|
|
compact_log() {
|
|
timestamp=$(date -u +%Y%m%dT%H%M%SZ)
|
|
backup="${LOG_FILE}.${timestamp}"
|
|
suffix=1
|
|
|
|
while [ -e "$backup" ] || [ -e "${backup}.gz" ]; do
|
|
backup="${LOG_FILE}.${timestamp}.${suffix}"
|
|
suffix=$((suffix + 1))
|
|
done
|
|
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
echo "logrotate: would archive $LOG_FILE to $backup"
|
|
echo "logrotate: would keep last $KEEP_LINES lines"
|
|
return 0
|
|
fi
|
|
|
|
tmp="${LOG_FILE}.tmp.$$"
|
|
rm -f "$tmp"
|
|
cp -p "$LOG_FILE" "$backup" || fail "failed to create archive"
|
|
if ! tail -n "$KEEP_LINES" "$LOG_FILE" > "$tmp"; then
|
|
rm -f "$tmp"
|
|
fail "failed to compact log"
|
|
fi
|
|
if ! cat "$tmp" > "$LOG_FILE"; then
|
|
rm -f "$tmp"
|
|
fail "failed to replace log"
|
|
fi
|
|
rm -f "$tmp"
|
|
|
|
if command -v gzip >/dev/null 2>&1; then
|
|
gzip -f "$backup" || fail "failed to compress archive"
|
|
backup="${backup}.gz"
|
|
fi
|
|
|
|
echo "logrotate: archived $backup"
|
|
echo "logrotate: kept last $KEEP_LINES lines"
|
|
}
|
|
|
|
cleanup_archives() {
|
|
[ "$KEEP_ARCHIVES" -ge 0 ] || return 0
|
|
|
|
archives=$(
|
|
ls -1t "$LOG_FILE".*.gz "$LOG_FILE".[0-9]* 2>/dev/null || true
|
|
)
|
|
[ -n "$archives" ] || return 0
|
|
|
|
printf '%s\n' "$archives" |
|
|
awk '!seen[$0]++' |
|
|
awk -v keep="$KEEP_ARCHIVES" 'NR > keep' |
|
|
while IFS= read -r old; do
|
|
[ -n "$old" ] || continue
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
echo "logrotate: would remove $old"
|
|
else
|
|
rm -f "$old"
|
|
fi
|
|
done
|
|
}
|
|
|
|
if [ "$FILE_SIZE" -gt "$MAX_BYTES" ]; then
|
|
echo "logrotate: size ${FILE_SIZE} bytes exceeds ${MAX_BYTES} bytes"
|
|
compact_log
|
|
else
|
|
echo "logrotate: size ${FILE_SIZE} bytes is within ${MAX_BYTES} bytes"
|
|
fi
|
|
|
|
cleanup_archives
|
|
echo "logrotate: complete"
|