现在的位置: 首页 > 综合 > 正文

深入理解unix shell启动脚本

2013年03月06日 ⁄ 综合 ⁄ 共 2055字 ⁄ 字号 评论关闭

写在前面:开始用debian的时候,经常碰到的问题就是执行文件找不到,要链接的动态库找不到。所以我们学会了ldd等命令。我当时把自己的LD_LIBRARY_PATH设置在.profile文件中。当我开多个终端开发时。每个终端都要去source ~.profile以下才可以。最近要做一个打包器,一个基本的需求就是给不同的平台设置环境变量,不同的shell启动脚本是不一样的。所以这次必须折腾清楚。。

shell启动脚本:就是shell启动的时候自动执行的脚本。用户(也就是你)环境变量的设置和alias,umask的设置放在启动脚本中,这样每次启动shell的时候都会自动生效。

shell执行启动脚本的方式(这个时候你肯定想试fork还是source):启动shell的方法不同,执行脚本的步骤也是不一样的。

1、作为交互登陆shell启动,或者使用—login参数启动:整体上看shell的生命周期很简单pre-hooks,main,posthooks

交互shell是指用户在提示符下输入命令的shell而不是执行脚本的shell,登录Shell就是在输入用户名和密码登录后得到的Shell,比如从字符终端登录或者用telnet/ssh从远程登录, 但是从图形界面的窗口管理器登录之后会显示桌面而不会产生登录Shell(也不会执行启动脚本),在图形界面下打开终端窗口得到的Shell也不是登录Shell。

这样启动会执行以下的脚本:

1、首先执行/etc/profile,这是*nix系统对shell提供的全局配置文件,如果想某些设置对所有的用户有效的话可以在这里设置。

2、然后依次查找当前用户主目录的~/.bash_profile~/.bash_login~/.profile三个文件,找到第一个存在并且可读的文件来执行,如果希望某个设置只对当前用户生效,可以写在这个脚本里,由于这个脚本在/etc/profile之后执行,/etc/profile设置的一些环境变量的值在这个脚本中可以修改,也就是说,当前用户的设置可以覆盖(Override)系统中全局的设置。~/.profile这个启动脚本是sh规定的,bash规定首先查找以~/.bash_开头的启动脚本,如果没有则执行~/.profile,是为了和sh保持一致。

3、在退出登录时会执行~/.bash_logout脚本。

2、以交互非登录Shell启动

在图形界面下打开一个终端,或者是在登陆shell提示符下输入bash或者ksh等,这样就得到一个交互非登陆shell,这种shell在启动时自动执行~/.bashrc, 通常在~/.bash_profile中调用~/.bashrc

if [ -f ~/.bashrc ]; then
    . ~/.bashrc
 fi
这几行的意思是如果~/.bashrc文件存在则source它。多数Linux发行版在创建帐户时会自动创建~/.bash_profile和~/.bashrc脚本,~/.bash_profile中通常都有上面这几行。所以,如果要在启动脚本中做某些设置,使它在图形终端窗口和字符终端的Shell中都起作用,最好就是在~/.bashrc中设置。
题外话:为什么登录Shell和非登录Shell的启动脚本要区分开呢?
最初的设计是这样考虑的,如果从字符终端或者远程登录,那么登录Shell是该用户的所有其它进程的父进程,也是其它子Shell的父进程,所以环境变量在登录Shell的启动脚本里设置一次就可以自动带到其它非登录Shell里,而Shell的本地变量、函数、alias等设置没有办法带到子Shell里,需要每次启动非登录Shell时设置一遍,所以就需要有非登录Shell的启动脚本,所以一般来说在~/.bash_profile里设置环境变量,在~/.bashrc里设置本地变量、函数、alias等。如果你的Linux带有图形系统则不能这样设置,由于从图形界面的窗口管理器登录并不会产生登录Shell,所以环境变量也应该在~/.bashrc里设置

3、非交互启动

./test.sh这样是为执行脚本fork出来的shell不是交互shell。相当于自动执行以下命令:

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

如果环境变量BASH_ENV的值不是空字符串,则把这个值当作脚本的名字,source这个脚本。

4、以sh命令启动

如果以sh命令启动bashbash将模拟sh的行为,以~/.bash_开头的那些启动脚本就不认了。所以,如果作为交互登录Shell启动,或者使用--login参数启动,则依次执行以下脚本:

1、/etc/profile

2、~/.profile

如果作为交互Shell启动,相当于自动执行以下命令:

if [ -n "$ENV" ]; then . "$ENV"; fi

如果作为非交互shell启动,则不执行任何“启动脚本”。通常我们写的shell脚本都以#!/bin/sh开头,都属于这种方式。

抱歉!评论已关闭.