ScreenSaver Setup - Bash Script

Lucasw
New Contributor III

Hey all,

Noticed there are a couple threads on here about setting screensavers. Below is a screenshot after running the script. I have not had much luck with 10.11.4 and the following script:

#!/bin/sh

#copy VVHSS folder to /Library/ScreenSavers
echo "Mounting Share...."
protocol="smb" # This is the protocol to connect with (afp | smb)
    echo "Protocol: $protocol"
serverName="SERVERNAME"   # This is the address of the server, e.g. my.fileserver.com
    echo "Server: $serverName"
shareName="Shares"    # This is the name of the share to mount
    echo "Sharename: $shareName"
# Mount the drive 
    mount_script=`/usr/bin/osascript  > /dev/null << EOT
    tell application "Finder" 
    activate
    mount volume "$protocol://${serverName}/${shareName}"
    end tell
EOT`

#copy files
echo "Copying Files...."
rm -r /Library/Screen Savers/VVHSS
cp -r /Volumes/Shares/SSaver /Library/Screen Savers/VVHSS

## Set Screensaver to Photo Slideshow
/usr/bin/defaults -currentHost write com.apple.screensaver 'CleanExit' -string "YES"
/usr/bin/defaults -currentHost write com.apple.screensaver 'PrefsVersion' -int "100"
/usr/bin/defaults -currentHost write com.apple.screensaver 'idleTime' -int "150"
/usr/bin/defaults -currentHost write com.apple.screensaver "moduleDict" -dict-add "path" -string "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver"
/usr/bin/defaults -currentHost write com.apple.screensaver "moduleDict" -dict-add "type" -int "0" 
/usr/bin/defaults -currentHost write com.apple.screensaver 'ShowClock' -bool "true"
/usr/bin/defaults -currentHost write com.apple.screensaver 'tokenRemovalAction' -int "0"

## Set Type of Slideshow to "Flipup" (Results inconsistent)
/usr/bin/defaults -currentHost write com.apple.ScreenSaver.iLifeSlideshows 'styleKey' -string "Flipup" 

## Set location of photos to Fan Art 
/usr/bin/defaults -currentHost write com.apple.ScreenSaverPhotoChooser 'SelectedSource' -int "4"
/usr/bin/defaults -currentHost write com.apple.ScreenSaverPhotoChooser 'SelectedFolderPath' "/Library/Screen Savers/VVHSS"
/usr/bin/defaults -currentHost write com.apple.ScreenSaverPhotoChooser 'ShufflesPhotos' -bool "false"

## Removes the .plist LaunchAgent from inside the User Launch Agent Folder. 
rm -f ~/Library/LaunchAgents/set-screensaver.plist

#apply instantly - Kills settings panel
killall cfprefsd

#allow all users access to VVHSS Folder
chmod -R 0777 /Library/Screen Savers/VVHSS

echo "Script Completed....."

f0b9b3808cd04e0a89708c0185432ca1

13 REPLIES 13

mm2270
Legendary Contributor III

All those /usr/bin/defaults -currentHost style commands are not going to work. -currentHost means the ~/Library/Preferences/<some plist> path of the user running the script, which in the case of one run from Casper will be root. You need to change all of those to start with to affect the logged in user.

There may be other problems with it other than that, but that was the first thing that struck me about it.

Lucasw
New Contributor III

How about using it this way?

#!/bin/sh
# grab current user
curUser=`ls -l /dev/console | cut -d " " -f 4`

# grab the system's uuid
if [[ `ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-50` != "00000000-0000-1000-8000-" ]]; then
    macUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-62`
fi

#jamf displayMessage -message $curUser

defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist CleanExit "YES"
defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist PrefsVersion -int 100

#copy VVHSS folder to /Library/ScreenSavers
echo "Mounting Share...."
protocol="smb" # This is the protocol to connect with (afp | smb)
    echo "Protocol: $protocol"
serverName="SERVERNAME"   # This is the address of the server, e.g. my.fileserver.com
    echo "Server: $serverName"
shareName="Shares"    # This is the name of the share to mount
    echo "Sharename: $shareName"
# Mount the drive 
    mount_script=`/usr/bin/osascript  > /dev/null << EOT
    tell application "Finder" 
    activate
    mount volume "$protocol://${serverName}/${shareName}"
    end tell
EOT`

#copy files
echo "Copying Files...."
rm -r /Library/Screen Savers/VVHSS
cp -r /Volumes/Shares/SSaver /Library/Screen Savers/VVHSS

defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist idleTime -int 300

defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist moduleDict -dict moduleName "iLifeSlideshows" path "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver" type -int 0
defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist identifier "/Library/Screen Savers/VVHSS"
defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist LastViewedPhotoPath "/Library/Screen Savers/VVHSS"
defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist SelectedFolderPath "/Library/Screen Savers/VVHSS"
defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist SelectedSource -int 4

#NO SHUFFLE?defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.ScreenSaverPhotoChooser.$macUUID.plist ShufflesPhotos -int 1

defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows.$macUUID styleKey "Flip-up"
defaults write /Users/$curUser/Library/Preferences/ByHost/com.apple.ScreenSaver.iLifeSlideShows styleKey "Flip-up"

#apply instantly - Kills settings panel
killall cfprefsd

#allow all users access to VVHSS Folder
chmod -R 0777 /Library/Screen Savers/VVHSS

echo "Script Completed....."

mm2270
Legendary Contributor III

That is better, but you may want to look over recent threads that discuss some (possible) best practices regarding getting the logged in user name, here and here. Hint: there is no one perfect way to do it, and it will greatly depend on how your Macs are set up. I personally use:

stat -f%Su /dev/console

to get the current user as its simple, clean and reliable. It still may run afoul of some of the known issues, but if those aren't a concern, then its short and to the point.

Also, getting the UUID can be shortened with:

ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformUUID/{print $4}'

Trying to cut a specific length of characters can possibly get you into trouble, so I probably wouldn't do it myself.

Outside of that, I can't say if any of the above will work right with El Capitan. Each OS revision from Apple introduces unique challenges, or things that break that worked in just the previous OS version, so I can't be sure even the changes above are enough. But experiment and see.

Josh_Smith
Contributor III

I use this script to set the screensaver for every user and the user template....users can change it if they want to. The logic for byhost configuration was based off of Rich Trouton's first run script for configuring similar items. I've tested this on 10.9-10.11

#!/bin/sh
##########################
#Define Variables here:
PathToScreenSaver=""
ScreenSaverName=""

if [[ `ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-50` != "00000000-0000-1000-8000-" ]]; then
    macUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-62`
fi

 for USER_TEMPLATE in "/System/Library/User Template"/*
  do
    /usr/bin/defaults write "${USER_TEMPLATE}"/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist moduleDict -dict path -string "$PathToScreenSaver" moduleName -string "$ScreenSaverName" type -string 1
  done


 for USER_HOME in /Users/*
  do
    USER_UID=`basename "${USER_HOME}"`
    if [ ! "${USER_UID}" = "Shared" ]; then
      if [ ! -d "${USER_HOME}"/Library/Preferences ]; then
        /bin/mkdir -p "${USER_HOME}"/Library/Preferences
        /usr/sbin/chown "${USER_UID}" "${USER_HOME}"/Library
        /usr/sbin/chown "${USER_UID}" "${USER_HOME}"/Library/Preferences
      fi
      if [ -d "${USER_HOME}"/Library/Preferences ]; then
        sudo -u "${USER_UID}" /usr/bin/defaults write "${USER_HOME}"/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist moduleDict -dict path -string "$PathToScreenSaver" moduleName -string "$ScreenSaverName" type -string 1
      fi
    fi
  done

########################

Lucasw
New Contributor III

Is this for .saver files? Or can i put a folder of photos for "PathToScreenSaver"?

I tried this script with my variables in place and get the following:

Could not write domain /Users/MYUSERNAME/Library/Preferences/ByHost/com.apple.screensaver.0E686C6B-2D55-512F-83D4-4134AA60E0FC.plist; exiting

Josh_Smith
Contributor III

It should work for .saver or .qtz, sorry I didn't realize you were doing a folder. The same logic should apply, but I haven't tried it. I'm using it with a screensaver I made in Quartz Composer.

Lucasw
New Contributor III

Newest Version of my script, it will run with no errors on another machine. However still no luck with the screensaver being set?

#!/bin/sh
##########################
if [[ `ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-50` != "00000000-0000-1000-8000-" ]]; then
    macUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-62`
fi

for USER_HOME in /Users/*
  do
    USER_UID=`basename "${USER_HOME}"`
    if [ ! "${USER_UID}" = "Shared" ]; then
      if [ ! -d "${USER_HOME}"/Library/Preferences ]; then
        /bin/mkdir -p "${USER_HOME}"/Library/Preferences
        /usr/sbin/chown "${USER_UID}" "${USER_HOME}"/Library
        /usr/sbin/chown "${USER_UID}" "${USER_HOME}"/Library/Preferences
      fi
      if [ -d "${USER_HOME}"/Library/Preferences ]; then
        sudo -u "${USER_UID}" /usr/bin/defaults write "${USER_HOME}"/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist moduleDict -dict moduleName "iLifeSlideshows" path "/System/Library/Frameworks/ScreenSaver.framework/Resources/iLifeSlideshows.saver" type -int 0
        sudo -u "${USER_UID}" /usr/bin/defaults write "${USER_HOME}"/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist identifier "/Library/Screen Savers/VVHSS"
        sudo -u "${USER_UID}" /usr/bin/defaults write "${USER_HOME}"/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist LastViewedPhotoPath ""
        sudo -u "${USER_UID}" /usr/bin/defaults write "${USER_HOME}"/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist SelectedFolderPath "/Library/Screen Savers/VVHSS"
        sudo -u "${USER_UID}" /usr/bin/defaults write "${USER_HOME}"/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist SelectedSource -int 4
      fi
    fi
  done

#apply instantly - Kills settings panel
killall cfprefsd

#allow all users access to VVHSS Folder
chmod -R 0777 /Library/Screen Savers/VVHSS

########################

Matt
Valued Contributor

I've noticed a lot of extension attributes preloaded into the JSS are broken. When looking into it further it seems like the keys in the PLIST files are no longer found or the files themselves are no longer found. Is it possible that Apple has completely FUBAR'd some of their manageable policies and plists? Is MCX now officially dead then?

sean
Valued Contributor

@mm2270 Mike, perhaps you are aware, but 10.8 +

defaults read /Library/Preferences/com.apple.apsd.plist MachineUniqueIdentifier

@Matt They've probably been renamed to something else, moved to a different location or moved to a different plist; some will be deprecated or perhaps, for example, moved to a database file. Pretty sure plists are so embedded they aren't going anywhere for a while.

Lucasw
New Contributor III

Ok so im thinking of another approach... anyone have experience with using Xcode to create .saver packages?

I also saw this article on how to manually create a .Saver package(outdated im guessing) and created this(gave me null error when trying to install):
48f4b0d1e72d410792177ea7c37774f6

wmateo
Contributor

@Josh.Smith I tried this script using a .saver but screensaver activates using Quartz composer. Also, doesn't "select" my custom saver, even though it activates it. How can I do this with a .saver?

Josh_Smith
Contributor III

@wmateo I have only used it with a .qtz, but I think you just need to change the type string value from 1 to 0 at the end of the defaults command:

example:

sudo -u "${USER_UID}" /usr/bin/defaults write "${USER_HOME}"/Library/Preferences/ByHost/com.apple.screensaver.$macUUID.plist moduleDict -dict path -string "$PathToScreenSaver" moduleName -string "$ScreenSaverName" type -string 0

Default screensaver (Computer Name.saver):

{
    CleanExit = YES;
    PrefsVersion = 100;
    moduleDict =     {
        displayName = "Computer Name";
        moduleName = "Computer Name";
        path = "/System/Library/Frameworks/ScreenSaver.framework/Resources/Computer Name.saver";
        type = 0;
    };
    tokenRemovalAction = 0;
}

wmateo
Contributor

@Josh.Smith I was able to recreate this script you referenced above using a .saver bundle. I removed the type -int 0 at the end of the defaults write command since I was not using a .qtz file.

Note that this script also requires a logout or reboot since it's grabbing the preference of the user templates.

Thanks for sharing!