+++ /dev/null
-#!/bin/bash
-
-
-[[ $EUID == 0 ]] || exec sudo -E "${BASH_SOURCE[0]}" "$@"
-
-source /a/bin/errhandle/err
-
-# inspired from
-# https://github.com/kdave/btrfsmaintenance
-
-
-# Man page says we could also use a range, i suppose it would be
-# logical to use a pattern like 5..10 10..20,
-# but I don't know if this would help us at all.
-dusage="5 10"
-musage="5"
-
-e() {
- echo "cron: $*"
- if ! $dryrun; then
- "$@"
- fi
-}
-
-check-idle() {
- type -p xprintidle &>/dev/null || return 0
- export DISPLAY=:0
- # a hours, a movie could run that long.
- idle_limit=$((1000 * 60 * 60 * 2))
- idle_time=$idle_limit
- while read -r user; do
- new_idle_time=$(sudo -u $user xprintidle 2>/dev/null) ||:
- if [[ $new_idle_time && $new_idle_time -lt $idle_time ]]; then
- idle_time=$new_idle_time
- fi
- done < <(users | tr " " "\n" | sort -u)
- if (( idle_time < idle_limit )); then
- idle=false
- else
- idle=true
- fi
-}
-
-
-usage() {
- cat <<EOF
-Usage: ${0##*/} [ARGS]
-Do btrfs maintence or stop if xprintidle shows a user
-
-force Run regardless of user idle status
-check Only check if an existing maintence should be cancelled due to
- nonidle user. Also, runs in a loop every 20 seconds for 10
- minutes.
-
-Note: Uses util-linux getopt option parsing: spaces between args and
-options, short options can be combined, options before args.
-EOF
- exit $1
-}
-
-
-force=false
-check=false
-dryrun=false
-if [[ $1 ]]; then
- case $1 in
- check)
- check=true
- ;;
- force)
- force=true
- ;;
- dryrun)
- dryrun=true
- ;;
- *)
- echo "$0: error: unexpected arg" >&2
- usage 1
- ;;
- esac
-fi
-
-
-main() {
- idle=true
- if ! $force; then
- check-idle
- fi
-
- tmp=$(mktemp)
-
- fnd="findmnt --types btrfs --noheading"
- for x in $($fnd --output "SOURCE" --nofsroot | sort -u); do
- mnt=$($fnd --output "TARGET" --first-only --source $x)
- [[ $mnt ]] || continue
-
- if ! btrfs dev stats -c $mnt >$tmp; then
- if diff -q $mnt/btrfs-dev-stats $tmp; then
- diff -u $mnt/btrfs-dev-stats $tmp | mail -s "$HOSTNAME: error: btrfs dev stats -c $mnt" root@localhost
- cat $tmp >$mnt/btrfs-dev-stats
- fi
- fi
- rm -f $tmp
-
- if ! $idle; then
- if $dryrun; then
- echo "$0: not idle. if this wasnt a dry run, btrfs scrub cancel $mnt"
- else
- btrfs scrub cancel $mnt &>/dev/null ||:
- continue
- fi
- fi
- if $check; then
- continue
- fi
-
- # for comparing before and after balance.
- # the log is already fairly verbose, so commented.
- # e btrfs filesystem df $mnt
- # e df -H $mnt
- if btrfs filesystem df $mnt | grep -q "Data+Metadata"; then
- for usage in $dusage; do
- e ionice -c 3 btrfs balance start -dusage=$usage -musage=$usage $mnt
- done
- else
- e ionice -c 3 btrfs balance start -dusage=0 $mnt
- for usage in $dusage; do
- e ionice -c 3 btrfs balance start -dusage=$usage $mnt
- done
- e ionice -c 3 btrfs balance start -musage=0 $mnt
- for usage in $musage; do
- e ionice -c 3 btrfs balance start -musage=$usage $mnt
- done
- fi
- date=
- scrub_status=$(btrfs scrub status $mnt)
- if printf "%s\n" "$scrub_status" | grep -i '^status:[[:space:]]*finished$' &>/dev/null; then
- date=$(printf "%s\n" "$scrub_status" | sed -rn 's/^Scrub started:[[:space:]]*(.*)/\1/p')
- fi
- if [[ ! $date ]]; then
- # output from older versions, at least btrfs v4.15.1
- date=$(
- printf "%s\n" "$scrub_status" | \
- sed -rn 's/^\s*scrub started at (.*) and finished.*/\1/p'
- )
- fi
- if [[ $date ]]; then
- if $dryrun; then
- echo "$0: last scrub finish for $mnt: $date"
- fi
- date=$(date --date="$date" +%s)
- # if date is sooner than 90 days ago
- # the wiki recommends 30 days or so, but
- # it makes the comp lag like shit for a day,
- # so I'm going with 90 days.
- if (( date > EPOCHSECONDS - 60*60*24*30 )); then
- if $dryrun; then
- echo "$0: skiping scrub of $mnt, last was $(( (EPOCHSECONDS - date) / 60/60/24 )) days ago, < 30 days"
- fi
- continue
- fi
- fi
- # -c 2 -n 4 is from btrfsmaintenance, does ionice
- e btrfs scrub start -Bd -c 2 -n 4 $mnt
- done
-}
-
-loop-main() {
- while true; do
- main
- sleep 60
- done
-}
-
-if $check; then
- loop-main
-else
- main
-fi