Fork me on GitHub
linux_shell_4_shell特性

linux_shell_4_shell特性

去年的这个时候,我曾经写过一些关于shell特性的文章,下面是第3篇:linux_shell_3_shell变量特性。 今天我们继续来学习一些关于

Linux shell的内容。

【1】shell

        在用户登录到系统后,系统会给用户分配一个默认的shell,用户通过这个shell来与系统进行交互。我们可以通过环境变量SHELL来查看

用户登录到系统后获取的shell。如下命令所示:

[volcanol@volcanol ~]$ echo $SHELL
/bin/bash

       这里我的系统登录后分配的shell为bash shell。

       一般的linux或者类unix系统都会提供多个shell,系统提供那些shell可以通过 /etc/shells  文件查看,如下所示:

 [volcanol@volcanol ~]$ cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin

      可以看到,我的系统有两个可用的shell,sh和bash;还有一个不能用的shell   nologin ;注意不同的系统这个文件内容一般不一样。

      在系统的passwd文件中可以查看和配置用户登录后默认取得的shell, 我们查看一下passwd文件。

复制代码

[root@volcanol ~]# cat -n /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
11 operator:x:11:0:operator:/root:/sbin/nologin
12 games:x:12:100:games:/usr/games:/sbin/nologin
13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
15 nobody:x:99:99:Nobody:/:/sbin/nologin
16 avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
17 usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
18 dbus:x:81:81:System message bus:/:/sbin/nologin
19 rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
20 rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
21 oprofile:x:16:16:Special user account to be used by OProfile:/home/oprofile:/sbin/nologin
22 abrt:x:499:498::/etc/abrt:/sbin/nologin
23 rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
24 nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
25 tcpdump:x:72:72::/:/sbin/nologin
26 torrent:x:498:493:BitTorrent Seed/Tracker:/var/lib/bittorrent:/sbin/nologin
27 avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
28 saslauth:x:497:492:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
29 haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
30 openvpn:x:496:491:OpenVPN:/etc/openvpn:/sbin/nologin
31 apache:x:48:48:Apache:/var/www:/sbin/nologin
32 ntp:x:38:38::/etc/ntp:/sbin/nologin
33 nm-openconnect:x:495:490:NetworkManager user for OpenConnect:/:/sbin/nologin
34 mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
35 smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
36 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
37 smolt:x:494:489:Smolt:/usr/share/smolt:/sbin/nologin
38 pulse:x:493:488:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
39 gdm:x:42:42::/var/lib/gdm:/sbin/nologin
40 volcanol:x:500:500:volcanol:/home/volcanol:/bin/bash

复制代码

            可以看到我的系统中一共默认有40个用户,而只有用户 1 和用户40 才分配里一个可用的shell, 这个shell为bash shell,这也就是为什么

root用户和volcanol用户登入到系统后,默认的shell为bash的原因。

【2】内建命令/内置命令(bulitin command )

       bash默认提供里一些基本的命令,这些命令在安装完bash后就能使用;可以通过type命令查看一个命令是内置命令,还是系统内可执行的二进

制文件。

       在看鸟哥的书的时候,发现有时候,他在做文档的时候对大小写,分的不是很清除,可能是因为打字的原因,他对type命令的描述就存在一些

偏差。

-p :如果后面接的name 为外部命令时,才会显示完整文件名;

          我们通过命令测试一下:

[root@volcanol ~]# type -p ls
[root@volcanol ~]# 

       可以发现,什么也没有输出,原因是什么呢?

复制代码
type [-aftpP] name [name ...]
              With  no options, indicate how each name would be interpreted if
              used as a command name.  If the -t option is used, type prints a
              string  which  is  one  of alias, keyword, function, builtin, or
              file if  name  is  an  alias,  shell  reserved  word,  function,
              builtin,  or disk file, respectively.  If the name is not found,
              then nothing  is  printed,  and  an  exit  status  of  false  is
              returned.   If  the  -p  option is used, type either returns the
              name of the disk file that would be executed if name were speci‐
              fied as a command name, or nothing if ``type -t name'' would not
              return file.  The -P option forces a PATH search for each  name,
              even if ``type -t name'' would not return file.  If a command is
              hashed, -p and -P print the hashed value,  not  necessarily  the
              file that appears first in PATH.  If the -a option is used, type
              prints all of the places that contain an executable named  name.
              This  includes  aliases  and  functions,  if  and only if the -p
              option is not also used.  The table of hashed  commands  is  not
              consulted  when  using -a.  The -f option suppresses shell func‐
              tion lookup, as with the command builtin.  type returns true  if
              all of the arguments are found, false if any are not found.
复制代码

         通过man 1 type 查看,可以发现type也是一个bulitin command ,可以发现需要 -P(upcase),才是那个意思。

[root@volcanol ~]# type -p ls
[root@volcanol ~]# type -P ls
/bin/ls

           如果不带参数,type命令将指出命令将如何解释:

[root@volcanol ~]# type ls
ls is aliased to `ls --color=auto'

          如果带参数-a ,则会显示以下信息:别名 和 可执行文件的路径

[root@volcanol ~]# type -a ls
ls is aliased to `ls --color=auto'
ls is /bin/ls

       如果带产生 -t ,则支持是内置、外部命令等信息:

复制代码

[root@volcanol ~]# type -t ls
alias
[root@volcanol ~]# type -t type
builtin
[root@volcanol ~]# type -t passwd
file

复制代码

      alias: 表示命令为别名

      bultin: 表示为bash内置命令

      file: 表示为外部命令,即为 */bin 或者 */sbin 等目录下的可执行文件。 

【3】命令别名 alias

      在shell中提供里命令别名的功能,通过命令别名可以简化命令的输入过程,同时也可以防止输入错误。

      在bash中设置的命令别名仅在当前登录的shell 环境中起作用,logout或者reboot 后命令别名将不再起作用。通过alias命令设置命令别名,

我们可以看看如何设置命令别名:

[root@volcanol ~]# alias tt='type -t'
[root@volcanol ~]# tt passwd
file

     在当前shell环境中设置的命令别名,仅在当前登录获取的PID 代表的shell中可用,如果重新获取一个新的shell,那么命令别名在新的shell中

将不可用:

[root@volcanol ~]# tt passwd
file
[root@volcanol ~]# bash
[root@volcanol ~]# tt passwd
命令未找到。 安装软件包“rubygem-treetop”以提供命令“tt”? [N/y] [root@volcanol ~]# 

      如果要使当前用设置的命令别名一直可用,这需要将命令别名设置到用户登录脚本或者系统登录脚本。这个脚本一般是用户home目录的:

 .bashrc 

复制代码
[root@volcanol ~]# cat /root/.bashrc
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

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

       如果您要设置一个一直可用的命令别名,可以将命令别名在这个脚本中设置。

       通过unalias命令,可以取消命令别名的定义。

复制代码
[root@volcanol ~]# type rm
rm is aliased to `rm -i'
[root@volcanol ~]# unalias rm
[root@volcanol ~]# type rm
rm is /bin/rm
复制代码

        如上所示,我的系统登录脚本设置里 rm为 rm -i 的命令别名,而我通过命令unalias 取消里这个别名,利用type 查看的时候

就显示出rm 为/bin/rm 这个外部命令。而再次登录则rm又变成了 rm -i 。

复制代码
[root@volcanol ~]# exit
logout
[volcanol@volcanol ~]$ su -
密码:
[root@volcanol ~]# type rm
rm is aliased to `rm -i'
复制代码

【3】shell的doskey 功能的设置

       在bash shell中提供了类似如doskey的功能,我们可以通过 上下箭头来查看历史命令(目前linux下的各种shell都支持doskey的功能)。

DOSKEY的功能,就不具体介绍了,这里想介绍的shell的历史命令记忆功能。

        在用户的home目录下面有一个名为: .bash_hitory的配置文件, 这个文件记录了用户曾经执行过的命令:

复制代码
[root@volcanol ~]# cat .bash_history 
cd /home/volcanol/download/
ls
rpm -ivh flash-plugin-10.3.183.90-release.i386.rpm 
tar -xzf 92ce_se_de_linux_mac80211_0005.1230.2011.tar.gz 
ls
cd rtl_92ce_92se_92de_linux_mac80211_0005.1230.2011/
ls
make
make install
reboot
yum install rhythmbox
cd /home/volcanol/
ls
cd download/
ls
zip --hlep
zip --help
复制代码

       例如上面显示的就是我用root用户执行过的命令。

      .bash_history文件可以记录的命令的条数与环境变量HISTFILESIZE有关:

[root@volcanol ~]# set | grep HIS
HISTCONTROL=ignoredups
HISTFILE=/root/.bash_history
HISTFILESIZE=1000
HISTSIZE=1000

      默认可以记忆1000条历史命令的记录。

      在shell中可以利用history命令查看曾经执行过的命令,这样比查看命令历史记录文件快捷。如果不带参数histoty会将命令历史记录文件

中的所有命令都显示出来。如果带n(n为数字)则会显示最近执行的n条命令:

复制代码
[root@volcanol ~]# history 5
  434  cat .bash_history 
  435  set | gerp HIS
  436  set | grep HIS
  437  history
  438  history 5
复制代码

     history常用的参数有:

       -c: 清除.bash_history 文件的内容

      -r: 将.bash_histroy文件的内容加载到当前shell的执行环境,

      -w: 因为只有在用户注销logout的时候,系统才会将最近一次登录执行过的命令,才更新到.bash_history文件中,而有时为了防止出现意外

可以利用-w 参数,立即将命令更新到命令历史记录文件.bash_history.

       关于history还有很多有用的功能,这里就不再介绍了。

【4】命令的执行顺序

        我们知道,在系统中由于别名的存在,执行一个命令可能会有很多命令可以执行,那么系统执行命令的顺序如何呢?大体顺序如下所示:

                1、如果用户输入的命令是绝对路径,或者可到达的相对路径,则优先执行绝对路径或者相对路径下的命令。

               2、如果用户没有输入绝对路径、或者相对路径,这优先执行命令别名所代表的命令

               3、如果既没有1或者2的条件,则优先执行bash的内建命令

                4、如果没有1、2和3的条件,则通过用户设置的PATH环境变量搜索命令,能搜索到命令则执行,否则就提示命令找不到。

Exp:

  如我们输入  /bin/ls  命令,这优先执行/bin/ls 命令;

  如我们输入 ls  命令,则优先执行 alias 设置的ls 别名所代替的命令。

  我们还可以通过 type -a 命令来查看我们的命令执行顺序:

[root@volcanol ~]# type -a ls
ls is aliased to `ls --color=auto'
ls is /bin/ls

          如上,当我们输入ls 命令时,执行的顺序为 type -a ls 输出的顺序,在前的优先执行。

【5】登录提示信息

       当您以运行级别登录系统后,在tty1中(假设您登录就是tty1终端)会输出一些系统提示信息,这些信息是个定制的,我们通过配置 /etc/issue 文件来达到

定制欢迎信息的目的。

[root@volcanol ~]# cat -n /etc/issue
     1    Fedora release 14 (Laughlin)
     2    Kernel \r on an \m (\l)
     3    

         这个文件的第一行在登录的时候原样输出,这里第二行是我们可以定制输出的内容,当然您可以添加任何您想输出的内容。这个文件有些转义

字符序列在登录的时候会替换为一些特别的信息:

 Exp 上面的第二行中的 :

           \r 在登录后会替换为当前系统核心的版本信息  

           \m 在登录后会替换为当前系统的硬件等级信息 i386、i686或者还相应的CPU硬件等级信息

           \l    显示您登入的是第几个终端界面,tty1 ~ tty6 中的一个

   

      由于linux支持远程用户利用telnet等协议登录,同样我们也可以在用户通过telnet登录时给出提示信息,这时需要配置 /etc/issue.net 文件。

[root@volcanol ~]# cat -n /etc/issue.net 
     1    Fedora release 14 (Laughlin)
     2    Kernel \r on an \m (\l)

        可以发现,默认 /etc/issue  和 /etc/issue.net 文件具有相同的提示信息,这两个库文件的配置提示信息方法一样,您可以根据需要配置。

下面是两个文件支持的转义字符序列:

复制代码
\d 本地端时间癿日期;
\l 显示第几个终端机接口;
\m 显示硬件癿等级 (i386/i486/i586/i686...);
\n 显示主机癿网络名称;
\o 显示 domain name;
\r 操作系统癿版本 (相当亍 uname -r)
\t 显示本地端时间癿时间;
\s 操作系统癿名称;
\v 操作系统癿版本。
复制代码

       有时候在设置的时候,需要广播信息,就是对所有用户都给出登录基本一致的提示信息,这可以通过修改 /etc/motd 配置文件实现。

[root@volcanol ~]# cat -n /etc/motd
[root@volcanol ~]# ls /etc/motd -l
-rw-r--r--. 1 root root 0  6月 29 2010 /etc/motd

        默认 /etc/motd ,是没有任何内容的,同样您可以用配置/etc/isuue 或 /etc/isuue.net 文件一样的方法配置这个文件。

【6】bash 环境等的设置

       用户在登录到系统后,会获取两部分bash环境配置信息,一部分是系统环境设置信息,一部分是用户个人的环境设置信息。

系统环境设置信息对所有的用户都一样,而用户个人环境设置信息仅对用户个人有效。

       前面说过可以通过配置 ~/.bashrc 和 ~/.bash_profile 来设置个人环境信息。

       通过配置系统环境配置文件: /etc/profile 来设置系统的环境信息。

复制代码
[volcanol@volcanol ~]$ cat /etc/profile
# /etc/profile

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

# It's NOT good idea to change this file unless you know what you
# are doing. Much better way is to create custom.sh shell script in
# /etc/profile.d/ to make custom changes to environment. This will
# prevent 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

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
复制代码

       上面的这个文件就是我的系统默认的系统配置文件,这个文件一般不建议用户修改,除非您确实需要修改,如上面的注释提示的,

如果您需要配置一些系统环境:

复制代码
# /etc/profile
系统环境配置文件 # System wide environment and startup programs,
for login setup # Functions and aliases go in /etc/bashrc
这个文件设置系统环境变量和在启动时系统需要执行的程序,如果您需要设置系统启动函数
或者别名,那么可以在/etc/bashrc文件中配置 # It
's NOT good idea to change this file unless you know what you # are doing. Much better way is to create custom.sh shell script in # /etc/profile.d/ to make custom changes to environment. This will # prevent need for merging in future updates.
不建议修改这个文件的内容,除非您知道您的修改不会造成任何异常。更好的配置方法是
您自定义一个脚本文件,并将您自定义的脚本存放到 /etc/profile.d 目录下,然后通
过您自定义的脚本文件来改变环境变量。
这将防止未来功能合并(最后一句感觉怪怪的)
复制代码

         从这里可以看到,在启动的时候,系统会读取 /etc/bashrc 文件和执行   /etc/profile.d/* 下的脚本文件。 

复制代码
[volcanol@volcanol ~]$ ls -al /etc/profile.d/
总用量 112
drwxr-xr-x.   2 root root  4096  6月 21 23:49 .
drwxr-xr-x. 114 root root 12288  6月 26 16:34 ..
-rw-r--r--.   1 root root   630  9月 18 2010 ccache.csh
-rw-r--r--.   1 root root   655  9月 18 2010 ccache.sh
-rw-r--r--.   1 root root   299  9月 30 2010 colorgrep.csh
-rw-r--r--.   1 root root   304  9月 30 2010 colorgrep.sh
-rw-r--r--.   1 root root  1133 10月  1 2010 colorls.csh
-rw-r--r--.   1 root root  1143 10月  1 2010 colorls.sh
-rw-r--r--.   1 root root    80  3月  1 2010 cvs.csh
-rw-r--r--.   1 root root    78  3月  1 2010 cvs.sh
-rw-r--r--.   1 root root   192  9月 30 2010 glib2.csh
-rw-r--r--.   1 root root   192  9月 30 2010 glib2.sh
-rw-r--r--.   1 root root    58 10月  5 2010 gnome-ssh-askpass.csh
-rw-r--r--.   1 root root    70 10月  5 2010 gnome-ssh-askpass.sh
-rw-r--r--.   1 root root  1745  9月 27 2010 lang.csh
-rw-r--r--.   1 root root  2706  9月 27 2010 lang.sh
-rw-r--r--.   1 root root   122  2月  7 2007 less.csh
-rw-r--r--.   1 root root   108  2月  7 2007 less.sh
-rw-r--r--.   1 root root   840 10月  5 2010 PackageKit.sh
-rw-r--r--.   1 root root   990  9月  7 2010 qt.csh
-rw-r--r--.   1 root root   933  9月  7 2010 qt.sh
-rw-r--r--.   1 root root  2142  5月 19 2010 udisks-bash-completion.sh
-rw-r--r--.   1 root root    74  7月 27 2010 vim.csh
-rw-r--r--.   1 root root   248  7月 27 2010 vim.sh
-rw-r--r--.   1 root root   161 11月 27 2007 which2.csh
-rw-r--r--.   1 root root   169 11月 27 2007 which2.sh
复制代码

         可以看到启动的时候将执行很多的脚本文件。

复制代码
# /etc/bashrc

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

# It's NOT good idea to change this file unless you know what you
# are doing. Much better way is to create custom.sh shell script in
# /etc/profile.d/ to make custom changes to environment. This will
# prevent need for merging in future updates.

# By default, we want this to get set.
# Even for non-interactive, non-login shells.
# 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
如果   
用户的UID 大于 199 且 用户的组ID = 用户ID 则 umask =002
否则
Umask = 022
# are we an interactive shell
?
下面的脚本内容设定 PS1 环境提示 if [ "$PS1" ]; then case $TERM in xterm*) if [ -e /etc/sysconfig/bash-prompt-xterm ]; then PROMPT_COMMAND=/etc/sysconfig/bash-prompt-xterm else PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}"; echo -ne "\007"' fi ;; screen) if [ -e /etc/sysconfig/bash-prompt-screen ]; then PROMPT_COMMAND=/etc/sysconfig/bash-prompt-screen else PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}"; echo -ne "\033\\"' fi ;; *) [ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-default ;; esac


# Turn on checkwinsize shopt -s checkwinsize
打开检查窗口大小变化功能, 这样在每个命令执行后将检查CLI窗口的大小是否变化
[
"$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

下面的代码执行non-login-shell时的脚本 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 } # Only display echos from profile.d scripts if we are no login shell # and interactive - otherwise just process them to set envvars
这里可以清楚的看到,系统是在执行/etc/bashrc文件时调用执行的/etc/profile.d/*的脚本 这里也给出了一个遍历目录并执行所有可执行文件的方法

  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
复制代码

         /etc/bashrc 文件完成下列作用:

依据不同的UID 设定 umask 值;
依据不同的 UID 设定提示字符 (就是 PS1 发量);
调用执行 /etc/profile.d/*.sh 脚本

         修改完配置文件后,需要在用户下次登录系统时才会生效,那有么有一种方法不注销本次登录,而使我们的配置

文件生效呢? 

          修改完配置文件后,可以通过source命令来使新的文件生效。

[root@www ~]# source ~/.bashrc <==底下这两个命令是一样的
[root@www ~]# . ~/.bashrc

           . ~/.bashrc 表示将~/.bashrc 文件的配置内容导入到当前的shell环境

 

今天就说到这里,未完待续......................

 
 
posted on 2013-06-27 14:12  HackerVirus  阅读(282)  评论(0编辑  收藏  举报