Vim编辑器与shell脚本
目录
Vim文本编辑器
Shell脚本
Shell编程变量
流程控制语句
计划任务服务程序
参考资料
XUQ 2019.3.27 初稿
Vim文本编辑器
1.为什么要使用文本编辑器?
“在Linux系统中一切都是文件,而配置一个服务就是在修改其配置文件的参数”。而且在日常工作中大家也肯定免不了要编写文档,这些工作都是通过文本编辑器来完成的。
Linux中有很多配置文件,类似于windows中的注册表;默认由vi编辑器(文本编辑工具)进行管理和维护;vim为增强版(着色)。
2.三种工作模式:
命令模式:控制光标移动,可对文本进行复制、粘贴、删除和查找等工作。
输入模式:正常的文本录入。
末行模式:保存或退出文档,以及设置编辑环境。
不同模式之间的切换
图5-1 Vim编辑器模式切换方法
在每次运行Vim编辑器时,默认进入命令模式,此时需要先切换到输入模式后再进行文档编写工作,而每次在编写完文档后需要先返回命令模式,然后再进入末行模式,执行文档的保存或退出操作。在Vim中,无法直接从输入模式切换到末行模式。
3.基本命令操作
命令 |
作用 |
dd |
删除(剪切)光标所在整行 |
5dd |
删除(剪切)从光标处开始的5行 |
yy |
复制光标所在整行 |
5yy |
复制从光标处开始的5行 |
n |
显示搜索命令定位到的下一个字符串 |
N |
显示搜索命令定位到的上一个字符串 |
u |
撤销上一步的操作 |
p |
将之前删除(dd)或复制(yy)过的数据粘贴到光标后面 |
表5-1 命令行常用命令
命令 |
作用 |
: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 |
?字符串 |
在文本中从下至上搜索该字符串 |
/字符串 |
在文本中从上至下搜索该字符串 |
表5-2 末行常用命令
4.vim编辑器命令操作(略,这里建议上网查看相关视频)
Shell脚本
1.什么是shell脚本?
Linux系统中的shell脚本是一个特殊的应用程序,它介于操作系统内核与用户之间,充当了一个“命令解释器的角色”,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。
最常用的shell是bash,也就是bourne again shell ;bash由于免费和易用,是大多数linux操作系统的默认shell环境。
图5-2 shell与系统关系
2.Shell脚本命令的工作方式
交互式(Interactive):用户每输入一条命令就立即执行。
批处理(Batch):由用户事先编写好一个完整的Shell脚本,Shell会一次性执行脚本中诸多的命令。
在Shell脚本中除了需要用到很多Linux命令以及正则表达式、管道符、数据流重定向等语法规则,还需要把内部功能模块化后通过逻辑语句进行处理,最终形成日常所见的Shell脚本。
3.编写简单的脚本
要熟练掌握shell编程语言,需要大量练习。Shell脚本编程需要注意以下几点:
1.shell脚本名称命名一般为英文的大写,小写;不能用特殊符号,空格来命名;一般以脚本功能命名。
2.shell脚本后缀以.sh结尾
3.shell脚本内容首行需以#!/bin/bash开头
4.shell脚本中变量名称尽量使用大写字母,字母间不能使用“-“,可以使用”_“; 不能以数字,特殊符号开头
结构:声明-注释-代码
功能:接收参数;处理参数
示例:使用vim编写一个shell脚本
[root@redhat7 桌面]# echo $SHELL <==查看SHELL变量,发现当前系统默认使用Bash作为命令解释器
/bin/bash
[root@redhat7 桌面]# vim fist_shell.sh <==使用vim编写脚本
[root@redhat7 桌面]# cat fist_shell.sh
#!/bin/bash <==脚本声明,定义该脚本所使用的shell类型
#This is my Fisrt shell <==#表示注释,没实际意义,shell不会去解析它
#By author Nick.net 2019 <==脚本创建人
echo "Hello World!!!" <==shell脚本主命令执行该脚本呈现的内容
[root@redhat7 桌面]# bash fist_shell.sh <==bash直接执行脚本
Hello World!!!
[root@redhat7 桌面]# ./fist_shell.sh <==输入路径执行脚本
bash: ./fist_shell.sh: 权限不够
[root@redhat7 桌面]# chmod o+x fist_shell.sh <==赋予脚本可执行权限
[root@redhat7 桌面]# ./fist_shell.sh
Hello World!!!
[root@redhat7 桌面]# /bin/sh fist_shell.sh <==通过/bin/sh直接执行,不需要执行权限
Hello World!!!
4.shell,shell编程,shell脚本,shell命令间的区别?
Shell 是一个整体概念,shell编程与shell脚本统称为shell编程,shell命令是shell编程底层具体的语句和实现方法。
Shell编程变量
1.概述
Shell属于非类型的解释语言,不需要事先声明变量;Shell给一个变量赋值,就是定义了变量。在linux中,可以使用“=“为变量赋值;shell为弱类型语言,定义变量不需要声明类型,如果需要声明,可使用declare指定类型。
2.shell变量分类
系统变量:对参数判断和命令返回值判断时使用
环境变量:程序运行时需要设置
用户变量(局部变量):shell脚本内部或者临时局部
Shell变量在定义时,首个字符必须为字母(a~z,A~Z),不能以数字开头,中间不能有空格,可以使用”_“,不能使用“-“,也不能使用数字和符号。
示例:
[root@redhat7 桌面]# vim var.sh
[root@redhat7 桌面]# cat var.sh
#!/bin/bash
#By author Nick.net 2019
A=123 <==定义一个变量(A变量名,123变量值)
echo "Printf variables is $A." <==引用变量($+变量名)
[root@redhat7 桌面]# /bin/sh var.sh
Printf variables is 123.
2.1.常见系统变量
$0 当前的脚本名称
$n 当前脚本的第n个参数,n=1,2,…9
$* 当前脚本的所有参数(不包括程序本身)
$# 当前脚本的参数个数(不包括程序本身)
$? 命令或程序执行完后的状态,返回0表示执行成功,反之则显示一个非零的数字
$$ 程序本身的PID号
2.2.用户变量
A=123 自定义变量A
IP1=192.168.3.15 自定义变量IP1
N_SOFT=nginx-1.12.0.tar.gz 自定义变量N_SOFT
…
2.3.常见环境变量(略,请查看必备命令-环境变量)
3.接收用户参数
为了让Shell脚本程序更好地满足用户的一些实时需求,灵活完成工作,必须要让脚本程序能够像之前执行命令时那样,接收用户输入的参数。Linux系统中接收参数的变量,变量之间可以使用空格间隔。
图5-3 Shell脚本程序中的参数位置变量
示例:
[root@linuxprobe ~]# vim example.sh
#!/bin/bash
echo "当前脚本名称为$0"
echo "总共有$#个参数,分别是$*。"
echo "第1个参数为$1,第5个为$5。"
[root@linuxprobe ~]#bash example.sh one two three four five six
当前脚本名称为example.sh
总共有6个参数,分别是one two three four five six。
第1个参数为one,第5个为five。
3.判断用户的参数
Shell脚本中的条件测试语法可以判断表达式是否成立,若条件成立则返回数字0,否则便返回其他随机数值。
图5-4 条件测试语句的执行格式
按照测试对象来划分,条件测试语句可以分为4种:文件测试语句;逻辑测试语句;整数值比较语句;字符串比较语句。
3.1.文件测试即使用指定条件来判断文件是否存在或权限是否满足等情况的运算符
运算符 |
作用 |
-d |
测试文件是否为目录类型 |
-e |
测试文件是否存在 |
-f |
判断是否为一般文件 |
-r |
测试当前用户是否有权限读取 |
-w |
测试当前用户是否有权限写入 |
-x |
测试当前用户是否有权限执行 |
图5-2 文件测试所用的参数
示例:
[root@redhat7 桌面]# [ -d /etc/fstab ] <==判断/etc/fstab是否为一个目录类型的文件
[root@redhat7 桌面]# echo $? <==通过Shell解释器的内设$?变量显示上一条命令执行后的返回值(结果)。
1 <==如果返回值为0,则目录存在;如果返回值为非零的值,则意味着目录不存在。
[root@redhat7 桌面]# [ -f /etc/fstab ] <==判断/etc/fstab是否为一个一般文件
[root@redhat7 桌面]# echo $?
0 <==如果返回值为0,则文件存在,且为一般文件
3.2.逻辑语句用于对测试结果进行逻辑分析,根据测试结果可实现不同的效果
&&(逻辑“与”):若前面的命令执行成功,则执行它后面的语句
||(逻辑“或”):若前面的命令执行失败,则执行它后面的语句
!(逻辑“非”):取反
示例:
[root@redhat7 桌面]# [ -f /etc/fstab ] && echo "OK" <==如果有这个文件就输出OK
OK
[root@redhat7 桌面]# [ -f /etc/fstab ] && echo "OK" || echo "ERROR"
OK
[root@redhat7 桌面]# [ -f /etc/f23 ] && echo "OK" || echo "ERROR" <==测试一个不存在的文件,输出ERROR
ERROR
[root@redhat7 桌面]# [ $USER = root ] <==设置$USER变量,判断当前用户是否为管理员
[root@redhat7 桌面]# echo $?
0
[root@redhat7 桌面]# [ $USER = root ] && echo "admin" || echo "user" <== …若是管理员,输出admin,不是输出user
admin
[root@redhat7 桌面]# su admin
[admin@redhat7 桌面]$ [ $USER = root ] && echo "admin" || echo "user"
user
[admin@redhat7 桌面]$ su root
密码:
[root@redhat7 桌面]# [ $USER = root ] && echo "admin" || echo "user"
user <==…为什么是user呢?命令有错误吗?
[admin@redhat7 ~]$ su – root
密码:
上一次登录:三 3月 27 13:21:04 CST 2019pts/0 上
[root@redhat7 ~]# [ $USER = root ] && echo "admin" || echo "user"
admin <==前面犯了个错误,没有使用 su – 命令切换变量环境,现在切换为root变量环境,测试正常
[root@redhat7 桌面]# [ !$USER = root ]
[root@redhat7 桌面]# echo $?
1
3.3.整数比较运算符仅是对数字的操作,不能将数字与字符串、文件等内容一起操作,而且不能想当然地使用日常生活中的等号、大于号、小于号等来判断。
因为等号与赋值命令符冲突,大于号和小于号分别与输出重定向命令符和输入重定向命令符冲突。因此一定要使用规范的整数比较运算符来进行操作。
运算符 |
作用 |
-eq |
是否等于 |
-ne |
是否不等于 |
-gt |
是否大于 |
-lt |
是否小于 |
-le |
是否等于或小于 |
-ge |
是否大于或等于 |
表5-3 可用的整数比较运算符
示例:
[root@redhat7 桌面]# [ 10 -gt 10 ] <==判断10是否大于10
[root@redhat7 桌面]# echo $?
1
[root@redhat7 桌面]# [ 10 -eq 10 ] <==判断10是否等于10
[root@redhat7 桌面]# echo $?
0
[root@redhat7 桌面]# free -m <==查看内存
total used free shared buffers cached
Mem: 1826 987 839 9 0 337
-/+ buffers/cache: 648 1178
Swap: 2047 0 2047
[root@redhat7 桌面]# free -m | grep Mem: <==过滤出剩余内存的量行
Mem: 1826 989 837 9 0 337
[root@redhat7 桌面]# free -m | grep Mem: | awk '{print $4}' <==只保留第四列
836
[root@redhat7 桌面]# FreeMem=`free -m | grep Mem: | awk '{print $4}'` <==赋值给变量
[root@redhat7 桌面]# echo $FreeMem
836
[root@redhat7 桌面]# [ $FreeMem -lt 1024 ] && echo "Insufficient Memory" <==判断内存可用量是否小于1024,若小于则提示
Insufficient Memory <==内存不足
3.4.字符串比较语句用于判断测试字符串是否为空值,或两个字符串是否相同。它经常用来判断某个变量是否未被定义(即内容为空值),理解起来也比较简单。
注意:写脚本前先判断变量是否被使用,避免产生冲突。
运算符 |
作用 |
= |
比较字符串内容是否相同 |
!= |
比较字符串内容是否不同 |
-z |
判断字符串内容是否为空 |
表5-4 常见的字符串比较运算符
示例:
[root@redhat7 桌面]# [ -z $String ] <==判断String变量是否为空(是否被使用)
[root@redhat7 桌面]# echo $?
0
[root@redhat7 桌面]# echo $LANG
zh_CN.UTF-8
[root@redhat7 桌面]# [ $LANG != "zh.CN" ] && echo "Not en.CN" <==保存当前语系的环境变量值LANG不是中文(zh_CN)时,则会满足逻辑测试条件并输出“Not zh.CN”
Not en.CN
流程控制语句
Linux shell 编程中,if, for, while, case 等条件流程控制语句用得非常多,熟练掌握以上流程控制语句及语法,对编写shell脚本有很大的帮助。
1.if条件测试语句
if条件测试语句可以让脚本根据实际情况自动执行相应的命令。从技术角度来讲,if语句分为单分支结构、双分支结构、多分支结构;其复杂度随着灵活度一起逐级上升。
if条件语句的单分支结构由if、then、fi关键词组成,而且只在条件成立后才执行预设的命令,相当于口语的“如果……那么……”。(if开始,fi结束)
1.1.单分支的if语句
图5-5 单分支的if语句
示例:
单分支的if条件语句来判断/media/cdrom文件是否存在,若存在就结束条件判断和整个Shell脚本,反之则去创建这个目录。
[root@redhat7 桌面]# vim mkcdrom.sh
[root@redhat7 桌面]# cat mkcdrom.sh
#!/bin/bash
DIR="/media/cdrom"
if [ ! -e $DIR ] <==判断这个文件是否不存在
then
mkdir -p $DIR <==若不存在就创建这个目录
fi
[root@redhat7 桌面]# ls -d /media/cdrom <==没有目录
ls: 无法访问/media/cdrom: 没有那个文件或目录
[root@redhat7 桌面]# bash mkcdrom.sh <==执行脚本
[root@redhat7 桌面]# ls -d /media/cdrom <==脚本执行创建目录
/media/cdrom
1.2. 双分支结构if条件语句
if条件语句的双分支结构由if、then、else、fi关键词组成,它进行一次条件匹配判断,如果与条件匹配,则去执行相应的预设命令;反之则去执行不匹配时的预设命令,相当于口语的“如果……那么……或者……那么……”。
图5-6 双分支的if语句
示例:
验证某台主机是否在线,然后根据返回值的结果,要么显示主机在线信息,要么显示主机不在线信息。
使用ping命令来测试与对方主机的网络联通性,为了避免用户等待时间过长,需要通过-c参数来规定尝试的次数,并使用-i参数定义每个数据包的发送间隔,以及使用-W参数定义等待超时时间。
[root@redhat7 桌面]# vim chkhost.sh
[root@redhat7 桌面]# cat chkhost.sh
#!/bin/bash
ping -c 3 -i 0.2 -w 3 $1 &> /dev/null <==$1:对象,调取到第一个接收到的参数;> /dev/null 重定向到黑洞文件(回收站)
if [ $? -eq 0 ] <=$? 判断上一条语句,若返回值为0,则证明主机存在
then
echo "Host $1 is on-line."
else
echo "Host $1 is off-line."
Fi
[root@redhat7 桌面]# bash chkhost.sh 192.168.0.6
Host 192.168.0.6 is off-line.
1.3.多分支结构if条件语句(最常用)
if条件语句的多分支结构由if、then、else、elif、fi关键词组成,它进行多次条件匹配判断,这多次判断中的任何一项在匹配成功后都会执行相应的预设命令,相当于口语的“如果……那么……如果……那么……”。
图5-7 多分支的if语句
示例:
使用多分支的if条件语句来判断用户输入的分数在哪个成绩区间内,然后输出如Excellent、Pass、Fail等提示信息。在Linux系统中,read是用来读取用户输入信息的命令,能够把接收到的用户输入信息赋值给后面的指定变量,-p参数用于向用户显示一定的提示信息。
[root@redhat7 桌面]# vim chkscore.sh
[root@redhat7 桌面]# cat chkscore.sh
#!/bin/bash
read -p "Enter your score (0-100):" GRADE <==read -p 读取用户指定的值,赋值给变量;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@redhat7 桌面]# bash chkscore.sh
Enter your score (0-100):89
89 is Excellent
[root@redhat7 桌面]# bash chkscore.sh
Enter your score (0-100):81
81 is pass
[root@redhat7 桌面]# bash chkscore.sh
Enter your score (0-100):39
39 is Fail
[root@redhat7 桌面]# bash chkscore.sh
Enter your score (0-100):136
136 is Fail
为什么输入的分数为136时,依然显示Fail呢?
没有成功匹配脚本中的两个条件判断语句,因此自动执行了最终的兜底策略。(脚本还不是很完美,添加大于100,小于0时,能给error提示的语句,但测试了下,没有成功)
1.4 if判断括括号区别
() 用于多个命令组,命令替换,初始化数组
(())整数扩展,运算符,重定义变量值,算术运算比较
[ ] bash内部命令,”[”与test是等同的,正则字符范围,引用数组元素编号,不支持”+”, “-”, “*”, “/”数学运算符,逻辑测试使用-a, -o
[[ ]] bash程序语言的关键字,不是一个命令,[[ ]]比[ ]更通用,不支持”+”, “-”, “*”, “/”数学运算符,逻辑测试使用&&,||
{} 用于命令集合或者范围
2.for条件循环语句
for循环语句允许脚本一次性读取多个信息,然后逐一对信息进行操作处理,当要处理的数据有范围时,使用for循环语句再适合不过了。
图5-8 for循环语句的语法格式
示例:
使用for循环语句从列表文件中读取多个用户名,然后为其逐一创建用户账户并设置密码。
[root@redhat7 桌面]# vim users.txt <==创建用户名称的列表文件users.txt
[root@redhat7 桌面]# cat users.txt
andy
barry
carl
[root@redhat7 桌面]# vim Example.sh
[root@redhat7 桌面]# cat Example.sh
#!/bin/bash
#Author is Nick.net 2019.3
read -p "Enter The Users Password :" PASSWD <==read命令读取用户输入的密码值,然后赋值给PASSWD变量
for UNAME in `cat users.txt` <==定义一个UNAME变量,从 users.txt为变量赋值
do <==开启循环
id $UNAME &> /dev/null <== id测试用户是否存在;/dev/null是一个被称作Linux黑洞的文件,把输出信息重定向到这个文件等同于删除数据(类似于没有回收功能的垃圾箱),可以让用户的屏幕窗口保持简洁
if [ $? -eq 0 ] <==使用$?判断用户值是否为0,若为0,用户肯定存在
then
echo "$UNAME is exists" <==用户存在
else
useradd $UNAME &> /dev/null <==用户不存在,创建出来,并将创建信息放入垃圾箱
echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null <==重置用户密码
fi
done-
[root@redhat7 桌面]# bash Example.sh
Enter The Users Password :12345 <==回车
andy , Create failure <==用户账户创建成功
barry , Create failure
carl , Create failure
[root@redhat7 桌面]# tail -3 /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
问题:用户无法使用设置的密码登陆
原因:已经创建好了用户,只能一次使用;没有启动else下的两行命令,第二行的passwd --stdin根本就没运行,密码没有创建;我在root-桌面和root-~创建了脚本和文本
解决:删除用户,重新执行脚本
[root@redhat7 桌面]# cat bash.sh <==创建一个删除用户的脚本
#! /bin/bash
#Author is Nick.net 2019.3
for USER in `cat users.txt`
do
userdel -r $USER
done
[root@redhat7 桌面]# bash bash.sh
[root@redhat7 桌面]# tail -6 /etc/passwd
gdm:x:42:42::/var/lib/gdm:/sbin/nologin <==用户已被删除
…
[root@redhat7 ~]# cat Example.sh <==修改脚本
#!/bin/bash
#Author is Nick.net 2019.3
read -s -p "Enter The Users Password :" PASSWD <==使用 -s选项不显示密码
for UNAME in `cat users.txt`
do
id $UNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "$UNAME is exists"
else
useradd $UNAME &> /dev/null
fi
echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null <==12,13行互换,优化脚本,即使用户存在,也可以创建密码。
done
[root@redhat7 ~]# bash Example.sh <==执行脚本
Enter The Users Password :andy is exists <==密码没有明文显示
barry is exists
carl is exists
[root@redhat7 ~]# su - barry
上一次登录:三 3月 27 16:55:51 CST 2019pts/0 上
[barry@redhat7 ~]$ su – carl
密码:
上一次登录:三 3月 27 16:55:41 CST 2019pts/0 上 <==测试成功
(这里感谢群里小伙伴的帮助,一起解决问题,优化脚本)
注意:`命令`=$(命令),执行里面的命令
测试主机是否在线
[root@redhat7 桌面]# cat ipadds.txt <==IP文本
192.168.0.6
192.168.0.7
192.168.0.8
[root@redhat7 桌面]# vim CheckHosts.sh
[root@redhat7 桌面]# cat CheckHosts.sh
#!/bin/bash
for IP in `cat ipadds.txt`
do
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ] ; then
echo "Host $IP is On-line."
else
echo "Host $IP is off-line."
fi
done
流程(思路):读取文档—赋值变量IP—进入for循环语句使用ping命令测试是否在线—如果在线返回值为0,则告诉在线—如果在线返回值不为0.则进入else测试环节,告诉不在线,如果不写会测序崩溃,必要的格式(规则)。
[root@redhat7 桌面]# bash CheckHosts.sh
Host 192.168.0.6 is off-line.
Host 192.168.0.7 is off-line.
Host 192.168.0.8 is off-line.
3.while条件循环语句
while条件循环语句是一种让脚本根据某些条件来重复执行命令的语句,它的循环结构往往在执行前并不确定最终执行的次数,完全不同于for循环语句中有目标、有范围的使用场景。
while循环语句通过判断条件测试的真假来决定是否继续执行命令,若条件为真就继续执行,为假就结束循环。
图5-9 while循环语句的语法格式
示例:
使用多分支的if条件测试语句与while条件循环语句,编写一个用来猜测数值大小的脚本Guess.sh
while条件循环语句中的条件测试始终为true,因此判断语句会无限执行下去,直到用户输入的数值等于expr命令取得的数值后,这两者相等之后才运行exit 0命令,终止脚本的执行。
[root@redhat7 桌面]# vim Guess.sh
[root@redhat7 桌面]# cat Guess.sh
#!bin/bash
PRICE=$(expr $RANDOM % 1000) <==使用$RANDOM变量来调取出一个随机的数值(范围为0~32767),将这个随机数对1000进行取余操作,并使用expr命令取得其结果
TIMES=0 <==统计循环了多少次
echo "商品实际价格为0-999之间,猜猜看是多少?"
while true
do
read -p "请输入您猜猜测的价格数目:" INT <==通过read命令输入的数值进行比较判断
let TIMES++ <==每当循环到let TIMES++命令时都会让TIMES变量内的数值加1,(0+1,2+1…)用来统计循环总计执行了多少次。这可以让用户得知总共猜测了多少次之后,才猜对价格
if [ $INT -eq $PRICE ] ; then
echo "恭喜您答对了。实际价格是 $PRICE"
echo "您总共猜测了 $TIMES 次"
exit 0 <==强制退出
elif [ $INT -gt $PRICE ] ; then
echo "太高了!"
else
echo
echo "太低了!"
fi
done
[root@redhat7 桌面]# bash Guess.sh
商品实际价格为0-999之间,猜猜看是多少?
请输入您猜猜测的价格数目:500
太高了!
请输入您猜猜测的价格数目:100
太低了!
请输入您猜猜测的价格数目:250
太低了!
请输入您猜猜测的价格数目:375
太高了!
请输入您猜猜测的价格数目:320
太低了!
请输入您猜猜测的价格数目:350
太低了!
请输入您猜猜测的价格数目:360
太低了!
请输入您猜猜测的价格数目:370
太高了!
请输入您猜猜测的价格数目:365
恭喜您答对了。实际价格是 365
您总共猜测了 9 次
报错
[root@redhat7 桌面]# bash Guess.sh
商品实际价格为0-999之间,猜猜看是多少?
请输入您猜猜测的价格数目: <==使用空格
Guess.sh: 第 9 行:[: -eq: 期待一元表达式
Guess.sh: 第 13 行:[: -gt: 期待一元表达式
太低了!
请输入您猜猜测的价格数目:a <==使用字母
Guess.sh: 第 9 行:[: a: 期待整数表达式
Guess.sh: 第 13 行:[: a: 期待整数表达式
太低了!
原因:字母和符号无法与数字进行比较
4.case条件测试语句
case语句是在多个范围内匹配数据,若匹配成功则执行相关命令并结束整个条件测试;而如果数据不在所列出的范围内,则会去执行星号(*)中所定义的默认命令。
图5-10 case条件测试语句的语法结构
示例:
前面写的一个Guess.sh脚本中有一个致命的弱点—只能接受数字,当输入字母可能会崩溃。我们必须有一定的措施来判断用户的输入内容,当用户输入的内容不是数字时,脚本能予以提示,从而免于崩溃。过在脚本中组合使用case条件测试语句和通配符编写脚本Checkkeys.sh如下
[root@redhat7 桌面]# vim Checkkeys.sh
[root@redhat7 桌面]# cat Checkkeys.sh
#!/bin/bash
read -p "请输入一个字符,并按enter键确认:" KEY
case "$KEY" in
[a-z]|[A-Z])
echo "您输入的是字母。"
;;
[0-9])
echo "您输入的数字。"
;;
*) <==兜底,如果..则…
echo "您输入的是空格,功能键或其他控制字符。"
esac
[root@redhat7 桌面]# bash Checkkeys.sh
请输入一个字符,并按enter键确认:2
您输入的数字。
[root@redhat7 桌面]# bash Checkkeys.sh
请输入一个字符,并按enter键确认:a
您输入的是字母。
[root@redhat7 桌面]# bash Checkkeys.sh
请输入一个字符,并按enter键确认:$ [[12
您输入的是空格,功能键或其他控制字符。
计划任务服务程序
1.什么是计划任务
在指定的时间段自动启用或停止某些服务或命令,从而实现运维的自动化。
计划任务分为一次性计划任务与长期性计划任务
2.一次性计划任务
只执行一次,一般用于满足临时的工作需求;一次性计划任务,前提是对应的系统服务atd必须已经运行;计划任务执行任务的时间必须安排在当前系统时间后。
命令: at
格式:at 时间
如果想要查看已设置好但还未执行的一次性计划任务,可以使用“at -l”命令;要想将其删除,可以用“atrm 任务序号”。在使用at命令来设置一次性计划任务时,默认采用的是交互式方法。
示例:
[root@linuxprobe ~]# at 23:30
at > systemctl restart httpd
at > <==此处请同时按下Ctrl + D组合键来结束编写计划任务
job 3 at Mon Apr 27 23:30:00 2017 <==将系统设置为在今晚23:30分自动重启网站服务
[root@linuxprobe ~]# at -l <==查看
3 Mon Apr 27 23:30:00 2017 a root
或
[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 <==删除任务
[root@linuxprobe ~]# at -l
4 Mon Apr 27 23:30:00 2017 a root
3.周期性计划任务
linux 系统则是由 cron (crond) 这个系统服务来控制的。Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的。
crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进程,crond进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。
Crontab工具:按照预先设置的时间周期(分钟、小时、天……)重复执行用户指定的命令操作;
3.1.管理cron计划任务
crontab -e 编辑计划任务
crontab -l 查看计划任务
crontab -u username -e 在username用户下编辑计划任务
crontab -u username -l 查看username下的计划任务
crontab -u username -r 删除某个用户的计划任务
注意:root用户可以管理指定用户的计划任务;普通用户只能管理自己的计划任务
3.2.时间数值的特殊表示方法
* 表示该范围内的任意时间
, 表示间隔的多个不连续时间点
- 表示一个连续的时间范围
/ 指定间隔的时间频率
示例:
0 17 * * 1-5 周一到周五每天17:00
30 8 * * 1,3,5 每周一、三、五的8点30分
0 8-18/2 * * * 8点到18点之间每2小时
0 * */3 * * 每3天
注意:在crond服务的计划任务参数中,所有命令一定要用绝对路径的方式来写,如果不知道绝对路径,请用whereis命令进行查询
示例:
[root@linuxprobe ~]# whereis rm
rm: /usr/bin/rm /usr/share/man/man1/rm.1.gz /usr/share/man/man1p/rm.1p.gz
感悟:有人说学linux不会shell编程,就是不懂linux。前面也知道shell编程,但感觉太难,就没有去练。这两天认真的学习了shell脚本基础,总结了一些经验,算是入了门,希望后面能学会shell编程。
参考资料
刘瑞 Linux就该怎么学
吴光科 曝光-linux企业运维实战