一、前言
3.8。Noting to say.
二、原文
http://docstore.mik.ua/orelly/unix3/upt/ch03_08.htm
三、翻译
3.8. Setup Files Aren't Read When You Want?
C shell在特定的时候会读取.cshrc,.login,.logout(3.3)。只有login C shells 才会读取.login 和.loginout文件。在csh刚设计时,这个方案工作的很好。你登陆时启动的shell被标记为login shell,这个shell进而读取前面提到的那三个文件。你从login shell开启的其他shell(shell escape,shell script.etc)只读取.cshrc。其他版本的shell变体大体原理一样,但他们可能有多个setup 文件——不同版本之间辨别登陆式shell和未登录式shell的问题也是一样的道理。
现在,Unix 有了窗口式的交互式shell(比如xterm(24.20)),远程shell(如rsh(1.21),ssh),以及其他shell。这些shell可能需要从.login和.logout文件中读取其他一些设置。根据调用方式的不同,这些shell可能不是登陆式shell——因而,他们可能只读取.cshrc( .tcshrc等)。你要怎么来控制呢?由于所有的子孙shell(subshells,24.4)都读取.cshrc,所以把你所有的命令都放.cshrc下可能就很不妥了...很显然,你肯定不希望在退出shelle时运行如tset一样的终端设置命令(5.3)。
基本上所有的shell都有这样的问题。像zsh,bash这样的shell会在不同的时期读取不同的setup文件,很容易按照你的意愿进行设定。其他的一些,可能就费事了。
对于希望登陆时就执行的命令,把他们全部写入到所有shell都要读取的文件中,不考虑shell是否登陆。(在C shell中,用.cshrc代替 .login).当setup文件的“login-only”命令读取完毕后,设置ENV_SET为环境变量(35.3)作为标志符。(变量的名字没有特别规定,可以自己选定)。之后就可以使用这个变量来察看login-only命令是否已经执行,且在未登录shell中跳过执行。(没懂。。)
由于环境变量会从进程传递给他的子孙进程,所以subshell会从父shell中复制这个标志符,可以用.cshrc检测。如果这个变量存在,则login-only命令被跳过。这避免了子shell再次读取这段命令。
这是.cshrc中的一段内容,可以说明以上内容:
...Normal .cshrc stuff...
if ($?prompt && ! $?ENV_SET) then
# Do commands that used to go in .login file:
setenv EDITOR /usr/ucb/vi
tset
...
setenv ENV_SET done
endif
你可以在你的csh.login,ksh .profile文件中注释说明你自己的操作。
你退出的时候读取的文件(C shell中是.logout)很有可能只被读一次——当你的终极shell('top-level')退出的时候。如果你的top-level shell是未登录的,那你也可以强制读取这个文件。操作如下:首先,和先前对.cshrc文件的更改一样,在你使用exit命令之前加一个别名(alias)来读取你的logout文件。同时,将你的shell设置为强制使用exit命令退出,使用 set ignoreeof.下面是 设置好的.bashrc的一段:
case Section 35.10, / Section 36.25, function Section 29.11, . Section 35.29
case "$-/${ENV_SET:-no}" in
*i*/no)
# This is an interactive shell / $ENV_SET was not set earlier.
# Make all top-level interactive shells read .bash_logout file:
set -o ignoreeof
function exit {
. ~/.bash_logout
builtin exit
}
;;
esac
其中 builtin exit(Section 27.9) 阻止了一个循环来确保bash使用bash 自带的exit命令来退出,而不是调用你刚刚自己定义的exit函数。在C Shell中,使用""exit (Section 27.10)。但并不是所有的shell都要这么做,如果你在你的shell手册上找不到信息,用别的shell测试(Section 3.6),准备好要杀死 kill(Section 24.12) 一个循环的shell了。
--JP and SJC