Linux学习(三)

vim编辑器与shell脚本

vim文本编辑器

在linux系统中一切都是文件,而配置一个服务就是在修改其配置文件的参数

vim编辑器中设置了三种模式 命令模式 末行模式 编辑模式,每种模式分别又支持多种不同的命令快捷键,这大大提高了工作效率.而且在用户习惯之后会感觉相当顺手.

  • 命令模式:控制光标移动,可以对文本进行复制 粘贴 删除和查找等工作
  • 输入模式:正常的文本录入
  • 末行模式:保存和退出文档,以及设置编辑环境

image-20220322185811678

每次运行vim编辑器时默认进入命令模式,此时需要切换到输入模式后再进行文档的编辑工作.而每次在编写完文档后需要先返回命令模式,然后再进入末行模式,执行文档的保存或者退出操作.在vim中,无法直接从输入模式切换到末行模式,vim编辑器中内置的命令有成百上千种用法

命令模式中最常用的一些命令

命令 作用
dd 删除(剪切)光标所在整行
5dd 删除(剪切)从光标处开始的5行
yy 复制光标所在整行
5yy 复制从光标处开始的5行
n 显示搜索命令定位到的下一个字符串
N 显示搜索命令定位到的上一个字符串
u 撤销上一步的操作
p 将之前删除(dd)或复制(yy)过的数据粘贴到光标后面

末行模式主要用于保存或退出文件,以及设置vim编辑器的工作环境,还可以让用户执行外部的linux命令或跳转到所编写文档的特定行数,像要切换到末行模式,在命令模式中输入一个冒号就可以了

末行模式中最常用的一些命令

命令 作用
:w 保存
:q 退出
:q! 强制退出(放弃对文档的修改内容)
:wq! 强制保存退出
:set nu 显示行号
:set nonu 不显示行号
:命令 执行该命令
:整数 跳转到该行
:s/one/two 将当前光标所在行的第一个one替换成two
:s/one/two/g 将当前光标所在行的所有one替换成two
:%s/one/two/g 将全文中的所有one替换成two
?字符串 在文本中从下至上搜索该字符串
/字符串 在文本中从上至下搜索该字符串

用vim编写简单文档

我的系统没有先下一个

sudo yum install -y vim

如果存在该文档,则是打开它,如果不存在,则是创建一个临时输入文件

image-20220322192350259

打开之后默认进入的是vim编辑器的命令模式,此时只能执行该模式下的命令,而不能随意输入文本内容,我们需要切换到输入模式才可以编写该文档

可以分别使用 a i o 三个键从命令模式切换到输入模式,其中a键与i键分别是在光标后面一位和光标当前位置切换到输入模式,而o键则是在光标下面在创建一个空行,此时可以敲击a键进入到编辑器的输入模式

image-20220322192713731

进入到输入模式后,可以随意输入文本内容,vim编辑器不会把您输入的文本内容当做命令而执行

image-20220322192816517

在编写完成之后,想要保存并退出,必须先敲击键盘上的esc键从输入模式返回命令模式,再输入”wq!”切换到末行模式才能完成保存并退出的操作

当在末行模式中输入”:wq!”命令时,就意味着强制保存并退出文档,然后就可以使用cat命令查看该文档的内容了

image-20220322193137900

继续编辑这个文件,因为要在原有文本内容下面追加内容,所以在命令模式中敲击o键进入模式更高效

编写shell脚本

可以将shell终端解释器当成是人与计算机硬件之间的翻译官,它作为用户和系统内部的通讯媒介,除了能够使用支持各种变量与参数,还提供了诸如循环 分支等高级变成语言才有的控制结构特性.想要正确使用shell中的这些功能特性,准确下达命令尤为中要,shell脚本命令的工作方式有下面两种.

  • 交互式(interactive):用户每输入一条命令就立即执行
  • 批处理(batch):由用户事先编写好的一个完整的shell脚本,shell会一次性执行脚本中诸多的命令

在shell脚本中不仅会用到之前的linux命令以及正则表达式 管道符 数据流重定向等语法规则,还需要把内部功能模块化后通过逻辑语句进行处理,最终形成日常所见的shell脚本

通过查看shell变量可以发现,当前系统已经默认使用bash作为命令行终端解释器了

image-20220322201356549

编写简单的脚本

如果想查看当前所在工作路径并列出当前目录下所有的文件及属性信息,实现这个功能的脚本应该类似于下面这样

image-20220322201953373

加上.sh后缀表示是一个脚本文件

在上面这个wanan.sh脚本中实际上出现了三种不同的元素:第一行的脚本声明(#!)用来告诉系统使用哪一种shell解释器来执行该脚本,第二行的注释信息(#)是对脚本功能和某些命令的介绍信息,使得自己或他人在日后看到这个脚本内容时,可以快速知道该脚本的作用或一些警告信息,第三 四行的可执行语句也就是我们平时执行的linux命令了

image-20220322202427864

接收用户的参数

但是像上面的脚本程序只能执行一些预先定义好的功能,未免太过死板,为了让脚本程序能更好的满足用户的一些实时需求,以便灵活完成工作,必须要让脚本程序能够像之前执行命令时那样,接收用户输入的参数

image-20220322202722657

这就意味着命令不仅需要能够接收用户输入的内容,还要有能力进行判断区别,根据不同的输入调用不同的功能

其实,linux系统中的shell脚本语言早就考虑到了这些,已经内设了用于接收参数的变量,变量之间使用空格间隔,例如,$0对应的是当前shell脚本程序的名称,$#对应的是总共有几个参数,$*对应的是所有位置的参数值,$?对应的是显示上一次命令的执行返回值,而$1 $2 $3…则分别对应着第n个位置的参数值

image-20220322203152198

image-20220322203407520

image-20220322203438427

判断用户的参数

系统在执行mkdir命令时会判断用户输入的信息,即判断用户指定的文件夹名称是否已经存在,如果存在则提示错误,反之则自动创建.shell脚本中的条件测试语法可以判断表达式是否成立,若条件成立则返回数字0,否则便返回非零值.条件测试语法 执行格式如下,条件表达式两边均应有一个空格

image-20220322203843765

按照测试对象来划分,条件测试语句可以分为4种

  • 文件测试语句
  • 逻辑测试语句
  • 整数值比较语句
  • 字符串比较语句

文件测试即使用指定条件来判断文件是否存在或权限是否满足等情况的运算符

文件测试所用的参数

操作符 作用
-d 测试文件是否为目录类型
-e 测试文件是否存在
-f 判断是否为一般文件
-r 测试当前用户是否有权限读取
-w 测试当前用户是否有权限写入
-x 测试当前用户是否有权限执行

下面使用文件测试语句来判断/etc/fstab是否为一个目录行文件,然后通过shell解释器的内置$?变量显示上一条命令执行后的返回值.如果返回值是0则目录存在,如果返回值是非零的值,则意味着它不是目录,或者不存在这个目录

image-20220322204328968

在使用文件测试语句来判断/etc/fstab是否为一般文件,如果返回值为0,代表文件存在,且为一般文件

image-20220322204454524

判断和查询一定要敲两次吗

逻辑语句用于对测试结果进行逻辑分析,根据测试结果可以实现不同的效果,例如在shell终端中逻辑”与”的运算符号是&& 他表示前面的命令执行成功后才会执行它后面的命令,因此可以用来判断/dev/cdrom文件是否存在,若存在则输出exist字样

image-20220322204830660

除了逻辑与外还有逻辑或,他在linux系统中的运算符为|| 代表当前命令执行失败后才会执行它后面的命令,因此可以用来结合系统环境变量USER来判断当前用户是否非管理员身份

image-20220322205326783

第三种逻辑语句是非,在linux系统中的运算符号是一个叹号(!) 它表示把条件测试中的判断结果取相反值,也就是说,如果原本测试结果是正确的,则将其变成错误的,原本测试错误的结果,则将其变成正确的

image-20220322205600378

叹号应该放在判断语句的前面,代表对整个的测试语句进行取反值的操作,而不应该写成”$USER != root 因为 != 代表的是不等于符号≠,尽管执行效果一样,但缺少了逻辑关系

  • &&是逻辑与,只有当前面的语句执行成功的时候才会执行后面的语句
  • ||是逻辑或,只有当前面的语句执行失败的时候才会执行后面的语句
  • !是逻辑非,代表对逻辑测试结果取反值,之前若为正确则变成错误,若为错误则变成正确

整数比较运算符仅是对数字的操作,不能将数字与字符串 文件等内容一起操作,而且不能像当然的使用日常生活中的等号 大于号 小于号来进行判断,因为等号与复制命令符冲突,大于号和小于号分别与输出重定向命令符合输入重定向命令符冲突,因此一定要使用规范的整数比较运算符来进行操作

可用的整数比较运算符

操作符 作用
-eq 是否等于
-ne 是否不等于
-gt 是否大于
-lt 是否小于
-le 是否等于或小于
-ge 是否大于或等于

free命令可以用来获取当前系统正在使用及可以使用的内存量信息,先使用free -m命令查看内存使用量情况 ,然后通过 grep men 命令过出剩余内存量的行,在用awk ‘{print $4}’命令值保留第四列

image-20220322211215956

如果想把这个命令写入到shell脚本中,那么建议把输出结果赋值给一个变量,以方便其他命令进行调用

image-20220322211425345

上面用于获取内存可用量的命令,接下来我们使用整数运算符来判断内存可用量的值是否小于1024,若小于则会提示 lnsufficient Memory (内存不足) 的字样

image-20220322211734881

字符串比较语句用来判断测试字符串是否为空值,或者两个字符串是否相同, 它通常用来判断某个变量是否被定义(即内容为空值)

常见的字符串比较运算符

操作符 作用
= 比较字符串内容是否相同
!= 比较字符串内容是否不同
-z 判断字符串内容是否为空

image-20220322211927354

当用于保存当前语系的环境变量值LANG不是英语时,则会满足逻辑测试条件并输出

image-20220322212138817

流程控制语句

if条件测试语句

if条件测试语句可以让脚本根据实际情况自动执行相应的命令,if条件测试语句的单分支结构由if then fi关键词组成,而且只在条件成立后才执行预设的命令

image-20220322212455541

下面使用单分支的if条件语句俩判断/media/cdrom目录是否存在,若不存在就创建这个目录,反之则结束条件判断和整个shell脚本的执行

image-20220322212746118

这里使用bash脚本名称的方式来执行脚本,在正常情况下顺利执行完脚本文件没有任何输出信息,但是可以使用ls命令验证/media/cdrom目录是否创建成功

下面使用双分支的if语句来验证某台主机是否在线,然后根据返回值的结果,要么显示主机在线,要么显示主句不在线信息.这里的脚本主要使用ping命令来测试与对方主机的网络连通性,而linux系统中的ping命令栏不像windows一样尝试四次就结束,因此为了避免用户等待时间过长,需要通过-c参数来规定尝试的次数,并使用-i参数定义每个数据包的发送间隔,以及使用-W参数定义等待超过时间

image-20220323111708471

$? 的作用是显示上一次命令的执行返回值.若前面那条语句执行成功,则$?变量会显示数字0 反之则显示一个非零的数字.一次可以用整数比较运算符来判断$?变量是否为0 从而获知那条语句的最终判断情况

image-20220323124721697

if条件语句的多分支结构由if then else fi 关键词组成,它进行多次条件判断,这多次判断中的任何一项在匹配成功后都会执行相应预设的命令,相当于口语的如果 那么 如果那么.

在linux系统中,read是用来读取用户输入信息的命令,能够把接受到的用户输入信息赋给后面的指定变量,-p参数用于向用户显示一些提示信息

image-20220323124926187

image-20220323125337033

image-20220323125428594

for条件循环语句

for循环语句允许脚本一次性读取多个信息,然后逐一对信息进行操作处理,当要处理的数据有范围时,使用for循环语句就在合适不过

image-20220323125622957

image-20220323125643672

/dev/null是一个被称为linux黑洞的文件,把输入信息重定向到这个文件等同于删除数据,类似于没有回收功能的垃圾箱,可以让用户的屏幕保持整洁

执行批量创建用户的Shell脚本addusers.sh,在输入为账户设定的密码后将由脚本自动检查并创建这些账户。由于已经将多余的信息通过输出重定向符转移到了/dev/null黑洞文件中,因此在正常情况下屏幕窗口除了“用户账户创建成功”(Create success)的提示后不会有其他内容。

在Linux系统中,/etc/passwd是用来保存用户账户信息的文件。如果想确认这个脚本是否成功创建了用户账户,可以打开这个文件,看其中是否有这些新创建的用户信息。

image-20220323125901488

while条件循环语句

while条件循环语句是一种让脚本根据某些条件来重复执行命令的语句,他的循环结果往往在执行前不确定最终执行的次数,完全不同于for循环中有目标有范围的使用场景.

image-20220323130101126

image-20220323130237839

case条件测试语句

case条件测试语句和switch语句的功能非常相似!case语句是在多个范围内匹配数据,若匹配成功则执行相关命令并结束整个条件测试;如果数据不在所列出的范围内,则会去执行星号(*)中所定义的默认命令。

image-20220323130227986

计划任务服务程序

计划任务分为一次性计划任务与长期性计划任务

  • 一次性计划任务:今晚23:30重启网站服务
  • 长期性计划任务:每周一的凌晨3:25把/home/wwwroot目录打包备份到backup.tar.gz

顾名思义,一次性计划任务只执行一次,一般用于临时的工作需求.可以使用at命令实现这种功能,只需要写成 at 时间 的形式就行.如果想要查看已经设置好的但未执行的一次性计划任务,可以使用at -l 命令;要想将其删除,可以使用 “atrm任务序号”

at命令的参数及其作用

参数 作用
-f 指定包含命令的任务文件
-q 指定新任务名称
-l 显示待执行任务列表
-d 删除指定待执行任务
-m 任务执行后给用户发邮件

在使用at命令来设置一次性计划任务时默认采用的是交互式方法.

image-20220323130900907

在输入完成systemctl restart httpd之后按下ctrl 加上 d来结束编写计划任务

image-20220323131012997

也可以使用管道符达到非交互式的方式创建计划一次性任务的目的

image-20220323133521329

image-20220323134108264

可以使用atrm命令轻松删除其中一条

image-20220323134152695

这里还有一种特殊场景把一计划任务写入到shell脚本中,当用户激活该脚本后再开始倒计时执行,而不是像上面那样在固定的时间进行

一般会使用at now +2 MINUTE 的方式进行操作,这表示2分钟(MINUTE)后执行这个任务,也可以将其代替为小时(HOUR) 日(DAY) 月(MONTH)

image-20220323134306764

还有些时候,我们希望linux系统能都周期性的有规律的执行某些具体的任务,那么linux系统中默认弃用crond服务简直在合适不过.创建编辑计划任务的命令时crontab -e,查看当前计划任务的命令为crontab -l,删除某条计划任务的命令为crontab -r.另外如果是管理员身份登录,可以在crontab命令中加上-u 参数来编辑他人的计划任务.

crontab命令中的参数及其作用

参数 作用
-e 编辑计划任务
-u 指定用户名称
-l 列出任务列表
-r 删除计划任务

分 时 日 月 星期 命令,这是使用crond服务设置任务的参数格式,如果有些字段没有被设置,则需要使用星号(*)占位

image-20220323134842478

使用crond设置任务的参数字段说明

字段 说明
分钟 取值为0~59的整数
小时 取值为0~23的任意整数
日期 取值为1~31的任意整数
月份 取值为1~12的任意整数
星期 取值为0~7的任意整数,其中0与7均为星期日
命令 要执行的命令或程序脚本

假设在每周一 三 五的凌晨3:25,都需要使用tar命令把某个网站的数据目录进行打包处理,使其作为一个备份文件.我们可以使用crontab -e命令来创建计划任务,为自己创建计划任务时无需使用-u参数.crontab -e命令的具体实现效果和crontab -l命令的结果

image-20220323135225649

除了使用逗号(,)来分别表示多个时间段,例如”8,9,12”表示8月,9月,12月.还可以使用减号(-)来表示一段连续的时间周期,(例如字段”日”的取值为”12-15”,则表示每月的12-15日).还可以用除号(/)表示执行任务的间隔时间(例如”*/2”表示没间隔两分钟执行一次任务)

如果在crond服务中需要同时包含多条计划任务的命令语句,应该每行仅写一条.例如我们在添加一条计划任务,它的功能是每周一至周五的凌晨一点自动清空/tmp目录中的所有文件.尤其需要注意的是,在crond服务的计划任务参数中,所有命令一定要用绝对路径的方式来写,如果不知道绝对路径,请用whereis命令来进行查询.rm命令的路径为下面输出信息中的加粗部分

image-20220323135959125

  • 在crond服务的配置参数中,一般会像shell脚本那样以#号开头写上注释信息,这样在日后回顾这段命令代码时可以快速了解其功能需求以及编写人员等重要信息.
  • 计划任务中的”分”字段必须有数值,绝对不能为空或者是(*)号,而”日”和”星期”字段不能同时使用,否则就会发生冲突

删除crond计划任务使用crondtab -e命令进入编辑界面,删除里面的文本信息即可.也可以使用crondtab -r命令直接进行删除

image-20220323140419505