#!/bin/zsh # Keeps a network share mounted on this Mac (2026-10-22: Location Assets dropped off NA ProP and PROP OUT # could not see the bundle). Installs a LaunchAgent for the logged-in user that looks every minute and at # login: mounted and answering = nothing; not mounted = mount it again with the login saved in the Keychain # (tick "Remember this password" when connecting once by hand); mounted but dead (after sleep or a network # drop) = unmount it, then mount it again. Never asks for a password and never shows a dialog. # # Run on the Mac, as the user who uses the share: # zsh mac-keep-mounted.sh # zsh mac-keep-mounted.sh location-assets "smb://Kenobi@Chronicles-NA._smb._tcp.local/Location%20Assets" "/Volumes/Location Assets" # Undo: launchctl bootout gui/$(id -u)/org.waterschurch.keep-mounted.; rm ~/Library/LaunchAgents/org.waterschurch.keep-mounted..plist ~/Library/Scripts/keep-mounted-.sh set -e NAME=$1 URL=$2 MP=$3 [[ -n $NAME && -n $URL && -n $MP ]] || { echo "usage: zsh mac-keep-mounted.sh " >&2; exit 2; } LABEL=org.waterschurch.keep-mounted.$NAME SCRIPT=$HOME/Library/Scripts/keep-mounted-$NAME.sh LOG=$HOME/Library/Logs/keep-mounted-$NAME.log HOST=${${URL#*://}#*@}; HOST=${HOST%%/*} mkdir -p "$HOME/Library/Scripts" "$HOME/Library/LaunchAgents" "$HOME/Library/Logs" cat > "$SCRIPT" <> "\$LOG"; } if mount | grep -qF " on \$MP ("; then # Dead only when looking at it hangs (killed after 20 s: status 142). A refusal (macOS's privacy rules for # a background job) or any other error leaves a working share alone. /usr/bin/perl -e 'alarm 20; exec @ARGV' /bin/df "\$MP" >/dev/null 2>&1 [[ \$? -ne 142 ]] && exit 0 say "mounted but not answering (20 s): unmounting" /usr/sbin/diskutil unmount force "\$MP" >> "\$LOG" 2>&1 || /sbin/umount -f "\$MP" >> "\$LOG" 2>&1 || true fi SERVER=\${HOST%%._smb._tcp.local}; SERVER=\${SERVER%%.local} if ! /usr/bin/perl -e 'alarm 6; exec @ARGV' /usr/bin/nc -z -G 4 "\$SERVER.local" 445 >/dev/null 2>&1; then exit 0 # the server is not on the network right now: try again in a minute fi say "not mounted: mounting \$URL" /usr/bin/osascript -e 'with timeout of 40 seconds' -e "mount volume \"\$URL\"" -e 'end timeout' >> "\$LOG" 2>&1 || say "mount failed" mount | grep -qF " on \$MP (" && say "mounted at \$MP" || say "not at \$MP after mounting: \$(mount | grep -i smbfs | tr '\n' ' ')" EOS chmod 755 "$SCRIPT" cat > "$HOME/Library/LaunchAgents/$LABEL.plist" < Label$LABEL ProgramArguments/bin/zsh$SCRIPT RunAtLoad StartInterval60 ProcessTypeBackground EOP launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true launchctl bootstrap "gui/$(id -u)" "$HOME/Library/LaunchAgents/$LABEL.plist" echo "installed $LABEL: keeps $MP mounted (log: $LOG)"