目录html
1、shell脚本介绍
2、shell脚本结构和执行
3、date命令用法
4、shell脚本中的变量
5、hell脚本中的逻辑判断
6、文件目录属性判断
7、if特殊用法
8、case判断
9、for循环
10、while循环
11、break跳出循环
12、continue结束本次循环
十3、exit退出整个脚本
十4、扩展linux
shell是一种脚本语言, 是用户与内核进行交互的一种接口。shell
shell可使用逻辑判断、循环等语法,也能够自定义函数。编程
shell是系统命令的集合vim
shell脚本能够实现自动化运维,能大大增长咱们的运维效率bash
shell脚本一般在编辑器中编写,由命令及其注释组成,注释是跟在#号后的内容,用来对脚本进行解释。less
第一行 位于脚本左上角的第一行会指出由哪一个程序来执行脚本中的行。这一行一般称为shbang,写做#!/bin/bash运维
一个bash shell程序由一组unix/linux命令、bash命令、程序结构控制语句和注释组成编辑器
为便于区分,通常以.sh结尾。函数
例如:
#!/bin/bash # Scriptname: greet for name in $* # same as for name in $@ do echo Hi $name done
shell的执行方式有二种
//执行方式1 [root@localhost sh]# vim greet.sh [root@localhost sh]# chmod u+x greet.sh [root@localhost sh]# ./greet.sh kennminn Hi kennminn 或者 [root@localhost sh]# chmod u+x greet.sh [root@localhost sh]# pwd /root/script/sh [root@localhost sh]# /root/script/sh/greet.sh kennminn Hi kennminn //执行方式2 [root@localhost sh]# bash greet.sh kennminn Hi kennminn
查看脚本的执行过程 bash -x script-name
[root@localhost sh]# bash -x greet.sh kennminn + for name in '$*' + echo Hi kennminn Hi kennminn
查看脚本是否有语法错误
//没有语法错误时 [root@localhost sh]# bash -n greet.sh kennminn //将最后一行的done删掉 [root@localhost sh]# vim greet.sh #!/bin/bash # Scriptname: greet for name in $* # same as for name in $@ do echo Hi $name [root@localhost sh]# bash -n greet.sh kennminn greet.sh: line 7: syntax error: unexpected end of file
date命令打印系统日期和时间。
[root@localhost sh]# date Sun Jul 29 21:08:24 EDT 2018
经常使用格式
命令 | 含义 |
---|---|
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" | 一分钟前 |
eg:
//显示日期 [root@localhost sh]# date +%Y-%m-%d 2018-07-29 [root@localhost sh]# date +%F 2018-07-29 [root@localhost sh]# date +%D 07/29/18 //显示时间 [root@localhost sh]# date +%H:%M:%S 09:22:23 [root@localhost sh]# date +%T 09:22:30 //显示时间戳 [root@localhost sh]# date +%s 1532913790 //显示1天后的日期 [root@localhost sh]# date -d "+1 day" Tue Jul 31 09:24:16 CST 2018 //显示1天前的日期 [root@localhost sh]# date -d "-1 day" Sun Jul 29 09:24:43 CST 2018 //显示1小时前的时间 [root@localhost sh]# date -d "-1 hour" +%T 08:25:43 //将时间戳以日期格式显示 [root@localhost sh]# date -d @1532913790 Mon Jul 30 09:23:10 CST 2018 //显示指定日期的时间戳 [root@localhost sh]# date +%s -d "2018-06-23" 1529683200 //显示日历 [root@localhost sh]# cal July 2018 Su Mo Tu We Th Fr Sa 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 //显示指定月的日历 [root@localhost sh]# cal 7 17 July 17 Su Mo Tu We Th Fr Sa 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
变量就是为某个信息片断所起的名字,标志内存中的一段地址。
当脚本中使用某个字符串较频繁而且字符串长度很长时就应该使用变量代替
使用条件语句时,常使用变量 if [ $a -gt 1 ]; then ... ; fi
引用某个命令的结果时,用变量替代 n=wc -l 1.txt
或者n=$(wc -l 1.txt)
写和用户交互的脚本时,变量也是必不可少的 read -p "Input a number: " n; echo $n 若是没有指定变量名n,默认变量名为REPLY
内置变量 $0, $1, $2… $0表示脚本自己,$1 第一个参数,$2 第二个 .... $#表示参数个数,
$*表示获取当前shell脚本全部传参的个数,不加引号和$@相同,加上引号则将全部的参数视为单个字符串。至关于”$1 $2 $3”。
$@表示获取当前shell脚本全部传参的参数,不加引号和$*相同。若是给$@加上双引号,例如”$@”,则表示将全部的参数视为不一样的独立字符串,至关于”$1”,”$2”,”$3”….这是将多参数传递给其余程序的最佳方式,由于它会保留全部的内嵌在每一个参数里的任何空白。当”$@”和”$*”都加双引号时,二者是有区别的,都不加双引号,二者无区别。
变量有环境变量和用户自定义变量
用户自定义变量变量名能够由一个字母、数字或下划线符号组成,不能以数字开头。长度不超过20个字符。变量名区分大小写,请留意:Var1 和var1不是同一个变量。
例如:
//等号(=)两端不能有空格 //引用变量值的方式:在变量名前加$ [root@localhost sh]# name=terry [root@localhost sh]# echo $name terry [root@localhost sh]# name =terry -bash: name: command not found
shell中只能进行整数运行,若是须要进行浮点数,须要借助bc命令
整数运算语法
1.$[ ]
[root@localhost sh]# n=5;echo $[$n+1] 6
2.$(())
[root@localhost sh]# n=5;echo $(($n+1)) 6 [root@localhost sh]# n=5;echo $((n+1)) 6
3.(())
[root@localhost sh]# ((n+=1));echo $n 6
4.expr
//注意+号两边要有空格 [root@localhost sh]# expr 4 + 5 9 [root@localhost sh]# r=`expr 4 + 5` [root@localhost sh]# echo $r 9
5.let
[root@localhost sh]# let n=n+1 [root@localhost sh]# echo $n 1
格式1:if 条件 ; then 语句; fi
[root@localhost sh]# vim if1.sh #!/bin/bash a=3 if [ $a -gt 2 ] then echo ok! fi [root@localhost sh]# chmod u+x if1.sh [root@localhost sh]# ./if1.sh ok! 或者 [root@localhost sh]# a=3;if [ $a -gt 2 ]; then echo ok! ; fi ok!
格式2:if 条件; then 语句; else 语句; fi
[root@localhost sh]# vim if2.sh #!/bin/bash a=1 if [ $a -gt 2 ] then echo ok! else echo It\'s no ok! fi [root@localhost sh]# ./if2.sh It's no ok! [root@localhost sh]# sh -x ./if2.sh + a=1 + '[' 1 -gt 2 ']' + echo 'It'\''s' no 'ok!' It's no ok!
格式3:if …; then … ;elif …; then …; else …; fi
[root@localhost sh]# vim if3.sh #/bin/bash a=2 if [ $a -eq 3 ];then echo The number is three. elif [ $a -gt 3 ];then echo the number is great then three. else echo the number is less then three. fi [root@localhost sh]# chmod u+x if3.sh [root@localhost sh]# ./if3.sh the number is less then three. [root@localhost sh]# sh -x ./if3.sh + a=2 + '[' 2 -eq 3 ']' + '[' 2 -gt 3 ']' + echo the number is less then three. the number is less then three.
test命令的数值比较功能
比较 | 描述 |
---|---|
n1 -eq n2 | 检查n1是否等于n2 |
n1 -ge n2 | 检查n1是否大于等于n2 |
n1 -gt n2 | 检查n1是否大于n2 |
n1 -le n2 | 检查n1是否小于等于n2 |
n1 -lt n2 | 检查n1是否小于n2 |
n1 -ne n2 | 检查n1是否不等于n2 |
test命令的字符串比较
比较 | 描述 |
---|---|
str1 = str2 | 检查str1和str2是否相等 |
str1 != str2 | 检查str1和str2是否不相等 |
str1 < str2 | 检查str1是否比str2小 |
str1 > str2 | 检查str1是否比str2大 |
可使用 && ||结合多个条件
if [ $a -gt 5 ] && [ $a -lt 10 ] &&表示而且
if [ $b -gt 5 ] || [ $b -lt 3 ] ||表示或者
文件比较
比较 | 描述 |
---|---|
-d file | 检查文件是否存且是一个目录 |
-e file | 检查文件是否存在 |
-f file | 检查文件是否存且是一个文件 |
-r file | 检查文件是否存在且可读 |
-s file | 检查文件是否存在且非空 |
-w file | 检查文件是否存在并可写 |
-x file | 检查文件是否存在并可执行 |
-o file | 检查文件是否存在并属当前用户全部 |
-G file | 检查文件是否存在而且默认组与当前用户相同 |
file1 -nt file2 | 检查file1是否比file2新 |
file1 -ot file2 | 检查file1是否比file2旧 |
[root@localhost sh]# vim file1.sh #/bin/bash f1='/tmp/tt.txt' if [ -f $f1 ];then echo "$f exist" else touch $f1 fi //第一次文件不存在时 [root@localhost sh]# sh -x file1.sh + f1=/tmp/tt.txt + '[' -f /tmp/tt.txt ']' + touch /tmp/tt.txt //第二次文件已经存在 [root@localhost sh]# sh -x file1.sh + f1=/tmp/tt.txt + '[' -f /tmp/tt.txt ']' + echo ' exist' exist //判断文件目录是否存在 [root@localhost sh]# cp file1.sh file2.sh [root@localhost sh]# vim file2.sh #/bin/bash f1='/tmp/tt.txt' if [ -f $f1 ];then echo "$f exist" fi [root@localhost sh]# ./file2.sh exist //判断文件是否可读 [root@localhost sh]# cp file2.sh file3.sh [root@localhost sh]# vim file3.sh #/bin/bash f1='/tmp/tt.txt' if [ -r $f1 ];then echo "$f is readable" fi [root@localhost sh]# ./file3.sh is readable
比较 | 描述 |
---|---|
-n str2 | 检查str1的长度是否非0 |
-z str2 | 检查str1的长度是否为0 |
[root@localhost sh]# vim file4.sh #!/bin/bash file='/tmp/tt.txt' if [ -n "$file" ];then echo "the file $file is not empty" fi [root@localhost sh]# ./file4.sh the file /tmp/tt.txt is empty
其余特殊用法
使用命令来作判断条件
//-q表示静默模式 //grep命令匹配其返回值是0,若是没有匹配则返回值是非0 [root@localhost sh]# if grep -q 'hjm' /etc/passwd;then echo user exist;fi user exist
使用! 在参数前 表示取反 [ ! -e file ] 表示文件不存在
中括号中不能使用<,>,==,!=,>=,<=这样的符号
语法:
case 变量名 in value1) command ;; value2) command ;; *) commond ;; esac
在case程序中,能够在条件中使用|,表示或的意思, 好比
a|b) command ;;
eg
[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 [root@localhost sh]# vim grade.sh [root@localhost sh]# sh -x ./grade.sh + read -p 'Please input number: ' n Please input number: 60 + '[' -z 60 ']' ++ echo 60 ++ sed 's/[0-9]//g' + n1= + '[' '!' -z '' ']' + '[' 60 -lt 60 ']' + '[' 60 -ge 60 ']' + '[' 60 -lt 80 ']' + tag=2 + case $tag in + echo 'liang hao' liang hao
语法格式
for 变量名 in 条件; do …; done
eg
//计算1到100的和 [root@localhost sh]# vim sum.sh #!/bin/bash result=0 for i in $(seq 1 100) do result=$((result+i)) done echo $result [root@localhost sh]# chmod u+x sum.sh [root@localhost sh]# ./sum.sh 5050 //遍历/etc目录并把目录列出来 [root@localhost sh]# vim for2.sh #!/bin/bash cd /etc for file in * do [ -d $file ] && ls $file done [root@localhost sh]# chmod u+x for2.sh [root@localhost sh]# ./for2.sh | more abrt-action-save-package-data.conf abrt.conf gpg_keys.conf plugins ld libnssckbi.so.x86_64 mta mta-aliasesman ...下略
语法格式
while 条件; do … ; done
eg
//每隔30秒查看系统负载,当大于10时发邮件 [root@localhost sh]# 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 [root@localhost sh]# chmod u+x while1.sh [root@localhost sh]# sh -x while1.sh + : ++ w ++ cut -d . -f1 ++ awk -F 'load average: ' '{print $2}' ++ head -1 + load=0 + '[' 0 -gt 10 ']' + sleep 30 : ture 1 都是表明为正 所以while : 就是一个死循环 为了避免让while脚本不意外终止 可使用screen命令 再到screen下执行此脚本 //提示让用户只能输入数字 [root@localhost sh]# 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 [root@localhost sh]# sh while2.sh Please input a number: a Please input number! Please input a number: v Please input number! Please input a number: 1 1 echo $n|sed 's/[0-9]//g 把数字替换为空,再来判断剩下的内容
eg
[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 [root@localhost sh]# chmod u+x break.sh [root@localhost sh]# ./break.sh [root@localhost sh]# ./break.sh 1 1 2 2 3 aaaa
忽略本次循环,直接进行下一次循环
eg
[root@localhost sh]# mv break.sh continue.sh [root@localhost sh]# 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 [root@localhost sh]# ./continue.sh 1 1 2 2 3 4 4 5 5 aaaa
eg
[root@localhost sh]# mv continue.sh exit.sh [root@localhost sh]# 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 [root@localhost sh]# ./exit.sh 1 1 2 2 3
总结:
break,continue都是在for while循环中使用的
break出现时候会跳出本次循环 直接忽略掉了break后面的代码
continue出现时候也会忽略掉了continue后面的代码并从新再来执行循环
exit直接跳出脚本 通常exit 后面会跟一个数字 给用户返回该值
select用法
http://www.apelearn.com/bbs/thread-7950-1-1.html