2014年5月25日星期日

Linux_059:RHEL Bash初始化过程

环境:RHEL 6.5

RHEL使用Bourne Again shell(Bash),本文介绍其初始化过程。
首先明确两个概念:
(1)交互式 shell:指用户在提示符下输命令的shell,而非执行脚本的shell。
(2)登录 shell:指在输入用户名和密码登录后得到的shell。

1. 交互式登录 shell
用户输入用户名和密码登录后,Bash初始化过程如下:
/etc/profile->~/.bash_profile->~/.bashrc—>/etc/bashrc—>~.bash_logout

(1)/etc/profile 文件内容:
# /etc/profile

# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

pathmunge () {
    case ":${PATH}:" in
        *:"$1":*)
            ;;
        *)
            if [ "$2" = "after" ] ; then
                PATH=$PATH:$1
            else
                PATH=$1:$PATH
            fi
    esac
}


if [ -x /usr/bin/id ]; then
    if [ -z "$EUID" ]; then
        # ksh workaround
        EUID=`id -u`
        UID=`id -ru`
    fi
    USER="`id -un`"
    LOGNAME=$USER
    MAIL="/var/spool/mail/$USER"
fi

# Path manipulation
if [ "$EUID" = "0" ]; then
    pathmunge /sbin
    pathmunge /usr/sbin
    pathmunge /usr/local/sbin
else
    pathmunge /usr/local/sbin after
    pathmunge /usr/sbin after
    pathmunge /sbin after
fi

HOSTNAME=`/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
    export HISTCONTROL=ignoreboth
else
    export HISTCONTROL=ignoredups
fi

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL

# By default, we want umask to get set. This sets it for login shell
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
if [ $UID -gt 199 ] && [ "`id -gn`" = "`id -un`" ]; then
    umask 002
else
    umask 022
fi

for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done

unset i
unset -f pathmunge

(2)~/.bash_profile 文件内容:
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

export PATH

(3)~/.bashrc 文件内容:
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

# User specific aliases and functions

(4)/etc/bashrc 文件内容:
# /etc/bashrc

# System wide functions and aliases
# Environment stuff goes in /etc/profile

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

# are we an interactive shell?
if [ "$PS1" ]; then
  if [ -z "$PROMPT_COMMAND" ]; then
    case $TERM in
    xterm*)
        if [ -e /etc/sysconfig/bash-prompt-xterm ]; then
            PROMPT_COMMAND=/etc/sysconfig/bash-prompt-xterm
        else
            PROMPT_COMMAND='printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
        fi
        ;;
    screen)
        if [ -e /etc/sysconfig/bash-prompt-screen ]; then
            PROMPT_COMMAND=/etc/sysconfig/bash-prompt-screen
        else
            PROMPT_COMMAND='printf "\033]0;%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
        fi
        ;;
    *)
        [ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-default
        ;;
      esac
  fi
  # Turn on checkwinsize
  shopt -s checkwinsize
  [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
  # You might want to have e.g. tty in prompt (e.g. more virtual machines)
  # and console windows
  # If you want to do so, just add e.g.
  # if [ "$PS1" ]; then
  #   PS1="[\u@\h:\l \W]\\$ "
  # fi
  # to your custom modification shell script in /etc/profile.d/ directory
fi

if ! shopt -q login_shell ; then # We're not a login shell
    # Need to redefine pathmunge, it get's undefined at the end of /etc/profile
    pathmunge () {
        case ":${PATH}:" in
            *:"$1":*)
                ;;
            *)
                if [ "$2" = "after" ] ; then
                    PATH=$PATH:$1
                else
                    PATH=$1:$PATH
                fi
        esac
    }

    # By default, we want umask to get set. This sets it for non-login shell.
    # Current threshold for system reserved uid/gids is 200
    # You could check uidgid reservation validity in
    # /usr/share/doc/setup-*/uidgid file
    if [ $UID -gt 199 ] && [ "`id -gn`" = "`id -un`" ]; then
       umask 002
    else
       umask 022
    fi

    # Only display echos from profile.d scripts if we are no login shell
    # and interactive - otherwise just process them to set envvars
    for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            if [ "$PS1" ]; then
                . "$i"
            else
                . "$i" >/dev/null 2>&1
            fi
        fi
    done

    unset i
    unset pathmunge
fi
# vim:ts=4:sw=4

2. 交互式非登录 shell
如何得到一个交互式非登录 shell ? 有两种最简单的方式:
(1)在图形界面下,打开一个终端窗口。
(2)在登录shell提示符下再输入bash命令。
以这样的方式得到的互式非登录 shell ,初始化过程是这样的:~/.bashrc—>/etc/bashrc。
这里特别要强调的是,交互式非登录 shell没有执行/etc/profile和~/.bash_profile,但是继承了登录 shell的初始化设置(因为毕竟第一次是登录进来的嘛)。

3. 为什么登录shell和非登录shell的初始化过程不一样呢?
从字符终端或者远程登录得到的登录shell是该用户的所有其它进程的父进程,也是其它子shell的父进程,所以环境变量在登录shell的启动脚本里设置一次就可以自动带到其它非登录shell里。
而非登录shell的本地变量、函数、alias等设置没有办法带到子shell里,需要每次启动非登录shell时再设置一遍。

结论:
(1)在 /etc/proflie 中设置全局环境变量,对所有用户生效,只在用户登录时执行一次。
(2)在 ~/.bash_profile 中设置本地环境变量,对单一用户生效,只在用户登录时执行一次。
~/.bash_profile和/etc/profile的关系可以类比Windows下的用户环境变量设置和系统环境变量设置。
(3)在 ~/.bashrc 中设置本地变量、函数、alias等,对单一用户生效,在用户登录或打开新shell时执行。
(4)/etc/bashrc 在用户登录或打开新shell时执行。
(5)~.bash_logout 在用户退出shell时被执行。

参考文献:
1. http://blog.csdn.net/ctthuangcheng/article/details/17161463
2. http://blog.csdn.net/guosha/article/details/3334477
3. http://www.linuxde.net/2013/10/15352.html
4. http://blog.csdn.net/chlstar/article/details/7170601
5. http://linux.chinaitlab.com/administer/929819.html

没有评论: