shell简介
本文最后更新于:July 24, 2019 am
简单介绍一下shell的概念、分类以及脚本的几种执行方式。
1、什么是shell
Shell的中文翻译名是贝壳的意思,也就是相当于下图所示,是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,用户每输入一条命令,Shell就解释执行一条。这种从键盘一输入命令,就可以立即得到回应的对话方式,称为交互的方式。
Shell存在于操作系统的最外层,负责与用户直接对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,然后输出到屏幕返回给用户。输入系统用户名和密码并登录到Linux后的所有操作都是由Shell解释与执行的。
2、什么是shell脚本
当命令或程序语句不在命令行下执行,而是通过一个程序文件来执行时,该程序就被称为Shell脚本。
如果在Shell脚本里内置了很多条命令、语句及循环控制,然后将这些命令一次性执行完毕,这种通过文件执行脚本的方式称为非交互的方式。Shel脚本类似于DOS或windows系统下的批处理程序(扩展名一般为“*.bat”)。用户可以在Shell脚本中敲入一系列的命令及命令语句组合。这些命令、变量和流程控制语句等有机地结合起来,就形成了一个功能强大的Shell脚本。
比如下面的这个脚本,就是用来清空log日志中的messages文件
1 |
|
上面的这个脚本就是最简单的由命令直接堆砌而成的脚本文件,需要注意的是,脚本在执行的时候可能会有权限限制,一般需要使用chmod +x
给脚本加执行权限,还可能需要切换到root
用户或者使用sudo
。
实际上我们可以看到上面的脚本其实一条命令就能解决
1 |
|
接下来我们对上面的脚本进行改进,加入执行用户和切换目录的判断以及根据执行结果返回不同的信息。
1 |
|
3、shell脚本语言的种类
Shell脚本语言是弱类型语言(无须定义变量的类型即可使用),在Unix/Linux中主要有两大类Shell:一类是Bourne shell
,另一类是Cshell
。
3.1 Bourne shell
Bourne shell又包括Bourne shell(sh)、Korn shell(ksh)、Bourne Again Shell(bash)三种类型。
- Bourne shell(sh)由AT&T的Steve Bourne开发,是标准的UNIX Shell,很多UNIX系统都配有sh。
- Korn shell(ksh)由David Korn开发,是Bourne 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。
在Linux中,一般使用的shell是bash,所以说bash其实是shell的一个子集,当然也还有其他的一些流行的shell工具。如果我们想要Linux中的一个用户无法登录使用shell交互,最简单的方法就是在
/etc/passwd
文件中设置该用户的默认shell为/sbin/nologin
即可。
3.2 Cshell
Cshel又包括csh、tcsh两种类型。
- csh由Berkeley大学开发,随BSDUNIX发布,它的流程控制语句很像C语言,支持很多Bourne shell所不支持的功能,例如:作业控制、别名、系统算术、命令历史、命令行编辑等。
- tcsh是csh的增强版,加入了命令补全等功能,在FreeBSD、Mac OSX等系统上替代了csh。
3.3 shell目前形势
以上介绍的这些Shell中,较为通用的是标准的Bourne shell(sh)和Cshell(csh)。其中Bourne shell(sh)已经被Bourne Again shell(bash)所取代。
Linux系统中的主流Shell是bash,bash是由Bourne Shell(sh)发展而来的,同时bash还包含了csh和ksh的特色,但大多数脚本都可以不加修改地在sh上运行,如果使用了sh后发现结果和预期有差异,那么可以尝试用bash替代sh。
Shel脚本语言的优势在于处理偏操作系统底层的业务,例如:Linux系统内部的很多应用(有的是应用的一部分)都是使用Shell脚本语言开发的,因为有1000多个Linux系统命令为它做支撑,特别是Linux正则表达式及三剑客grep、awk、sed等命令。
对于一些常见的系统脚本,使用Shell开发会更简单、更快速,例如:让软件一键自动化安装、优化,监控报警脚本,软件启动脚本,日志分析脚本等,虽然PHP/Python语言也能够做到这些,但是,考虑到掌握难度、开发效率、开发习惯等因素,它们可能就不如Shell脚本语言流行及有优势了。对于一些常规的业务应用,使用Shell更符合Linux运维简单、易用、高效的三大基本原则。
在常用的操作系统中,Linux下默认的Shell是Bourne Again shell(bash);Solaris和FreeBSD下默认的是Bourne shell(sh);AIX下默认的是Korn Shell(ksh)。
4、脚本的执行
Shell脚本的执行通常可以采用以下几种方式。
4.1 bash script-name
或sh script-name
:
这是当脚本文件本身没有可执行权限(即文件权限属性x位为-号)时常使用的方法,或者脚本文件开头没有指定解释器时需要使用的方法。
4.2 path/script-name
或./script-name
:
指在当前路径下执行脚本(脚本需要有执行权限),需要将脚本文件的权限先改为可执行(即文件权限属性加x位),具体方法为chmod +x script-name
。然后通过脚本绝对路径或相对路径就可以直接执行脚本了。
4.3 source script-name
或.script-name
:
这种方法通常是使用source
或.
(点号)读入或加载指定的Shel脚本文件(如san.sh),然后,依次执行指定的Shell脚本文件san.sh中的所有语句。这些语句将在当前父Shell脚本father.sh进程中运行(其他几种模式都会启动新的进程执行子脚本)。
因此,使用source
或.
可以将san.sh自身脚本中的变量值或函数等的返回值传递到当前父Shel脚本father.sh中使用。这是它和其他几种方法最大的区别,也是值得读者特别注意的地方。
这里说起来可能不好理解,我们用一个简单脚本来操作一下。
这里我们可以看到,这个脚本的主要操作是使用pwd
命令打印出当前的目录
然后我们分别用上面的方法1和这里的方法3来执行这个脚本
这里我们可以看到,使用方法1的时候,并没有打印出当前目录userdir
,或者说,当前目录userdir
这个变量为空。再使用方法3来执行该脚本,我们可以看到这时候的变量userdir
就不为空了。
结论:通过source
或.
加载执行过的脚本,由于是在当前Shell中执行脚本,因此在脚本结束之后,脚本中的变量(包括函数)值在当前Shell中依然存在;而sh和bash执行脚本都会启动新的子Shell执行,执行完后退回到父Shell,因此,变量(包括函数)值等无法保留。
实在不懂就看下小七画的这个灵魂流程图
。
在进行Shell脚本开发时,如果脚本中有引用或执行其他脚本的内容或配置文件的需求时,最好用.”或source先加载该脚本或配置文件,处理完之后,再将它们加载到脚本的下面,就可以调用source加载的脚本及配置文件中的变量及函数等内容了。
source
或.
命令的功能是:在当前Shell中执行source
或.
加载并执行的相关脚本文件中的命令及语句,而不是产生一个子Shell来执行文件中的命令。
source
或.
的实际功能相同,都是读入脚本并执行。注意
.
和后面的脚本名之间要有空格。如果大家学过PHP开发就知道,
source
或.
相当于include的功能。HTTP服务软件Apache、Nginx等配置文件里都支持这样的用法。
4.4 sh<script-name
或cat scripts-namelsh
:
同样适用于bash,不过这种用法不是很常见。一般都是用来实现拼接字符串等骚操作
的,留个坑,以后有机会再来试一下。