Implementing
Standard Login Scripts
John Spurgeon and Ed Schaefer
Consider a server model where numerous Unix servers are distributed
across numerous production sites hosting database engines and other
software applications. Also, assume that only the local systems
administrators have command-line access. We think standardizing
the administrator's login scripts is a good way to maintain high
application availability.
We could implement standard login scripts via skeleton directories.
In the Solaris environment, the useradd command provides
the -k option, which specifies a skeleton directory. Files from
a skeleton directory, such as .profile, are copied into users' home
directories when new accounts are created.
There are two reasons we shy away from using skeleton directories
to standardize login scripts. First, it can be difficult to make
changes to scripts once users have been added. Not only do files
in the skeleton directories have to be modified, but all of the
existing users' scripts have to be updated, too. Second, we did
not want to give users access to the logic responsible for setting
up the majority of their environment, and we thought that preventing
users from modifying $HOME/.profile was too restrictive.
Instead, we placed the necessary environment setup commands in
two special files: /etc/profile and /etc/.kshrc. When a user logs
in, the program called "login" spawns a shell -- typically the Korn
shell on our servers. The Korn shell looks for login scripts /etc/profile
and $HOME/.profile and executes them if they exist. The Korn shell
also looks for the file referenced by the environment variable ENV
(set to /etc/.kshrc on our servers) and executes it if it exists;
this happens whenever the Korn shell is invoked -- not just at login
time.
Listing 1 shows what /etc/profile looks like on all of our servers.
Note the use of the "dot" command to source files, such as /etc/setenv_path.
Modularizing our login scripts this way keeps them short and easy
to read. Another feature of our login scripts is the use of the
readonly function to protect the value of certain variables,
such as ENV.
The most interesting thing about /etc/profile is the way ENV is
set:
readonly ENV='${ENVFILE[(_$-=1)+(_=0)-(_$-!=_${-%%*i*})]}'
This code evaluates to a two-position array: ENVFILE[0]=/etc/.kshrc
and ENVFILE[1] is null. When a shell is interactive, ENVFILE[0] executes,
thus setting the commands in /etc/.kshrc. Obviously, a non-interactive
shell does nothing since ENVFILE[1] is null. For a more detailed explanation,
see:
http://docs.hp.com/en/B2355-90046/ch23s02.html
Recall that the file referenced by $ENV is executed every time a new
shell spawns. This can lead to inefficiencies if a file like /etc/.kshrc
contains commands that only need to be executed at login time. This
complicated way of setting ENV prevents /etc/.kshrc from being read
when the shell is not in interactive mode.
Listing 2 is our /etc/.kshrc file. Like /etc/profile, it is also
a short script due to the use of several dot commands. The script
begins with the following if statement:
if [[ -o interactive ]]
This is a simple way to test for an interactive shell. The if
statement probably isn't necessary, because it has essentially the
same effect as setting ENV the way we did. If you're bothered by inefficiencies,
choose one technique or the other. If you're paranoid that something
could go wrong with the ENV approach, you may want to use both.
We don't include full listings of all the dot scripts shown in
/etc/profile and /etc/.kshrc, since many of them are peculiar to
our environment. However, a few are worth sharing.
Listing 3, /opt/logins/bin/disable_interrupts, and Listing 4,
/opt/logins/bin/enable_interrupts, are two scripts we use to manipulate
the environment during the login process to prevent users from interrupting
the login scripts and gaining premature access to a command line.
Listing 5 is a file we created named setenv_user. In setenv_user,
we set and export some custom environment variables, such as REAL_USER
and EFFECTIVE_USER, as well as several common variables, such as
TERM, MAIL, PAGER, LESS, PS1, and PS2.
Finally, note the following command in /etc/.kshrc:
trap "/etc/.logout" 0
This trap statement causes the shell to execute the command
/etc/.logout when the shell exists.
Login scripts need to be tailored to the requirements of your
environment and the preferences of your users. The approach we've
taken to managing our login scripts won't work for everyone. But,
hopefully, we've presented a few useful techniques -- some of which
you might want to adopt.
Our next column builds upon our custom login idea. We present
a method for archiving individual user's history files by manipulating
shell variable HISTFILE.
References
Hewlett Packard. 1992. SHELLS: User's Guide, HP 9000 Computers.
Palo Alto, CA. -- http://docs.hp.com/en/B2355-90046/ch23s02.html
John Spurgeon is a software developer and systems administrator
for Intel's Factory Information Control Systems, IFICS, in Aloha,
Oregon. Outside of work, he enjoys turfgrass management, triathlons,
ultra-marathon cycling, and spending time with his family.
Ed Schaefer is a frequent contributor to Sys Admin.
He is a software developer and DBA for Intel's Factory Information
Control Systems, IFICS, in Aloha, Oregon. Ed also hosts the monthly
Shell Corner column on UnixReview.com. He can be reached at: shellcorner@comcast.net. |