Files
gangyan/scripts/log-trim-daemon.sh

60 lines
1.5 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Keep a log file capped by trimming from the front.
# Usage:
# ./log-trim-daemon.sh --file /path/to/app.log --max-mb 5 --interval-sec 3
set -euo pipefail
FILE=""
MAX_MB=5
INTERVAL_SEC=3
while [ $# -gt 0 ]; do
case "$1" in
--file) FILE="${2:-}"; shift 2 ;;
--max-mb) MAX_MB="${2:-}"; shift 2 ;;
--interval-sec) INTERVAL_SEC="${2:-}"; shift 2 ;;
-h|--help)
echo "Usage: $0 --file PATH [--max-mb 5] [--interval-sec 3]"
exit 0
;;
*)
echo "Unknown arg: $1" >&2
exit 2
;;
esac
done
if [ -z "${FILE}" ]; then
echo "Missing --file" >&2
exit 2
fi
MAX_BYTES=$((MAX_MB * 1024 * 1024))
TMP="${FILE}.trimtmp.$$"
LOCK="${FILE}.trimlock"
mkdir -p "$(dirname "$FILE")"
touch "$FILE" 2>/dev/null || true
while true; do
if [ -f "$FILE" ]; then
size=$(stat -c%s "$FILE" 2>/dev/null || echo 0)
if [ "${size:-0}" -gt "$MAX_BYTES" ]; then
# Keep only the last MAX_BYTES bytes.
# IMPORTANT: do NOT replace the file inode (mv),否则 tail -f/编辑器可能还在看旧 inode
# 会出现“日志不更新/看不到最新内容”的错觉。这里用 copy+truncate 保持 inode 不变。
(
flock -w 2 9 || exit 0
tail -c "$MAX_BYTES" "$FILE" > "$TMP" 2>/dev/null || true
# 覆盖写回同一文件inode 不变)
if [ -s "$TMP" ]; then
cat "$TMP" > "$FILE" 2>/dev/null || true
fi
rm -f "$TMP" 2>/dev/null || true
) 9>"$LOCK" || true
fi
fi
sleep "$INTERVAL_SEC"
done