20.1 Shell脚本介绍
20.2 Shell脚本结构和执行
20.3 date命令用法
Y年 m月 d日
[root@centos01 shell]# date +%Y%m%d
20181026
H小时 M分钟 S秒
[root@centos01 shell]# date +%H-%M-%S
03-56-41
F 代表年月日
[root@centos01 shell]# date +%F
2018-10-26
T 代表小时 分钟 秒
[root@centos01 shell]# date +%T
03:25:34
s(小写)时间戳
把当前时间转换成时间戳
[root@centos01 shell]# date +%s
1540539856
把时间戳转换成时间
[root@centos01 shell]# date -d @1540539856
Fri Oct 26 03:44:16 EDT 2018
把以前的时间转换成时间戳
[root@centos01 shell]# date +%s -d "2017-10-26 03:44:16"
1509003856
把以前的时间戳转换成时间
[root@centos01 shell]# date -d @1509003856
Thu Oct 26 03:44:16 EDT 2017
w 周(0--6)0代表周日
[root@centos01 shell]# date +%w
5
W(大写) 今年的第几周
[root@centos01 shell]# date +%W
43
-1 day 一天以前
date -d "-1 day" +%F
一小时以前
date -d "-1 hour"
一分钟以前
date -d "-1 min"
-1 month 一月以前
date -d "-1 month" +%F
-1 year 一年以前
date -d "-1 year" +%F
20.4 Shell脚本中的变量
20.5 Shell脚本中的逻辑判断
-gt 大于 -lt 小于 -ge 大于等于 -le 小于等于 -eq 等于 -ne 不等于
[ $a -gt 5 ] 注意方括号里面有空格
&& 并且 前面的成立的时候才会执行后面的
|| 或者 前面不成立的时候才会执行后面的
20.6 文件目录属性判断
20.7 if特殊用法
-w 精确匹配一个词 -q 匹配到不显示 !没有过滤到这个用户
20.8 case判断(上)
案例
#!/bin/bash
read -p "Please input a number: " n
if [ -z "$n" ]
then
echo "Please input a number."
exit 1
fi
n1=`echo $n|sed 's/[0-9]//g'`
if [ -n "$n1" ]
then
echo "Please input a number."
exit 1
fi
if [ $n -lt 60 ] && [ $n -ge 0 ]
then
tag=1
elif [ $n -ge 60 ] && [ $n -lt 80 ]
then
tag=2
elif [ $n -ge 80 ] && [ $n -lt 90 ]
then
tag=3
elif [ $n -ge 90 ] && [ $n -le 100 ]
then
tag=4
else
tag=0
fi
case $tag in
1)
echo "no good"
;;
2)
echo "good"
;;
3)
echo "very good"
;;
4)
echo "great"
;;
*)
echo "The number range is 0-100."
;;
esac
20.10 for循环
ls 会以空隔为分隔符,注意!
20.11 while循环(上)
20.12 while循环(下)
20.13 break跳出循环
20.14 continue结束本次循环
执行过程
[root@centos01 shell]# sh -x continue.sh
++ seq 1 5
+ for i in '`seq 1 5`'
+ echo 1
1
+ '[' 1 -eq 3 ']'
+ echo 1
1
+ for i in '`seq 1 5`'
+ echo 2
2
+ '[' 2 -eq 3 ']'
+ echo 2
2
+ for i in '`seq 1 5`'
+ echo 3
3
+ '[' 3 -eq 3 ']'
+ continue
+ for i in '`seq 1 5`'
+ echo 4
4
+ '[' 4 -eq 3 ']'
+ echo 4
4
+ for i in '`seq 1 5`'
+ echo 5
5
+ '[' 5 -eq 3 ']'
+ echo 5
5
+ echo ok
ok
20.15 exit退出整个脚本
课堂串讲
20.1 shell脚本介绍
20.2 shell脚本结构和执行
20.3 date命令用法
20.4 shell脚本中的变量
20.1 shell脚本介绍
shell
是一种脚本语言
。它既有自己的语法规制,可以使用逻辑判断、循环等语法
,也可以自定义函数
。
shell是系统命令的集合
,并且通过主机的语法可以对命令进行判断等。
shell脚本可以实现自动化运维
,它能大大增加我们的运维效率。
20.2 Shell脚本结构和执行
- shell脚本结构
- 开头需要加
#!/bin/bash
#!/bin/bash
是告诉系统通过/bin/bash解析器
来解析操作脚本的 - 以
#
开头的行作为解释说明 - 脚本的名字以
.sh
结尾,用于区分这是一个shell脚本
- 开头需要加
1 | [root@kun05 shell]# vim hello.sh |
1 2 3 4 5 | #!/bin/bash # written by kun # date 2018-7-11 echo "this is first shell script." echo "Hello World!" |
- 执行方法有两种
- chmod +x 1.sh; ./1.sh
- bash 1.sh
1 2 3 4 | [root@kun05 shell]# chmod a+x hello.sh [root@kun05 shell]# ./hello.sh this is first shell script. Hello World! |
也可以
1 2 3 | [root@kun05 shell]# sh hello.sh this is first shell script. Hello World! |
查看脚本执行过程 bash -x 1.sh
1 2 3 4 5 | [root@kun05 shell]# sh -x hello.sh + echo 'this is first shell script.' this is first shell script. + echo 'Hello World!' Hello World! |
查看脚本是否语法错误 bash -n 1.sh
1 2 3 4 5 6 | #!/bin/bash # written by kun # date 2018-7-11 echo "this is first shell script." echo "Hello World!" for |
1 2 3 | [root@kun05 shell]# sh -n hello.sh hello.sh:行6: 未预期的符号 `newline' 附近有语法错误 hello.sh:行6: `for ' |
这里是for循环没写完整
20.3 date命令用法
date 显示当前系统时间 在shell脚本中才用于标志时间
1 2 | [root@kun05 shell]# date 2018年 07月 12日 星期四 05:45:33 CST |
命令 | 含义 |
---|---|
date +%Y | 年(4位) |
date +%y | 年(2位) |
date +%m | 月 |
date +%d | 日 |
date +%D | 以 月/日/年 格式显示日期 |
date +%F | 以 年-月-日 格式显示日期 |
date +%H | 小时 |
date +%M | 分钟 |
date +%S | 秒 |
date +%T | 以时:分:秒 格式显示时间 等于 date +%H:%M:%S |
date +%s | 时间戳 表示距离1970年1月1日到现的秒数 |
date +%w | 这个星期的第几周 |
date +%W | 今年的第几周 |
date +%h | 月份缩写 等于 date +%b |
date -d “-1 day” | 一天前 |
date -d “+1 day” | 一天后 |
date -d “-1 year” | 一年前 |
date -d “-1 month” | 一个月前 |
date -d “-1 hour” | 一小时前 |
date -d “-1 min” | 一分钟前 |
显示日期
1 2 3 4 5 6 7 8 | [root@kun05 shell]# date +%Y%m%d 20180712 [root@kun05 shell]# date +%D 07/12/18 [root@kun05 shell]# date +%F 2018-07-12 |
显示时间
1 2 | [root@kun05 shell]# date +%T 06:02:30 |
显示时间戳
1 2 | [root@kun05 shell]# date +%s 1531346417 |
显示一天后的时间
1 2 | [root@kun05 shell]# date -d "+1 day" +%F 2018-07-13 |
显示一小时前的时间
1 2 | [root@kun05 shell]# date -d "-1 hour" +%T 05:20:06 |
用时间戳来显示日期
1 2 | [root@kun05 shell]# date -d @1531346417 2018年 07月 12日 星期四 06:00:17 CST |
指定时间来显示对应的时间戳
1 2 | [root@kun05 shell]# date +%s -d"2018-07-13 06:02:30" 1531432950 |
cal 显示系统日历
1 2 3 4 5 6 7 8 | [root@kun05 shell]# cal 七月 2018 日 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
20.4 Shell脚本中的变量
- 当脚本中使用某个字符串较频繁并且字符串长度很长时就应该使用变量代替,既可以更加工作效率,也可以方便更改
- 使用条件语句时,常使用变量 if [ $a -gt 1 ]; then … ; fi
- 引用某个命令的结果时,用变量替代 n=`wc -l 1.txt`
- 写和用户交互的脚本时,变量也是必不可少的 read -p “Input a number: “ n; echo $n 如果没写这个n,可以直接使用$REPLY
- 内置变量 $0, $1, $2…
$0
表示脚本本身文件名
,$1
表示第一个参数
,$2
第二个 ….$#
表示参数个数
- 数学运算a=1;b=2;
c=$(($a+$b))
或者$[$a+$b]
20.5 shell脚本中的逻辑判断
20.6 文件目录属性判断
20.7 if特殊用法
20.8/20.9 case判断
20.5 Shell脚本中的逻辑判断
语法格式
格式1:if 条件 ; then 语句; fi
脚本形式
1 2 3 4 5 6 7 8 | [root@kun05 shell]# vim if1.sh #!/bin/bash a=3 if [ $a -gt 2 ] then echo ok fi |
1 2 | [root@kun05 shell]# sh if1.sh ok |
命令行形式
1 2 3 | [root@kun05 shell]# a=3 [root@kun05 shell]# if [ $a -gt 2 ];then echo ok;fi ok |
或者
1 2 3 4 5 | [root@kun05 shell]# a=3 [root@kun05 shell]# if [ $a -gt 2 ] > then echo ok > fi ok |
格式2:if 条件; then 语句; else 语句; fi
1 2 3 4 5 6 7 8 9 10 | [root@kun05 shell]# vim if2.sh #!/bin/bash a=1 if [ $a -gt 2 ] then echo ok else echo nook fi |
1 2 3 4 5 | [root@kun05 shell]# sh -x if2.sh + a=1 + '[' 1 -gt 2 ']' + echo nook nook |
格式3:if 条件1; then 语句1;elif 条件2; then 语句2; else 语句3; fi
意思为符合条件1则执行语句1,不符合则再判断是否符合条件2,都不符合则执行语句3
1 2 3 4 5 6 7 8 9 10 11 12 13 | [root@kun05 shell]# vim if3.sh #!/bin/bash a=2 if [ $a -eq 3 ] then echo "the num = 3" elif [ $a -gt 3 ] then echo "the num > 3" else echo "the num < 3" fi |
1 2 3 4 5 6 | [root@kun05 shell]# sh -x if3.sh + a=2 + '[' 2 -eq 3 ']' + '[' 2 -gt 3 ']' + echo 'the num < 3' the num < 3 |
逻辑判断表达式:if [ $a -gt $b ]
if [ $a -lt 5 ]
if [ $b -eq 10 ]
也可以使用数学形式 if (($a>$b))
if(($a<5))
if(($b==10))
为了方便记忆 我们可以选择记忆带[]格式的表达式,但要注意[]两侧都是空格
参数 | 数学符号 | 含义 |
---|---|---|
-gt | > | 大于(greater than) |
-lt | < | 小于 (less than) |
-eq | == | 等于(equal) |
-ge | >= | 大于等于 |
-le | <= | 小于等于 |
-ne | != | 不等于 |
可以使用 &&
||
结合多个条件if [ $a -gt 5 ] && [ $a -lt 10 ]
&&表示并且if [ $b -gt 5 ] || [ $b -lt 3 ]
||表示或者
20.6 文件目录属性判断
参数 | 含义 |
---|---|
[ -f file ] | 判断是否是普通文件,且存在 |
[ -d file ] | 判断是否是目录,且存在 |
[ -e file ] | 判断文件或目录是否存在 |
[ -r file ] | 以当前用户来判断文件是否可读 |
[ -w file ] | 以当前用户来判断文件是否可写 |
[ -x file ] | 以当前用户来判断文件是否可执行 |
判断文件是否存在
1 2 3 4 5 6 7 8 9 10 | [root@kun05 shell]# vim file1.sh #!/bin/bash f="/tmp/test" if [ -f $f ] then echo "$f exist" else touch $f fi |
第一次文件不存在则创建文件
1 2 3 4 | [root@kun05 shell]# sh -x file1.sh + f=/tmp/test + '[' -f /tmp/test ']' + touch /tmp/test |
第二次文件存在
1 2 3 4 5 | [root@kun05 shell]# sh -x file1.sh + f=/tmp/test + '[' -f /tmp/test ']' + echo '/tmp/test exist' /tmp/test exist |
判断文件/目录是否存在
1 2 3 4 5 6 | #!/bin/bash f="/tmp/test" if [ -e $f ] then touch $f fi |
即使已经存在了再touch则会更改文件/目录的是时间
判断文件是否可读
1 2 3 4 5 6 7 8 | [root@kun05 shell]# vim file2.sh #!/bin/bash f="/tmp/test" if [ -r $f ] then echo "$f readable" fi |
1 2 | [root@kun05 shell]# sh file2.sh /tmp/test readable |
有时候为了方便可以写成下面代码
1 2 3 | #!/bin/bash f="/tmp/test" [ -f $f ] && rm -f $f |
它表示文件存在则执行rm语句 等同于
1 2 3 4 5 6 | #!/bin/bash f="/tmp/test" if [ -f $f ] then rm -f $f fi |
[ -f $f ] || rm -f $f
它表示文件不存在则执行rm语句 等同于[ ! -f $f ] && rm -f $f
20.7 if特殊用法
参数 | 含义 |
---|---|
[ -z “$a” ] | 表示当变量a的值为空 |
[ -n “$a” ] | 表示当变量a的值不为空 |
判断变量是否不为空
1 2 3 4 5 6 7 8 | [root@kun05 shell]# vim file3.sh #!/bin/bash f=/tmp/test if [ -n "$f" ] then echo ok fi |
1 2 | [root@kun05 shell]# sh file3.sh ok |
-
其他特殊用法
-
使用命令来做判断条件
1 2
[root@kun05 shell]# if grep -wq 'root' /etc/passwd;then echo root exist;fi root exist
grep -w 'root'
只搜索root此单词-q
不在屏幕打印出来 - 使用! 在参数前 表示取反 [ ! -e file ] 表示文件不存在
- 中括号中不能使用<,>,==,!=,>=,<=这样的符号
-
20.8/20.9 case判断
语法格式
1 2 3 4 5 6 7 8 9 10 11 | case 变量名 in value1) command ;; value2) command ;; *) commond ;; esac |
在case程序中,可以在条件中使用|
,表示或
的意思, 比如
1 2 3 | 2|3) command ;; |
判断学生的成绩脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | [root@kun05 shell]# vim case1.sh #!/bin/bash read -p "Please input number: " n #让用户输入数字 if [ -z "$n" ] then echo "Please input number: " exit 1 fi #判断用户是否没填数字 n1=`echo $n|sed 's/[0-9]//g'` if [ ! -z "$n1" ] then echo "Please input number: " exit 1 fi #判断用户是否填纯数字 if [ $n -lt 60 ] then tag=1 elif [ $n -ge 60 ] && [ $n -lt 80 ] then tag=2 elif [ $n -ge 80 ] && [ $n -lt 90 ] then tag=3 elif [ $n -ge 90 ] && [ $n -le 100 ] then tag=4 else tag=0 fi #给分数赋值给tag case $tag in 1) echo "bu ji he" ;; 2) echo "liang hao" ;; 3) echo "you xiu" ;; 4) echo "fei chang bang" ;; *) echo "The number range is 0-100" ;; esac #对tag进行判断 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | [root@kun05 shell]# sh -x case1.sh + read -p 'Please input number: ' n Please input number: asdfsad + '[' -z asdfsad ']' ++ echo asdfsad ++ sed 's/[0-9]//g' + n1=asdfsad + '[' '!' -z asdfsad ']' + echo 'Please input number: ' Please input number: + exit 1 [root@kun05 shell]# sh -x case1.sh + read -p 'Please input number: ' n Please input number: 89 + '[' -z 89 ']' ++ echo 89 ++ sed 's/[0-9]//g' + n1= + '[' '!' -z '' ']' + '[' 89 -lt 60 ']' + '[' 89 -ge 60 ']' + '[' 89 -lt 80 ']' + '[' 89 -ge 80 ']' + '[' 89 -lt 90 ']' + tag=3 + case $tag in + echo 'you xiu' you xiu |
20.10 for循环
20.11/20.12 while循环
20.13 break跳出循环
20.14 continue结束本次循环
20.15 exit退出整个脚本
20.10 for循环
语法格式
1 | for 变量名 in 条件; do …; done |
计算出0到100的总和
1 2 3 4 5 6 7 8 9 | [root@kun05 shell]# vim for1.sh #!/bin/bash sum=0 for i in `seq 1 100` do sum=$[$i+$sum] done echo $sum |
1 2 | [root@kun05 shell]# sh for1.sh 5050 |
遍历/etc目录并把目录列出来
1 2 3 4 5 6 7 8 | [root@kun05 shell]# vim for2.sh #!/bin/bash cd /etc for i in `ls /etc` do [ -d $i ] && ls $i done |
注意
:for循环是以空格
作为分隔符 ,因此文件名中到空格的要注意
1 2 3 4 5 6 7 8 | [root@kun05 for]# touch 1 2 [root@kun05 for]# touch 3\ 4.txt [root@kun05 for]# ll 总用量 0 -rw-r--r-- 1 root root 0 7月 14 05:07 1 -rw-r--r-- 1 root root 0 7月 14 05:07 2 -rw-r--r-- 1 root root 0 7月 14 05:07 3 4.txt |
1 2 3 4 5 | [root@kun05 for]# for i in `ls .`;do echo $i;done 1 2 3 4.txt |
这里for循环把3 4.txt 分为了两个文件
20.11/20.12 while循环
语法格式
1 | while 条件; do … ; done |
每隔30秒查看系统负载,当大于10时发邮件
1 2 3 4 5 6 7 8 9 10 11 12 | [root@kun05 shell]# vim while1.sh #!/bin/bash while : do load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d . -f1` if [ $load -gt 10 ] then /usr/local/sbin/mail.py coco44566@163.com "load high" "$load" fi sleep 30 done |
1 2 3 4 5 6 7 8 9 | [root@kun05 shell]# sh -x while1.sh + : ++ head -1 ++ awk -F 'load average: ' '{print $2}' ++ cut -d . -f1 ++ w + load=0 + '[' 0 -gt 10 ']' + sleep 30 |
:
ture
1
都是代表为正
因此while :
就是一个死循环
为了不让while脚本不意外终止 可以使用screen
命令 再到screen下执行此脚本
提示让用户只能输入数字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | [root@kun05 shell]# vim while2.sh #!/bin/bash while : do read -p "Please input a number: " n if [ -z "$n" ] then echo "Please input sth!" continue fi ##判断用户是否直接回车 n1=`echo $n|sed 's/[0-9]//g'` if [ -n "$n1" ] then echo "Please input number!" continue fi #判断用户是否输入纯数字 echo $n break done |
1 2 3 4 5 6 7 | [root@kun05 shell]# sh while2.sh Please input a number: Please input sth! Please input a number: a Please input number! Please input a number: 1 1 |
echo $n|sed 's/[0-9]//g
把数字给过滤掉来判断是否有其他字符
20.13 break跳出循环
1 2 3 4 5 6 7 8 9 10 11 12 13 | [root@kun05 shell]# vim break.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then break fi echo $i done echo aaaa |
1 2 3 4 5 6 7 | [root@kun05 shell]# sh break.sh 1 1 2 2 3 aaaa |
20.14 continue结束本次循环
忽略continue之下的代码,直接进行下一次循环
1 2 3 4 5 6 7 8 9 10 11 12 13 | [root@kun05 shell]# vim continue.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then continue fi echo $i done echo aaaa |
1 2 3 4 5 6 7 8 9 10 11 | [root@kun05 shell]# sh continue.sh 1 1 2 2 3 4 4 5 5 aaaa |
20.15 exit退出整个脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 | [root@kun05 shell]# vim exit.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then exit 1 fi echo $i done echo aaaa |
1 2 3 4 5 6 | [root@kun05 shell]# sh exit.sh 1 1 2 2 3 |
返回exit 后面设置的值
1 2 | [root@kun05 shell]# echo $? 1 |
总结
break
,continue
都是在for
while
循环中使用的- break出现时候会跳出本次循环 直接忽略掉了break后面的代码
- continue出现时候也会忽略掉了continue后面的代码并重新再来执行循环
- exit直接跳出脚本 一般exit 后面会跟一个数字 给用户返回该值