Files
webgui/sbin/mover

193 lines
4.7 KiB
Bash
Executable File

#!/bin/bash
#Copyright 2005-2024, Lime Technology, Inc.
#License: GPLv2 only
# This is the 'mover' script used for moving files between pools and/or the main unRAID array.
# It is typically invoked via cron.
# The script is set up so that hidden directories (i.e., directory names beginning with a '.'
# character) at the topmost level of a pool or an array disk are not moved. This behavior
# can be turned off by uncommenting the following line:
# shopt -s dotglob
# Files at the top level of a pool or an array disk are never moved.
# The 'find' command generates a list of all files and directories of a share.
# For each file, if the file is not "in use" by any process (as detected by 'in_use' command),
# then the file is moved, and upon success, deleted from the source disk. If the file already
# exists on the target, it is not moved and the source is not deleted. All meta-data of moved
# files/directories is preserved: permissions, ownership, extended attributes, and access/modified
# timestamps.
# If an error occurs in copying a file, the partial file, if present, is deleted and the
# operation continues on to the next file.
PIDFILE="/var/run/mover.pid"
CFGFILE="/boot/config/share.cfg"
DEBUGGING=""
move() {
/usr/bin/find "$1" -depth 2>/dev/null | /usr/libexec/unraid/move $DEBUGGING
}
start() {
if [ -f $PIDFILE ]; then
if ps h $(cat $PIDFILE) | grep mover ; then
echo "mover: already running"
exit 1
fi
fi
if [ -f $CFGFILE ]; then
# Only start if shfs includes pools
if ! grep -qs 'shareCacheEnabled="yes"' $CFGFILE ; then
echo "mover: cache not enabled"
exit 2
fi
fi
echo $$ >/var/run/mover.pid
echo "mover: started"
shopt -s nullglob
for SHARECFG in /boot/config/shares/*.cfg ; do
SHARE=$(basename "$SHARECFG" .cfg)
source <(fromdos < "$SHARECFG")
# maybe move from primary to secondary
if [[ $shareUseCache = yes && -n $shareCachePool && -d "/mnt/$shareCachePool/$SHARE" ]]; then
if [[ -n $shareCachePool2 ]]; then
# secondary is a pool
if [[ -d "/mnt/$shareCachePool2" ]]; then
move "/mnt/$shareCachePool/$SHARE"
fi
else
# secondary is the unRAID array, ensure at least one data disk is present
disks=(/mnt/disk[1-9]/ /mnt/disk[1-9][0-9]/)
if [[ ${#disks[@]} -gt 0 ]]; then
move "/mnt/$shareCachePool/$SHARE"
fi
fi
fi
# maybe move from secondary to primary
if [[ $shareUseCache = prefer ]]; then
if [[ -n $shareCachePool2 ]]; then
# secondary is a pool (primary is also a pool)
if [[ -d "/mnt/$shareCachePool2/$SHARE" && -n $shareCachePool && -d "/mnt/$shareCachePool" ]]; then
move "/mnt/$shareCachePool2/$SHARE"
fi
else
# secondary is the unRAID array
if [[ -n $shareCachePool && -d "/mnt/$shareCachePool" ]]; then
for SHAREPATH in /mnt/disk[1-9]/$SHARE/ /mnt/disk[1-9][0-9]/$SHARE/ ; do
move "$SHAREPATH"
done
fi
fi
fi
done
rm -f $PIDFILE
echo "mover: finished"
}
empty() {
if [ -f $PIDFILE ]; then
if ps h $(cat $PIDFILE) | grep mover ; then
echo "mover: already running"
exit 1
fi
fi
echo $$ >/var/run/mover.pid
echo "mover: started"
shopt -s nullglob
for SHAREPATH in /mnt/$DISK/* ; do
if [[ -d "$SHAREPATH" ]]; then
find "$SHAREPATH" -depth 2>/dev/null | /usr/libexec/unraid/move -e $DEBUGGING
fi
done
# output list of files which could not be moved
shopt -s dotglob ; FILES=/mnt/$DISK/* ; shopt -u dotglob
if [ ${#files[@]} -gt 2 ]; then
echo "mover: not moved:"
ls -1 --almost-all --recursive /mnt/$DISK
fi
rm -f $PIDFILE
echo "mover: finished"
}
killtree() {
local pid=$1 child
for child in $(pgrep -P $pid); do
killtree $child
done
[ $pid -ne $$ ] && kill -TERM $pid
}
stop() {
if [ ! -f $PIDFILE ]; then
echo "mover: not running"
exit 0
fi
killtree $(cat $PIDFILE)
sleep 2
rm -f $PIDFILE
echo "mover: stopped"
}
# Function to display usage
usage() {
echo "Usage: $0 start [-e] <disk_name>"
echo " $0 stop|status"
echo " <disk_name> must match pattern 'disk[0-9]*'"
exit 1
}
# validate disk name
validate_disk() {
if [[ ! "$1" =~ ^disk[0-9]+$ ]]; then
echo "Error: <disk_name> must match pattern 'disk[0-9]*'"
usage
fi
}
if [ "$#" -lt 1 ]; then
usage
exit 1
fi
case $1 in
start)
if [ -z "$2" ]; then
start
elif [ "$2" == "-e" ]; then
if [ -z "$3" ]; then
usage
else
validate_disk "$3"
DISK="$3"
empty
fi
else
usage
fi
;;
stop)
stop
;;
status)
[ -f $PIDFILE ]
;;
*)
usage
;;
esac