简单来讲Shell其实就是一个命令解释器,而它的做用就是解释并执行用户输入的命令及程序。用户每输入一条命令,Shell就解释执行一次。这种方式很容易让你们想起在Windows环境中使用的command命令,咱们在cmd窗口输入一条命令,按下Enter键,则执行相应的命令和结果。
Shell位于操做系统的最外层,对外提供与用户交互式的对话并返回相应的执行结果,对内则是将用户输入的命令解释给操做系统。Shell在操做系统中所处的位置以下图所示:
linux
Shell在英文中的意思就是外壳、贝壳等,从图中也能够看出,Shell就像壳同样包住了系统的核心(Kernel)shell
Shell命令与Command命令对比
编程
在理解了Shell以后,咱们再来看看Shell脚本。当命令或程序语句不是在命令行中执行时,而是经过程序文件来执行时,该程序就称之为Shell脚本,我依然拿Windows来作比例。当咱们须要执行比较少的命令时,咱们能够一个一个命令的进行手动输入,若是须要执行成百上千的命令时,你会怎么办?聪明的你确定会脱口而出,用批处理(扩展名通常为bat或cmd)。其实Shell脚本就相似于批处理,经过在脚本中定义变量、执行命令、调用函数和逻辑判断、循环等造成一个有机的总体,便造成一个功能强大、自动化程度较高的脚本。vim
@echo off set date=%date:~0,4%-%date:~5,2%-%date:~8,2% echo "当前时间为:"%date% cd /d "D:\" mkdir SystemInfo cd /d "SystemInfo" systeminfo>systeminfo%date%.txt start systeminfo%date%.txt pause
# !/bin/bash currentName=`whoami` echo $currentName if [ "$currentName" = "root" ] then echo "Current Login User is root" else echo "Current Login User is :"$currentName fi
Shell 脚本语言是弱类型语言,即无须定义变量类型便可使用。在UNIX/Linux中主要有两大类Shell:Bourne Shell和C Shell。bash
Bourne Shell包括Bourne Shell(sh)、Korn Shell(ksh)、Bourne Again Shell(bash)三种类型。微信
Bourne Shell
由AT&T的Steve Bourne开发,是标准的UNIX Shell,不少UNIX系统都配有sh。编程语言
Korn Shell(ksh)
由David Korn开发,是Bournd Shell(sh)的超集合而且添加了csh引入的新功能,是目前不少UNIX系统标配的Shell,这些系统上的/bin/sh每每指向/bin/ksh的符号连接编辑器
Bourne Again Shell(bash)
由GNU项目组开发,主要目标是与POSIX标准操持一致,同时兼容sh。bash从csh和ksh借鉴了不少功能,是各类Linux发行版本默认配置的Shell。Linux系统上的/bin/sh每每是指向/bin/bash的符号连接。但bash和sh仍是有不少不一样之处,虽然bash扩展了一些命令和参数,但bash并不彻底兼容sh,二者之间有些行为并不一致。在大多数状况下区别不太大,有时还可使用bash替代sh。函数
C Shell包括csh和tcsh两种。csh由Berkeley大学开发,随之BSD UNIX发布,它的流程控制语句很像C语言,支持不少Bourne Shell所不支持的功能,如做业控制、别名、系统算术、命令历史、命令行编辑等。tcsh是csh的加强版,加入了命令补全等功能,在FreeBSD、Mac OS X等系统上代替了csh。
以上介绍的这些Shell中,较为通用的是标准的Bourne Shell(sh)和C Shell(csh),而其中Bourne Shell(sh)已经被Bourne Again Shell(bash)所取代。可经过如下命令查看CentOS 7.3系统Shell的支持状况。
[admin@CentOS7 tmp]$ cat /etc/shells /bin/sh #Linux经常使用的Shell,指向/bin/bash /bin/bash #Linux经常使用的Shell,也是默认使用的Shell /sbin/nologin #Linux经常使用的Shell,用于禁止用户登陆 /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh
Linux系统中主流的Shell是bash,而bash是由Bourne Shell(sh)发展而来,同时bash还包含了csh和ksh的特点。所以大多数脚本均可以不作修改便可在sh运行,若是使用sh后结果与预期有差别,能够尝试用bash代替sh.
在经常使用的操做系统中,Linux中默认的Shell是Bourne Again Shell(bash),Solaris和FreeBSD下默认的是Bourne Shell(sh),AIX下默认的是Korn Shell(ksh)。那么问题来了,咱们该如何查看所使用系统的Shell?以CentOS为例查看系统默认的Shell:
[admin@CentOS7 tmp]$ echo $SHELL /bin/bash
[admin@CentOS7 tmp]$ grep root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin
root用户结尾的/bin/bash就是用户登陆后的Shell解释器。后续文章中重点讲解的是Bourne Again Shell(bash)。
在Linux系统中,Shell脚本一般是在编辑器vi/vim中进行编写。可由UNIX/Linux命令、bash shell命令、程序结构控制语句、注释等组成,推荐使用vim。
#!/bin/bash 或 #!/bin/sh
注意事项:
一、第一行通常要求小于255个字符。
二、#!/bin/bash不是注释,在执行脚本时,内核会根据#!后的解释器肯定使用哪一个解释器来执行脚本的内容。
三、这一行必须位于每一个脚本顶端的第一行,若是不是第一行则是表明注释
#!/bin/bash echo "bash test" #!/bin/bash #表明该行是注释 #!/bin/sh #表明该行是注释
从上图能够看到sh为bash的软连接,大多数状况下,脚本开头使用#!/bin/bash和#!/bin/sh是没有区别的。但仍是建议采用#!/bin/bash。
通常状况下,安装完Linux系统以后会自动安装好bash软件,查看bash版本以下所示:
[admin@CentOS7 etc]$ cat /etc/redhat-release CentOS Linux release 7.3.1611 (Core) #当前系统版本 [admin@CentOS7 etc]$ bash --version GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu) # bash 版本,后续省略自由软件提示信息
若是想体验更高版本的bash,升级方法以下所示:
yum -y update bash #在线升级 rpm -qa bash #查看bash安装包 bash-4.2.46-20.el7_2.x86_64
如下是经常使用脚本开头的写法,不一样语言的脚本在开头通常都要加上以下标识内容:
#!/bin/sh #!/bin/bash #!/usr/bin/awk #!/bin/sed #!/usr/bin/tcsh #!/usr/bin/perl
CentOS中默认的Shell均为bash。所以即在脚本中未加#!/bin/bash,它也会使用bash去解释。若是不但愿使用系统默认的Shell解释器,就须要自行指定解释器。建议你们一开始就养成好习惯,遵循Shell编程规范,在开头第一行指定所使用的解释器
若是在开头未指定解释器,要使用对应的解释器来执行脚本时,可使用以下方法:
Shell脚本: bash test.sh或sh test.sh Python脚本:python test.py
在不少编程语言中,都会支持单行和多行注释,方便阅读和维护,在Shell中,使用#对所在行进行注释,注释的内容并不会看成命令执行。注释可单独一行也能够紧跟在命令后面。建议在写脚本添加必要的注释,方便本身也方便后续维护者或使用者。
注释中尽可能不要使用中文,脚本中也尽可能不要使用中文。
Shell脚本的执行流程
当脚本运行时,它会先查找系统环境变量ENV,该变量指定了环境文件(加载顺序一般是/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc等),在加载了上述环境变量文件后,Shell开始执行Shell脚本中的内容。
Shell脚本执行的顺序是从上到下,从左到右依次执行每一行的命令及语句。若是Shell中存在脚本嵌套(子脚本)时,就会执行嵌套脚本的内容,完成后再返回父脚本继续执行父脚本内后续的命令和语句。一般状况下,执行Shell脚本时,会向系统内核启动一个新的进程,以便在该进程中执行脚本的命令和子脚本,其流程图以下所示:
Shell脚本的执行方式
【1】bash script-name或sh script-name
这种方式是当脚本文件自己没有可执行权限(即文件属性没有x占位符)时常使用的方式或脚本文件没有指定解释器时经常使用的方法。
【2】path/script-name或./script-name
这种方式是指在当前路径下执行脚本,前提是脚本必须有可执行权限,具体方法为chmod +x script-name。而后经过相对路径或绝对路径执行脚本。
【3】source script-name或. script-name
这种方法一般使用source或" . "读入或加载指定的Shell脚本,如son.sh,而后依次执行指定的Shell脚本文件son.sh中的全部语句。这些语句将在当前父Shell脚本father.sh中运行(其余几种模式都会启动新的进程执行子脚本)。
使用source或" . "能够将son.sh自身脚本中的变量值或函数等的返回值传递到当前父Shell脚本father.sh中使用,这是和其余两种方法最大的区别,所以须要特别注意。
【4】sh<script-name或cat script-name | sh
这种方法一样适用于bash,这种方法并不常见,了解知道便可。其原理就是利用了管道技术。
你们能够看看如下脚本的正确答案是哪个?
参考的答案选项以下所示:
正确答案是无内容输入。缘由可查看Shell脚本的几种执行方式。
经过这个示例咱们能够得出以下结论:
每种语言都有本身的开发规范,虽然不是强制遵照,但有规范的代码不便方便阅读、维护、多人协同开发,同时也能减小出现Bug的几率。主要的规范以下所示:
#!/bin/bash 或 #!/bin/sh
#Date:2017-11-29 22:50 #Author:Surpassme #Description:This is sample shell scripts #Version:1.5
【3】Shell脚本中尽可能不要使用中文
虽然说Linux也能兼容中文,但仍是存在切换系统环境后中文出现乱码的问题。若是非要用中文,可对系统进行字符集调整。如export LANG="zh_CN.UTF-8",并在脚本中从新定义字符集设置和系统保持一致。
【4】Shell脚本尽可能添加扩展名.sh
一、成对的符号尽可能一次性写全,防止遗漏 二、中括号([])两端至少要保留一个空格。 三、流程控制语句,应一次性将格式写完,再添加内容 四、良好的代码缩进,方便阅读 五、脚本的各个符号必须为英文状态下的符号 六、常规变量的字符串定义时应加双引号("")而且等号先后均不能有空格,须要强引用(指所见即所得的字符串引用),则使用单引号(''),若是是命令引用,则用反引号(``)
本文同步在微信订阅号上发布,如各位小伙伴们喜欢个人文章,也能够关注个人微信订阅号:woaitest,或扫描下面的二维码添加关注: