Dockutil and group script

bbinder
New Contributor

Hi all,

I know that some of you seem to use the dockutil software. I use it and it works great, but I'm looking to do a few things in the script with groups, but don't script much at all.

Say I've got a basic script, like this one here:

#!/bin/bash
# Enable and configure Dock for Students
LoggedInUser=`/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'`
LoggedInUserHome=`dscl /LDAPv3/127.0.0.1 -read /Users/$LoggedInUser | grep NFSHomeDirectory: | cut -c 19- | head -n 1`
plist=$LoggedInUserHome/Library/Preferences/com.apple.dock.plist
sudo -u $LoggedInUser dockutil --remove all "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/Google Chrome.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/Safari.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/Firefox.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/Self Service.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/Microsoft Office 2008/Microsoft Word.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/Microsoft Office 2008/Microsoft Excel.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/Microsoft Office 2008/Microsoft PowerPoint.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/iWork '09/Pages.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/iWork '09/Numbers.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/iWork '09/Keynote.app/ "${plist}"
sudo -u $LoggedInUser dockutil --add /Applications/ "${plist}" --section others
sudo -u $LoggedInUser dockutil --add '~/Documents' "${LoggedInUserHome}"

It works out great for students, no problem.
If I wanted to do something like, make a statement that says, I'll give you 2 more application icons if you are a member of GroupX, is there a simple way to do that?

I thought it might be easy to just create 2 scripts: 1 for staff and 1 for students.
Then, I can do, if | else statements, based on what groups they are in. Once it finds their group, it gives them that dock.

The issue is I don't know how to put that together and I'm not sure what happens when they are a member of 2 groups, unless there's some hierarchal way of doing it where I would put groups that would have more icons at the top of the script and it stops processing once it hits that group. That's not a perfect design, but it would work for probably everyone right now.

Any thoughts? Thanks much!
Brian

25 REPLIES 25

talkingmoose
Moderator
Moderator

You can use an if/then statement to distinguish between teachers and students: "If user is part of teachers group then add these dock icons. Otherwise, add these other dock icons (students)." Something like:

#!/bin/sh

ROLE=$( some code here where the result is "student" or "teacher" )

if [ "$ROLE" = "teacher" ] ; then
    your code to add teacher dock icons here
else
    your code to add student dock icons here
fi

What you need to do is determine how you'll identify a student vs. a teacher. Is that information stored in your LDAP directory too?

rockpapergoat
Contributor III

why not use mcx for this?

talkingmoose
Moderator
Moderator

MCX would be the ideal solution, however, the option to apply these just once is broken in a few iterations of Casper. I don't encourage forcing preferences like Dock items on the user.

bbinder
New Contributor

Thanks for the responses. I ideally wanted to use Casper but like talkingmoose said, it doesn't work that well. I've tried Casper for dock stuff and it is really inconsistent. Using self service and dockutil is really simple and I have yet to see it fail. Plus teachers can do what they wish with their docks and reset it to a clean dock anytime they wish and have it work all the time.

I guess the role thing sounds interesting. I was just hoping I could do it via a group but that's not ideal I would suppose. I'd have to see if I could have it read an attribute in their OD record maybe? Like if in a section they had a code like tt5 or something it would see that and then add a change to the dock? That wouldn't actually be bad at all since I could likely add that code to group members in mass via WGM.

I'm not sure how to get it to read something I put in OD records though. Have you ever done such a thing? Typing this on my iPhone so hopefully I didn't make too many errors in this post.

jarednichols
Honored Contributor

OP-
You *should* be able to do some sort of dscl query to see what groups they belong to. If it were me, I'd use a Case statement to match and then set $Role. I've done something very similar with AD.

talkingmoose
Moderator
Moderator

Jared's thinking what I'm thinking.

The original script already has a dscl query in it to determine the path of the user's home folder (NFSHomeDirectory). You should be able to modify that line to pull a list of groups, a title or something from LDAP that identifies the role of the user (assuming your LDAP directory contains that information).

tlarkin
Honored Contributor

Hey Everyone,

If you have live LDAP lookups enabled in the JSS, and assign a LDAP user you can scope by LDAP group. If this doesn't work, because your LDAP configuration is large and complicated (I've seen some crazy ones personally), then you can try the scripting method. You can also force LDAP logins to Self Service and scope it from there as well.

You can query your LDAP servers via dscl command line once a Mac is bound to a LDAP server. An example might be:

dscl /Search read /Users/username

This will pull all the information down, from there you would have to read specific LDAP attributes, or start awk/grep-ing the info you need.

Hope this helps,
Tom

bentoms
Release Candidate Programs Tester

The following is my method of what Tom describes above: http://macmule.com/2012/05/16/submit-user-information-from-ad-into-the-jss-at-login///

tlarkin
Honored Contributor

Hi Ben,

It looks like you are popular on the Internet. I had a customer recently that was using several of your scripts from your website. Keep up the good work. :-)

Thanks,
Tom

bentoms
Release Candidate Programs Tester

Coolio :)

It's kinda your fault anyways for being so helpful to me (as well as others), when this was a list.

Just giving something back.

bbinder
New Contributor

Oh man, great information everyone. Bentoms, I was perusing your stuff already so I'll be checking out that link shortly. I'm going to do a bit of fiddling around with things here in a test setup and see how it works when I apply a couple of script modifications.

I'll post back with my findings as soon as I test them out. Thanks again everyone - much appreciated!

I wish I could get a notification of RSS feed to work on this site. Can't get anything to come up using a few different apps. I'll have to look that over as well.

Thanks again!

tkimpton
Valued Contributor II

Sweet! Thanks Ben that is an awesome script :)

Kumarasinghe
Valued Contributor

Is there a way to run this script in a policy at "login"?
It will get "root" as the user when you run it as a login script.

bentoms
Release Candidate Programs Tester

which script?

Kumarasinghe
Valued Contributor

The dockutil script to configure user dock at login.

bentoms
Release Candidate Programs Tester

Ah. See the 1st 4 lines or so of the script?

That's basically getting the logged in Users details & telling Dockutil to use them.

So even though it's being run as root, it will run a command like:

/Users/<loggedInUser>/Library/Preferences/

With Casper if you use $3 in a script @ login, $3 will be the username of the user logging in.

rmanly
Contributor III

@Kumarasinghe - If you run it as the user as the user via launchd then it will run as the user and there is no need to populate variables or even specify the plist as dockutil's ddefault behavior assumes current user.

There used to be an awesome intro to launchd article on AFP548 that would give you the basics you need to accomplish this but it looks like it did not make the migration.

http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/Cre...

Also, for assigning the variable ```
LoggedInUserHome
``` you definitely don't need the first grep and I'm sure the cut | head portion can be cleaned up as well... but you can just ask dscl to give you the info you want like so:

LoggedInUserHome=$(dscl /LDAPv3/127.0.0.1 -read /Users/$LoggedInUser NFSHomeDirectory | cut -c 19- | head -n 1)

P.S. also dockutil doesn't screw up permissions so if you are already telling it to work on a specific plist you don't need to tell it to run as a specific user

EDIT: P.P.S. it is also smart enough now to just take a home directory as an argument instead of the full path to the plist, which would clean up the script as well.

Kumarasinghe
Valued Contributor

Thanks Ben and Ryan.

@rmanly
I think you are referring to this article.
http://web.archive.org/web/20110527183309/http://www.afp548.com/article.php?story=20050620071558293

Kumarasinghe
Valued Contributor

@bentoms

1st 4 lines would get the logging in user ONLY if you have "Perform login actions in background" selected in Computer Management Framework Settings > Login/Logout Hook of JSS. If its is unticked, logged in user will be root.

$3 method works with "Perform login actions in background" unticked but not when ticked.

I think plist files creation times may be different when you use "Perform login actions in background" as policies will apply in the same time when the OS is creating those default plist files.

cbrewer
Valued Contributor II

Anyone else care to share their dockutil scripts? I've got my login script for staff working well on 10.6 and 10.7. With 10.8, however, the dock restart process isn't working correctly. When the dock does restart, it only adds 1 of the items in my script. If I look in the dock plist I can see the other items I've added but they don't show up until I bounce the Dock process one more time. I'm working around it by waiting a few seconds after my dockutil commands run and then killing the dock again, but it's not real elegant.

aschultz
New Contributor II

I am interested in using Docutil, and map to LDAP user groups. I have read this thread completely, but I am a bit confused as to the workflow. Can anyone make a recommendation / procedure? I want to modify the docutil by LDAP user groups, ie Student, Teacher, Workgroup, etc.

jamesdurler
Contributor

I'm having an issue with dockutil and a user launch agent at login to add an item to the dock. the launch agent executes a script.

running the script manually and it adds the dock item perfectly. however, when executed by a launch agent it does not add the dock item. I can see it is trying as the dock is killed and refreshed.

anyone experienced any similar issues with dockutil + launch agents?

fabian_ulmrich
Contributor
Contributor

Hey @jamesdurler][/url

When you run the script manually, you probably run it as the user or? I experienced similar issues like this, because I did not authenticate as the specific user I would like to change the .plist for? May you wanna post your agent and script as well?

Cheers!

jamesdurler
Contributor

Hi @fabsen83

The weird thing is i can get it to work by adding a dummy line after trying to add my dock item that i want.

If i just have the one line to add an item it fails - If i have a line to add my item, then another entry to add another dock item it adds the first item but not the second item.

Having a sole item by itself fails everytime! really strange.

anyway heres my script:

#!/bin/bash

#Script to check if we have a network connection and then mount users home drive
#This will be delivered by launch agent

#Author: James Durler
#Date: 3/12/2014

logFile="/Users/$USER/Library/logs/homedrive.log"
touch $logFile

function mountDrive {

#Using $USER to determine the user running this command to be used in the dscl command to find users SMB Home Path smbhome=dscl '/Active Directory/ARTSLOCAL/All Domains' -read /Users/$USER SMBHome | awk '{print $2}' | sed -e 's/\\/smb:///g' | sed 's:\:/:g' echo "Untrimmed SMB Home Path is $smbhome" >> $logFile #trim the variable smbhome, so we can test if the file share we are trying to mount to is available #first we are removing the smb:// - this should always be the start of the users smbhome path newsmbhome=$(echo $smbhome | cut -c 7-) echo "Removed the smb:// variable is now $newsmbhome" >> $logFile #now remove everything after the first /, so delimitting by the / after INF-FS06 newersmbhome=$(echo $newsmbhome | cut -f1 -d"/") echo "Removed everything after the first slash, we now have the file share to ping for availability $newersmbhome" >> $logFile

#now pinging the file share to see if it is available if ping -c 1 $newersmbhome &> /dev/null;then #file share is available echo "Mounting Home Drive" >> $logFile mkdir /Volumes/Home Drive mount -t smbfs $smbhome /Volumes/Home Drive/ echo "adding dock item" >> $logFile /Users/Shared/dockutil --add /Volumes/Home Drive/ /Users/Shared/dockutil /Users/Shared/dockutil else #file share is unavailable echo "File share is not responding" fi
}

#Check if the home drive is already mounted before doing anything else
if [ -d /Volumes/Home Drive ]
then
echo "Home Drive already Mounted, exiting Script"
exit 0
fi

if ping -c 1 inf-dc01 &> /dev/null;then
#inf-dc01 is responsive, get users SMB home path echo "inf-dc01 is responsive, getting users SMB home path" mountDrive

elif ping -c 1 inf-dc02 &> /dev/null;then #inf-dc02 is responsive, get users SMB home path echo "inf-dc02 is responsive, getting users SMB home path" mountDrive

elif ping -c 1 inf-dc03 &> /dev/null;then #inf-dc03 is responsive, get users SMB home path echo "inf-dc03 is responsive, getting users SMB home path" mountDrive

elif ping -c 1 inf-dc04 &> /dev/null;then #inf-dc04 is responsive, get users SMB home path echo "inf-dc04 is responsive, getting users SMB home path" mountDrive

else echo "No Domain Controller is responding, do nothing" fi

Heres my launch agent created with lingon:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict> <key>KeepAlive</key> <false/> <key>Label</key> <string>com.UAL.HomeDrive</string> <key>ProgramArguments</key> <array> <string>/Users/Shared/rwar.sh</string> </array> <key>RunAtLoad</key> <true/> <key>StartInterval</key> <integer>30</integer>
</dict>
</plist>

fabian_ulmrich
Contributor
Contributor

@jamesdurler][/url

I see - think your script is fine, but for me a little bit complex and loads of pinging to make sure everything is available. For me it's a long time ago and I don't know the latest version of dockutil - you might need to kill cfprefsd before killing the Dock itself. This issue is really weird, sorry, but if it works with the dummy line why not just keeping it and reporting this issue to the developer of dockutil!? I will check the latest version of dockutil - maybe I can figure out something new.