UD Addon: SMB Unremounter: unmount offline shares and remount them


Recommended Posts

I had massive performance problems with SMB shares that went offline, but were still mounted through Unassigned Devices (UD). As an example lsof took minutes to execute and the unraid mover was nearly dead. While dlandon is not sure how to solve this without risking other issues, I came to this script which could be executed by User Scripts Plugin and a custom schedule of "*/15 * * * *" (every 15 minutes):

  • At first it checks if mounted SMB servers went offline and if yes, unmounts their SMB shares
  • In the second part it checks the UD configuration file for unmounted, but online SMB servers and if the "auto mount" option has been enabled through the UD dashboard, it will automatically remount them
  • Note: This script relies on UD, it's not usable without it
#!/bin/bash
# #####################################
# Script:      SMB Unremounter
# Description: Automatically unmounts SMB shares which went offline and remounts them if host is available again.
# Author:      Marc Gutt
# 
# Changelog:
# 0.1
# - first release
# 
# ######### Settings ##################
timeout_seconds=1
# #####################################
# 
# ######### Script ####################
# make script race condition safe
if [[ -d "/tmp/${0///}" ]] || ! mkdir "/tmp/${0///}"; then exit 1; fi; trap 'rmdir "/tmp/${0///}"' EXIT;
# settings
# auto unmount offline smb shares
while read line; do
    smb_server=$(echo $line | grep -oP '^//.*?/')
    smb_server=${smb_server:2:-1}
    smb_share=$(echo $line | grep -oP '^//.*? on ')
    smb_share=${smb_share:0:-4}
    timeout $timeout_seconds ping -c 1 $smb_server
    if [[ $? -eq 124 ]]; then
        echo "Automatically unmount offline $smb_share"
        /sbin/umount -t cifs $smb_share
    else
        echo "$smb_share is online"
    fi
done < <(mount -t cifs)
# auto mount smb shares
next_server=""
while read line || [ -n "$line" ]; do
    if [[ -n "${next_server}" ]]; then
        # check if it is an SMB server
        if [[ $line == "protocol"* ]]; then
            if [[ $line != *"SMB"* ]]; then
                echo "Non-SMB Server $next_server skipped"
                next_server=""
                continue
            else
                echo "$next_server is an SMB share"
            fi
        fi
        # check automount setting
        if [[ $line == "automount"* ]]; then
            if [[ $line == *"yes"* ]]; then
                smb_server=$(echo $next_server | grep -oP '//.*?/')
                smb_server=${smb_server:2:-1}
                smb_share=$(echo $next_server | grep -oP '//.*?\]')
                smb_share=${smb_share:0:-1}
                echo "Auto mounting of $smb_share is enabled"
                # check if share is already mounted
                if mount -t cifs | grep -q "$smb_share on "; then
                    echo "$smb_share is already mounted"
                    next_server=""
                    continue
                fi
                # check if server is online
                timeout $timeout_seconds ping -c 1 $smb_server
                if [[ $? -eq 0 ]]; then
                    echo "Automatically mount $smb_share"
                    csrf_token=$(cat "/var/local/emhttp/var.ini" | grep -oP '^csrf_token=".*?"')
                    csrf_token=${csrf_token:12:-1}
                    wget --post-data "action=mount&device=${smb_share}&csrf_token=${csrf_token}" "http://tower/plugins/unassigned.devices/UnassignedDevices.php"
                else
                    echo "$smb_server is offline"
                fi
            fi
            next_server=""
        fi
        continue
    fi
    next_server=$(echo $line | grep -oP '^\[//.*?\]')
done < <(cat "/boot/config/plugins/unassigned.devices/samba_mount.cfg")

 

Edited by mgutt
  • Like 2
Link to comment

Suggestions:

Change this:

/boot/config/plugins/unassigned.devices/samba_mount.cfg

To this:

/tmp/unassigned.devices/config/samba_mount.cfg

A copy of the unassigned devices configurations are moved to the /tmp file system when Unraid is started and updated whenever a change is made in UD.  It is also copied back to the flash when a change is made so the flash is kept current.  The idea is to cut down on the flash file accesses which are slower than ram.

 

Also add -fl (force, lazy unmount) to the umount command.  The unmount will be forced and will immediately return.

 

And some criticism:

  • It almost appears that you are blaming UD for the issues with commands like 'lsof'.  'lsof', and 'df' both will hang badly when a a CIFS share is off-line.  What you are running into is what I found with these commands.  If a CIFS share goes off-line, you can type 'df' it will indefinitely hang and not time out.  To get around this, UD only queries the remote shares when a user is on the UD page.  Nothing is done in the background.  The commands will also time out so UD does not appear to hang.
  • I am not a fan of mounting and unmounting a remote share like this.  It seems a bit brute force and prone to problems, when a much cleaner approach would be to keep the remote server on-line.  Unfortunately this depends on a solid, reliable network.
  • You have said you like the remote shares with a local mount point for backups and I guess I get that, but you are running into the disadvantages of CIFS mounts.  You are probably pushing it a bit farther than is practical.
  • You apparently have made changes to UnassignedDevices.php.  Because of this, I can offer no support to anyone using your script.
  • Confused 1
Link to comment
22 minutes ago, dlandon said:

Also add -fl (force, lazy unmount) to the umount command.  The unmount will be forced and will immediately return.

Usually not needed. It takes longer, but it unmounts. But I will maybe update the script, so it's done through UD as well.

23 minutes ago, dlandon said:

It almost appears that you are blaming UD

Of course umount (or whatever) is responsible for this and it's known since a decade and I do not blame UD for that, but only UD can solve this as long this bug is present. My apologies if understood differently. Note: I never asked for a default solution, only an optional UD setting, which does a similar thing than the SMB unremounter. But the script works as good. I'm absolutely fine with that.

32 minutes ago, dlandon said:

keep the remote server on-line

Nothing can guarantee this and smb shares are not only provided through permanently online servers. Every windows client supports smb shares. Not unusual. Not a good idea to mount them? Maybe. But happens.

43 minutes ago, dlandon said:

but you are running into the disadvantages of CIFS mounts

I don't see any, except of the offline hanging which is "solved" by the script.

59 minutes ago, dlandon said:

You apparently have made changes to UnassignedDevices.php.

Why do you think that? I'm using the usual recent version and calling it through wget. Else it won't make sense to provide this script as nobody could use it.

 

But I found a bug in my script. I forget to parse the server name so the URL would be wrong for most users. Will fix that in the next release. Will contain your suggestion as well. Thanks for that!

  • Like 2
Link to comment
  • 1 year later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.