shell脚本基础.md

shell

一:简介

shell相当于解释器,用于用户和内核之间的语言翻译

概念

将要执行的命令按顺序保存到另一个文本文件

给该文件可执行权限

可结合各种shell控制语句以完成更复杂的操作

应用场景

重复性操作

交互性任务

批量事务处理

服务运行状态监控

定时任务执行

缓冲与缓存的区别

缓冲用于写,缓存用于读

缓冲:减缓压力

image-20220620191507570

A的速度是1000每秒,B的速度是500每秒,相当于A工作一秒B工作两秒有这一秒的时间差,则会影响A的工作效率。当有了缓冲区之后,A把已完成的工作送到缓冲区,这样A、B双方的工作都不会被影响。高速到低速,高性能到低性能

缓存:例如看视频时出现的加载,进度条下方出现的灰色部分,是临时性加载到内存中的

shell的作用

image-20220620193650092

(1):用户借助shell,控制内核,内核依托硬件存在,硬件收到请求后,将用户所需要的资源输出

(2):用户启动程序,程序控制内核,内核再向系统硬件申请资源,硬件输出资源给用户

(3):shell和应用程序之间相互控制

shell的运行环境

shell的类型,常用的是—/bin/bash

image-20220620194729472

不同的shell具备了不同的功能,shell默认登陆时/bin/bash,流行的shell还有ash、bash、ksh、csh、zsh等,不同的shell有不同的功能和用途。想要修改时可以使用chmod -s或chsh -s来重新指定。

shell脚本

定义:就是把我们原来的命令或语句整合到一起,按照一定的顺序和逻辑放入文件中,然后通过这个程序文件去执行,我们称这样的程序文件为shell脚本。

初阶shell脚本功能

自动化完成软件的安装部署,如批量部署LAMP架构服务

自动化完成系统的管理,如批量添加用户

自动化完成备份,如数据库定时备份

自动化的分析处理,如网站访问量

shell脚本使用场景

在需要完成大量复杂、重复性的工作时,不需要再命令行重复执行命令,直接运行shell脚本即可,大大的节省了时间提高了效率

shell脚本的构成

第一行:#!/bin/bash(脚本申明,表示此行一下的代码语言时通过/bin/bash程序来执行)

除第一行之外以下行开头有#号都表示注释

image-20220623151619860

输出结果

image-20220623151756197

echo:可执行语句,用于输出 " " 之间的字符串。引号之间需要作为字符串才能被输出,单纯的字符串可以不用加引号就可以直接输出

image-20220623152255865

但是依然能输出

image-20220623152318077

但是如果有一些特殊符号,就需要用引号引起,将其变成字符串才能输出

image-20220623152610087

输出失败

image-20220623152546531

下面开始玩一个脚本

image-20220623153934229

查看内容

image-20220623154009838

输出

image-20220623154024556

查看下,创建成功

image-20220623154118814

脚本的执行方式

1:在当前路径下(相对路径和绝对路径)执行脚本

./first.sh或/home/first.sh

此方法需要有执行权限:chmod +x first.sh

2:sh、bash执行文件,

sh first.sh、bash first.sh

此方法不需要对脚本添加权限

(当脚本太长时,sh -x可以对脚本进行调试,可以把每一条执行的结果打出来)

3:source脚本文件路径

source first.sh

可以没有执行权限

source表示加载/刷新环境,所以会把脚本加载一遍,所以不需要执行权限

4:sh < first.sh或者 cat first.sh

(看看就好)

二:重定向与管道

重定向

用户通过操作系统处理信息的过程中,包含以下几类交互设备文件

标准输入(stdin):默认的设备是键盘,文件编号0,命令将从标准输入文件中读取在执行过程中需要的输入数据。

标准输出(stdout):默认的设备是显示器,文件编号1,命令将执行后的输出结果发送到标准输出文件。

标准错误(stderr):默认的设备是显示器,文件编号为2,命令将执行期间的各种错误信息发送到标准错误文件。

从键盘接收用户输入的各种命令字串,辅助控制信息,并将命令结果输出到屏幕上;如果命令执行错误,也会将错误信息反馈到屏幕上

image-20220623163313245

不管是标准性输还是标准性错误输出,都会以追加的方式写入系统日志中,分别写入标准输出日志和标准错误输出日志中。

重定向输出

将命令的正常输出结果保存到指定的文件中,而不是直接显示在显示屏上

符号

(>):当文件中没有信息时,会把信息注入进去,如果文件有内容,则表示将原有内容覆盖,把旧内容改为新内容

(>>):表示追加,文件有内容时,不会将原有内容覆盖,而是继续写入新内容

image-20220623164353438

覆盖

image-20220623165550838

追加

image-20220623165636632

重定向输入

重定向输入指的是命令中接收输入的路径由默认的键盘改为指定的文件,而不是等待从键盘输入。重定向输入使用“<”操作符。通过重定向输入可以使一些交互式操作过程能够通过读取文件来完成。

“<” 表示重定向输入,必须要文件才可以注入

image-20220623172737605

cat

从shell角度来说,也像是一种管道一样的东西,从这边输入什么,就会从那边输出什么,默认情况下,cat命令会接收标准输入设备(键盘)的输入,并显示到控制台,但如果用文件代替键盘作为输入设备,那么该命令会以指定的文件作为输入设备,并将文件中的内容读取并显示到控制台

“ cat > ”:以覆盖的方式标准性输出;“cat>>”:以追加的方式标准性输出;“cat <”:把什么东西交给cat去处理,例如“cat < 1.txt”:把1.txt交给cat处理;“cat <<”:表示分界符

image-20220624090824599

0可以任意,一般为EOF

可以把输入重定向和输出重定向结合使用,把从屏幕输出的内容保存到文件

image-20220624091953023

错误重定向 stderr(2)

错误重定向是指将执行命令过程中出现的错误信息(如选项或参数错误等)保存到指定的文件,而不是直接显示在屏幕上,错误重定向的符号:“2>”

作用:

在实际应用中,错误重定向可用来收集程序执行的错误信息,为排错提供依据,还可以将无关紧要的错误信息重定向到空文件/dev/null 中,以保持脚本输出的简洁

(/dev/null可以看做是一个黑洞,所有写入它的文件都会永远丢失,而且从那读取文件啥也没有)

使用“2>”操作符时,会像使用“>”操作符一样覆盖目标文件的内容,若要追加内同而不是覆盖,使用"2>>"

当命令输出的结果可能既包含标准输出信息,也会包含错误信息,可以使用操作符“>” "2>“将两类输出信息分别保存到不同的文件,也可以使用”&>"将两类输出信息保存到同一个文件

&>和>&

&表示混合

1>&2:把标准输出重定向到标准错误

2>&1:把标准错误重定向到标准输出

管道

连接两条指令,将前一个命令的结果输出给第二个命令来二次使用。

管道操作为不同命令之间的协同工作提供了一种工作机制,位于管道符号“|” 左侧的命令输出的结果,将作为右侧命令的输入在shell脚本应用中,管道操作通常用来过滤所需要的关键信息

相对于管道而言,管道左边属于标准性输入,管道右边属于标准性输出,把左边的结果集输出给右边

现在利用管道提取一下文件中的内容

先将信息复制到本地

image-20220624165158111

提取/bin/bash中以":"为分割的第六个字符

image-20220624165739441

小结

stdin 标准输入(0)

stdout 标准输出 (1)

stderr 标准错误输出 (2)

重定向输出/追加:“ > " " >>‘’

重定向输入 “<” 定义分界符 “<<”

1、cat配合的是重定向输出

cat原本功能是加载和读取,以标准方式,原本的输出位子在屏幕上;加了重定向之后,原本的输出位置发生了改变,可以理解为:对stdout输出到的位置进行改写,同时,重定向输出,还具有检测目标文件是否存在,是,则执行输出,否,则先创建文件,再输出到文件中

2、cat配合的是重定向输入

在cat原本的功能中,标准性的输入,是通过读取文件来捕捉、获取到的,现在重定向输入,所控制的方向在于stdin输入时,也就是:

cat读取–》文件》获取文件内容(stdin) 》输出到屏幕上(stdout)

重定向输入 “<” 读取文件内容,并给予cat(stdin) -> cat 获取–》输出到屏幕上(stdout)

3:写好shell脚本之后可以进行脚本的调试:

bash -x:显示执行过程,通常当脚本很长的时候便于定位

bash-n:检查语法,如果用vim编写的话,正常的话会变色

三:环境变量

环境变量指的是处于运行需要而由Linux系统提前创建的一类变量,主要用于设置用户的工作环境,包括用户目录、命令查找路径、用户当前目录、登陆终端等。环境变量的值由Linux系统自动维护,会随着用户状态的改变而改变。

env可以查看当前工作环境下的环境变量,LANG表示语言和字符集,PWD表示当前所在的工作目录,PATH表示命令搜索路径等、RANDOM表示随机数,会返回0-32767的整数、USER表示当前账户的账户名称等,一般都用于全大写定义,注意和自定义变量区分。

image-20220624173319838

定义一个变量 A=B:A就是变量名,B是变量值,echo输出A时,就相当于输出B

image-20220624173015458

PATH变量用于设置可执行程序的默认搜索路径,当仅指定文件名称来执行命令程序时,Linux系统将在PATH变量指定的目录范围查找对应的可执行文件,如果找不到则会提示”command not found“

image-20220628085103884

只读变量

shell中有一种特殊情况,已经设定,其值是不可以改变的,这种变量称为制度变量。在创建变量的时候可将其设置为只读属性,也可以将已存在的变量设置为只读属性,只读变量主要用于变量值不允许被修改的情况,它既不可以修改值也不能被删除

位置变量

当执行命令行操作时,第一个字段表示命令或脚本程序名,其余的字符串参数按照从左到右的顺序依次赋值给位置变量,位置变量也称为位置参数,使用$1、$1、$2、$3、$4…表示

image-20220630110610174

image-20220628090821963

在上图中,第一个脚本时$0,佳明是$1,屠明龙是$2,好吃是$3,他们之间是利用空格进行分割,

image-20220628091010324

上图中,屠明龙和好吃之间加了逗号,于是他们就成为了一个整体,即“屠明龙,好吃”是$2

预定义变量

预定义变量是由Bash程序预先预定义变量定义好的一类特殊变量,用户只能使用使用预定义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值,预定义变量使用“$”符号和另一个符号组合表示

$#:表示命令行中位置参数的个数

$*:表示所有位置参数的内容,这些内容当作一个整体

$@:表示列出所有位置参数,但是是以单个的形式的列出

$?:表示前一条命令执行后的返回状态,返回值为0表示执行正确,返回非0值表示执行出现异常

$0:表示当前执行的脚本或程序的名称

$$:表示返回当前进程的进程号

$!:返回最后一个后台进程的进程号

环境变量

shell变量及赋值

shell的变量

变量是用来临时保存数据的,并且该诗句是可以变化的,任何语言都离不开变量,如果内容需要多次使用并会重读出现,这样就可以使用变量了,如果需要修改直接修改变变量就可以了

常见shell的变量的类型包括自定义变量、环境变量、只读变量,位置变量,预定义变量

变量什么时候适用

1、特殊变量

2、自定义变量

2.1:在脚本中频繁出现的主机名,IP、PATH(路径,尤其是工作路径)

2.2:路径过长的

自定义变量

Bash中的变量操作相对比较简单,在定义一个变量时,一般不需要提前进行声明,而是直接指定变量名称并赋值

格式:变量名=变量值

变量名:临时存放数据的地方

变量名:临时的可以变化的数据

(A=B) 等号两边没有空格。变量名需以字母或下划线开头,名称中不要包含特殊字符

用echo查看和引用变量的值,用过在变量前面加$,可以引用一个变量的值,使用echo命令可以查看变量,可以在一条echo命令中同时查看多个变量值。在同一个环境中,如果定义了同一个变量名,那么后一个变量值会覆盖前一个变量值

image-20220701145937821

当变量名容易和紧跟其后的其他字符相混淆时,需要加 “ {} ”将其括起来,否则无法确定正确的变量名称。对于未定义的变量,将显示空值

echo

-n不换行输出

-e输出转义字符

常见的转义符有

\c不换行输出,但后面没有字符的情况下,作用相当于echo -n

\n换行

\t转移后表示插入tab,即制表符

双引号“”

主要起界定字符串的作用,特别是当要赋值的内容中包含空格时,必须以双引号括起来:其他情况下双引号通常可以省略

单引号‘’

当要赋值的内容中包含$、“、\、等具有特殊含义的字符时,应使用单引号括起来,在单引号的范围内,将无法引用其他变量的值,任何字符均作为普通字符看待,输出什么就显示什么,但赋值的内容中包含单引号,需使用反斜杠进行转义,以免冲突。

反撇号`

主要用于命令替换,允许将执行耨个命令的屏幕输出结果赋值给变量(必须时能够执行的命令行,否则会出错)

反撇号不可以嵌套,可以用$()来代替反撇号操作,以解决嵌套的问题

交互式定义变量

read :给变量赋值

image-20220701163636735

变量赋值

1:直接变量名=变量值

2:引用环境中的变量

3:通过定义一段可正确执行的指令,来做赋值处理

4:交互式赋值

-p:提示用户的信息

-n:定义字符数

-s:不显示用户输入的内容,常用于输入密码

-t:定义超时时间,超过了多长时间没输自动退出

变量的作用范围

默认情况下,新定义的变量只在当前的shell环境中有效,因此称为局部变量,当进入子程序或新的子shell化境时,局部变量将无法使用

ecport:

为了使用户定义的变量在所有的子shell环境中能够继续使用,较少重复设置工作,可以通过内部命令export将指定的变量导出为全局变量。用户可以同时支持性多个变量名称作为参数,变量名之间以空格分割,在使用export导出全局变量时,也可以为变量进行赋值,这样在新定义全局变量时就不需要提前进行赋值了

数值变量的运算及特殊变量

在bash shell环境中,只能进行简单的整数运算。不支持小数运算

整数值的运算主要通过内部命令expr进行

运算符与变量之间必须至少一个空格

运算内容:加(+)减(-)乘(*)除(/)取余(%)

运算符号 ( ( ) ) 和 (())和 [ ]

运算命令:expr和let

运算工具:bc

expr

image-20220704090559604

不仅支持常量还支持变量的运算

image-20220704091053403

let运算

let运算可以改变变量本身的值,但是不显示结果,需要echo,其他的运算方式可以做运算但不改变变量本身的值

”;“分号分割。let是给变量赋值的

image-20220704091720905

image-20220704091937265

练习:求圆的面积

image-20220704095155834

image-20220704095206389

shell条件语句
一:条件测试操作

1.1文件测试

想要shell脚本程序具备一定的只能,面临的第一个问题就是如何区分不同的情况一确定执行何种操作。

shell环境根据命令执行后的返回值($?)来判断是否执行成功,当返回值为0时表示成功,否则表示失败或异常(非0),使用专门的测试工具–test 命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值为0时表示条件成立)

语法格式:

格式1 test 条件表达式

格式2 [ 条件表达式 ] 或 [[ 条件表达式 ]]

文件测试指的是根据给定的路径名称,判断对应的是文件还是目录,或者判断文件是否可读可写可执行。文件测试的常见操作选项如下,使用时将测试对象放在操作选项之后即可。

-d:测试是否为目录

-e:测试目录或文件是否存在

-f:测试是否为文件

-r:测试当前用户是否有权限读取

-w:测试当前用户是否有权限写入

-x:测试是否设置有可执行权限

-b:测试是否为设备文件

-c:测试是否为字符设备文件

-s:测试存在却文件大小为空

-L:测试是否为链接文件

!:匹配后的结果取反,除了匹配到的所有取反

执行条件测试操纵后,通过预定义变量$?可以获得测试命令的返回值,从而判断该条件是否成立,

image-20220704100922974

可以看到当前有个目录为脚本,当我使用test -d时,返回值时0,代表这是个目录

当我test -f时,判断是否是文件,不是文件,所以返回值是1

image-20220704101446376

还可以加” ! “取反

1.2:整数值比较

整数值比较指的是根据给定的两个整数值,判断第一个数与第二个数的关系,如是否大于,等于,小于第二个数。整数值比较的常用操作如下,使用时将操作选项放在要比较的两个整数之间

常用测试操作符

-eq:A等于B =

-ne:A不等于B !=

-gt:A大于B >

-lt:A小于B <

-le:A小于或等于B <=

-ge:A大于或等于B >=

小结

条件判断

test 选项 参数 (PATH路径)

[ 选项 条件表达式 比较 参数 ]

1.3:字符串比较

字符串通常用来检查用户输入,系统环境是否满足条件,在提供交互式操作的shell脚本中,也可以用来判断用户输入的位置参数是否符合要求。字符串比较的常用操作选项如下

= 第一个字符串与第二个字符串相同。

!=第一个字符串与第二个字符串不相同

-z 检查字符串是否为空,对于未定义或赋予控制的变量将视为空串

image-20220704104046527

1.4 逻辑测试

逻辑测试指的是判断两个或多个条件之间的依赖关系。当系统任务取决于多个不同的条件时,根据这些条件是否同时成立或者只要有其中一个成立的情况,需要有一个测试的过程。

常用的逻辑测试操作如下,使用时放在不同的测试语句或命令之间

&& 逻辑与,表示而且,只有当前两个条件都成立时,整个测试命令的返回值才为0,使用test命令测试时,&&可改为-a

|| 逻辑或,表示或者,只要前后两个条件中有哟个成立,整个测试命令返回值为0,是同test测试时,可改为-o

! 逻辑否,表示不,只有当指定的条件不成立时,整个测试命令返回值才为0

image-20220704105001023

1:判断两个条件都成立时,输出yes

2:判断两个条件其中一个成立时,输出yes

3:判断两个条件其中一个成立时(另一个不成立),输出yes

4:判断两个条件都成立时(其中一个不成立),输出yes,可以看到返回值为1,表示不正确,无法输出yes

四:if判断

4.1:单分支判断

单分支if语句:对于单分支的选择结构,只有在条件成立时才会执行相应的代码,否则不执行任何操作

即成立和不成立。

image-20220704110016138

image-20220704110359169

if 条件测试操作

then

命令序列

fi #注意后面有个结尾,开头结尾要凑成一对否则会报语法错误

例:

image-20220704111055494

image-20220704111114870

4.2:双分支判断

双分支if语句只是在单分支的基础上针对”条件不成立“情况执行的另一种操作,而不是做事不管的不执行任何操作

image-20220704114000340

image-20220704110825300

image-20220704110840884

image-20220704112844495

image-20220704112816915

4.3:多分支判断

与单分支,双分支相比,多分支语句的节后能够根据多个互斥的条件分别执行不同的操作

image-20220704113726585

image-20220704113745183

4.4:嵌套if语句

例判断httpd服务是否启动

判断是否启动

如果启动—输出已启动

如果没启动—判断是否安装-----如果安装-----启动

​ 如果每有安装----------------安装-------------成功-------------启动

​ 不成功------------报错

image-20220704114410085

case语句

case

语句可以使脚本程序的结构更加清晰,层次丰明,常用于服务的启动重启,停止的脚本,有的服务不提供这种控制脚本,需要用case语句编写

case语句主要适用于以下情况:某个变量存在多种取值,需要对其中的每一种取值分别执行不同的命令序列。这中情况与多分支的if语句非常相似,只不过if语句需要判断多个不同的条件,而case语句只是判断一个变量的不同取值

格式:

case 变量值 in

模式1)

命令序列

;;

模式2)

命令序列

;;

*)

默认命令序列

esac

case行尾必须 为单词”in“,每一个魔兽必须以右括号)结束,双分号表示命令序列的结束。

模式字符串中,可以用方括号表示一个连续的范围,如[ 0-9 ],还可以用竖杠表示或,A|B

执行流程

首先使用变量与模式1进行比较,若取值相同则执行模式1后的命令序列,知道遇见双分号,跳转至esac,表示结束分支;如果与1不匹配,则继续与模式2进行比较,若取值相同则执行模式2。如果匹配不到任何值,则会执行默认模式*,后的命令序列。

五:循环

5.1:for循环

在实际工作中,经常会遇到某项任务需要多次执行的情况,而每次执行时仅仅是处理的对象不一样,其他命令相同。使用简单的if语句已经难以满足要求,而顺序编写全部代码更是繁琐。

for循环语句

5.1.1:语法结构

(1)列表循环

(2)不带列表循环

(3)类C风格的循环

遍历

for 变量名 in {list}

do

​ command

done

for i in {a…c}

do

​ echo $i

image-20220704121931709

image-20220704121954083

done

for i in {1…5}

do

​ echo $i

done

image-20220704122105460

image-20220704122117348

for i in seq 5

do

echo $i

done

image-20220704122641649

image-20220704122658973

遍历

image-20220704130327242

image-20220704130338462

将a b c 这三个值赋予给i,并且输出1 2 3

for循环中for i in {list}使用方式

i为自定义变量名

in首先将in之后的内容定义为一个list,然后循环对列表中的元素进行取值,并且每次取值后赋予给变量i

list列表:1,定义循环次数,2,每个元素,在每次循环时都会被一次取出,然后赋值给变量名

以do为分割

然后command:定义每次循环时,要输出的指令

done结束

image-20220705091302000

image-20220705091246571

例2

image-20220705094023442

image-20220705094006095

for ((i=1;i<=10;i++))

第一个i的意思是定义初始值,第二个i是定义了循环的次数,第三个i的意思是加1,也可以写成i+=1,同样的,i–。

5.2 while循环

5.2.1:语法结构(3种)

while true:死循环

while循环一般用于有条件判断的循环,若判断条件为真,则进入循环,当条件为假就跳出循环

while 表达式

do

command

done

例:打印1-5

image-20220705100605649

image-20220705100535453

例2

image-20220705101401753

image-20220705101345912

循环控制语句

for循环一般会搭配条件判断语句和流程控制语句一起执行,那么就会出现需要跳过循环和终止循环的情况,控制循环的命令有以下三个

continue:继续,但不会执行循环一下的代码,开始重新开始下一次循环

例:打印1-5,不打印3

image-20220705114336120

break:打断,退出本次循环,加-n 数字,表示结束哪层循环

image-20220705114615656

image-20220705114523251

exit:退出脚本

image-20220705115332964

image-20220705115316212

直接跳出程序,不会输出hi

如果用sourse去加载这个脚本,相当于刷新了这个环境,所以会直接退出终端,建议不要轻易尝试

5.3:until循环

until false 死循环

image-20220705114305610

image-20220705114247729

跟while相反,条件为假进入循环,条件为真退出循环

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值