Classic Shell Scripting - Arnold Robbins [214]
The shell determines whether it is a login shell by examining the value of $0. If the value begins with a hyphen, then the shell is a login shell; otherwise, it is not. You can tell whether you have a login shell by this simple experiment:
$ echo $0
Display shell name
-ksh Yes, this is a login shell
The hyphen does not imply that there is a file named /bin/-ksh. It just means that the parent process set the zeroth argument that way when it ran the exec( ) system call to start the shell.
If you routinely deal with only a single shell, then the initialization and termination files described in the following sections are not much of a problem: once you get them suitably customized, you can probably leave them untouched for years. However, if you use multiple shells, you need to consider more carefully how to set up your customizations to avoid duplication and maintenance headaches. The . (dot) and test commands are your friends: use them in your customization scripts to read a small set of files that you have carefully written to be acceptable to all Bourne-family shells, and on all hosts to which you have access. System managers also need to make the system-wide customization scripts in /etc work for all users.
Bourne Shell (sh) Startup
When it is a login shell, the Bourne shell, sh, does the equivalent of:
test -r /etc/profile && . /etc/profile Try to read /etc/profile
test -r $HOME/.profile && . $HOME/.profile Try to read $HOME/.profile
That is, it potentially reads two startup files in the context of the current shell, but does not require that either exist. Notice that the home-directory file is a dot file, but the system-wide one in /etc is not.
The system shell-startup file created by local management might look something like this:
$ cat /etc/profile
Show system shell startup file
PATH=/usr/local/bin:$PATH Add /usr/local/bin to start of system path
export PATH Make it known to child processes
umask 022 Remove write permission for group and other
A typical $HOME/.profile file could then modify the local system's default login environment with commands like this:
$ cat $HOME/.profile
Show personal shell startup file
PATH=$PATH:$HOME/bin Add personal bin directory to end of system path
export PATH Make it known to child processes
alias rm='rm -i' Ask for confirmation of file deletions
umask 077 Remove all access for group and other
When a child shell is subsequently created, it inherits the parent's environment strings, including PATH. It also inherits the current working directory and the current file-permission mask, both of which are recorded in the process-specific data inside the kernel. However, it does not inherit other customizations, such as command abbreviations made with the alias command, or variables that were not exported.
The Bourne shell provides no way to automatically read a startup file when the shell is not a login shell, so aliases are of limited use. Since remote command execution also does not create a login shell, you cannot even expect PATH to be set to your accustomed value: it may be as simple as /bin:/usr/bin. We have to deal with this in the build-all script in Section 8.2.
On exit, the Bourne shell does not read a standard termination file, but you can set a trap to make it do so (we cover traps in detail in Section 13.3.2). For example, if you put this statement in $HOME/.profile:
trap '. $HOME/.logout' EXIT
then the $HOME/.logout script can do any cleanup actions that you need, such as wiping the screen with the clear command. However, since there can be only one trap for any given signal, the trap will be lost if it is overridden later in the session: there is thus no way to guarantee that a termination script will be executed. For nonlogin shells, each script or session that needs exit handling has to set an explicit EXIT trap, and that too cannot be guaranteed to be in effect on exit.
These limitations, the lack of support for command history,[5] and in some older implementations, job