第 3 章 Bash环境

目录

3.1. Shell初始化文件
3.1.1. 跨系统配置文件
3.1.2. 单独用户配置文件
3.1.3. 改变shell配置文件
3.2. 变量
3.2.1. 变量的类型
3.2.2. 建立变量
3.2.3. 导出变量Exporting variables
3.2.4. 保留变量
3.2.5. 特殊参数
3.2.6. 脚本借助变量的循环使用
3.3. 引用字符
3.3.1. Why?
3.3.2. 转义字符
3.3.3. 单引号
3.3.4. 双引号
3.3.5. ANSI-C引用
3.3.6. 场合
3.4. Shell扩展
3.4.1. 概要
3.4.2. 括号扩展
3.4.3. ~扩展
3.4.4. Shell参数和变量扩展
3.4.5. 命令替换
3.4.6. 算术扩展
3.4.7. 过程替换Process substitution
3.4.8. 字分割
3.4.9. 文件名扩展
3.5. 别名
3.5.1. 什么是别名?
3.5.2. 建立和移除别名
3.6. 更多 Bash 选项
3.6.1. 显示选项
3.6.2. 改变选项
3.7. 总结
3.8. 练习

摘要

本章我们讨论几种能影响Bash环境的不同方法:

  • 编辑shell初始化文件

  • 使用变量

  • 使用不同引用风格

  • 实现算术运算

  • 指派别名

  • 使用扩充和替换

3.1. Shell初始化文件

3.1.1. 跨系统配置文件

3.1.1.1. /etc/profile

当用 --login 选项或者以sh 来调用交互模式时,Bash读取 /etc/profile 的指令。通常是一些设置shell变量 PATH, USER, MAIL, HOSTNAMEHISTSIZE

在某些系统上, umask 的值在 /etc/profile中配置;其他的一些系统中这个文件包含了指向了其他配置文件的指针:

  • /etc/inputrc, 可以配置命令行响铃风格的跨系统的行读取初始化文件。

  • /etc/profile.d 包含了配置特别程序的跨系统行为的文件。

你想应用到所有用户环境的所有设置都必须在这个文件中,这个文件看上去可能像这样:

# /etc/profile

# System wide environment and startup programs, for login setup

PATH=$PATH:/usr/X11R6/bin

# No core files by default
ulimit -S -c 0 > /dev/null 2>&1

USER="`id -un`"
LOGNAME=$USER
MAIL="/var/spool/mail/$USER"

HOSTNAME=`/bin/hostname`
HISTSIZE=1000

# Keyboard, bell, display style: the readline config file:
if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ]; then
    INPUTRC=/etc/inputrc
fi

PS1="\u@\h \W"

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC PS1

# Source initialization files for specific programs (ls, vim, less, ...)
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        . $i
    fi
done

# Settings for program initialization
source /etc/java.conf
export NPX_PLUGIN_PATH="$JRE_HOME/plugin/ns4plugin/:/usr/lib/netscape/plugins"

PAGER="/usr/bin/less"

unset i

这个配置文件设置了一些基本shell环境变量和一些用户需要在web浏览器中运行Java 和/或 Java应用程序的一些变量。参见 第 3.2 节 “变量”.

参见 第 7 章 条件语句 得到更多关于条件 if 如何使用在这些文件中; 第 9 章 重复性任务 讨论诸如 for 的循环结构。

Bash的源代码包含了用于普通和单独使用的 profile 文件例子。这些和上面这个例子需要做某些改变才能在你的环境中工作!

3.1.1.2. /etc/bashrc

在提供多种类型shell的系统中,因为 /etc/profile 也会被诸如 Bourne shell的其他shell读取,最好把Bash特殊配置文件放到 /etc/profile 中。shell产生的错误 Errors generated by shells that don't understand the Bash syntax are prevented by splitting the configuration files for the different types of shells. 由于这样的情况,用户的 ~/.bashrc 可能指向 /etc/bashrc 以便于在登陆shell的初始化进程中包含它。

你也可能发现你系统中的 /etc/profile 只存放了shell环境和程序启动设置,尽管 /etc/bashrc 包含了为shell函数和别名的跨系统定义。/etc/bashrc 文件可能指向 /etc/profile 或者单用户shell初始化文件。

源代码包含了 bashrc 例子文件,或者你可能在 /usr/share/doc/bash-2.05b/startup-files 找到一份拷贝。这是和Bash文档一起提供的 bashrc 一个部分:

alias ll='ls -l'
alias dir='ls -ba'
alias c='clear'
alias ls='ls --color'

alias mroe='more'
alias pdw='pwd'
alias sl='ls --color'

pskill()
{
        local pid

        pid=$(ps -ax | grep $1 | grep -v grep | gawk '{ print $1 }')
        echo -n "killing $1 (process $pid)..."
        kill -9 $pid
        echo "slaughtered."
}

除了普通的别名之外,它还包含了更有用的别名甚至在你拼写错误的时候仍然能够让它工作。我们会在 第 3.5.2 节 “建立和移除别名”讨论别名。这个文件包含了一个函数,pskill;函数会在 第 11 章 函数 中具体学习。

3.1.2. 单独用户配置文件

[注意] 我没有这些文件?!

默认情况下这些文件可能在你的主目录中,需要的话也可以建立他们。

3.1.2.1. ~/.bash_profile

这是个别地为配置用户环境的首选的配置文件。在这个文件中,用户可以增加额外的配置选项或者改变默认设置:

franky~> cat .bash_profile
#################################################################
#                                                               #
#   .bash_profile file                                          #
#                                                               #
#   Executed from the bash shell when you log in.               #
#                                                               #
#################################################################

source ~/.bashrc
source ~/.bash_login
case "$OS" in
  IRIX)
    stty sane dec
    stty erase
    ;;
#  SunOS)
#    stty erase
#    ;;
  *)
    stty sane
    ;;
esac

这个用户配置了登陆到不同操作系统的退格字符。除此之外,读取用户的 .bashrc.bash_login 文件。

3.1.2.2. ~/.bash_login

这个文件包含了只有在你登陆进系统的才执行的特殊的设置。在这个例子中,我用它来配置 umask 的值来显示一个当前连接的用户列表。该用户也得到了当前月的日历:

#######################################################################
#                                                                     #
#   Bash_login file                                                   #
#                                                                     #
#   commands to perform from the bash shell at login time             #
#   (sourced from .bash_profile)                                      #
#                                                                     #
#######################################################################
#   file protection
umask 002       # all to me, read to group and others
#   miscellaneous
w
cal `date +"%m"` `date +"%Y"`

在没有 ~/.bash_profile的情况下,这个文件就被读取。

3.1.2.3. ~/.profile

在没有 ~/.bash_profile~/.bash_login文件的情况下,~/.profile 就被读取。他能保存一些可以被其它的shell访问的配置。注意其他的shell可能不能识别Bash的语法。

3.1.2.4. ~/.bashrc

如今,更加普遍的是使用一个非登陆shell,比如使用X终端窗口登陆进图形模式的时候。打开一个这样的窗口之后,用户不需要提供用户名和密码;无需认证。此时Bash会搜索 ~/.bashrc ,所以也指向登陆时读取的文件,同时也意味着你不需要在多个文件中输入相同的设置。

在这个用户的.bashrc 里,在读取了跨系统的 /etc/bashrc 之后定义了一些别名和为特定的程序使用的变量:

franky ~> cat .bashrc
# /home/franky/.bashrc

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

fi

# shell options

set -o noclobber

# my shell variables

export PS1="\[\033[1;44m\]\u \w\[\033[0m\] "
export PATH="$PATH:~/bin:~/scripts"

# my aliases

alias cdrecord='cdrecord -dev 0,0,0 -speed=8'
alias ss='ssh octarine'
alias ll='ls -la'

# mozilla fix

MOZILLA_FIVE_HOME=/usr/lib/mozilla
LD_LIBRARY_PATH=/usr/lib/mozilla:/usr/lib/mozilla/plugins
MOZ_DIST_BIN=/usr/lib/mozilla
MOZ_PROGRAM=/usr/lib/mozilla/mozilla-bin
export MOZILLA_FIVE_HOME LD_LIBRARY_PATH MOZ_DIST_BIN MOZ_PROGRAM

# font fix
alias xt='xterm -bg black -fg white &'

# BitchX settings
export IRCNAME="frnk"

# THE END
franky ~>

更多的例子能在bash的包内找到。记住例子可能需要修改才能在你的环境内工作。

别名将在 第 3.5 节 “别名” 讨论。

3.1.2.5. ~/.bash_logout

这个文件包含了登出系统时候的特别指令。在这个例子中,终端窗口在登出的时候被清空。在关闭时留下一个干净的窗口对远程连接来说非常有用。

franky ~> cat .bash_logout
#######################################################################
#                                                                     #
#   Bash_logout file                                                  #
#                                                                     #
#   commands to perform from the bash shell at logout time            #
#                                                                     #
#######################################################################
clear
franky ~>

3.1.3. 改变shell配置文件

当对上述文件进行任何修改的时候,用户可以重新连接到系统,或者 source 这个改变的文件来生效。以这样的方式来解释脚本的话,修改就会再当前的shell生效。

图 3.1. 不同用户的不同提示

Prompt 1 is "franky ~>; prompt is then changed with "export PS1="\[\033[1;42m\]$USER is in \w\[\033[0m\] " resulting in a green reverse video prompt displaying username and present working directory in humanly readable form.  Prompt for root is set using a similar PS1 configuration to be bright red reverse video.

多数shell脚本在一个私有的环境中执行:变量在子进程中不能继承除非他们被父进程export出来。Source一个包含shell命令的文件是对你自己的环境应用修改和在当前shell设置变量的一个方法。

这个例子也证明了不同用户设置不用的提示的用法。这样的情况下,红色意味着危险。当你有一个绿色的提示,就不需要担心太多

注意 source resourcefile 和使用 . resourcefile 是一样的。

你会在所有这些配置文件前不知所措,同时发现自己面对着来源并不很清晰的设置,使用 echo 语句,就像条是脚本那样;参见 第 2.3.2 节 “调试部分脚本”。可以像这样加上几行:

echo "Now executing .bash_profile.."

或者像这样:

echo "Now setting PS1 in .bashrc:"
export PS1="[some value]"
echo "PS1 is now set to $PS1"