Casper based share mount script

Look
Valued Contributor III

I know there are a lot of variations on this theme out there but here is a script I have made for mounting shares straight out of Casper without requiring anything on the client machine that might be a fit for someones needs. Primarily I wanted a scripted solution but without a deployment requirement and plus I felt like doing it.
It accepts a single parameter in the form smb://server/share
If it has no parameter it uses the AD home drive of the user
It is designed to be called with the login trigger or a custom trigger
It is designed to be scoped to the appropriate group with access rights to the share
It seperates away from the rest of the policies and continues to run in the background to allow other login processes to continue
It runs invisibily to the user until the drives show on the Desktop
It logs individual share activities to /Library/Logs/Sharemounts/Sharemounts_share.log
As always test and use at your own risk! I have done some testing with 10.10 and 10.9 and with a custom launchDaemon to detect network changes and wake events and it seems to do as required, but we are not using it in production yet. If anyone has any improvements or feedback let me know.

THERE IS NOW AN UPDATED VERSION FURTHER DOWN THE THREAD

#!/bin/bash
#Mounts the requested share if it doesn't already exist
#Accepts shares in the standard form smb://server/share
#In the event of the share being left blank it will attempt to mount the AD home share

#Start seperate process
(
#Initialise variables  
Run_Delay=10
Run_Limit=5
Share_Path=$4
if [ -z "$Share_Path" ]; then
Share_Path="home"
Share_Name="home"
else
Share_Name="$(echo $Share_Path | awk -F"/" '{print $NF}')"
fi
Log_Name=$Share_Name
Current_User=$(stat -f%Su /dev/console)

#Notify start of process
mkdir -p /Library/Logs/Sharemounts
echo "$(date) Sharemount for $Share_Name share started" > /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log

#Loop through attempting to mount share as current user
while [[ -z "$(mount | awk '/'$Current_User'/ && /'$Share_Name'/')" ]] && [[ $Run_Count -lt $Run_Limit ]] ; do
let Run_Count=$Run_Count+1
echo "Sharemount attempt $Run_Count to mount $Share_Name" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
if [[ "$Current_User" ]] && [[ "$Current_User" != "root" ]] && [[ "$(ps -c -u $Current_User | awk /Finder/)" ]]; then
echo "Sharemount user $Current_User and Finder verified proceeding with mount attempt" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
if [ "$Share_Path" == "home" ];then
Machine_Domain=$(dscl /Active Directory/ -read . SubNodes | awk '{print $2}')
Share_Path="smb:$(dscl "/Active Directory/$Machine_Domain/All Domains" -read /Users/$Current_User SMBHome | awk '{print $2}' | sed 's/\///g')"
Share_Name="$(echo $Share_Path | awk -F"/" '{print $NF}')"
fi
echo Sharemount attempting to connect to $Share_Path >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
su -m $Current_User -c /usr/bin/osascript<<END
tell application "Finder"
mount volume "$Share_Path"
end tell
END
sleep 1
else
echo "Sharemount user $Current_User or Finder failure refreshing parameters before next attempt" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
fi
if [[ -z "$(mount | awk '/'$Current_User'/ && /'$Share_Name' /')" ]]; then
sleep $Run_Delay
Current_User=$(stat -f%Su /dev/console)
fi
done

#Test for and output results
if [[ -z "$(mount | awk '/'$Current_User'/ && /'$Share_Name' /')" ]]; then
echo "$(date) Sharemount for $Share_Name share FAILED" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
else
echo "$(date) Sharemount for $Share_Name share SUCCEEDED" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
fi
) &
#End seperate process
12 REPLIES 12

Look
Valued Contributor III

Oh and it might need some tweaking for none AD environments... as this is what I have been testing in.

dmw3
Contributor III

@Look I have been trying to use this script but keep coming back with two errors:

"/Users/####/Desktop/N Drive.app/Contents/Resources/script: line 56: unexpected EOF while looking for matching `"'
/Users/####/Desktop/N Drive.app/Contents/Resources/script: line 60: syntax error: unexpected end of file"

I have wrapped the script with Platypus to make a clickable app, apart from changing:

Share_Path="smb://server.com/groups"
Share_Name="N-Drive"

There is no other changes, any help would be appriechiated thanks

dmw3
Contributor III

@Look I can get this script to run via Self-Service but not wrapped as a clickable app

Look
Valued Contributor III

@dmw3 Here is a somewhat updated version, not specifically related to your issue but maybe it helps...
To be honest it was never really intended to be run as an app, it was intended as a script stored in Casper applied to a login policy but given a declared variable at the top it might work. Also be aware used in this manner there is no group checking or anything as this was controlled using the scope in Casper.
The Share_Name doesn't really need to be assigned it is intended to work with just the one variable and generates it from the path given, I also think there isn't much point as I think it only names the mount point the Users will probably still just see "groups" in the case of the share you gave.

It looks like somewhere you have picked up or lost an ' somewhere during editing.

#!/bin/bash
#Mounts the requested share if it doesn't already exist
#Accepts shares in the standard form smb://server/share
#In the event of the share being left blank it will attempt to mount the AD home share

#Start seperate process
(
#Initialise variables  
Run_Count=0
Run_Delay=10
Run_Limit=5
Share_Path=$4
Current_User=$(stat -f%Su /dev/console)
if [ -z "$Share_Path" ]; then
Share_Path="AD_home"
Log_Name="ADhome"
Share_Name="$Current_User"
else
Share_Name="$(echo $Share_Path | awk -F"/" '{print $NF}')"
Log_Name=$Share_Name
fi

#Notify start of process
mkdir -p /Library/Logs/Sharemounts
echo "$(date "+%H:%M:%S") Sharemount $Log_Name: STARTED" > /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
chmod 777 /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log

#Loop through attempting to mount share as current user
while [[ -z "$(mount | awk '/'$Current_User'/ && //'$Share_Name' /')" ]] && [[ $Run_Count -lt $Run_Limit ]] ; do
let Run_Count=$Run_Count+1
if [[ "$Current_User" ]] && [[ "$Current_User" != "root" ]] && [[ "$(ps -c -u $Current_User | awk /Finder/)" ]]; then
echo "$(date "+%H:%M:%S") Sharemount attempt $Run_Count: user $Current_User and Finder verified proceeding" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
if [ "$Share_Path" == "AD_home" ];then
Machine_Domain=$(dscl /Active Directory/ -read . SubNodes | awk '{print $2}')
Share_Path="smb:$(dscl "/Active Directory/$Machine_Domain/All Domains" -read /Users/$Current_User SMBHome | awk '{print $2}' | sed 's/\///g')"
Share_Name="$(echo $Share_Path | awk -F"/" '{print $NF}')"
fi
True_Path=$(echo $Share_Path | sed 's//////'$Current_User'@/g')
echo $(date "+%H:%M:%S") Sharemount verified: attempting to connect to $True_Path >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
/usr/bin/osascript<<END
tell application "Finder"
mount volume "$True_Path"
end tell
END
sleep 1
else
echo "$(date "+%H:%M:%S") Sharemount attempt $Run_Count: user $Current_User invalid or Finder not ready refreshing parameters" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
fi
if [[ -z "$(mount | awk '/'$Current_User'/ && //'$Share_Name' /')" ]]; then
sleep $Run_Delay
Current_User=$(stat -f%Su /dev/console)
fi
done

#Test for and output results
if [[ -z "$(mount | awk '/'$Current_User'/ && //'$Share_Name' /')" ]]; then
echo "$(date "+%H:%M:%S") Sharemount $Log_Name: FAILED after $Run_Count attempts" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
else
echo "$(date "+%H:%M:%S") Sharemount $Log_Name: SUCCEEDED after $Run_Count attempts" >> /Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
fi
) &
#End seperate process

dmw3
Contributor III

@Look Thanks for the updated script, with a slight modification works well. just what I was hoping to have so I could wrap it in an app.

This now allows us to place the app in the dock and user just need to click on it to mount a drive associated with a letter icon on the app.

Had to change this for it to work:
/Library/Logs/Sharemounts
to
~/Library/Logs/Sharemounts
goes for
~/Library/Logs/Sharemounts/Sharemount_"$Log_Name".log
as well, as a normal user the script could not create the log file in the original place.ff062291211b4df88e29f74cb0d635fc

bentoms
Release Candidate Programs Tester

FWIW, here's yet another method :)

McKinnonTech
New Contributor III

@Look Does this still work for you?

I'm able to mount the folder, but is there a way to mount it to the desktop?

Look
Valued Contributor III

@McKinnonTech Yes, however I have modifed the script somewhat in recent times, I am off work sick so will check it Monday.
However one thing is, if the folder is mounting correctly for the current user it should automatically show on the desktop regardless off mount point (as long as you have show network shares set in the Finder preferences).

McKinnonTech
New Contributor III

That would be awesome, thanks @Look

Edit: It looks like the script I wrote wasn't successfully changing my Finder Preferences.
My image still isn't rolled out, so I might see if I can set that as a default preference in the User Templates or something. Still interested in seeing your modified version.

Look
Valued Contributor III

@McKinnonTech As requested here is the current version, the whole thing has been simplified somewhat. Not certain it is actually better, but it works.
We are mid development cycle for next years configurations (we redeploy classrooms in January) so this will probably get some more work put into it before the end of the year if I think it needs it.

#!/bin/bash
#2017 Version Samuel Look
#All care no responsibility
#Mounts the requested share if it doesn't already exist if left blank it will attempt to mount AD SMBhome
#Accepts shares in the form smb://server/share
#Intended to be run as a Login policy from Casper on AD bound machines only and has only been tested in this context.

##### Start seperate process #####
(

##### SUBROUTINES #####

Share_Path_Valid() {
if [[ -z "$Share_Path" ]]; then
Machine_Domain=$(dscl /Active Directory/ -read . SubNodes | awk '{print $2}')
Share_Path="$(dscl "/Active Directory/$Machine_Domain/All Domains" -read /Users/$Current_User SMBHome | awk '!/is not valid/' | sed -e 's/SMBHome: /smb:/g' -e 's/\///g')"
fi
if [[ "$Share_Path" ]]; then
logger "Sharemount:$Share_Name Path check PASS $Share_Path"
return 0
else
logger "Sharemount:$Share_Name Path check FAIL"
return 1
fi
}

#####

User_Ready() {
Loop_End=$((SECONDS + 60))
Current_User=$(stat -f%Su /dev/console | awk '!/root/')
while [[ -z "$Current_User" ]] && [[ $SECONDS -lt $Loop_End ]]; do
sleep 10
Current_User=$(stat -f%Su /dev/console | awk '!/root/')
done
if [[ "$Current_User" ]]; then
logger "Sharemount:$Share_Name User check PASS $Current_User"
return 0
else
logger "Sharemount:$Share_Name User check FAIL"
return 1
fi
}

#####

Finder_Ready() {
Loop_End=$((SECONDS + 60))
while [[ -z "$(ps -c -u $Current_User | awk /com.apple.dock/)" ]] && [[ $SECONDS -lt $Loop_End ]]; do
sleep 5
done
if [[ "$(ps -c -u $Current_User | awk /Finder/)" ]]; then
logger "Sharemount:$Share_Name Finder check PASS"
return 0
else
logger "Sharemount:$Share_Name Finder check FAIL"
return 1
fi
}

#####

Not_Mounted() {
if [[ -z "$(mount | awk '/'$Current_User'/ && //'$Share_Name' /')" ]]; then
logger "Sharemount:$Share_Name Mount check PASS $Share_Name"
return 0
else
logger "Sharemount:$Share_Name Mount check FAIL already mounted"
return 1
fi
}

#####

Mount_Drive() {
True_Path=$(echo $Share_Path | sed 's//////'$Current_User'@/g')
logger "Sharemount:$Share_Name Attempting to mount $True_Path"
osascript<<END
tell application "Finder"
mount volume "$True_Path"
end tell
END
}

##### START #####

Share_Path=$4
Share_Name="$(echo $Share_Path | awk -F"/" '{print $NF}')"

if User_Ready && Finder_Ready && Share_Path_Valid && Not_Mounted; then
Mount_Drive
else
logger "Sharemount:$Share_Name Conditions not met to attempt drive mounting $Share_Path"
fi

##### End seperate process #####
) &

##### FIN #####

edgardeveij
New Contributor II

Is this really running as a background process?

I get the

(  ....   ) &

but does it properly detach from the script? (I never tried, just curious)

Shouldn't you add "disown" to let it run in the background by itself?

Look
Valued Contributor III

@edgardeveij From a practical standpoint it certainly works, prior to having it done like that if a sharemount stalled it prevented all other Casper policies from running and in fact hung the login process (we don't have the run in background option selected, not sure why but I haen't gone into the details of changing it yet).
I can't really answer it from a technical standpoint, however it does seem to behave differently depending on whether the brackets are on their own line or on the end of a line with another command, hence why I have them seperated out like that.
I think the disown function seperates it right away from the session as well, i.e. if you were running it from a terminal you could then close the terminal without closing the process, versus being just able to run other processes alongside the current one in the same terminal. As all these events are within the same session it doesn't seem to be neccesary.
I am sure someone from a more pure linux/programming background will answer it correctly for us.