一、Shell脚本概述
在linux进行较复杂的工作时,需要大量重复的输入和交互操作费力费时,且容易出错。这是就可以通过编写一个Shell脚本程序,可以批量处理、自动化地完成一系列维护任务。
1.1 Shell的作用
Shell在linux系统中充当了一个“命令解释器”的角色,负责接收用户输入的操作指令并进行解释,将需要执行的操作传递给内核执行,最后输出执行结果。
不同的linux系统有时使用的Shell解释器不同,内部指令、命令行提示符等方面会有一些区别。可以通过/etc/shell文件了解当前系统所支持的Shell脚本种类。
1.2 编写第一个Shell脚本
Bash(/bin/bash)是目前大多数Linux版本采用的默认Shell。接下来的所有Shell操作,均已bash为例。
一个文件里面包含一些命令且这个文件有执行权限,这个文件就是一个Shell脚本了,例如执行以下操作可以创建一个脚本sh.sh:
vim sh.sh
#在该文件中添加命令
#!/bin/bash cd /boot #进入/boot目录 pwd #显示当前所在目录的路径 ls -lh vml* #以列表形式显示当前目录中的以vml开头的文件,并且附带大小单位。 #保存退出
chmod +x sh.sh #给sh.sh添加可执行权限
#最后执行
执行该脚本输出的结果为:
执行脚本的命令有:bash、sh、./、.、source。其中bash、sh和./执行命令的方式是相同的,都是先打开一个子bash,再执行指令;.和source相同,在当前bash中执行脚本中的指令。
1.3 重定向和管道操作
1. 重定向
Linux系统使用文件来描述各种硬件、设备等资源,用户通过操作系统处理信息的过程中,包括以下几类交互设备文件:
- 标准输入(STDIN):默认的设备是键盘,文件编号为0,命令将从标准输入文件中读取在执行过程中需要输入的数据。
- 标准输出(STDOUT):默认的设备是显示器,文件标号为1,命令将执行后的输出结果发送到标准输出文件。
- 标准错误(STDERR):默认的设备是显示器,文件编号为2,命令将执行期间的各种错误信息发送到标准错误文件。
在Linux系统中,可以改变输入、输出内容的方向,而不使用默认的标准输入、输出设备,这种操作称为重定向。
重定向输出就是指将命令的正常输出结果保存到指定的文件中,而不是直接显示在屏幕上,使用">"和">>"作为操作符,分别用于覆盖和追加文件。若文件不存在,则新建文件。例如可以使用cat查看某个文件的内容,并将内容输出到新的文件:
cat 文件A > 文件B
重定向输入指将命令中接收输入的途径有默认的键盘改为指定的文件,而不是等待键盘输入。使用"<"作为操作符。通过重定向输入可以使一些交互式操作过程能够通过读取文件来完成,例如可以使用重定向输入实现简单的自动密码设置的功能:
vim pass.txt
#在pass.txt中输入要设置的密码 123456
passwd --stdin fkk < pass.txt
#从 pass.txt 文件中取密码,需要注意SELinux会影响此命令执行,若执行失败可尝试关闭 SELinux
执行之后的结果为:
错误重定向可以将执行命令过程中出现的错误信息保存到指定的文件,而不是显示在屏幕上。错误重定向使用"2>"作为操作符,其中"2"是指错误文件的编号。执行以下操作可以将对源码包进行配置时出现的错误信息保存到error.log文件中:
./configure 2> error.log
cat error.log
#cat命令的输出:
configure: error: APR not found. Please read the documentation.
configure: error: APR not found. Please read the documentation.
错误重定向也可以使用">>"操作符将信息追加到文件中。当想要把正常信息和错误信息分开保存到同一个文件中时,可以使用"&>"操作符。
2. 管道操作
管道(pipe)操作为不同命令之间的协同工作提供了一种机制,位于管道符号"|"左侧的命令输出的结果,将作为右侧命令的输入(处理对象),同一行命令中可以使用多个管道。例如,要在某个目录中查询是否有“A”文件,但是目录中的文件过多,就可以使用管道结合"grep"命令:
ls | grep A
二、Shell变量的作用、类型
Shell变量用于存放系统和用户需要使用的特定参数,而且这些参数可以根据用户的设定或系统环境的变化而响应变化。常见的Shell变量的类型包括自定义变量、环境变量、只读变量、位置变量、预定义变量。
2.1 自定义变量
又称为本地变量,由用户自己定义的变量,只在用户自己的Shell环境中有效。
1. 定义新的变量
定义变量的基本格式为“变量名=变量值”,等号两边不能有空格。变量名程需以字母或下滑线开头,名称中不要包含特殊字符(如+、-、*、/、.、?、%、&、#等)。例如,定义一个名称为name的变量,值为fkk:
name=fkk
2. 查看和引用变量的值
通过在变量名称前添加前导符号"$",可以引用一个变量的值,而使用echo可以查看变量,在一条echo命令中可以查看多个变量值。若变量名称和紧跟其后的其他字符相混淆时,需要添加大括号"{}"将其括起来,否则无法确定正确的变量名称。例如要显示"fkk"和字符串"2.5":
echo ${fkk}2.5
#输出
fkk2.5
3. 变量赋值的特殊操作
除了"="还有一些特殊的赋值操作,可以更灵活地为变量赋值,以便适用于各种复杂的管理任务。
-
双引号(“):当要赋值的内容中包括空格时,必须以双引号括起来,此外,在双引号内,"$"符也会起作用,在单引号内,"$"会被视作变量值的一部分。
-
单引号('):若赋值的内容中包含$、"、\等具有特殊含义的字符时,要使用单括号括起来。在单引号内无法引用其它变量的值,任何字符均作为普通字符串看待,但赋值内容中包含单引号时,要使用"\"符号进行转义。
-
反撇号(`):反撇号允许将执行某个命令的屏幕输出结果赋值给变量,反括号括起来的内容必须是命令。例如,若要查找useradd命令程序的位置并列出其详细属性,可以执行以下操作:
ln -lh `which useradd`
#输出
-rwxr-x---. 1 root root 101K 8月 2 2011 /usr/sbin/useradd
上述操作相当于连续执行了两条命令——先通过which useradd命令查找出useradd命令的程序位置,然后根据查找结果列出文件属性。执行过程中,会用which useradd命令的输出结果替换整个反撇号范围。
- read命令
read命令用来提示用户输入信息,从而实现简单的交互过程。执行时将从标准输入设备(键盘)读入一行内容,并以空格为分隔符,将读入的各字段依次赋值给指定的变量(多余的内容赋值给最后一个变量)。可以在read命令后面使用"-p"选项设置提示信息。使用的格式为:
read [-p 提示信息] 变量名 #使用之后由用户输入变量的值
4. 设置变量的作用范围
默认新定义的变量只能在当前Shell环境中使用,称为局部变量。可以通过内部命令"export"将指定的变量导出为全局变量(也可以在导出的同时为变量赋值),可以同时指定多个变量作为参数,无需使用"$"符号,变量名之间以空格分割。使用格式为:
export 变量名[=变量值]
5. 数值变量的运算
在Base Shell环境中,只能进行简单的整数运算,不支持小数运算。整数值的运算主要通过内部命令"expr"进行,基本格式如下:(注意运算符和变量名之间必须有至少一个空格)
expr 变量1 运算符 变量2 [运算符 变量3]...
常用的几种运算符如下所示:
- +:加法运算;
- -:减法运算;
- \*:乘法运算,要搭配转义字符"\"使用;
- /:除法运算;
- % :求模运算,又称取余运算,用来计算数值相除后的余数。
若要将计算后的值赋值给其他变量,可以结合反撇号使用。
2.2 特殊的Shell变量
除了自定义的Shell变量外,在Linux系统和Bash Shell环境中还有一系列的特殊变量——环境变量、只读变量、位置变脸、预定义变量。下面分别进行介绍:
1. 环境变量
环境变量指的是出于运行需要而由 Linux系统提前创建的一类变量,主要用于设置用户的工作环境,包括用户宿主目录、命令査找路径、用户当前目录、登录终端等。环境变量的值由 Linux系统自动维护,会随着用户状态的改变而改变。使用"env"命令可以查看当前工作环境下的环境变量。
在Linux中,环境变量的全局配置文件为/etc/profile,在此文件中定义的变量作用于所有的用户。此外,每个用户还有自己的独立配置文件(~/.bash_profile)。
2. 只读变量
只读变量在赋值之后,不会再被改变。使用格式为:
readonly 变量名
unset 变量名 #用于删除只读变量
3. 位置变量
在脚本或函数执行中,有时需要使用来自外部输入的变量,而要使用这个变量,就需要位置变量,又称位置参数,使用"$1、$2....."表示。下面会演示使用该变量的方法(前提是脚本或函数需要外部输入的变量):
脚本:
执行脚本和执行后的结果:
在./sh.sh后面就是来自外部的输入,脚本内的”$1“和”$2“就是两个位置参数。
4. 预定义变量
预定义变量是由 Bash程序预先定义好的一类特殊变量,用户只能使用预定义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值。预定义变量使用“$”符号和另一个符号组合表示,较常用的几个预定义变量的含义如下:
- $#:表示命令行中位置参数的个数;
- $*:表示所有位置参数的内容;
- $?:表示前一条命令执行后的返回状态,返回值为0表示执行正确,返回任何非0的值均表示执行出现异常
- $0:表示当前执行的脚本或程序的名称。