第4章 Vim编辑器与Shell命令脚本

4.1 Vim文本编辑器

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

Vim编辑器中设置了三种模式——命令模式、末行模式和编辑模式:

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

第4章 Vim编辑器与Shell命令脚本_第1张图片
在每次运行Vim编辑器时,默认进入命令模式,此时需要先切换到输入模式后再进行文档编写工作,而每次在编写完文档后需要先返回命令模式,然后再进入末行模式,执行文档的保存或退出操作。
表4-1总结了在命令模式中最常用的一些命令:

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

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

命令 作用
: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
?字符串 在文本中上至下搜索该字符串
/字符串 在文本中上至下搜索该字符串

可以分别使用a、i、o三个键从命令模式切换到输入模式。其中,a键与i键分别是在光标后面一位和光标当前位置切换到输入模式,而o键则是在光标的下面再创建一个空行,此时可敲击a键进入到编辑器的输入模式。
为了便于在局域网中查找某台特定的主机,或者对主机进行区分,除了要有IP地址外,还要为主机配置一个主机名,主机之间可以通过这个类似于域名的名称来相互访问。在Linux系统中,主机名大多保存在/etc/hostname文件中,hostname命令用于查看当前的主机名称,但有时主机名称的改变不会立即同步到系统中,所以如果发现修改完成后还显示原来的主机名称,可重启虚拟机后再行查看。

配置网卡信息

在Linux系统中,一切都是文件,因此配置网络服务的工作其实就是在编辑网卡配置文件。

编写Shell脚本

可以将Shell终端解释器当作人与计算机硬件之间的“翻译官”,它作为用户与Linux系统内部的通信媒介,除了能够支持各种变量与参数外,还提供了诸如循环、分支等高级编程语言才有的控制结构特性。

  • Shell脚本命令的工作方式有两种:交互式和批处理。
  1. 交互式(Interactive):用户每输入一条命令就立即执行。
  2. 批处理(Batch):由用户事先编写好一个完整的Shell脚本,Shell会一次性执行脚本中诸多的命令。
    查看SHELL变量可以发现当前系统已经默认使用Bash作为命令行终端解释器了:
[root@linuxprobe ~]# echo $SHELL
/bin/bash

编写简单的脚本

[root@linuxprobe ~]# vim example.sh
#!/bin/bash
#For Example BY linuxprobe.com
pwd
ls -al

Shell脚本文件的名称可以任意,但为了避免被误以为是普通文件,建议将.sh后缀加上,以表示是一个脚本文件。
第一行的脚本声明(#!)用来告诉系统使用哪种Shell解释器来执行该脚本;第二行的注释信息(#)是对脚本功能和某些命令的介绍信息,使得自己或他人在日后看到这个脚本内容时,可以快速知道该脚本的作用或一些警告信息;第三、四行的可执行语句也就是我们平时执行的Linux命令了。

[root@linuxprobe ~]# bash example.sh
/root/Desktop
total 8
drwxr-xr-x.2 root root 23 Jul 23 17:31 .
dr-xr-x——.14 root root 4096 Jul 23 17:31 ..
-rwxr——r——.1 root root 55 Jul 23 17:31 example.sh

除了上面用bash解释器命令直接运行Shell脚本文件外,第二种运行脚本程序的方法是通过输入完整路径的方式来执行。但默认会因为权限不足而提示报错信息,此时只需要为脚本文件增加执行权限即可。

[root@linuxprobe ~]# ./example.sh
bash:./Example.sh:Permission denied
[root@linuxprobe ~]# chmod u+x example.sh
[root@linuxprobe ~]# ./example.sh
/root/Desktop
total 8
drwxr-xr-x.2 root root 23 Jul 23 17:31 .

接收用户的参数

Linux系统中的Shell脚本语言早就考虑到了这些,已经内设了用于接收参数的变量,变量之间可以使用空格间隔。

  1. $0对应的是当前Shell脚本程序的名称
  2. $#对应的是总共有几个参数
  3. $*对应的是所有位置的参数值
  4. $?对应的是显示上一次命令的执行返回值
  5. $1、$2、$3……则分别对应着第N个位置的参数值
    第4章 Vim编辑器与Shell命令脚本_第2张图片

例:

[root@linuxprobe ~]# vim example.sh
#!/bin/bash
echo "当前脚本名称为$0"
echo "总共有$#个参数,分别是$*。"
echo "第1个参数为$1,第5个为$5。"
[root@linuxprobe ~]# sh example.sh one two three four five six
当前脚本名称为example.sh
总共有6个参数,分别是one two three four five six。
第1个参数为one,第5个为five。

判断用户的参数

Shell脚本中的条件测试语法可以判断表达式是否成立,若条件成立则返回数字0,否则便返回其他随机数值。切记,条件表达式两边均应有一个空格。
第4章 Vim编辑器与Shell命令脚本_第3张图片
按照测试对象来划分,条件测试语句可以分为4种:

  1. 文件测试语句;
  2. 逻辑测试语句;
  3. 整数值比较语句;
  4. 字符串比较语句。

文件测试即使用指定条件来判断文件是否存在或权限是否满足等情况的运算符,具体的参数如表4-3所示:

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

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

[root@linuxprobe ~]# [ -d /etc/fstab ]
[root@linuxprobe ~]# echo $?
1

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

[root@linuxprobe ~]# [ -f /etc/fstab ]
[root@linuxprobe ~]# echo $?
0

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

[root@linuxprobe ~]# [ -e /dev/cdrom ] && echo "Exist"
Exist

除了逻辑“”外,还有逻辑“”,它在Linux系统中的运算符号为||,表示当前面的命令执行失败后才会执行它后面的命令

root@linuxprobe ~]# echo $USER
root
[root@linuxprobe ~]# [ $USER = root ] || echo "user"
[root@linuxprobe ~]# su - linuxprobe
[linuxprobe@linuxprobe ~]$ [ $USER = root ] || echo "user"
user

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

整数比较运算符 仅是对数字的操作,不能将数字与字符串、文件等内容一起操作,而且不能想当然地使用日常生活中的等号、大于号、小于号等来判断。因为等号与赋值命令符冲突,大于号和小于号分别与输出重定向命令符和输入重定向命令符冲突。因此一定要使用规范的整数比较运算符来进行操作。可用的整数比较运算符如表4-4所示:

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

字符串比较语句 用于判断测试字符串是否为空值,或两个字符串是否相同。它经常用来判断某个变量是否未被定义(即内容为空值),字符串比较中常见的运算符如表4-5所示:

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

接下来通过判断String变量是否为空值,进而判断是否定义了这个变量:

[root@linuxprobe ~]# [ -z $String]
[root@linuxprobe ~]# echo $?
0

流程控制语句

流程控制语句:

  1. if条件测试语句
  2. for循环语句
  3. while循环语句
  4. case语句

4.3.1 if条件测试语句
if条件测试语句可以让脚本根据实际情况自动执行相应的命令。从技术角度来讲,if语句分为单分支结构、双分支结构、多分支结构;其复杂度随着灵活度一起逐级上升。

if条件语句的单分支结构由if、then、fi关键词组成,而且只在条件成立后才执行预设的命令。
单分支的if语句属于最简单的一种条件判断结构,语法格式如图4-17所示。
第4章 Vim编辑器与Shell命令脚本_第4张图片
注意: shell脚本中的头部 #!/bin/bash 要符号字母之间必须没有缝隙,if、then与后面的条件命令之间不能紧挨着,必须有空格隔开。
if条件语句的双分支结构也是一种很简单的判断结构,语法格式如图4-18所示。
第4章 Vim编辑器与Shell命令脚本_第5张图片
Linux系统中的ping命令不像Windows一样尝试4次就结束,因此为了避免用户等待时间过长,需要通过**-c参数来规定尝试的次数,并使用-i参数定义每个数据包的发送间隔,以及使用-W参数**定义等待超时时间。

[root@linuxprobe ~]# vim chkhost.sh
#!/bin/bash
ping -c 3 -i 0.2 -W 3 $1 &> /dev/null
if [ $? -eq 0 ]
then
echo "Host $1 is On-line."
else
echo "Host $1 is Off-line."
fi

概念:
/dev/null : 在类Unix系统中,/dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF。
在程序员行话,尤其是Unix行话中,/dev/null 被称为位桶(bit bucket)或者黑洞(black hole)。空设备通常被用于丢弃不需要的输出流,或作为用于输入流的空文件。这些操作通常由重定向完成。
把/dev/null看作"黑洞"。它等价于一个只写文件,并且所有写入它的内容都会永远丢失,而尝试从它那儿读取内容则什么也读不到。然而, /dev/null对命令行和脚本都非常的有用。

第4章 Vim编辑器与Shell命令脚本_第6张图片
在Linux系统中,read是用来读取用户输入信息的命令,能够把接收到的用户输入信息赋值给后面的指定变量,-p参数用于向用户显示一定的提示信息。例:

[root@linuxprobe ~]# vim chkscore.sh
#!/bin/bash
read -p "Enter your score(0-100):" GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; then
echo "$GRADE is Excellent"
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then
echo "$GRADE is Pass"
else
echo "$GRADE is Fail"
fi
[root@linuxprobe ~]# bash chkscore.sh
Enter your score(0-100):88
88 is Excellent

4.3.2 for条件循环语句
for循环语句允许脚本一次性读取多个信息,然后逐一对信息进行操作处理,当要处理的数据有范围时,使用for循环语句再适合不过了。
第4章 Vim编辑器与Shell命令脚本_第7张图片
案例:
下面使用for循环语句从列表文件中读取多个用户名,然后为其逐一创建用户账户并设置密码。首先创建用户名称的列表文件users.txt,每个用户名称单独一行。读者可以自行决定具体的用户名称和个数:

[root@linuxprobe ~]# vim users.txt
andy
barry
carl
duke
eric
george

接下来编写Shell脚本Example.sh。

  • id 用户名 命令查看用户的信息,并使用$?判断这条命令是否执行成功,也就是判断该用户是否已经存在。
  • /dev/null 是一个被称作Linux黑洞的文件,把输出信息重定向到这个文件等同于删除数据(类似于没有回收功能的垃圾箱),可以让用户的屏幕窗口保持简洁。
  • –stdin 这个选项用于从标准输入管道读入新的密码:
    使用 echo 方式来重置Linux 系统用户密码:
    echo “新密码”|passwd --stdin 用户名
[root@rhel7 ~]# passwd --stdin rusky   为rusky用户设置密码。
Changing password for user rusky.
zxcvbnm
passwd: all authentication tokens updated successfully.
[root@rhel7 ~]# echo "qwert"
qwert
[root@rhel7 ~]# echo "qwert" | passwd --stdin rusky  把echo返回的字符qwert设置为用户rusky的密码
Changing password for user rusky.
passwd: all authentication tokens updated successfully.
 [root@linuxprobe ~]# vim Example.sh
#!/bin/bash
read -p "Enter The Users Password:" PASSWD
for UNAME in `cat users.txt`
do
	id $UNAME &> /dev/null
	if [ $? -eq 0 ]
		then
			echo "Already exists"
		else
			useradd $UNAME &> /dev/null
			echo "$PASSWD" | passwd ——stdin $UNAME &> /dev/null
		if [ $? -eq 0 ]
		then
			echo "$UNAME , Create success"
			else
			echo "$UNAME , Create failure"
		fi
	fi
done

其中echo “$PASSWD” | passwd ——stdin $UNAME &> /dev/null 是把前面用户输入的密码通过管道符直接作为stdin输入,加入到给用户赋值密码命令passwd 密码 用户名。

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

[root@linuxprobe ~]# bash Example.sh
Enter The Users Password:linuxprobe
andy , Create success
barry , Create success
carl , Create success
duke , Create success

查看创建的用户列表:

[root@linuxprobe ~]# tail -6 /etc/passwd
andy:x:1001:1001:/home/andy:/bin/bash
barry:x:1002:1002:/home/barry:/bin/bash
carl:x:1003:1003:/home/carl:/bin/bash

4.3.3 while条件循环语句
while条件循环语句 是一种让脚本根据某些条件来重复执行命令的语句,它的循环结构往往在执行前并不确定最终执行的次数,完全不同于for循环语句中有目标、有范围的使用场景。while循环语句通过判断条件测试的真假来决定是否继续执行命令,若条件为真就继续执行,为假就结束循环。
第4章 Vim编辑器与Shell命令脚本_第8张图片

  • $RANDOM 变量来调取出一个随机的数值(范围为0~32767)
  • expr命令 是一个手工命令行计数器,用于在UNIX/LINUX下求表达式变量的值,一般用于整数值,也可用于字符串。
[root@linuxprobe ~]# vim Guess.sh
#!/bin/bash
PRICE=$(expr $RANDOM1000)
TIMES=0
echo "商品实际价格为0-999之间,猜猜看是多少?"
while true
do
	read -p "请输入您猜测的价格数目:" INT
	let TIMES++
	if [ $INT -eq $PRICE ] ; then
		echo "恭喜您答对了,实际价格是 $PRICE"
		echo "您总共猜测了 $TIMES 次"
		exit 0
	elif [ $INT -gt $PRICE ] ; then
		echo "太高了!"
	else
		echo "太低了!"
	fi
done
root@linuxprobe ~]# bash Guess.sh
商品实际价格为0-999之间,猜猜看是多少?
请输入您猜测的价格数目:500
太低了!
请输入您猜测的价格数目:800
太高了!
请输入您猜测的价格数目:650
太低了!
请输入您猜测的价格数目:720
太高了!
请输入您猜测的价格数目:690
太低了!
请输入您猜测的价格数目:700
太高了!
请输入您猜测的价格数目:695
太高了!
请输入您猜测的价格数目:692
太高了!
请输入您猜测的价格数目:691
恭喜您答对了,实际价格是 691
您总共猜测了 9
  • 4.3.4 case条件测试语句
  • case语句 是在多个范围内匹配数据,若匹配成功则执行相关命令并结束整个条件测试;而如果数据不在所列出的范围内,则会去执行星号(*)中所定义的默认命令。case语句的语法结构如图4-22所示。
  • 第4章 Vim编辑器与Shell命令脚本_第9张图片
[root@linuxprobe ~]# vim Checkkeys.sh
#!/bin/bash
read -p "请输入一个字符,并按Enter键确认:" KEY
case "$KEY" in
	[a-z]|[A-Z])
	echo "您输入的是 字母。"
	;;
[0-9])
	echo "您输入的是 数字。"
	;;
*)
	echo "您输入的是 空格、功能键或其他控制字符。"
esac
[root@linuxprobe ~]# bash Checkkeys.sh
请输入一个字符,并按Enter键确认:6
您输入的是 数字。
[root@linuxprobe ~]# bash Checkkeys.sh
请输入一个字符,并按Enter键确认:p
您输入的是 字母。
[root@linuxprobe ~]# bash Checkkeys.sh
请输入一个字符,并按Enter键确认:^[[15~
您输入的是 空格、功能键或其他控制字符。
  • 4.4 计划任务服务程序

计划任务 分为一次性计划任务与长期性计划任务。
顾名思义,一次性计划任务只执行一次,一般用于满足临时的工作需求。

  1. at命令:实现这种功能,只需要写成“at 时间”的形式就可以。
  2. “at -l”命令:如果想要查看已设置好但还未执行的一次性计划任务,可以使用;
  3. atrm 任务序号:要想将其删除该任务
    在使用at命令来设置一次性计划任务时,默认采用的是交互式方法。
[root@linuxprobe ~]# at 23:30
at > systemctl restart httpd
at > 此处请同时按下Ctrl + D组合键来结束编写计划任务
job 3 at Mon Apr 27 23:30:00 2017
[root@linuxprobe ~]# at -l
3 Mon Apr 27 23:30:00 2017 a root

可以把前面学习的管道符(任意门)放到两条命令之间,让at命令接收前面echo命令的输出信息,以达到通过非交互式的方式创建计划一次性任务的目的。

[root@linuxprobe ~]# echo "systemctl restart httpd" | at 23:30
job 4 at Mon Apr 27 23:30:00 2017
[root@linuxprobe ~]# at -l
3 Mon Apr 27 23:30:00 2017 a root
4 Mon Apr 27 23:30:00 2017 a root

如果我们不小心设置了两个一次性计划任务,可以使用下面的命令轻松删除其中一个:

[root@linuxprobe ~]# atrm 3

如果我们希望Linux系统能够周期性地、有规律地执行某些具体的任务,那么Linux系统中默认启用的crond服务简直再适合不过了。
crond服务:

  • crontab -e:创建、编辑计划任务的命令

  • crontab -l:查看当前计划任务

  • crontab -r:删除某条计划任务的命令

  • 另外,如果您是以管理员的身份登录的系统,还可以在crontab命令中加上-u参数来编辑他人的计划任务。
    crond服务设置任务的参数格式分、时、日、月、星期 命令
    注意:如果有些字段没有设置,则需要使用星号(*)占位
    第4章 Vim编辑器与Shell命令脚本_第10张图片

字段 说明
取值为0-59的整数
取值为0-23的任意整数
取值为1-31的任意整数
取值为1-12的任意整数
取值为1-7的任意整数,其中0与7均为星期日
[root@linuxprobe ~]# crontab -e
no crontab for root - using an empty one
crontab:installing new crontab
[root@linuxprobe ~]# crontab -l25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot
  1. 逗号(,):表示多个时间段,例如“8,9,12”表示8月、9月和12月。
  2. 减号(-):表示一段连续的时间周期(例如字段“日”的取值为“12-15”,则表示每月的12~15日)。
  3. 除号(/):表示执行任务的间隔时间(例如“/2”表示每隔2分钟执行一次任务)之外。

注意

  1. 如果在crond服务中需要同时包含多条计划任务的命令语句,应每行仅写一条。
  2. 在crond服务的计划任务参数中,所有命令一定要用绝对路径的方式来写,如果不知道绝对路径,请用whereis命令进行查询,rm命令路径为下面输出信息中加粗部分。
[root@linuxprobe ~]# whereis rm
rm:/usr/bin/rm /usr/share/man/man1/rm.1.gz /usr/share/man/man1p/rm.1p.gz
[root@linuxprobe ~]# crontab -e
crontab:installing new crontab
[root@linuxprobe ~]# crontab -l
25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot0 1 * * 1-5 /usr/bin/rm -rf /tmp/*

注意事项

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

你可能感兴趣的:(vim,编辑器,linux)