Run Scripts At Login

Though still a standard practice on most Windows networks, Mac OS X administrators seldom create scripts to run at the beginning or the end of user sessions. The common problems they once solved, like resetting home directories or mounting network shares, can now be accomplished through server functionality or free third-party software. But what if you have an uncommon problem? This feature can be the perfect solution, allowing administrators to address unique issues in their individual environments.

The first step in this process is to use a text editor to create and save a shell script, essentially a list of Unix commands run as the root (or System) user by the LoginWindow process. In this context, the $1 variable can be used to represent the username of the account logging in (or out). The example below, for instance, simply deletes the contents of the user's Cache directory:

#!/bin/bash
rm -rf /Users/$1/Library/Caches/*

As always, you'll want to test your script thoroughly before deployment, as any command run as root has the potential to be destructive. If you're unfamiliar with scripting the bash shell, you can consult the Bash Reference Manual or Kirk McElhearn's excellent book The Mac OS X Command Line.

Once your script is complete, you'll need to set it as executable, marking it as a program that can be run by the Unix shell. You'll also want the script owned by root, so that only administrative users can edit it. You accomplish both from the Terminal, replacing PATH-TO-SCRIPT with the location of the script you’ve created:

sudo chmod 744 PATH-TO-SCRIPT
sudo chown root:wheel PATH-TO-SCRIPT

Login Scripts with OS X Server:

In a managed client environment using Open Directory, you can utilize Computer Lists to control features that are machine-specific. The lists are created in the "Accounts" pane of Workgroup Manager, then assigned functionality in the "Preferences" pane. Click the "Scripts" button, then select the shell scripts you'd like to run on login or log-out. In order to browse to them, the scripts must reside somewhere in the visible file system (rather than in the invisible Unix subsystem).

This approach requires two significant additional steps: First, the client machines must communicate with the server using "trusted directory binding", meaning that Open Directory is configured to communicate using the Kerberos security system. Second, each client machine must have remote login scripts enabled via the Terminal by typing:

sudo defaults write \
/var/root/Library/Preferences/com.apple.loginwindow \
EnableMCXLoginScripts -bool TRUE

Login Scripts on OS X Client:

Although running login scripts without a server infrastructure must be done entirely on the command line, it has the benefit of being a one-step process. With the scripts installed locally on each machine, open the Terminal and type:

sudo defaults write com.apple.loginwindow LoginHook PATH-TO-SCRIPT

If you'd like to run a log-out script as well (or instead), just replace LoginHook with LogoutHook when you enter the command.

Keep in mind that complex scripts can significantly effect login times. For this reason, running multiple tasks at log-out is less likely to prompt a flurry of troubleshooting calls. Used judiciously, this technique can be an ideal way to maintain a dependable user experience without sacrificing customization.

Customize The User Template

Providing a consistent user experience across multiple machines is a common way for system administrators to minimize troubleshooting time and facilitate training. A new user begins work with a standardized environment, designed for their organization and familiar to those around them.

At the heart of this practice is a default set of user data, carefully designed around the needs of the group and applied to each account when it's first created. For Windows that data is typically stored in C:\Documents and Settings\Default User, while Unix systems have traditionally used /etc/skel. Mac OS X keeps its user template deep within the /System hierarchy, but while finding it can be difficult, customizing it to your needs is quite easy.

Start with an account created specifically for this purpose. Then choose the system preferences, dock items, browser bookmarks, server shortcuts, and application settings appropriate to your user base. If you install any individual applications or fonts on a per-user level, you can include those in ~/Applications and ~/Library/Fonts (where the tilde represents the user's home directory).

Once you've finished, open Keychain Access from the /Applications/Utilities folder and delete the "login" keychain (both references and files when prompted) so new users will get their own keychain file created for them. You'll also want to delete the cache files stored in ~/Library/Caches.

Now log out of the template, and log back in to an Admin account. Open the Terminal, and clear Apple's existing user template:

sudo rm -r /System/Library/User\ Template/English.lproj/*

Then copy your new template account to the system's user template directory:

su -
cp -R /Users/TEMPLATE/* /System/Library/User\ Template/English.lproj/
exit

To work properly in Leopard, you're actually making this change in the root shell, so exercise extreme caution as a typo could erase important system files, or potentially your entire OS X installation.

In the command above, replace TEMPLATE with the actual name of the template account you've created. If you're working in a language other than English, you'll also need to look in /System/Library/User Template/ and replace English.lproj appropriately.

Now, when you add a new user account, it'll be created with your customizations already in place. You can then delete the original account from the install you built it on, but be sure to back up the home directory. The process can be repeated on multiple machines, deployed on your server, or incorporated into a system image, all using the same template.