•shell是一种脚本语言 •可使用逻辑判断、循环等语法 •能够自定义函数 •shell是系统命令的集合 •shell脚本能够实现自动化运维,能大大增长咱们的运维效率
shell是什么
shell是一个命令解释器,它在操做系统的最外层,负责直接与用户对话,把用户的输入解释给操做系统,并处理各类各样的操做系统的输出结果,输出到屏幕返回给用户。这种对话方式能够是交互的方式(从键盘输入命令,能够当即获得shell的回应),或非交互(执行脚本程序)的方式
什么是shell脚本?
当linux命令或语句不在命令下执行(严格说,命令行执行的语句也是shell脚本),而是经过一个程序文件执行时,该程序就被称为shell脚本或shell程序,shell程序很相似DOS系统下的批处理程序(扩展名*.bat)。用户能够在shell脚本中敲入一系列的命令或命令语句组合。这些命令、变量和流程控制语句等有机的结合起来就造成了一个功能很强大的shell脚本。
shell脚本语言的种类
在UNIX/LINUX中主要有两大类shell。linux
•Bourne shell包括sh、ksh和bash。 •Bourne shell (sh) •Korn shell (ksh) •Bourne Again shell (bash) •POSIX shll (sh) •C shell包括csh和tcsh。 •C shell (csh) •TEXES/TOPS C shell(tcsh)
shell脚本语言是若类型语言,较为通用的shell有标准的Bourne shell(sh)和C shell(csh)。其中Bource shell(sh)已经被bash shell取代。
查看系统的shell。shell
[root@localhost ~]# cat /etc/shells /bin/sh /bin/bash #功能更强大 /sbin/nologin /bin/dash /bin/tcsh /bin/csh
•开头须要加#!/bin/bash,指定是哪一个解释器
•以#开头的做为解释说明
•脚本的名字以.sh结尾,用于区分这是一个shell脚本
•执行方法有几种
shell脚本的创建
在linux系统中,shell脚本(bash shll程序)一般是在编辑器(如vi/vim)中编写,由Unix/Linux命令、bash shell命令、程序结构控制语句和注释等内容组成
脚本开头(第一行)
一个规范的shell脚本在脚本第一行会指出由哪一个程序(解释器)来执行脚本中的内容,这一行内容在linux bash编程中通常为:
#! /bin/bash
或
#! /bin/sh <==255个字符之内
其中开头的"#!"字符又称为幻数,在执行bash脚本的时候,内核会根据"#!"后的解释器来肯定该用哪一个程序解释这个脚本的内容。注意,这一行必须在每一个脚本顶端的第一行,若是不是第一行则为脚本注释行
脚本注释
在shell脚本中,跟在(#)井号后面的内容表示注释,用来对脚本进行注释说明,注释部分不会被当作程序执行,仅仅是给用户看,系统解释器是看不到的,更不会执行。注释可自成一行,也能够跟在脚本命令后面与命令在同一行
shell脚本的执行
当shell脚本运行时,它会先查找系统环境变量ENV,该变量指定了环境文件(一般是.bashrc、.bash_profile、/etc/bashrc、/etc/profile等),而后从该环境变量文件开始执行脚本,当读取了ENV的文件后,shell会开始执行shell脚本中的内容。
特殊技巧:设置crond任务时,最好把系统环境变量在定时任务脚本中从新定义,不然,一些系统环境变量将不会被加载
执行说明
第一种方法是当脚本文件自己没有可执行权限(即文件x位为-号)时常使用的方法,或者文件开头没有指定解释器。
例如:编程
[root@localhost ~]# cat test.sh echo 'i am shell' [root@localhost ~]# sh test.sh i am shell [root@localhost ~]# bash test.sh i am shell
第二种方法须要先将脚本文件的权限改成可执行(即文件加X位),具体方法:chmod u+x script-name或chmod 755 script-name。而后经过脚本路径就能够直接执行脚本。
例如:vim
[root@localhost ~]# ll test.sh -rw-rw-r--. 1 root root 1217 7月 27 13:57 test.sh [root@localhost ~]# ./test.sh #使用第二种方式,"./"在当前目录下执行test.sh脚本文件,没法使用tab自动补全 -bash: ./test.sh: Permission denied 给test.sh添加可执行权限。 [root@localhost ~]# chmod u+x test.sh [root@localhost ~]# ./test.sh i am shell
第三种放法一般是使用source或"."点号读入或加载指定的shell脚本文件(如test.sh),而后,依次执行指定shell脚本文件test.sh中的全部语句
例如:bash
[root@lamp ~]# . test.sh i am shell [root@lamp ~]# source test.sh i am shell
说明:若是但愿父shell调用子shell的变量、函数等,用source或"."点号执行脚本less
命令:date
date 能够用来显示或设定系统的日期与时间。
命令参数运维
-d<字符串>:显示字符串所指的日期与时间。字符串先后必须加上双引号; -s<字符串>:根据字符串来设置日期与时间。字符串先后必须加上双引号;只有root权限才能设置,其余只能查看 -u:显示GMT; --help:在线帮助; --version:显示版本信息
日期格式字符串列表编辑器
%H 小时(以00-23来表示)。 %I 小时(以01-12来表示)。 %K 小时(以0-23来表示)。 %l 小时(以0-12来表示)。 %M 分钟(以00-59来表示)。 %P AM或PM。 %r 时间(含时分秒,小时以12小时AM/PM来表示)。 %s 总秒数。起算时间为1970-01-01 00:00:00 UTC。 %S 秒(以本地的惯用法来表示)。 %T 时间(含时分秒,小时以24小时制来表示)。 %X 时间(以本地的惯用法来表示)。 %Z 市区。 %a 星期的缩写。 %A 星期的完整名称。 %b 月份英文名的缩写。 %B 月份的完整英文名称。 %c 日期与时间。只输入date指令也会显示一样的结果。 %d 日期(以01-31来表示)。 %D 日期(含年月日)。 %j 该年中的第几天。 %m 月份(以01-12来表示)。 %U 该年中的周数。 %w 该周的天数,0表明周日,1表明周一,异词类推。 %x 日期(以本地的惯用法来表示)。 %y 年份(以00-99来表示)。 %Y 年份(以四位数来表示)。 %n 在显示时,插入新的一行。 %t 在显示时,插入tab。 MM 月份(必要) DD 日期(必要) hh 小时(必要) mm 分钟(必要) ss 秒(选择性)
实例:
•年月日ide
[root@localhost ~]# date +"%Y-%m-%d" 2018-07-29 [root@localhost ~]# date +"%y-%m-%d" 18-07-29
•输出昨天、前天,明天等的日期:函数
[root@localhost ~]# date -d "+1 day " +"%Y-%m-%d" 2018-07-28 [root@localhost ~]# date -d "+2 day " +"%Y-%m-%d" 2018-07-27 [root@localhost ~]# date -d "-1 day " +"%Y-%m-%d" 2018-07-30
•加减操做:
date -d "+1 day" +%Y%m%d #显示前一天的日期 date -d "-1 day" +%Y%m%d #显示后一天的日期 date -d "-1 month" +%Y%m%d #显示上一月的日期 date -d "+1 month" +%Y%m%d #显示下一月的日期 date -d "-1 year" +%Y%m%d #显示前一年的日期 date -d "+1 year" +%Y%m%d #显示下一年的日期
设定时间:
date -s #设置当前时间,只有root权限才能设置,其余只能查看 date -s 20120523 #设置成20120523,这样会把具体时间设置成空00:00:00 date -s 01:01:01 #设置具体时间,不会对日期作更改 date -s "01:01:01 2012-05-23" #这样能够设置所有时间 date -s "01:01:01 20120523" #这样能够设置所有时间 date -s "2012-05-23 01:01:01" #这样能够设置所有时间 date -s "20120523 01:01:01" #这样能够设置所有时间
•显示日历
[root@localhost ~]# 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
•当脚本中使用某个字符串,屡次频繁而且字符串长度很长时,就应该使用变量代替
•使用条件语句时,常使用变量 if [ $a -gt 1];then ...;fi
•引用某个命令的结果时,用变量替代 n=wc -l 1.txt
•写和用户交互的脚本时,变量也是必不可少的 read -p "lnput a number:" n; echo $n 若是没有写这个n, 能够直接使用$REPLY
•内置变量 $0,$1,$2... $0表示脚本自己,$1 第一个参数,$2第二个... $#: 表示参数个数
•数学运算a=1;b=2;c=$($a+$b)或者$[$a+$b]
Shell脚本中,充满着各类逻辑判断,是脚本中必备的
•if逻辑判断格式
格式1:if 条件 ; then 语句; fi 格式2:if 条件; then 语句; else 语句; fi 格式3:if …; then … ;elif …; then …; else …; fi
•数学逻辑判断表达式:
-gt (>); 大于 great than -lt(<); 小于 less than -ge(>=); 大于或等于 -le(<=); 小于或等于 -eq(==); 等于 equal -ne(!=) 不等于 not equa - - - - - - - - - - - - - - - - - - - - - - 方括号里面不能使用数学运算符<,>,=,等,两边中间都要有空格 要使用这些符号,只能使用两个括号(()),不用空格 例如 if [ $a -gt $b ]等同if (($a>$b)) if [ $a -lt 5 ]等同if (($a<5)) if [ $b -eq 10 ]等if (($b==10))
•多个条件组合-a,-o
-a表示而且,所有条件都成立 -o或者或者,知足一个条件成立 [root@localhost ~]# a=5;if [ $a -gt 4 -a $a -lt 6 ];then echo ok;fi ok [root@localhost ~]# a=5;if [ $a -gt 5 -o $a -lt 6 ];then echo ok;fi ok
•可使用 && || 结合多个条件
条件A&&条件B:A而且B 条件A||条件B:A或者B if [ $a -gt 5 ] && [ $a -lt 10 ]; then if [ $b -gt 5 ] || [ $b -lt 3 ]; then
•if逻辑判断例子
格式1:if 条件 ; then 语句; fi
#!/bin/bash a=5 if [ $a -gt 3 ] then echo "ok" fi
格式2:if 条件; then 语句; else 语句; fi
#!/bin/bash a=5 if [ $a -gt 3 ] then echo "ok" else echo "nook" fi
格式3:if …; then … ;elif …; then …; else …; fi
#!/bin/bash a=5 if [ $a -lt 4 ] then echo "<4" elif [ $a -lt 6 ] #注意elif能够嵌套屡次的 then echo "<6 && >4" else echo "nook" fi
在shell中一般要和文件或者目录打交道,那么对于他们的属性判断十分重要
[ -f file ]判断是不是普通文件,且存在 [ -d file ] 判断是不是目录,且存在 [ -e file ] 判断文件或目录是否存在 [ -r file ] 判断文件是否可读 [ -w file ] 判断文件是否可写 [ -x file ] 判断文件是否可执行
例子:
#!/bin/bash file="/tmp/1.txt" if [ -e $file ] then echo $file exist else touch $file
&& ||特殊用法,省略if
1.txt不存在,&&表示前一条命令执行成功,才会执行后面的命令 [root@localhost ~]# [ -e 1.txt ]&&touch 1.txt [root@localhost ~]# ll 总用量 4 -rw-------. 1 root root 1418 4月 26 05:41 anaconda-ks.cfg drwxr-xr-x 2 root root 60 6月 18 11:40 src1 1.txt不存在,||表示前一条命令执行不成功,才会执行后面的命令 [root@localhost ~]# [ -e 1.txt ]||touch 1.txt [root@localhost ~]# ll 总用量 4 -rw-r--r-- 1 root root 0 7月 29 22:13 1.txt -rw-------. 1 root root 1418 4月 26 05:41 anaconda-ks.cfg drwxr-xr-x 2 root root 60 6月 18 11:40 src1
if [ -z "$a" ] 这个表示当变量a的值为空时会怎么样 if [ -n "$a" ] 表示当变量a的值不为空 if grep -q '123' 1.txt; then 表示若是1.txt中含有'123'的行时会怎么样 if [ ! -e file ]; then 表示文件不存在时会怎么样 if (($a<1)); then …等同于 if [ $a -lt 1 ]; then… [ ] 中不能使用<,>,==,!=,>=,<=这样的符号
例子:
if [ -z “$a” ] 这个表示当变量a的值为空时会怎么样
#!/bin/bash n='wc -l /tmp/1.txt' if [ $n -lt 100 ] then echo "line num less than 100" fi # 若是/tmp/1.txt文件为空,或者被删除的话,脚本就会运行出错,出现bug 应该加上一个判断条件 #!/bin/bash n='wc -l /tmp/1.txt' if [ -z "$n" ] # [ -z "$n" ] 等同[ ! -n "$n" ],!表示取反 then echo "error" exit elif [ $n -lt 100 ] then echo "line num less than 100" fi 或者 #!/bin/bash if [ ! -f /tmp/1.txt ] then echo "/tmp/1.txt is not exist" exit fi n='wc -l /tmp/1.txt' if [ $n -lt 100 ] then echo "line num less than 100" fi
if [ -n “$a” ] 表示当变量a的值不为空,也能够判断文件,判断文件时能够不加双引号
if [ -n 01.sh ]; then echo "ok"; fi 另外 #!/bin/bash if [ -n "$b" ] then echo $b else echo "b is null" fi
一条命令也能够做为判断条件。判断user1用户是否存在
if grep -wq 'user1' /etc/passwd; then echo "user1 is exist"; else useradd user1;fi #grep -w 精准匹配单词,加-q能够不显示过滤信息
case判断格式
case 变量名 in value1) commond1 ;; value2) commod2 ;; value3) commod3 ;; esac
在case中,能够在条件中使用“|”,表示或的意思,如:
2|3) commond ;;
例子: 输入一个同窗的分数,判断成绩是否及格,优秀
[root@localhost sbin]# vim case1.sh #!/bin/bash read -p "Please input a number: " n # read -p 是读取用户的输入数据,定义到变量里面 if [ -z "$n" ] then echo "error not input" exit 1 #“exit 1”表示非正常运行致使退出程序 #退出以后,echo $?会返回1值,表示程序退出是由于出错了 fi n1=`echo $n|sed 's/[0-9]//g'` #判断用户输入的字符是否为纯数字 #若是是数字,则将其替换为空,赋值给$n1 if [ -n "$n1" ] then echo "Please input a number." exit 1 #判断$n1不为空时(即$n不是纯数字)再次提示用户输入数字并退出 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 #tag的做用是为判断条件设定标签,方便后面引用 case $tag in 1) echo "不及格" ;; 2) echo "及格" ;; 3) echo "良好" ;; 4) echo "优秀" ;; *) echo "The number range is 0-100." ;; esac
运行结果
[root@localhost shell]# sh case1.sh Please input a number: error not input [root@localhost shell]# sh case1.sh Please input a number: 12a23 Please input a number. [root@localhost shell]# sh case1.sh Please input a number: 45 不及格 [root@localhost shell]# sh case1.sh Please input a number: 65 及格 [root@localhost shell]# sh case1.sh Please input a number: 85 良好 [root@localhost shell]# sh case1.sh Please input a number: 95 优秀 [root@localhost shell]# sh case1.sh Please input a number: 120 The number range is 0-100.
•格式:
for 变量名 in 条件; do ...; done
例子:
•用for循环计算1到100的总和
[root@localhost shell]# cat for.sh #!/bin/bash sum=0 for i in `seq 1 100` do sum=$[$sum+$i] done echo $sum #输出的结果 [root@localhost shell]# sh for.sh 5050
•文件列表循环
[root@localhost shell]# cat for2.sh #!/bin/bash cd /etc/ for a in `ls /etc/` do if [ -d $a ] then ls -d $a fi done #for循环是以空格、回车符做为分割符分割。
•语法 while 条件; do ...; done
例子:
用while循环检测系统1分钟的负载,若是大于,发邮件通知
#!/bin/bash while : #while 跟冒号表示死循环 do load=`w|head -1 |awk -F 'load average: ' '{print $2}'| cut -d . -f1` if [ $load -gt 10 ] then top|mail -s "load is high:$load" admin@163.com fi sleep 30 done
循环判断输入的是否纯数字
#!/bin/bash while : do read -p "Please input a number:" n if [ -z "$n" ] then echo "You did not enter the number." continue fi n1=`echo $n|sed 's/[0-9]//g'` if [ ! -z "$n1" ] then echo "You can only enter a pure number." continue fi break done echo $n
break表示跳出循环,断续执行后面的语句
例子
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then break fi echo $i done echo aaaaaa
运行结果
[root@localhost ~]# sh break.sh 1 1 2 2 3 aaaaaa
能够看到上例中,只循环到第3次的时候,跳出了循环,直接执行了echo aaaaaa的语句
continue结束本次循环,不执行后面的语句,直到循环结束
[root@localhost etc]# cat continue.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then continue fi echo $i done echo aaaaaa
运行结果
[root@localhost etc]# sh continue.sh 1 1 2 2 3 4 4 5 5 aaaaaa
能够看到循环到第3次的时候,没有执行后面的语句,直到循环结束
exit退出脚本
[root@localhost etc]# cat exit.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then exit fi echo $i done echo aaaaaa
运行结果
[root@localhost etc]# sh exit.sh 1 1 2 2 3
能够看到第三次,直接退出了脚本