Posted on 11-14-2022 08:08 AM
So, we had an interesting task of getting Time Machine to work over SMB and making it all scripted for zero touch and automated for remounting on reboots.
We have a working script! And we are sharing it with y'all.
How does it work?
"Autofs" is the key to making this all work.
and crontab for activating the mounts on reboot or disconnect/reconnect/
We use computer serials as usernames for users SMB mounts to a Time Machine share. and each computer has their own folder by serial in the share, A Sparebundle file is the TimeMachine backup destination in each folder per computer.
We run the script via a policy per computer with parameters filled for the script.
notes:
one odd behavior, if the script fails, a reboot helps get it working, not sure why yet,
Requirements:
Terminal PPPC, with full disk access,
Crontab PPPC with full disk access.
script:
#/bin/bash
# INPUT PARAMETERS:
# password
# size
# server
#----------------------------------------------
# o pipefail
# -E = err trap inherited by hsell functions
# -e = exit immediately if a command exists with non-zero
# -u = treat unset variables as an error when substituting
set -xEe
password=$4
size=$5
server=$6
local_volume=/System/Volumes/Data/TM
serialnum=`system_profiler SPHardwareDataType | grep Serial | sed -e 's/.*: \(.*\)/\1/g'`
remotedest=//TM-$serialnum:$password@$server:/TM
sparsebundlevolumename=TimeMachine
sparsebundlemountpath=/System/Volumes/Data/$sparsebundlevolumename
timemachinedestination=/Volumes/$sparsebundlevolumename
backupdir=$local_volume/$serialnum
sparsebundle=$size.sparsebundle
sparsebundlefull=$backupdir/$sparsebundle
touch_volumes_script_full_path=/usr/local/bin/blueflame47_touch_tm_mounts.sh
echo "Password is: $password"
echo "Size is: $size"
echo "remote destination is: $remotedest"
echo "Computers serial number is: $serialnum"
echo "Remote destination is: $remotedest"
echo "Sparse bundle volume name is: $sparsebundlevolumename"
echo "Sparse bundle mount path is: $sparsebundlemountpath"
echo "Time machine destination is: $timemachinedestination"
echo "Backup dir is: $backupdir"
echo "Sparse bundle file name is: $sparsebundle"
echo "Sparse Bundle full path is: $sparsebundlefull"
# create the auto_smb configuration file, if missing
if [[ ! -f /etc/auto_smb ]]
then
echo "$local_volume -fstype=smbfs,soft,noowners,nosuid,rw :$remotedest" >> /etc/auto_smb
fi
# add auto_smb to auto_master, if missing
if [[ 0 -eq `grep -c auto_smb /etc/auto_master` ]]
then
echo "/- auto_smb -nosuid,noowners\n" >> /etc/auto_master
fi
# add auto_tm to auto_master, if missing
if [[ 0 -eq `grep -c auto_tm /etc/auto_master` ]]
then
echo "$sparsebundlemountpath auto_tm\n" >> /etc/auto_master
fi
# make the auto_tm reconnect script, if missing
if [[ ! -f /etc/auto_tm ]]
then
echo "#!/bin/bash \n\
set -xEe \n\
PHYSICAL_DRIVE_PATH='$local_volume' \n\
SPARSEBUNDLE_PATH='$sparsebundlefull' \n\
TIME_MACHINE_DESTINATION='$timemachinedestination' \n\
\n\
# Check existing states \n\
if [ -e \"\$TIME_MACHINE_DESTINATION\" ]; then \n\
echo 'Already mounted.' \n\
exit 0 \n\
fi \n\
\n\
if [ ! -e \"\$PHYSICAL_DRIVE_PATH\" ]; then \n\
echo 'Physical drive not attached' \n\
exit 1 \n\
fi \n\
cd \"\$PHYSICAL_DRIVE_PATH\" \n\
\n\
if [ ! -e \"\$SPARSEBUNDLE_PATH\" ]; then \n\
echo 'Virtual drive not found on physical drive' \n\
exit 1 \n\
fi \n\
\n\
hdiutil attach -nobrowse \"\$SPARSEBUNDLE_PATH\" \n\
" > /etc/auto_tm
chmod +x /etc/auto_tm
fi
# enable browsing of mounts
sed -e 's/^.*\(AUTOMOUNTD_NOBROWSE=\).*$/\1FALSE/' /etc/autofs.conf > /etc/autofs.new
mv /etc/autofs.new /etc/autofs.conf
# manually connect to physical mount
echo "Manually connecting to mount: $local_volume"
mount -t smbfs $remotedest $local_volume
# go into local physical volume
cd $local_volume
# create serialnum directory if missing
if [ ! -e $local_volume/$serialnum ];
then
echo "Creating $serialnum directory"
mkdir $serialnum
fi
# create the sparsebundle
if [ ! -e $local_volume/$sparsebundle ];
then
hdiutil create -size $size -layout GPTSPUD -partitionType Apple_HFS -type SPARSEBUNDLE -fs "Journaled HFS+" -volname $sparsebundlevolumename $size
fi
if [ ! -e $sparsebundlefull ];
then
echo "Copying $sparsebundle ... $sparsebundlefull"
cd $serialnum
cp -Rf ../$sparsebundle .
fi
# unmount if manually mounted
if [[ ! 0 -eq `mount | grep -c $local_volume` ]]
then
echo "Unmounting manual mount $local_volume"
umount -f $local_volume
fi
sleep 5
# restart autofs server, which will run: auto_master, auto_smb, auto_tm
automount -cv
#cd into TimeMachine dir to activate auto_tm script
cd $local_volume
du -hs $local_volume
cd $sparsebundlemountpath
du -hs $sparsebundlemountpath
sleep 20
# setup crontab for volume poke
echo "#!/bin/bash \n\
\n\
cd $local_volume \n\
/usr/bin/du -hs $local_volume \n\
cd $sparsebundlemountpath \n\
/usr/bin/du -hs $sparsebundlemountpath \n\
sleep 20\n\
" > $touch_volumes_script_full_path
chmod +x $touch_volumes_script_full_path
touch /etc/crontab
echo "30 * * * * $touch_volumes_script_full_path > /Users/admin/crontab.out 2>&1" > /tmp/2112
crontab < /tmp/2112
# attach to the sparse bundle
if [ ! -e $timemachinedestination ];
then
echo "Attaching $sparsebundlefull ..."
hdiutil attach -nobrowse $sparsebundlefull
fi
# make time machine run faster
sysctl debug.lowpri_throttle_enabled=0
# set time machine destination
echo "Setting time machine destination"
tmutil setdestination $timemachinedestination
# enable time machine backups
echo "Enabling time maching ..."
tmutil enable
# start initial backup
echo "Start initial backup -auto ..."
tmutil startbackup --auto
Posted on 11-14-2022 09:18 AM
Its been a while, but I'm sure TimeMachine doesn't support RAID.. just in case what-ever is on the end of the SMB is setup that way.. (this may have changed, but you know data and all that) ..try pulling a disk.. that'll test it! 🤣
Posted on 11-15-2022 06:15 AM
Also note that this script can be modified for SMB mounting Auto mount, without the Time Machine features.
If you need a persistant SMB share mounted ,
Side note: AutoFS, has a feature called "executable maps" which when the mount point is activated runs a script file. That is how we auto mounted the sparsebundle file for TimeMachine. its a cool feature.