《Linux就该这么学》培训笔记_ch04_Vim编辑器与Shell命令脚本
文章最后会post上书本的笔记照片。
文章主要内容:
Vim编辑器
Linux中一切都是文件,配置服务其实就是在修改其配置文件的参数。
Vim编辑器用于编辑文本文件内容,是vi编辑器的升级版,与Vi相比,Vim编辑器有代码着色。
Vim编辑器有3中模式:
- 命令模式:控制光标移动,可对文本进行复制、粘贴、删除和查找等工作。
- 输入模式:正常的文本录入。
- 末行模式:保存或退出文档,以及设置编辑环境。
运行Vim编辑器默认进入命令模式。按下a、i、o可进入输入模式进行文档编辑。按下Esc键退出当前模式并返回命令模式。按下:进入末行模式。输入模式和末行模式不能直接切换。
命令模式常用命令:
- dd:删除(剪切)光标所在整行
- ndd:删除(剪切)从光标处开始的n行。例子:10dd,即删除(剪切)从光标处开始的10行。1dd = dd(没有意义)
- yy:复制光标所在整行
- nyy:复制从光标处开始的n行。例子:7dd,即复制从光标处开始的7行。1yy = yy(没有意义)
- n:显示搜索命令定位到的下一个字符串
- N:显示搜索命令定位到的上一个字符串
- u:撤销上一步的操作
- p:将之前删除(dd)或复制(yy)过的数据粘贴到光标后面
a、i、o进入输入模式区别:
- a键:在光标后一位切换;
- i键:光标当前位置;
- o键:光标下面在创建一个空行;
末行模式可用命令:
命令 | 作用 |
: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 |
?字符串 | 在文本中从下至上搜索该字符串 |
/字符串 | 在文本中从上至下搜索该字符串 |
配置主机名称:
1 vim /etc/hostname #在Linux系统中,主机名大多保存在/etc/hostname文件中 2 kamin.com #把原始主机名删除后追加想要更改的主机名,按Esc键返回命令模式,按:进入末行模式执行wq!强制保存并退出
配置网卡信息:
- 首先切换到/etc/sysconfig/network-scripts目录中(存放着网卡的配置文件:ifcfg-enoXXXXXXXX);
- 使用Vim编辑器修改网卡文件ifcfg-enoXXXXXXXX,逐项写入下面的配置参数并保存退出。使用ifconfig命令可以确认网卡的默认名称。
- 重启网络服务并测试网络是否联通。
1 cd /etc/sysconfig/network-scripts/ #切换到存放网卡配置文件的目录 2 vim ifcfg-eno16777728 #修改网卡配置文件参数 3 TYPE=Ethernet #设备类型 4 BOOTPROTO=static #地址分配模式,有dhcp,static和none 5 NAME=eno16777728 #网卡名称,用DEVICE参数也行 6 ONBOOT=yes #是否启动 7 IPADDR=192.168.10.10 #ip地址 8 NETMASK=255.255.255.0 #子网掩码,可以写成PREFIX=24 9 GATEWAY=192.168.10.1 #网关地址 10 DNS1=192.168.10.1 #DNS地址 11 systemctl restart network #重启网卡服务 12 ping 192.168.10.10 #测试连通性
配置Yum软件仓库:
- 1.添加光盘,检查光盘是否被识别;
- 2.创建一个目录作为挂载点;
- 3.用mount命令把光盘挂载到挂载点;
- 4.进入/etc/yum.repos.d/目录,创建Yum仓库配置文件(xxx.repo,名字随意,但是后缀必须是repo),编辑好相关配置参数;
- 5.把光盘的挂载信息追加写入到/etc/fstab文件中,使得该挂载信息永久生效。
1 mkdir -p /media/cdrom #创建挂载点 2 mount /dev/cdrom /media/cdrom #把光盘挂载到/media/cdrom 3 cd /etc/yum.repos.d/ #进入到/etc/yum.repos.d/目录中 4 vim rhel7.repo #创建Yum仓库配置文件(文件名称随意,但后缀必须是.repo),5-9行是文件内容 5 [rhel7] #Yum软件仓库唯一标识符,避免与其他仓库冲突 6 name=rhel7 #Yum软件仓库的名称描述,易于识别仓库用处 7 baseurl=file:///media/cdrom #Yum软件仓库的路径。支持格式有FTP(ftp://..)、HTTP(http://)、本地(file:///) 8 enabled=1 #设置此源是否可用;1可用,0禁用 9 gpgcheck=0 #设置此源是否检验文件,1校验,0不校验 10 vim /etc/fstab #把挂载信息写入/etc/fstab,实现永久挂载。11行为文件的追加内容。 11 /dev/cdrom /media/cdrom iso9660 defaults 0 0 #设备文件 挂载目录 格式类型 权限选项 是否备份 是否自检(1是0否)
Shell脚本
Shell脚本名称随意,但一般后缀为.sh,以表示是脚本文件。
Shell脚本格式:(脚本声明和脚本正文必须有,脚本注释可以没有)
1 vim test.sh 2 #!/bin/bash #脚本声明,告诉系统用那种shell解释器执行该脚本 3 #This is a test program #脚本注释 4 pwd #脚本正文,常见命令配合流程控制语句等组成有一定功能的脚本程序 5 ls -l
运行Shell脚本方法:
- 1)bash 脚本文件所在位置/脚本文件名。ex:bash Desktop/test.sh
- 2)./脚本文件所在位置/脚本文件名。这种方式需要有文件的执行权限(默认没有)。要用chmod命令为文件增加执行权限。
1 bash Desktop/test.sh #方法1:bash 脚本的相对位置。 2 ./Desktop/test.sh #方法2:./脚本的相对位置。现在执行会报错,因为创建的脚本文件默认是没有执行权限的 3 chmod u+x Desktop/test.sh #为脚本文件增加属主的执行权限。 4 ./Desktop/test.sh #现在执行就可以了。
Shell脚本内设的用于接收参数的变量:
- $0:当前Shell脚本程序的名称
- $#:总共有几个参数
- $*:所有位置的参数值
- $?:显示上一次命令的执行返回值
- $1、$2、$3...:分别对应着第N个位置的参数值
实例:
1 vim example.sh 2 #!/bin/bash 3 echo "当前脚本名称为$0" #当前脚本名称为example.sh 4 echo "总共有$#个参数,分别是$*。" #总共有3个参数,分别是one two three 5 echo "第1个参数为$1,第3个为$3。" #第1个参数为one,第3个为three。 6 bash example.sh one two three
条件测试语句:[ 条件表达式 ]。两边均有空格,条件测试语句不能配合管道符。
文件测试语句参数:
操作符 | 作用 |
-d | 测试文件是否为目录类型 |
-e | 测试文件是否存在 |
-f | 判断是否为一般文件 |
-r | 测试当前用户是否有权限读取 |
-w | 测试当前用户是否有权限写入 |
-x | 测试当前用户是否有权限执行 |
1 [ -d /etc/fstab ] #/etc/fstab是存放设备挂载信息的配置文件,不是目录,因此返回值为1 2 echo $? #返回上一条命令执行后的返回值 3 [ -e /etc/fstab ] #/etc/fstab文件是实打实存在的文件,返回值0 4 [ -f /etc/fstab ] #/etc/fstab是一般文件,返回0 5 [ -r /etc/fstab ] #/etc/fstab文件当前用户root是可读的,返回0 6 [ -w /etc/fstab ] #/etc/fstab文件当前用户root是可写的,返回0 7 [ -x /etc/fstab ] #/etc/fstab文件当前用户root是不可执行的,返回1
逻辑测试语句参数(返回0则成功,返回1则失败):
- 逻辑与(&&):当前面的命令执行成功后才会执行后面的命令;
- 逻辑或(||):当前面的命令执行失败后才会执行后面的命令;
- 逻辑非(!):条件测试中的判断结果取反;
1 [ ! $USER = root ] && echo "user" || echo "root" #先判断当前登录用户的USER变量值是否为root,然后取反。即如果当前登录用户的USER变量值不为root,则输出user,反之输出root。
整数比较语句参数:
操作符 | 作用 |
-eq | 是否等于 |
-ne | 是否不等于 |
-gt | 是否大于 |
-lt | 是否小于 |
-le | 是否等于或小于 |
-ge | 是否大于或等于 |
以下例子创建变量FreeMem,记录系统当前剩余内存量。先通过free -m命令查看内存使用量情况(以MB来显示),然后通过grep Mem:命令过滤出剩余内存量的那行,最后通过awk '{print $4}'命令只保留第4列(这里列按空格区分开)
1 FreeMem=`free -m | grep Mem: | awk '{print $4}'` 2 [ $FreeMem -lt 1024 ] && echo "内存不足" #如果FreeMem的值小于1024,则输出内存不足
字符串比较语句参数:
操作符 | 作用 |
= | 比较字符串内容是否相同 |
!= | 比较字符串内容是否不同 |
-z | 判断字符串内容是否为空 |
1 SB="zhouhw" 2 [ $SB != "liwh" ] && echo "zhou hong wei is SB" #如果SB不等于liwh,则输出zhou hong wei is SB
流程控制语句
if语句
单分支:if...then...fi
双分支:if...then...else...fi
ping命令:用于测试与对方主机的网络连通性。格式:ping [参数] 对方主机ip地址。
常用参数:
- -c:规定尝试次数;
- -i:定义数据包发送间隔;
- -W:定义等待超时时间。
/dev/null:被称作Linux黑洞的文件,把输出重定向到这个文件等同于删除数据,让用户的屏幕窗口保持简洁。
1 vim chkhost.sh 2 #!/bin/bash #脚本声明 3 ping -c 3 -i 0.2 -W 3 $1 &> /dev/null #测试看能否ping通对方主机ip,并将输出结果重定向到/dev/null中保持界面整洁 4 if [ $? -eq 0 ] #如果$?为0则成功,说明能ping通对方主机,反之ping不通。 5 then 6 echo "Host $1 is On-line." 7 else 8 echo "Host $1 is Off-line." 9 fi
多分支:if...then...elif...then...else...fi
1 vim chkscore.sh 2 #!/bin/bash #脚本声明 3 read -p "Enter your score(0-100):" GRADE #read命令读取用户输入信息并赋值给后面指定变量GRADE,-p用于向用户显示一定的提示信息。 4 if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; then #如果85 ≤ GRADE ≤ 100,则Excellent 5 echo "$GRADE is Excellent" 6 elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then #如果70 ≤ GRADE ≤ 84,则Pass 7 echo "$GRADE is Pass" 8 else #兜底,即上面条件都不匹配,则执行这条之下的脚本 9 echo "$GRADE is Fail" 10 fi
for循环
for循环语句允许脚本一次性读取多个信息,然后逐一对信息进行处理。
红帽考试:编写一个可以批量创建用户的Shell脚本。
1 vim users.txt #创建用户名称的列表文件 2 zhangsan 3 lisi 4 wangwu 5 vim Example.sh #编写批量创建用户脚本 6 #!/bin/bash #脚本声明 7 read -p "Enter The Users Password : " PASSWD #读取用户输入的信息,赋值给PASSWD变量 8 for UNAME in `cat users.txt` #cat命令读取文件users.txt,for循环开始先把第一行赋值给UNAME变量,依此类推。 9 do #for循环逻辑开始 10 id $UNAME &> /dev/null #id命令检查系统中是否存在此用户 11 if [ $? -eq 0 ] ; then #根据上一次执行命令的结果是否为0,即如果该用户已存在,输出“已存在”,反之则创建该用户 12 echo "Already exists" 13 else 14 useradd $UNAME &> /dev/null #创建用户,并将输出结果重定向到黑洞文件保持界面整洁 15 echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null #通过管道符传递的方法设置密码,免去passwd命令原本需要交互式设置的麻烦 16 if [ $? -eq 0 ] ; then #虽然上两条命令基本上不会出错,但为了程序更严谨,还是要判断下命令是否执行成功,0成功非0失败,并分别输出相应提示信息。 17 echo "$UNAME , Create success" 18 else 19 echo "$UNAME , Create failure" 20 fi #里层if语句结束 21 fi #外层if语句结束 22 done #for循环结束
同理,批量ping对方主机的脚本思路类似。
while循环
若条件为真就继续执行,反之跳出循环。
实例:用多分支if语句配合while条件循环语句编写猜数字的小游戏脚本。
1 vim Guess.sh 2 #!/bin/bash 3 PRICE=$(expr $RANDOM % 1000) #使用$RANDOM变量来调取出一个随机的数值(范围为0~32767),将这个随机数对1000进行取余操作,并使用expr命令取得其结果 4 TIMES=0 #创建TIMES变量,用于累计用户猜数字的次数 5 echo "商品实际价格为0-999之间,猜猜看是多少?" 6 while true #条件永远为真,循环会无限执行下去,下面会有exit 0语句终止脚本执行 7 do #循环开始 8 read -p "请输入您猜测的价格数目:" INT #read读取输入的数值 9 let TIMES++ #TIMES变量自增1,即猜数字次数累计1次 10 if [ $INT -eq $PRICE ] ; then #如果输入的数字跟随机生成的数字一致,说明猜对了。(第三行生成的数字不在循环内,因此知道程序结束,生成的数字都是不会变的) 11 echo "恭喜您答对了,实际价格是 $PRICE" 12 echo "您总共猜测了 $TIMES 次" 13 exit 0 #终止脚本执行 14 elif [ $INT -gt $PRICE ] ; then #输入数字比生成数字高,提示太高 15 echo "太高了!" 16 else #兜底,既猜不对数字,又不是比生成数字高,那就是太低了 17 echo "太低了!" 18 fi #if语句结束 19 done #while循环结束
该脚本只能接收数字,如果输入数字以外的字符,脚本就会奔溃并报错,并判断条件一定跳到兜底,输出“太低了”。
case语句
实例:用case语句和通配符判断用户输入的字符是数字、字母还是其他字符。
1 vim Checkkeys.sh 2 #!/bin/bash 3 read -p "请输入一个字符,并按Enter键确认:" KEY #read读取用户输入信息 4 case "$KEY" in #case语句开始 5 [a-z]|[A-Z]) #如果输入的字符(只能是1位,aD则会跳到兜底)是大写字母或者小写字母,则输出是字母 6 echo "您输入的是 字母。" 7 ;; #是否为字母的判断逻辑结束 8 [0-9]) #如果是数字(只能1位,10、99等则会跳到兜底),则输出是数字 9 echo "您输入的是 数字。" 10 ;; #是否为数字的判断逻辑结束 11 *) #兜底,输出其他字符 12 echo "您输入的是 空格、功能键或其他控制字符。" 13 esac #case语句结束
计划任务服务程序
计划任务可以在指定的时间段自动启动或停止某些服务或命令,实现运维的自动化。
计划任务:
- 一次性计划任务:只执行一次,一般用于临时的工作需求。
- 长期性计划任务:按照设定的时间周期,重复执行用户指定的命令操作。
at命令:用于设置一次性计划任务。格式:at [时间]/[参数]。
at命令常见用法:
1 at 23:30 #at 24小时制时间 命令在当天23:30设置一个一次性计划任务,下面进入到at命令的交互式设置 2 at > systemctl restart network #浅蓝色为at命令交互式设置的默认开头,后面可以编辑相应命令,这里是设置了重启网卡服务的命令 3 at > 按下Ctrl + D结束编写计划任务 #如果计划任务编写完了,不要按Ctrl + C,这样会在没有保存计划任务的情况下强行退出at交互式设置。要按Ctrl + D来保存相关设置并退出at计划任务设置。 4 echo "systemctl restart network" | at 23:30 #通过管道符的方式设置计划任务,跟前面通过交互来设置的效果一样 5 at -l #at -l查看已设置好但还没执行的一次性计划任务,已执行的一次性计划任务会自动删除,所以已执行的一次性计划任务在这里是查不到的。其中列出信息的第一列表示任务序号。 6 atrm 1 #atrm 任务序号 删除对应任务序号的一次性计划任务。任务序号是按一次性计划任务的设置顺序来递增赋予的。 7 at -l #再查看一次已设置好但还没执行的一次性计划任务,会发现任务序号为1的计划任务已经不见了。
Linux中默认启用的crond服务是用来周期性的执行某种任务或等待处理某些事件的一个守护进程。crond服务通过crontab命令来实现。
crontab命令:用于配置周期性计划任务。格式:crontab [选项]。
常用参数:
- -e:创建、编辑计划任务;
- -l:查看当前计划任务;
- -r:删除某条计划任务;
- -u:编辑对应用户的计划任务(管理员身份才能用);
使用crond设置任务的参数格式:分 时 日 月 星期 命令,如果有些字段没有设置,则使用星号(*)占位。
注意:
- “分”字段必须有数值,不能为空或者是*号;
- “日”和“星期”字段不能同时使用,否则会发生冲突;
字段 | 说明 |
分钟 | 取值为0~59的整数 |
小时 | 取值为0~23的任意整数 |
日期 | 取值为1~31的任意整数 |
月份 | 取值为1~12的任意整数 |
星期 | 取值为0~7的任意整数,其中0与7均为星期日 |
命令 | 要执行的命令或程序脚本 |
实例:
- 1.先创建一个周期性计划任务,实现在每周一、三、五的凌晨3点25分把root用户桌面打包作为一个备份文件;
- 2.查看当前计划任务内容,再编辑计划任务,追加一条计划任务,实现在每周一到周五的凌晨1点钟把/tmp/目录下所有文件删掉;
1 crontab -e #进入周期性计划任务编辑界面,其实就是调用了Vim编辑器 2 25 3 * * 1,3,5 /usr/bin/tar -czvf backup,tar,gz /root/Desktop #写入周期性计划任务设置信息,在crond服务的计划任务参数中,所有命令必须使用绝对路径的方式来写,whereis命令可以查询命令的绝对路径。 3 crontab -l #查看当前计划任务 4 crontab -e #再次进入计划任务编辑,追加计划内容 5 0 1 * * 1-5 /usr/bin/rm -rf /tmp/*