Add strike system to arr_corruption_scan.sh — require repeat corrupt detections before remediating
This commit is contained in:
@@ -64,7 +64,13 @@
|
|||||||
# container almost certainly mounts shares differently)
|
# container almost certainly mounts shares differently)
|
||||||
#
|
#
|
||||||
# master.conf
|
# master.conf
|
||||||
# CORRUPTION_SCAN_STATE_FILE — path to the clean-file skip-cache (default in DATA_DIR)
|
# CORRUPTION_SCAN_STATE_FILE — path to the clean-file skip-cache (default in DATA_DIR)
|
||||||
|
# CORRUPTION_SCAN_STRIKES_FILE — path to the consecutive-corrupt-detection counter (default
|
||||||
|
# in DATA_DIR), keyed by host path
|
||||||
|
# CORRUPTION_SCAN_STRIKE_LIMIT — consecutive corrupt detections required before --remediate
|
||||||
|
# acts on a file (default 2) — guards against a one-off
|
||||||
|
# ffprobe hiccup (mid-write file, NFS blip) triggering an
|
||||||
|
# unnecessary delete+re-search. Resets on a clean re-probe.
|
||||||
# SONARR_VERSION_MAJOR — reused from sonarr_cleanup.sh for the API version check
|
# SONARR_VERSION_MAJOR — reused from sonarr_cleanup.sh for the API version check
|
||||||
#
|
#
|
||||||
# ==============================================================================================
|
# ==============================================================================================
|
||||||
@@ -165,6 +171,36 @@ CORRUPTION_SCAN_STATE_FILE="${CORRUPTION_SCAN_STATE_FILE:-$DATA_DIR/corruption_s
|
|||||||
mkdir -p "$(dirname "$CORRUPTION_SCAN_STATE_FILE")"
|
mkdir -p "$(dirname "$CORRUPTION_SCAN_STATE_FILE")"
|
||||||
touch "$CORRUPTION_SCAN_STATE_FILE"
|
touch "$CORRUPTION_SCAN_STATE_FILE"
|
||||||
|
|
||||||
|
CORRUPTION_SCAN_STRIKES_FILE="${CORRUPTION_SCAN_STRIKES_FILE:-$DATA_DIR/corruption_scan_strikes.tsv}"
|
||||||
|
CORRUPTION_SCAN_STRIKE_LIMIT="${CORRUPTION_SCAN_STRIKE_LIMIT:-2}"
|
||||||
|
mkdir -p "$(dirname "$CORRUPTION_SCAN_STRIKES_FILE")"
|
||||||
|
touch "$CORRUPTION_SCAN_STRIKES_FILE"
|
||||||
|
|
||||||
|
# Thin wrappers around common.sh's wd_state_get/wd_state_set — same shape as
|
||||||
|
# stability_watchdog.sh's get_strikes/set_strikes/increment_strikes/reset_strikes, keyed here
|
||||||
|
# by host path instead of a watchdog check name. Requires repeat corrupt detections across
|
||||||
|
# separate scan runs before --remediate acts, so a one-off ffprobe hiccup (mid-write file,
|
||||||
|
# NFS blip) can't trigger an unnecessary delete+re-search on its own.
|
||||||
|
get_scan_strikes() {
|
||||||
|
wd_state_get "$1" "$CORRUPTION_SCAN_STRIKES_FILE"
|
||||||
|
}
|
||||||
|
set_scan_strikes() {
|
||||||
|
wd_state_set "$1" "$2" "$CORRUPTION_SCAN_STRIKES_FILE"
|
||||||
|
}
|
||||||
|
increment_scan_strikes() {
|
||||||
|
local current
|
||||||
|
current=$(get_scan_strikes "$1")
|
||||||
|
[[ -z "$current" ]] && current=0
|
||||||
|
(( current++ ))
|
||||||
|
set_scan_strikes "$1" "$current"
|
||||||
|
echo "$current"
|
||||||
|
}
|
||||||
|
reset_scan_strikes() {
|
||||||
|
local current
|
||||||
|
current=$(get_scan_strikes "$1")
|
||||||
|
[[ -n "$current" && "$current" != "0" ]] && set_scan_strikes "$1" 0
|
||||||
|
}
|
||||||
|
|
||||||
if [[ "$SHOW_STATUS" == true ]]; then
|
if [[ "$SHOW_STATUS" == true ]]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━"
|
echo "━━━━━ $ICON_SUMMARY STATUS ━━━━━"
|
||||||
@@ -174,6 +210,7 @@ if [[ "$SHOW_STATUS" == true ]]; then
|
|||||||
echo "$ICON_GEAR FFprobe binary: $FFPROBE_BIN"
|
echo "$ICON_GEAR FFprobe binary: $FFPROBE_BIN"
|
||||||
echo "$ICON_GEAR FFprobe path map: ${#FFPROBE_PATH_MAP[@]} entries"
|
echo "$ICON_GEAR FFprobe path map: ${#FFPROBE_PATH_MAP[@]} entries"
|
||||||
echo "$ICON_GEAR State file: $CORRUPTION_SCAN_STATE_FILE"
|
echo "$ICON_GEAR State file: $CORRUPTION_SCAN_STATE_FILE"
|
||||||
|
echo "$ICON_GEAR Strike limit: $CORRUPTION_SCAN_STRIKE_LIMIT"
|
||||||
echo "$ICON_GEAR Remediate: $REMEDIATE"
|
echo "$ICON_GEAR Remediate: $REMEDIATE"
|
||||||
echo "$ICON_GEAR Scan limit: ${SCAN_LIMIT:-unlimited}"
|
echo "$ICON_GEAR Scan limit: ${SCAN_LIMIT:-unlimited}"
|
||||||
echo "$ICON_GEAR Path filter: ${PATH_FILTER:-none}"
|
echo "$ICON_GEAR Path filter: ${PATH_FILTER:-none}"
|
||||||
@@ -278,6 +315,7 @@ SCANNED=0
|
|||||||
SKIPPED_CACHED=0
|
SKIPPED_CACHED=0
|
||||||
SKIPPED_UNMAPPED=0
|
SKIPPED_UNMAPPED=0
|
||||||
CORRUPT_COUNT=0
|
CORRUPT_COUNT=0
|
||||||
|
STRIKE_HELD=0
|
||||||
REMEDIATED=0
|
REMEDIATED=0
|
||||||
REMEDIATE_FAILED=0
|
REMEDIATE_FAILED=0
|
||||||
|
|
||||||
@@ -318,6 +356,7 @@ while IFS= read -r item; do
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$result" == "clean" ]]; then
|
if [[ "$result" == "clean" ]]; then
|
||||||
|
reset_scan_strikes "$host_path"
|
||||||
echo -e "${host_path}\t${stamp}" >> "$FRESH_CLEAN_TMP"
|
echo -e "${host_path}\t${stamp}" >> "$FRESH_CLEAN_TMP"
|
||||||
[[ "$ENABLE_LOGGING" == true ]] && echo " $ICON_SUCCESS $host_path"
|
[[ "$ENABLE_LOGGING" == true ]] && echo " $ICON_SUCCESS $host_path"
|
||||||
continue
|
continue
|
||||||
@@ -326,13 +365,21 @@ while IFS= read -r item; do
|
|||||||
# corrupt:<reason>
|
# corrupt:<reason>
|
||||||
reason="${result#corrupt:}"
|
reason="${result#corrupt:}"
|
||||||
(( CORRUPT_COUNT++ ))
|
(( CORRUPT_COUNT++ ))
|
||||||
echo " $ICON_ERROR CORRUPT: $host_path"
|
strikes=$(increment_scan_strikes "$host_path")
|
||||||
|
echo " $ICON_ERROR CORRUPT: $host_path (strike $strikes/$CORRUPTION_SCAN_STRIKE_LIMIT)"
|
||||||
[[ "$ENABLE_LOGGING" == true ]] && echo " $reason"
|
[[ "$ENABLE_LOGGING" == true ]] && echo " $reason"
|
||||||
|
|
||||||
if [[ "$REMEDIATE" != true ]]; then
|
if [[ "$REMEDIATE" != true ]]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if (( strikes < CORRUPTION_SCAN_STRIKE_LIMIT )); then
|
||||||
|
warn " $host_path — strike $strikes/$CORRUPTION_SCAN_STRIKE_LIMIT, not yet remediating (needs repeat confirmation)"
|
||||||
|
(( STRIKE_HELD++ ))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
reset_scan_strikes "$host_path"
|
||||||
|
|
||||||
episode_id=$(echo "$item" | jq -r '.episodeId // empty')
|
episode_id=$(echo "$item" | jq -r '.episodeId // empty')
|
||||||
title=$(echo "$item" | jq -r '.sceneName // .relativePath // .path')
|
title=$(echo "$item" | jq -r '.sceneName // .relativePath // .path')
|
||||||
|
|
||||||
@@ -389,6 +436,7 @@ echo "$ICON_SUCCESS Skipped (cached): $SKIPPED_CACHED"
|
|||||||
echo "$ICON_WARN Skipped (unmapped): $SKIPPED_UNMAPPED"
|
echo "$ICON_WARN Skipped (unmapped): $SKIPPED_UNMAPPED"
|
||||||
echo "$ICON_ERROR Corrupt found: $CORRUPT_COUNT"
|
echo "$ICON_ERROR Corrupt found: $CORRUPT_COUNT"
|
||||||
if [[ "$REMEDIATE" == true ]]; then
|
if [[ "$REMEDIATE" == true ]]; then
|
||||||
|
echo "$ICON_WARN Held (strikes): $STRIKE_HELD"
|
||||||
echo "$ICON_SUCCESS Remediated: $REMEDIATED"
|
echo "$ICON_SUCCESS Remediated: $REMEDIATED"
|
||||||
echo "$ICON_ERROR Remediation failed: $REMEDIATE_FAILED"
|
echo "$ICON_ERROR Remediation failed: $REMEDIATE_FAILED"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1185,6 +1185,12 @@
|
|||||||
# queued behind other moves already in progress, not just its
|
# queued behind other moves already in progress, not just its
|
||||||
# own copy time
|
# own copy time
|
||||||
CORRUPTION_SCAN_STATE_FILE="${DATA_DIR}/corruption_scan_state.tsv" # clean-file skip-cache
|
CORRUPTION_SCAN_STATE_FILE="${DATA_DIR}/corruption_scan_state.tsv" # clean-file skip-cache
|
||||||
|
CORRUPTION_SCAN_STRIKES_FILE="${DATA_DIR}/corruption_scan_strikes.tsv" # consecutive corrupt-detection counts, keyed by host path
|
||||||
|
CORRUPTION_SCAN_STRIKE_LIMIT=2 # consecutive corrupt detections (across separate scan runs)
|
||||||
|
# required before --remediate deletes+re-searches — guards
|
||||||
|
# against a one-off ffprobe hiccup (mid-write file, NFS blip)
|
||||||
|
# triggering an unnecessary delete. Resets to 0 the moment a
|
||||||
|
# file probes clean again.
|
||||||
SONARR_EXTENSIONS=("mkv" "mp4" "avi" "m4v" "ts" "wmv" "mov")
|
SONARR_EXTENSIONS=("mkv" "mp4" "avi" "m4v" "ts" "wmv" "mov")
|
||||||
SONARR_PROTECTED_PATTERNS=(
|
SONARR_PROTECTED_PATTERNS=(
|
||||||
# Subtitles
|
# Subtitles
|
||||||
|
|||||||
Reference in New Issue
Block a user