From 1a69873e6ac32d91c89f60bdafe8228368d6ff60 Mon Sep 17 00:00:00 2001 From: Seth Grover Date: Mon, 8 Apr 2024 14:53:33 -0600 Subject: [PATCH] for idaholab/Malcolm#453, allow specifying a maximum gigabytes threshold for prune_files.sh --- shared/bin/prune_files.sh | 66 ++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/shared/bin/prune_files.sh b/shared/bin/prune_files.sh index 9d4c63f99..64949be66 100755 --- a/shared/bin/prune_files.sh +++ b/shared/bin/prune_files.sh @@ -1,53 +1,62 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright (c) 2024 Battelle Energy Alliance, LLC. All rights reserved. # recursion depth (1 = not recursive) DEPTH=1 -# threshold is an integer percentage between 1-100; the script will prune until disk usage drops below the threshold -THRESHOLD=90 # defaults to "prune when usage >= 90%"; +# THRESHOLD_PCT and MAXSIZE_GB define pruning triggers; either or both may trigger pruning. +# A value of 0 means that trigger is unused +# If either trigger condition matches, the script will prune until disk usage drops **below** the thresholds + +# THRESHOLD_PCT is an integer percentage between 1-100 ("prune when disk usage >= THRESHOLD_PCT%") +THRESHOLD_PCT=0 +# MAXSIZE_GB is an integer representing gigabytes ("prune when path contents >= MAXSIZE_GB") +MAXSIZE_GB=0 # if specified, this script will check and prune every $INTERVAL seconds INTERVAL=0 # defaults to "run once then exit" VERBOSE=0 # defaults to "not verbose" - -while getopts t:p:i:rv opts; do +while getopts i:m:p:rt:v opts; do case ${opts} in - p) PRUNE_PATH=${OPTARG} ;; - t) THRESHOLD=${OPTARG} ;; i) INTERVAL=${OPTARG} ;; + m) MAXSIZE_GB=${OPTARG} ;; + p) PRUNE_PATH=${OPTARG} ;; r) DEPTH=999 ;; + t) THRESHOLD_PCT=${OPTARG} ;; v) VERBOSE=1 ;; esac done INT_RE='^[0-9]+$' -if [ -z $PRUNE_PATH ] || [ ! -e "$PRUNE_PATH" ] || ! pushd >/dev/null 2>&1 $PRUNE_PATH ; then - echo "Please specify prune path with -p" +if [[ -z "$PRUNE_PATH" ]] || [[ ! -e "$PRUNE_PATH" ]] || ! pushd >/dev/null 2>&1 $PRUNE_PATH ; then + echo "Please specify prune path with -p" >&2 exit 1 fi -if [ -z $THRESHOLD ] || [[ ! "$THRESHOLD" =~ $INT_RE ]] || ! [ "$THRESHOLD" -ge 1 -a "$THRESHOLD" -le 100 ] ; then - echo "Please specify prune threshold (percentage, 1-100) with -t" +if [[ ! "$INTERVAL" =~ $INT_RE ]] || ! (( "$INTERVAL" >= 0 && "$INTERVAL" <= 86400 )) ; then + echo "Please specify prune check interval (seconds, 0-86400) with -i (0 = run once)" >&2 exit 1 fi -if [[ ! "$INTERVAL" =~ $INT_RE ]] || ! [ "$INTERVAL" -ge 0 -a "$INTERVAL" -le 86400 ] ; then - echo "Please specify prune check interval (seconds, 0-86400) with -i (0 = run once)" +if ( [[ -z "$THRESHOLD_PCT" ]] || [[ ! "$THRESHOLD_PCT" =~ $INT_RE ]] || ! (( "$THRESHOLD_PCT" >= 1 && "$THRESHOLD_PCT" <= 100)) ) && + ( [[ -z "$MAXSIZE_GB" ]] || [[ ! "$MAXSIZE_GB" =~ $INT_RE ]] || ! (( "$MAXSIZE_GB" >= 1 )) ); then + echo "Please specify at least one prune trigger: threshold (percentage, 1-100) with -t; or, maximum size (gigabytes, >= 1) with -m" >&2 exit 1 fi while true ; do # check initial disk capacity - USAGE=$(df -k . | awk '{gsub("%",""); capacity=$5}; END {print capacity}') - if [ $USAGE -gt $THRESHOLD ] ; then + USAGE_PCT=$(df -k . | awk '{gsub("%",""); capacity=$5}; END {print capacity}') + USAGE_GB=$(du -sh --block-size=1G . | awk '{print $1}') + # du -sh --block-size=1G ~/download/ | awk '{print $1}' + if ( (( $THRESHOLD_PCT > 0 )) && (( $USAGE_PCT > $THRESHOLD_PCT )) ) || ( (( $MAXSIZE_GB > 0 )) && (( $USAGE_GB > $MAXSIZE_GB )) ); then # we have exceeded the threshold, see if there is something to prune - [[ "$VERBOSE" == "1" ]] && echo "\"$PRUNE_PATH\" is at $USAGE% of capacity, pruning..." + [[ "$VERBOSE" == "1" ]] && echo "\"$PRUNE_PATH\" is at $USAGE_PCT% of capacity ($USAGE_GB GB), pruning..." >&2 # read files by modification time, oldest first, deleting until we've dropped below the threshold DELETED=0 @@ -56,20 +65,21 @@ while true ; do FILE_SIZE_HUMAN=$(numfmt --to=iec-i --suffix=B $FILE_SIZE) FILE_TIME_HUMAN=$(date -u -d @$FILE_TIME) - if [ -f "$FILE_TO_DELETE" ]; then + if [[ -f "$FILE_TO_DELETE" ]]; then if rm -f "$FILE_TO_DELETE" ; then DELETED=$((DELETED+1)) - echo "Pruned \"$FILE_TO_DELETE\" ($FILE_SIZE_HUMAN, $FILE_TIME_HUMAN)" + echo "Pruned \"$FILE_TO_DELETE\" ($FILE_SIZE_HUMAN, $FILE_TIME_HUMAN)" >&2 # re-check disk capacity - USAGE=$(df -k . | awk '{gsub("%",""); capacity=$5}; END {print capacity}') - if [ $USAGE -gt $THRESHOLD ] ; then + USAGE_PCT=$(df -k . | awk '{gsub("%",""); capacity=$5}; END {print capacity}') + USAGE_GB=$(du -sh --block-size=1G . | awk '{print $1}') + if ( (( $THRESHOLD_PCT > 0 )) && (( $USAGE_PCT > $THRESHOLD_PCT )) ) || ( (( $MAXSIZE_GB > 0 )) && (( $USAGE_GB > $MAXSIZE_GB )) ); then # we still exceed the threshold, continue to loop - [[ "$VERBOSE" == "1" ]] && echo "\"$PRUNE_PATH\" is at $USAGE% of capacity, pruning..." + [[ "$VERBOSE" == "1" ]] && echo "\"$PRUNE_PATH\" is at $USAGE_PCT% of capacity ($USAGE_GB GB), pruning..." >&2 else # we're below the limit, break - [[ "$VERBOSE" == "1" ]] && echo "\"$PRUNE_PATH\" is at $USAGE% of capacity" + [[ "$VERBOSE" == "1" ]] && echo "\"$PRUNE_PATH\" is at $USAGE_PCT% of capacity ($USAGE_GB GB)" >&2 break fi @@ -78,18 +88,18 @@ while true ; do done < <(find . -xdev -mindepth 1 -maxdepth $DEPTH -ignore_readdir_race -type f \( ! -path '*/spool/*' -o -path '*/spool/tmp*' \) -printf '%T@ %s %p\0' 2>/dev/null | sort -zn 2>/dev/null) - if [ $DELETED -gt 0 ] ; then - [[ "$VERBOSE" == "1" ]] && echo "Pruned $DELETED files in \"$PRUNE_PATH\"" + if (( $DELETED > 0 )) ; then + [[ "$VERBOSE" == "1" ]] && echo "Pruned $DELETED files in \"$PRUNE_PATH\"" >&2 else - echo "Nothing was pruned in \"$PRUNE_PATH\"!" + echo "Nothing was pruned in \"$PRUNE_PATH\"!" >&2 fi else - [[ "$VERBOSE" == "1" ]] && echo "\"$PRUNE_PATH\" is at $USAGE% of capacity" + [[ "$VERBOSE" == "1" ]] && echo "\"$PRUNE_PATH\" is at $USAGE_PCT% of capacity ($USAGE_GB GB)" >&2 fi - if [ $INTERVAL -gt 0 ] ; then - sleep $INTERVAL + if (( $INTERVAL > 0 )) ; then + for i in $(seq 1 $INTERVAL); do sleep 1; done else break fi