Tuesday, March 29, 2011

sshfs mounting script on mac

I use sshfs to securely mount remote disks. Sometimes, due to wifi issues the ssh connection breaks, and the remote disk gets unmounted.

So the remote folder is not always present and needs to be manually remounted. To prevent this, I wrote a script, that can be called via cron to periodically test if the remote disk is mounted, and if it is not mounted, then the script calls sshfs to remount the remote disk.

Before remounting the remote disk, it will first do a clean unmount. This is written for the mac, and uses the binary sshfs found here.

I like to think of this like a command line version of macfusion.

#!/bin/sh
#Author: rouble prmatta
#Version: 1.0
#Date: March 29th, 2011

USER=${USER}
LOCAL_MOUNT_FOLDER=""
LOCAL_MOUNT_FOLDER=""
REMOTE_MOUNT_FOLDER=""
SSHFS=${DATAHOME}/bin/mac/sshfs
LOG="${DATAHOME}/Logs/mount_remote_folder_on_${HOSTNAME}.log"

#Binaries
PING=/sbin/ping
AWK=/usr/bin/awk
ECHO=/bin/echo
DATE=/bin/date
TEE=/usr/bin/tee
TOUCH=/usr/bin/touch
LS=/bin/ls
UMOUNT=/sbin/umount
DISKUTIL=/usr/sbin/diskutil

echodate () {
   $ECHO [`$DATE +%y/%m/%d_%H:%M:%S`] $@
   $ECHO [`$DATE +%y/%m/%d_%H:%M:%S`] $@ >> $LOG
}

runcommand () {
   echodate $@
   $@ 2>&1 | $TEE -a $LOG
   return ${PIPESTATUS[0]};
}

setlogfile () {
   if [ -f $LOG ]
   then
       LOG_SIZE=`$LS -l $LOG | $AWK '{print $5}'`
       if [ $LOG_SIZE -gt 10485760 ]
       then
           $MV -f $LOG $LOG.bak
       fi
   else
       $TOUCH $LOG
   fi
}

usage () {
    echo ""
    echo "Usage:"
    echo ""
    echo "mount_remote_folder.sh  -s server-name -l local-mount-folder "
    echo "                        -r remote-mount-folder [-v volume-name] [-t test-file] [-f]"
    echo ""
    echo "  -s server name        :   name of the server from where to mount the directory"
    echo "  -l local mount folder :   name of the local folder to mount to"
    echo "  -r remote mount folder:   name of the remote folder to mount from"
    echo "  -t test file          :   name of a file to look for in the local folder to determine if "
    echo "                            we're already mounted successfully (optional)"
    echo "  -u user name          :   user name (optional)"
    echo "  -v volume name        :   name of the volume (optional)"
    echo "  -f                    :   force, this will re-mount if we are already mounted (optional)"
}

if [ $# -lt 2 ]
then
    echo "Not enough arguments."
    usage
    exit -1;
fi

setlogfile

fflag=0
while [ $# -gt 0 ]
do
    case "$1" in
        -f)  fflag=1;;
        -s)  SERVER="$2"; shift;;
        -l)  LOCAL_MOUNT_FOLDER="$2"; shift;;
        -r)  REMOTE_MOUNT_FOLDER="$2"; shift;;
        -v)  VOLNAME="$2"; shift;;
        -u)  USER="$2"; shift;;
        -t)  TESTFILE="$2"; shift;;
    esac
    shift
done

if [ "$SERVER" == "" ] 
then
    echo "No server specified."
    usage
    exit -1;
fi

if [ "$LOCAL_MOUNT_FOLDER" == "" ] 
then
    echo "No local mount folder specified."
    usage
    exit -1;
fi

if [ "$REMOTE_MOUNT_FOLDER" == "" ] 
then
    echo "No remote mount folder specified."
    usage
    exit -1;
fi

if [ "$VOLNAME" == "" ] 
then
    VOLNAME="$SERVER:$REMOTE_MOUNT_FOLDER"
fi

echodate "Using server $SERVER"
echodate "Using local mount folder $LOCAL_MOUNT_FOLDER"
echodate "Using remote mount folder $REMOTE_MOUNT_FOLDER"
if [ "$TESTFILE" != "" ] 
then
    echodate "Using test file $LOCAL_MOUNT_FOLDER/$TESTFILE"
fi

echodate ">>>>>>>>>>>>>>>>>>>>>> Starting mount operation..."

if [ $fflag -eq 0 ]
then
    if [ "$TESTFILE" != "" ]
    then
        if [ -d $LOCAL_MOUNT_FOLDER/$TESTFILE ]
        then
            echodate ">>>>>>>>>>>>>>>>>>>>>> $LOCAL_MOUNT_FOLDER/$TESTFILE already exists. Exiting."
            exit 0;
        else
            echodate "$LOCAL_MOUNT_FOLDER/$TESTFILE does not exist. Try to mount..."
        fi
    fi
#else
# If force flag is true then we will remount
fi

runcommand $PING -c 3 $SERVER
if [ $? -ne 0 ]
then
   echodate ">>>>>>>>>>>>>>>>>>>>>> ERROR! Cannot ping $SERVER exiting."
   exit 3;
fi

runcommand $DISKUTIL unmount force $LOCAL_MOUNT_FOLDER
runcommand $SSHFS $USER@$SERVER:$REMOTE_MOUNT_FOLDER $LOCAL_MOUNT_FOLDER -oauto_cache,reconnect,volname=$VOLNAME

if [ -d $LOCAL_MOUNT_FOLDER/$TESTFILE ]
then
   echodate ">>>>>>>>>>>>>>>>>>>>>> $LOCAL_MOUNT_FOLDER successfully mounted. Exiting."
   exit 0;
else
   echodate ">>>>>>>>>>>>>>>>>>>>>> $LOCAL_MOUNT_FOLDER NOT successfully mounted. Exiting."
   exit 4;
fi


You can call the script from cron as follows. Note that in this example, I call it every 5 minutes. Most of the time the script does nothing, but test for the existence of the test file.

*/5 * * * * /path/to/mount_remote_folder.sh -s example.com -l /local/folder -r /remote/folder -t test-file > /dev/null 2>&1 

No comments:

Post a Comment