前面讲了Shell的一些相关知识,我们了解了SHELL作为操作系统与用户打交道的分界面。SHELL扮演着非常重要的角色。现在LINUX操作系统中默认都会安装支持常见的SHell,可能/etc/shells来查看可用SHELL列表。对每一个登陆用户来说,系统创建用户时都会让用户选择使用何种shell,如果不选择,默认是BASH SHELL。可以使用usemod或者chsh对用户的shell进行修改。

Linux Shell 基本概念及编程(7)_第1张图片

通常现在LINUX使用比较多的是Bash,它具有比较多的功能,如命令别名、命令历史、命令及文件名补全等,特别是可以进行编程。当然每种SHELL都具有自身应用的特殊性,下图列出:

Linux Shell 基本概念及编程(7)_第2张图片

从这张图上可以看出BASH是吸收前面三种SHELL的优点,开发出来,现代编程中几乎使有的都是BASH。因此这里重点讲述一下BASH。

【1】变量 bash sell变量分系统环境变量(全局变量),预定义变量,位置变量(参数位置)及自定义变量。可以使用Set命令查看所有环境变量。常用的环境变量也是系统预定义的有  USER UID SHELL HOME PWD PATH PS1 PS2。其中USER,UID,SHELL,HOME,PWD,PATH这几个变量平常都经常用到,这里就不详细说明,这里需要说明的就是PS1和PS2这两个系统变量。

Linux Shell 基本概念及编程(7)_第3张图片

Linux Shell 基本概念及编程(7)_第4张图片

注意这些改变只在当前SHELL中起效,一量退出当前SHELL就不再起作用了。要想始终起作用,需要将这些变量设置成为系统环境变量。系统环境变量通常都是定义在系统配置文件中,系统常见的配置文件如下:/etc/bashrc  /etc/profile ~/.bash_profile ~/.bashrc及这些文件中include进来的其它文件。注意,如果说你自己想要定义一个属于某个用户的全局变量,一般定义在~/.bash_profile下。如果是多个用户都共享的全局变量一般在/etc里。

Linux Shell 基本概念及编程(7)_第5张图片

了解了环境变量,我们看一下位置变量,什么是位置变量?这个位置变量中的位置是命令的参数位置。了解这些位置参数变量,一般用于在SHELL脚本中控制参数个数和读取指定参数。其定义格式如下:

Linux Shell 基本概念及编程(7)_第6张图片

如上图所示,除了$0是系统预定义变量外,其它都是位置参数,根据位置来取得相应参数值。SHELL内部预定义了如下一些变量:

Linux Shell 基本概念及编程(7)_第7张图片

Linux Shell 基本概念及编程(7)_第8张图片

用户自定义变量。用户可以自定义两种变量,一种是局部变量,另一种是全局变量。局部变量的作用域在当前SHELL,退出当前SHELL就消失。全局变量则不是。全局变量使用export 变量名. 定义一个亦是名称  $NAME=WANG

Linux Shell 基本概念及编程(7)_第9张图片

【2】bash命令的一常见操作技巧如下:

     1)文件名及命令名称的使用tab键进行补全

     2)命令历史,可以上下方向键,或者使用history命令。通常history保存在~/.bash_history文件中。消除历史history –c,  history显示的是当前一个缓冲区中的所有保存的comand,还可以使用!!重复上一个命令,或者!-1及ctl+p都可以。以级!+上一次命令的command名如 !sftp

Linux Shell 基本概念及编程(7)_第10张图片

Linux Shell 基本概念及编程(7)_第11张图片

常见几个重要的控制参数  export HISTCONTROL=ignorespace  export HISTCONTROL=erasedups

    3)命令别名 alias,可以使用alias查看当前所有的别名,也可以设置一个新的别名,或者使用unalias取消一个别名。别名的好处就是省去了常用命令的组合参数的频繁输入。查看系统缺省定义的别名/etc/profile.d下。

Linux Shell 基本概念及编程(7)_第12张图片

4)管道与输入输出重定向,标准输入与输出,通常指的是显示器 tty和键盘,这些在操作系统中统统以文件方式看待,因此,操作系统会给他们一个缺省的文件描述符,在SHELL中,0是指标准输入。 1是指标准输出。2 是错误输出。这里有点混淆的是输出分成两种,一种标准输出,比喻说echo这种,还是一种是错误,这个错识是由SHELL内部打印出来的错误信息。将这个重定向到特定设备或者文件时使用> >> < 等操作符。

Linux Shell 基本概念及编程(7)_第13张图片

如上图所示,>> > <这些操作符通常是打开一个文本,如果将这些输出直接交由其它的命令处理,通常使用管道符号|,“|”符用于连接左右两个命令,将“|”左边的命令执行结果(输出)作为“|”右边命令的输入。 cmd1 |cmd2

[windriver@windriver-machine shtest]$ ls -latr ex1.sh exe
ls: cannot access exe: No such file or directory
-rwxrwxr-x 1 windriver windriver 95 2011-08-06 00:24 ex1.sh
[windriver@windriver-machine shtest]$ ls -latr ex1.sh exe 2>errors
-rwxrwxr-x 1 windriver windriver 95 2011-08-06 00:24 ex1.sh
[windriver@windriver-machine shtest]$ set |grep USER
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}"; echo -ne "\007"'
USER=windriver
[windriver@windriver-machine shtest]$

这里还要讨论一个问题?就是这里所谓的0,1,2文件描述符与通常意义上C语言中使用OPEN函数或者SELECT 打开的SOCKET中的FD是不是一样的吗?如果不一样,区别在哪?

Linux Shell 基本概念及编程(7)_第14张图片

首先我们确认一点文件描述符都是一样,它都来源于POXIS标准。POSIX 定义了 STDIN_FILENO、STDOUT_FILENO 和 STDERR_FILENO 来代替 0、1、2。这三个符号常量的定义位于头文件 unistd.h。所以不管是WINDOWS还是LINUX/UNIX其实都是有文件描述符,只是因为文件描述符它是从0起始的标准数值,在具体实现中会引起混淆,因此,像WINDOWS是使用文件句柄,而标准C语言操作的则是文件指针。默认的SHELL会打开0,1,2三个文件符,但是一个例外是守护进程打开”/dev/null”是会设定这个文件描述符是0,因为很多守护进行它是继承自SHELL父进程的,因此,子进程具有与父进程相同的文件描述符。