Linux是一个多用户、实时共享的操作系统,意味着不止一个用户可以登录同一个系统。系统管理员通过任务管理来分配不同用户的权限,比如安装、升级、卸载应用程序,运行编译程序,文件查看、编辑等等。
Linux允许通过两种主要方式来创建用户环境:系统级(全局)和用户级(个人)。一般情况下,Linux系统都会运行基本shell程序,当用户登录成功后shell会在初始化时根据某些文件开创建环境。
Linux中的Shell初始化
当Shell被调用时,会有一些初始化/启动文件被启用,它们的主要作用是为shell本身或用户设定运行环境,包含一些函数、 变量、别名等等。
Shell可以读取以下两种初始化文件:
- 系统级启动文件 – 包含一些应用于户所有用户的全局配置,一般存在于**/etc目录中,如 /etc/profiles 、/etc/bashrc** 或者 /etc/bash.bashrc。
- 用户级启动文件 – 包含一些应用于单用户的配置文件,一般存放在各个用户目录,这些配置可以覆盖系统级全局配置,如**.profiles**、 .bash_profile、 .bashrc 和 .bash_login.
Shell存在三种调用模式:
1. 交互式登录Shell
当用户成功登录系统后调用该Shell,使用**/bin/login登录,随后读取/etc/passwd**文件。
当启动交互式shell后,将读取**/etc/profile文件以及特定的用户文件~/.bash_profile**
login as: pi
[email protected]'s password:
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Apr 25 10:43:53 2017 from 211.137.135.200
pi@raspi:~ $
2. 非登录交互式Shell
当使用如**$/bin/bash** or $/bin/zsh的命令行时,将会系统非登录交互式shell。他也可以通过**/bin/su**命令来运行。
另外,在打开如konsole、terminator和xterm等图形化终端程序时 ,非登录交互式shell也将被调用。
这种情况下调用时,它将拷贝父shell的环境,并读取相应用户级的 ~/.bashrc 配置文件。
pi@raspi:~ $ sudo -s
root@raspi:/home/pi# cd
root@raspi:~# ls -la
total 56
drwx------ 8 root root 4096 Apr 13 10:26 .
drwxr-xr-x 22 root root 4096 Feb 1 20:28 ..
-rw------- 1 root root 2177 Apr 25 11:21 .bash_history
-rw-r--r-- 1 root root 765 Feb 1 20:48 .bashrc
drwx------ 3 root root 4096 Mar 2 14:28 .cache
drwxr-xr-x 3 root root 4096 Mar 3 11:15 .config
drwxr-xr-x 3 root root 4096 Mar 3 11:15 .local
drwxr-xr-x 2 root root 4096 Apr 13 10:26 .oracle_jre_usage
drwxr-xr-x 2 root root 4096 Feb 12 11:18 .pip
-rw-r--r-- 1 root root 140 Nov 20 2007 .profile
-rw------- 1 root root 41 Mar 3 11:39 .python_history
drwx------ 2 root root 4096 Mar 3 11:20 .ssh
-rw------- 1 root root 6342 Mar 30 17:30 .viminfo
3. 非交互式Shell
当运行脚本时则条用非交互式shell。在这种模式下,它将处理所运行的脚本中的命令、函数等操作,不需要进行交互式输入,除非脚本需求。使用的环境继承自父shell。
理解系统级Shell启动文件
下来,我们来看看一些系统级启动文件都有什么内容:
/etc/profile file文件存储登录时系统级环境配置和启动程序。如果你想配置应用于所有用户的环境设置,可以加入此文件。
比如,你可在这里设置全局路径变量。
pi@raspi:~ $ cat /etc/profile
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
if [ "`id -u`" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/usr/sbin:/usr/sbin:/bin"
else
#old bak PATH="/usr/local/sbin:/usr/local/usr/sbin:/usr/sbin:/bin:/usr/local/games:/usr/games"
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin:/sbin:/usr/local/games:/usr/games"
fi
export PATH
if [ "$PS1" ]; then
if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "`id -u`" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
export PATH=/usr/local/nginx/sbin:$PATH
注意:当你使用RHEL/CentOS7系统时,会看到如下提示"It’s not recommended 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"。
提示中的 /etc/profile.d/ 目录保存着所有的自定义修改运行环境的脚本。
pi@raspi:~ $ cd /etc/profile.d/
pi@raspi:/etc/profile.d $ ls -l
total 8
-rw-r--r-- 1 root root 663 Mar 23 2014 bash_completion.sh
-rw-r--r-- 1 root root 387 Mar 31 11:47 oneinstack.sh
pi@raspi:/etc/profile.d $
/etc/bashrc 或 /etc/bash.bashrc文件,包含应用于所有用户的系统级函数、变量、别名等配置信息。
如果你的系统包含多种Shell程序,建议你可以将一些特定的配置放到这里。
root@raspi:~# cat /etc/bash.bashrc
# System-wide .bashrc file for interactive bash(1) shells.
# To enable the settings / commands in this file for login shells as well,
# this file has to be sourced in /etc/profile.
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, overwrite the one in /etc/profile)
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
# Commented out, don't overwrite xterm -T "title" -n "icontitle" by default.
# If this is an xterm set the title to user@host:dir
#case "$TERM" in
#xterm*|rxvt*)
# PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
# ;;
#*)
# ;;
#esac
# enable bash completion in interactive shells
#if ! shopt -oq posix; then
# if [ -f /usr/share/bash-completion/bash_completion ]; then
# . /usr/share/bash-completion/bash_completion
# elif [ -f /etc/bash_completion ]; then
# . /etc/bash_completion
# fi
#fi
# if the command-not-found package is installed, use it
if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then
function command_not_found_handle {
# check because c-n-f could've been removed in the meantime
if [ -x /usr/lib/command-not-found ]; then
/usr/lib/command-not-found -- "$1"
return $?
elif [ -x /usr/share/command-not-found/command-not-found ]; then
/usr/share/command-not-found/command-not-found -- "$1"
return $?
else
printf "%s: command not found\n" "$1" >&2
return 127
fi
}
fi
理解用户级Shell启动文件
接下来,我们看一下用户级启动文件,它们中的配置只应用户对应用户,一般放置在相对应的用户目录中:
root@raspi:~# ls -la
total 56
drwx------ 8 root root 4096 Apr 13 10:26 .
drwxr-xr-x 22 root root 4096 Feb 1 20:28 ..
-rw------- 1 root root 2177 Apr 25 11:21 .bash_history
-rw-r--r-- 1 root root 765 Feb 1 20:48 .bashrc
drwx------ 3 root root 4096 Mar 2 14:28 .cache
drwxr-xr-x 3 root root 4096 Mar 3 11:15 .config
drwxr-xr-x 3 root root 4096 Mar 3 11:15 .local
drwxr-xr-x 2 root root 4096 Apr 13 10:26 .oracle_jre_usage
drwxr-xr-x 2 root root 4096 Feb 12 11:18 .pip
-rw-r--r-- 1 root root 140 Nov 20 2007 .profile
-rw------- 1 root root 41 Mar 3 11:39 .python_history
drwx------ 2 root root 4096 Mar 3 11:20 .ssh
-rw------- 1 root root 6342 Mar 30 17:30 .viminfo
~/.bash_profile包含一些用户级的环境变量、启动程序、配置信息等等。你可以在这里自定义路径信息、变量等内容:
# cat ~/.bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
export PATH
~/.bashrc文件中包含用户自定义别名和函数等。
pi@raspi:~ $ cat ~/.bashrc
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w \$\[\033[00m\] '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
#alias ll='ls -l'
#alias la='ls -A'
#alias l='ls -CF'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
~/.bash_login 文件包含一些登陆时运行的配置信息。当**/.bash_profile缺失时,bash将读取/.bash_login** 。
当 ~/.bash_profile 和 ~/.bash_login缺失时,bash将读取 ~/.profile文件。它同样包含配置信息、函数、变量、别名的信息。
下面,我们再看看两个bash初始化时非必须,但是比较重要的配置文件。
Linux系统有的一个历史命令功能,该功能按用户记录运行的所有命令历史,存储在 ~/.bash_history 文件中。
查看历史命令:
root@bwgzl:~# history
1 2017-04-25 11:41:34 root cd sf/
2 2017-03-31 10:46:17 root ls
3 2017-03-31 10:46:29 root ./setup-seafile-mysql.sh
4 2017-03-31 10:47:47 root mysql -u sf -h localhost -p
5 2017-03-31 10:47:57 root reboot
6 2017-03-31 10:48:28 root ls
7 2017-03-31 10:48:33 root ls
8 2017-03-31 10:48:36 root cd sf
9 2017-03-31 10:48:36 root ls
10 2017-03-31 10:48:42 root ./setup-seafile-mysql.sh
11 2017-03-31 10:48:48 root exit
12 2017-03-31 11:16:54 root cd /data/wwwroot/unixetc.com/
最后一个是 ~/.bash_logout 文件,它不用于shell启动,但存储一些特殊的指令当用户注销时执行。
一个很有用的例子就是当用户注销后,清空所有屏幕内容。
root@bwgzl:~# cat bash_logout
# ~/.bash_logout
clear