Shell编程之概述

本文主要对Shell的一些基本概念和Shell脚本的格式和执行进行简单总结,另外本文所使用的Linux环境为CentOS Linux release 8.1.1911,所使用的Shell为bash 4.4.19(1)-release

一、Shell基本概念

1.什么是Shell

Shell是一个用C语言编写的程序,它是用户使用Linux的桥梁,即连接了用户和Linux内核,让用户能够更加高效、安全、低成本地使用Linux内核,这就是Shell的本质。Shell本身不是Linux内核的一部分,它只是在内核的基础上编写的一个应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Shell编程之概述_第1张图片
Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

注意:Shell也是一种编程语言,它的解释器是Shell这个程序。我们平时所说的Shell,有时候是指连接用户和内核的这个程序,有时候又是指Shell编程。

2.进入Shell的两种方式

  • 通过Linux控制台终端:进入Shell CLI的一种方法是让Linux系统退出图形化桌面模式,进入文本模式。这样在显示器上就只有一个简单的shell CLI,这种模式称作Linux控制台。Linux系统启动后会自动创建几个虚拟控制台,虚拟控制台是运行在Linux系统内存中的终端会话。
  • 通过图形化终端:除了虚拟化终端控制台,还可以使用Linux图形化桌面环境中的终端仿真包,也就是我们常说的终端。终端仿真包会在一个桌面图形化窗口中模拟控制台终端的使用。常用的终端仿真器软件包有GNOME Terminal、Konsole Terminal和xterm。CentOS默认采用的都是GNOME桌面环境,GNOME桌面环境的默认终端仿真器是GNOME Terminal。

通过Ctrl + Alt + Fn(n=1,2,3,4,5...)快捷键可以从图形界面模式进入控制台模式,按F几就切换到控制台几,一般通过Ctrl + Alt + F1或F7快捷键可以进入图形界面。

3.Shell命令提示符

启动了终端仿真软件包或者登录Linux虚拟控制台后就会看到Shell命令提示符。默认Bash Shell提示符是美元符号$,这个符号表明Shell在等待用户输入。命令提示符不是命令的一部分,它只是起到一个提示作用。不同的Linux发行版采用不同格式的提示符。CentOS中默认的提示符格式如下:

[username@host ~]$ 

各个部分的含义如下:

  • []是提示符的分隔符号,没有特殊含义。
  • username表示当前登录的用户。
  • @是分隔符号,没有特殊含义。
  • host表示当前系统的主机名。
  • ~代表用户当前所在的目录为主目录(home目录)。如果用户当前位于主目录下的bin目录中,那么这里显示的就是bin。
  • $是命令提示符。Linux用这个符号标识登录的用户权限等级,如果是超级用户(root用户),提示符就是#,如果是普通用户,提示符就是$

注意:推荐初学者不要以root用户的身份直接使用shell来执行任务,因为如果shell具备较高的权限,命令中出现的输入错误有可能造成更严重的破坏,所以推荐使用普通用户登录系统,然后借助sudo这类工具来运行特权命令。使用sudo 执行命令的效果和root一样。

有些命令不能在一行内输入完成,需要换行,这个时候就会看到第二层命令提示符。第二层命令提示符默认为>,提示符>用来告诉用户命令还没输入完成,请继续输入。

命令提示符的格式不是固定的,用户可以根据自己的需要修改。Shell通过PS1PS2这两个环境变量来控制提示符的格式,修改PS1PS2的值就能修改命令提示符的格式,其中:

  • PS1控制第一层命令提示符的格式。
  • PS2控制第二层命令提示符的格式。

先查看PS1PS2的值:
2
通过直接修改变量的值来修改命令提示符的格式只在当前的Shell会话期间有效,再次启动Shell后将重新使用默认的命令提示符。永久修改命令提示符的格式可以在~/.bashrc文件中修改PS1PS2变量的值,然后source ~/.bashrc重写加载配置文件。

4.Shell命令的基本格式

Shell命令的基本格式如下:

command [选项] [参数]

[]表示可选的。Linux的选项又分为短格式选项和长格式选项:

  • 短格式选项是长格式选项的简写,用-和一个字母表示。
  • 长格式选项是完整的英文单词,用--和一个单词表示。

一般情况下,短格式选项是长格式选项的缩写,也就是一个短格式选项会有对应的长格式选项。有些命令不写选项和参数也能执行,有些命令在必要的时候可以附带选项和参数。参数是命令的操作对象,一般情况下,文件、目录、用户和进程等都可以作为参数被命令操作,如果可以省略参数,则一般都有默认参数。有些命令的选项后面也可以附带参数,这些参数用来补全选项,或者调整选项的功能细节。

5.Shell命令的本质

shell命令分为以下两种:

  • 内置命令:Shell自带的命令称为内置命令(builtin commands),在Shell内部是通过函数来实现的,当Shell启动后,这些命令所对应的函数代码就会被加载到内存中,所以内置命令的运行是非常快速的。内置命令不宜过多,过多的内置命令会让Shell的体积变得很大,占用过多的内存,Shell是一个常驻内存的程序,占用太多的内存会影响Shell的运行。Shell内置命令的本质是一个自带的函数,执行内置命令就是调用这个自带的函数,由于函数代码在Shell启动时候已经被加载到内存上,所以内置命令的执行速度很快。
  • 外部命令:一个外部命令对应的是一个应用程序。一般在Linux中执行外部命令时,不会去遍历整个文件系统来查找对应的应用程序,而只会在PATH环境变量的路径下查找是否有对应的应用程序,如果有就运行,没有就返回错误的信息给用户。我们自己用C语言或者C++编写一个应用程序并放到PATH指定的路径下面,那么这个程序也会成为Shell命令。Shell外部命令的本质上是一个应用程序,执行外部命令也就是启动一个新的应用程序,因为要创建新的进程并加载应用程序的代码,所以外部命令的执行速度会很慢。

6.Shell命令的选项和参数的本质

Shell内置命令就是一个内部的函数,外部命令就是一个应用程序。内置命令后面附带的所有选项和参数最终都以参数的形式传递给了函数,外部命令后面附带的所有选项和参数最终都以参数的形式传递给了应用程序。因为C语言或者C++程序的入口函数是main函数,所以传递给应用程序的参数最终都被main函数接收了,从这个角度看,传递给应用程序的参数其实也是传递给了函数。所以Shell命令后面附带的选项和参数最终都以参数的形式传递给了函数。选项中的-也被传递给了函数,用来区分该参数是否是命令的选项。

7.Shell执行命令的两种方式

  • 交互式(Interactive):解释执行用户的命令,用户输入一条命令,Shell就解释执行一条。
  • 批处理(Batch):用户事先写一个Shell脚本(Scrip),其中有很多条命令,让Shell一次把这些命令执行完,而不必一条一条地敲命令。

8.Shell脚本

Shell也是一种脚本语言,Shell脚本是一种为Shell编写的脚本程序。Shell脚本是解释执行的,不需要编译,Shell程序从脚本中一行一行读取并执行这些命令,相当于一个用户把脚本中的命令一行一行敲到Shell提示符下执行。

注意:业界所说的Shell通常都是指Shell脚本,但Shell和Shell脚本是两个不同的概念。Shell编程一般是指Shell脚本编程,不是指开发Shell自身。

9.Shell解释器

Linux上常见的Shell脚本解释器有bash、sh、csh、tcsh等。Linux通过cat /etc/shells可以查看系统中支持的解释器。几种常见的Shell解释器如下:

  • sh:全称Bourne Shell,是UNIX标准默认的Shell。
  • bash:全称BourneAgain Shell,是Linux标准默认的Shell。bash不但与sh兼容,还继承了csh、ksh等优点。
  • ash:是Linux中占用系统资源最少的一个小Shell,它只包含24个内部命令,因而使用起来很不方便。
  • csh:全称C shell,语法与C语言类似。
  • tcsh:tcsh是csh的增强版。
  • ksh:全称Korn Shell,集合了csh和sh的优点,并且与sh向下完全兼容。ksh的效率很高,其命令交互界面和编程交互界面都很好。

在现代Linux上,sh已经被bash代替,/bin/sh往往是指向/bin/bash的软链接,例如本文所使用的CentOS,进入/bin目录使用ll | grep bash可以看出来:
3
CentOS默认的解释器是Bash。通过echo $SHELL可以查看当前Linux系统默认使用的Shell解析器:
4

SHELL是Linux系统中的环境变量,它指明了当前使用的Shell程序的位置,也就是使用的哪个Shell。

二、Shell脚本的格式与执行方式

Shell脚本就是一个文本文件,创建Shell脚本文件就要先新建一个文件,然后将命令输入文件中,文件扩展名建议使用sh代表Shell,但扩展名并不影响脚本执行。

1.首行格式

Shell脚本文件的第一行必须指定要使用的Shell解释器,格式为:

#!/bin/bash

#用作注释行,但Shell脚本的第一行是个例外,!后面指定Shell使用的解释器。/bin/bash是Bash的解释器命令路径,即指定使用Bash解释器。使用shbash命令执行时,第一行可以不写#!/bin/bash,脚本文件自己作为可执行程序执行时,第一行可以不写#!/bin/bash,默认也是使用Bash解释器(CentOS中),不过还是建议写上。

2.注释格式

单行注释,格式为:

# 注释内容

多行注释,格式为:

:<<!
# 注释内容
# 注释内容
!

3.执行方式

首先编写如下Shell脚本文件,命名为test.sh

#!/bin/bash
echo "执行方式:"
# 获取标准输入并赋值给METHOD
read METHOD
# $$变量获取当前进程的PID
echo "$METHOD, PID:$$"

第一种执行方式是将脚本作为参数传递给解释器,以下几种写法本质上一样:

# 脚本文件用相对路径
# 使用sh的绝对路径
/bin/sh test.sh
# 使用sh命令,Shell会在/bin目录找到sh
sh test.sh
# 使用bash的绝对路径
/bin/bash test.sh
# 使用bash命令,Shell会在/bin目录找到bash
bash test.sh
# 脚本文件用绝对路径
sh /root/test.sh
bash /root/test.sh

这里以bash test.sh为例,首先输出当前进程PID,再执行脚本文件:
5
这种方式本质是使用Shell解释器运行脚本文件,脚本文件不需要执行权限,并且开启了一个新进程,在新进程中运行。

第二种方式是将Shell脚本作为可执行程序执行,首先给脚本文件添加可执行权限:

chmod +x ./test.sh

然后执行,用相对路径和绝对路径都可以:

# 脚本文件用相对路径
./test.sh
# 脚本文件用绝对路径
/root/test.sh

注意,脚本文件用相对路径时,一定要加./表示当前目录,整条命令的意思是执行当前目录下的test.sh脚本。如果不写./,Linux会到系统路径(由PATH环境变量指定)下查找test.sh,而系统路径下显然不存在这个脚本,所以会执行失败,除非将当前路径添加到系统路径中。

这里以./test.sh为例,首先输出当前进程PID,再执行脚本文件:
Shell编程之概述_第2张图片
这种方式的本质是Shell脚本自己作为一个程序执行,需要可执行权限,并且开启了一个新进程,在新进程中运行。

还有一种方式就是在当前进程中运行Shell脚本,使用source命令,该命令是内置命令中的一种。以下几种写法效果一样:

# 脚本文件用相对路径
source ./test.sh
. ./test.sh
# 不写./也可以
source test.sh
. test.sh
# 脚本文件用绝对路径
source /root/test.sh
. /root/test.sh

这里以source ./test.sh. ./test.sh. test.sh. /root/test.sh为例,首先输出当前进程PID,再执行脚本文件:
Shell编程之概述_第3张图片
这种方式的本质是source命令读取脚本文件中的代码并依次执行,不会开启一个新的进程,而是在当前进程中运行。使用source命令可以不用给脚本文件添加可执行权限,脚本文件用相对路径时加不加./都行。

你可能感兴趣的:(Shell,shell,shell编程,shell命令,shell脚本,shell脚本执行)