第二十章 shell编程
20.1 shell介绍
- shell是一种脚本语言
- 可以使用逻辑判断、循环等语法
- 可自定义函数
- shell是系统命令的集合
- shell脚本可以实现自动化运维,能大大增加我们的运维效率
20.2 shell脚本结构和执行
结构
- 开头需要“#!/bin/bash”
- 脚本内容中以#开头的行作为解释说明
- 编写脚本时备注:作者、时间、功能等信息,方便之后查看
- 脚本的名字用“.sh”结尾,用于区分这是一个shell脚本
例子:
1[root@cham002 shell]# vim 01.sh 2 3#!/bin/bash 4#written by cham 5#2017-09-08 6#echo w ls 7 8echo "123" 9w 10ls 11 12 13[root@cham002 shell]# sh 01.sh 14123 15 22:50:49 up 5 min, 1 user, load average: 0.02, 0.16, 0.11 16USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 17root pts/0 192.168.230.1 22:46 1.00s 0.10s 0.00s w 1801.sh
执行方法
- 给脚本添加执行权限“chmod a+x 01.sh”,然后直接执行该脚本“./01.sh”
- sh 01.sh (/bin/bash = .bin/sh = bash)
- 绝对路径执行 /root/shell/01.sh ./ 只是相对路径
-
1 [root@cham002 shell]# chmod a+x 01.sh 2 [root@cham002 shell]# ./01.sh 3 123 4 22:54:32 up 8 min, 1 user, load average: 0.07, 0.11, 0.10 5 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 6 root pts/0 192.168.230.1 22:46 0.00s 0.12s 0.00s /bin/bash ./01.sh 7 01.sh 8 9 [root@cham002 shell]# ls -l /bin/bash 10 -rwxr-xr-x. 1 root root 960392 8月 3 2016 /bin/bash 11 [root@cham002 shell]# ls -l /bin/sh 12 lrwxrwxrwx. 1 root root 4 10月 19 06:56 /bin/sh -> bash 13 14 [root@cham002 shell]# bash 01.sh 15 123 16 22:57:39 up 11 min, 1 user, load average: 0.00, 0.06, 0.08 17 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 18 root pts/0 192.168.230.1 22:46 3.00s 0.13s 0.00s bash 01.sh 19 01.sh 20 [root@cham002 shell]# sh 01.sh 21 123 22 22:57:48 up 12 min, 1 user, load average: 0.00, 0.06, 0.08 23 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 24 root pts/0 192.168.230.1 22:46 4.00s 0.13s 0.00s w 25 01.sh 26
sh参数
-
-x:sh -x test.sh 查看显示脚本执行过程
-
-n:sh -n test.sh 查看脚本是否存在语法错误
[root@cham002 shell]# sh -x 01.sh
- echo 123 123
- w 23:09:28 up 23 min, 1 user, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.230.1 22:46 0.00s 0.42s 0.00s sh -x 01.sh
- ls 01.sh
[root@cham002 shell]# sh -n 01.sh #没有任何输出代表没有错
20.3 date命令用法
date命令用于显示或设置系统时间与日期。
语法: date [option] 参数
Options:
-d <string>:显示字符串指定的日期与时间(字符串前后必须加上双引号)
-s<string>:根据字符串来设置时间与日期(字符串前后必须加双引号)
参数:
<+时间日期格式>:指定日期和时间显示的格式
1[root@cham002 shell]# date 22018年 02月 06日 星期二 23:15:10 CST
常用日期格式
1date +%Y(%y):以四位(两位)数字格式显示年份 2[root@cham002 shell]# date +%Y 32018 4[root@cham002 shell]# date +%y 518 6 7date "+%Y-%m-%d %H:%M:%S %w" 8以上参数分别表示:年、月、日、时、分、秒、星期 9[root@cham002 shell]# date "+%Y-%m%d %h:%M:%S %w" 102018-0206 2月:25:50 2 11 12 13[root@cham002 shell]# date +%m 月 1402 15[root@cham002 shell]# date +%d 日 1606 17[root@cham002 shell]# date +%H 时 1823 19[root@cham002 shell]# date +%M 分 2018 21[root@cham002 shell]# date +%S 秒 2253 23[root@cham002 shell]# date +%w星期几 242 25[root@cham002 shell]# date +%D 2月6号18年 2602/06/18 27[root@cham002 shell]# date +%Y%m%d 2820180206 29[root@cham002 shell]# date +%F 302018-02-06 31 32[root@cham002 shell]# date +%s时间戳 331517930389 34 35[root@cham002 shell]# date +%T 3623:20:51 37[root@cham002 shell]# date +%H%M%S 38232140 39[root@cham002 shell]# date +%H:%M:%S 4023:21:54 41[root@cham002 shell]# date +%W 4206 43 44cal=calendar(日历),“cal -y”可以查看一年的日历。 45[root@cham002 shell]# cal 46 二月 2018 47日 一 二 三 四 五 六 48 1 2 3 49 4 5 6 7 8 9 10 5011 12 13 14 15 16 17 5118 19 20 21 22 23 24 5225 26 27 28
打印指定日期&时间
有时候需要使用N天(小时、分钟、秒(比如昨天的、))前的日期或时间。
格式: date -d "-1 day" +%F
12月6号的昨天 2[root@cham002 shell]# date -d "-1 day" 32018年 02月 05日 星期一 23:35:58 CST 4[root@cham002 shell]# date -d "-1 day" +%F 52018-02-05 6 72月份的上个月 8[root@cham002 shell]# date -d "-1 month" +%F 92018-01-06 10 112月6号昨天的时间 12[root@cham002 shell]# date -d "-1 hour" +%T 1322:41:16 14[root@cham002 shell]# date -d "-1 hour" +%T—%F 1522:42:12—2018-02-06 16 17 18说明: 指定某时间或日期的时候,后面要跟对应的时间格式参数(以上方法同样使用于 周、时、分、秒 )。 19 20换算时间戳 21 22[root@cham002 shell]# date +%s 231517931910 24[root@cham002 shell]# date -d @1517931910 252018年 02月 06日 星期二 23:45:10 CST 26[root@cham002 shell]# date +%s -d "2018-02-06 22:42:12" 271517928132
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]
1[root@cham002 shell]# vim test.sh 2 3#!/bin/bash 4d=`date +%F` 5echo "today is $d" 6 7[root@cham002 shell]# sh test.sh 8today is 2018-02-07
说明: 该脚本中将变量d定义为了当前日
注意: 在shell脚本中将命令结果定义为变量时要使用反引号,调用变量的方法:“$变量名” 。
内置变量
$0,$1,$2,$3……
-
$0:表示脚本本身
-
$1:第一个参数
-
$2:第二个参数
-
$#:表示参数的个数
[root@cham002 shell]# vim sum.sh
#!/bin/bash a=6 b=6 sum=$[$a+$b] echo "$a+$b=$sum"
[root@cham002 shell]# sh sum.sh 6+6=12
注: 数学运算要用[ ]括起来,且前面要加符号$。
和用户交互模式
1[root@cham002 shell]# vim you.sh 2 3#!/bin/bash 4read -p "please input a number:" x 5read -p "please input a number:" y 6you=$[$x+$y] 7echo "$x+$y=$you" 8 9[root@cham002 shell]# sh you.sh 10please input a number:8 11please input a number:8 128+8=16 13[root@cham002 shell]# sh you.sh 14please input a number:7+14 15please input a number:7+14 167+14+7+14=42
注: read命令用于和用户交互,它把用户输入的字符串作为变量值,可以使用-t选项指定读取值时等待的时间(超出时间后自动退出脚本)。
shell脚本预设变量
有时候使用类似/etc/init.d/iptables restart的命令,前面的/etc/init.d/iptables文件其实就是一个shell脚本,后面的字符串restart就是预设变量。
1[root@cham002 shell]# vim option.sh 2#!/bin/bash 3you=$[$1+$2] 4echo "you=$1+$2=$you" 5echo "Result of $0" 6 7[root@cham002 shell]# sh option.sh 36 8 9[root@cham002 shell]# sh option.sh 3 6 10you=3+6= 11Result of option.sh 12 13[root@cham002 shell]# sh option.sh 7 8 14you=7+8= 15Result of option.sh
说明: 脚本中的$1和$2即为shell的预设变量,分别为脚本的第一个参数和第二个参数,shell脚本预设变量是没有限制的,注意$0位脚本本身的名字
20.5 Shell脚本中的逻辑判断
逻辑表达式
在[ ]中括号中:
- -lt:=little than 小于 <
- -le:=little && equal 小于等于 <=
- -eq:=equal 等于 ==
- -ne:=no equal 不等于 !=
- -gt:=greater than 大于 >
- -ge:=greater && equal 大于等于 >=
可以用用符号,但要在(( ))小括号中:类似: if (($a>1)); then echo ok;fi
ok
<,<=,==,!=,>,>=
注意: 使用双括号括起来
•格式1:if 条件 ; then 语句; fi
1[root@cham002 shell]# vim if1.sh 2 3#!/bin/bash 4a=5 5 if [ $a -gt 3 ] #注意[]内的空格 6 then 7 echo ok 8 fi 9 10[root@cham002 shell]# sh if1.sh 11ok
•格式2:if 条件; then 语句; else 语句; fi
1[root@cham002 shell]# vim if2.sh 2 3#!/bin/bash 4a=1 5if [ $a -gt 3 ] 6then 7 echo ok 8else 9 echo nook 10 fi 11 12[root@cham002 shell]# sh -x if2.sh 13+ a=1 14+ '[' 1 -gt 3 ']' 15+ echo nook 16nook
•格式3:if …; then … ;elif …; then …; else …; fi
1[root@cham002 shell]# vim if3.sh 2 3#!/bin/bash 4a=5 5if [ $a -lt 3 ] 6then 7 echo "a<3" 8elif [ $a -gt 6 ] 9then 10 echo "a>6" 11else 12 echo nook 13 fi 14~ 15 16[root@cham002 shell]# sh -x if3.sh 17+ a=5 18+ '[' 5 -lt 3 ']' 19+ '[' 5 -gt 6 ']' 20+ echo nook 21nook
关系
各个条件之间的关系可以使用逻辑连接符:
条件A&&条件B:并且
条件A||条件B:或者
• if [ $a -gt 5 ] && [ $a -lt 10 ]; then
• if [ $b -gt 5 ] || [ $b -lt 3 ]; then
20.6 文件目录属性判断
shell脚本中if经常用于判断文档的属性,比如判断是普通文件还是目录文件,判断文件是否有读、写、执行权限等。if常用的选项有以下几个:
- -e:判断文件或目录是否存在
- -d:判断是不是目录文件以及是否存在
- -f:判断是不是普通文件以及是否存在
- -r:判断是否有读权限
- -w:判断是否有写权限
- -x:判断是否有执行权限
格式
• [ -f file ]判断是否是普通文件,且存在
1[root@cham002 shell]# vim file1.sh 2 3#!/bin/bash 4f="/tmp/chamlinux" 5if [ -f $f ] 6then 7 echo $f exist 8else 9 touch $f 10fi 11 12 13[root@cham002 shell]# sh -x file1.sh 14+ f=/tmp/chamlinux 15+ '[' -f /tmp/chamlinux ']' 逻辑判断文件不存在 16+ touch /tmp/chamlinux 不存在就会创建 17 18再次执行 19[root@cham002 shell]# sh -x file1.sh 20+ f=/tmp/chamlinux 21+ '[' -f /tmp/chamlinux ']' 逻辑判断文件存在 22+ echo /tmp/chamlinux exist 23/tmp/chamlinux exist
•[ -d file ] 判断是否是目录,且存在
1[root@cham002 shell]# cp file1.sh file2.sh 2[root@cham002 shell]# vi !$ 3vi file2.sh 4 5#!/bin/bash 6f="/tmp/chamlinux" 7if [ -d $f ] 8then 9 echo $d exist 10else 11 touch $f 12fi 13 14[root@cham002 shell]# sh -x file2.sh 15+ f=/tmp/chamlinux 16+ '[' -d /tmp/chamlinux ']' 17+ touch /tmp/chamlinux
• [ -e file ] 判断文件或目录是否存在
1[root@cham002 shell]# vi file2.sh 2 3#!/bin/bash 4f="/tmp/chamlinux" 5if [ -e $f ] 6then 7 echo $d exist 8else 9 touch $f 10fi 11 12 13[root@cham002 shell]# sh -x file2.sh 14+ f=/tmp/chamlinux 15+ '[' -e /tmp/chamlinux ']' 16+ echo exist 17exist
• [ -r file ] 判断文件是否可读
1[root@cham002 shell]# vi file2.sh 2 3#!/bin/bash 4f="/tmp/chamlinux" 5if [ -r $f ] 6then 7 echo $f readable 8fi 9 10[root@cham002 shell]# sh -x file2.sh 11+ f=/tmp/chamlinux 12+ '[' -r /tmp/chamlinux ']' 13+ echo /tmp/chamlinux readable 14/tmp/chamlinux readable 15 16[root@cham002 shell]# sh file2.sh 17/tmp/chamlinux readable
•[ -w file ] 判断文件是否可写
1[root@cham002 shell]# vi file2.sh 2 3#!/bin/bash 4f="/tmp/chamlinux" 5if [ -w $f ] 6then 7 echo $f writeable 8fi 9 10[root@cham002 shell]# sh file2.sh 11/tmp/chamlinux writeable 12 13[root@cham002 shell]# sh -x file2.sh 14+ f=/tmp/chamlinux 15+ '[' -w /tmp/chamlinux ']' 16+ echo /tmp/chamlinux writeable 17/tmp/chamlinux writeable 18 19#对root用户来讲是可读可写的,如果是其他用户就可能是只读。 20[root@cham002 shell]# ls -l /tmp/chamlinux 21-rw-r--r-- 1 root root 0 2月 7 01:08 /tmp/chamlinux
• [ -x file ] 判断文件是否可执行
1[root@cham002 shell]# vi file2.sh 2 3#!/bin/bash 4f="/tmp/chamlinux" 5if [ -x $f ] 6then 7 echo $f exeable 8fi 9 10 11[root@cham002 shell]# sh file2.sh #因为不可执行所以没有输出,没有定义else 12[root@cham002 shell]# sh -x file2.sh 13+ f=/tmp/chamlinux 14+ '[' -x /tmp/chamlinux ']'
另外一种用法,判断这个文件或者目录存不存在,如果存在就删除,“&&”表示当前面的命令执行成功的时候才会执行后面的命令 。“||”表示文件不存在才会执行后面的操作
1[root@cham002 shell]# vi file2.sh 2 3#!/bin/bash 4f="/tmp/chamlinux" 5[ -f /tmp/chamlinux ] && rm -f $f 6 7 8如果文件不存在 9#!/bin/bash 10f="/tmp/chamlinux" 11if [ ! -f $f ] 12then 13 touch $f 14fi
20.7 if 特殊用法
•if [ -z "$a" ] 这个表示当变量a的值为空时会怎么样
1[root@cham002 shell]# vim if4.sh 2 3#!/bin/bash 4n=`wc -l /tmp/lalal` 5if [ -z "$n" ] 6then 7 echo error 8 exit 9elif [ $n -gt 100 ] 10then 11 echo fdsfsdfdf 12fi 13 14 15[root@cham002 shell]# sh -x if4.sh 16++ wc -l /tmp/lalal 17wc: /tmp/lalal: 没有那个文件或目录 18+ n= 19+ '[' -z '' ']' 20+ echo error 21error 22+ exit 23[root@cham002 shell]# 24 25 26[root@cham002 shell]# vim if4.sh 27 28#!/bin/bash 29if [ ! -f /tmp/lalal ] 30then 31 echo "/tmp/lalal not exist." 即,如果变量n为空则显示error并退出该脚本。 32 exit 33fi 34n=`wc -l /tmp/lalal` 35if [ -z "$n" ] 36then 37 echo error 38 exit 39elif [ $n -gt 100 ] 40then 41 echo fdsfsdfdf 42fi 43 44 45[root@cham002 shell]# sh -x if4.sh 46+ '[' '!' -f /tmp/lalal ']' 47+ echo '/tmp/lalal not exist.' 48/tmp/lalal not exist. 49+ exit 50[root@cham002 shell]# sh if4.sh 51/tmp/lalal not exist.
即,当该文件不存在的时候就会退出执行,不会提示存在语法错误。(该脚本存在逻辑错误,只做效果演示用)
注意: 在该表达式中引用变量时要用双引号引起来。
•if [ -n "$a" ] 表示当变量a的值不为空
1[root@cham002 shell]# ls 201.sh file1.sh file2.sh if1.sh if2.sh if3.sh if4.sh option.sh sum.sh test.sh you.sh 3[root@cham002 shell]# if [ -n 01.sh ]; then echo ok; fi 4ok 5 6[root@cham002 shell]# if [ -n 01.sh ]; then echo ok; fi 7ok 8[root@cham002 shell]# if [ -n "$b" ]; then echo $b; else echo "b is mull";fi 9b is mull
if grep -q '123' 1.txt; then 表示如果1.txt中含有'123'的行时会怎么样
1[root@cham002 shell]# if grep -w 'user1' /etc/passwd; then echo "user1 exist"; fi 2user1:x:1000:1000::/home/user1:/bin/bash 3user1 exist 4[root@cham002 shell]# if grep -wq 'user1' /etc/passwd; then echo "user1 exist"; fi 5user1 exist 6 7判断某参数存在: 8[root@cham002 shell]# vim if123.sh 9#!/bin/bash 10if 11 grep -wq 'user1' /etc/passwd 12then 13 echo "user1 exist." 14fi 15 16[root@cham002 shell]# sh if123.sh 17user1 exist. 18[root@cham002 shell]# sh -x if123.sh 19+ grep -wq user1 /etc/passwd 20+ echo 'user1 exist.' 21user1 exist. 22 23判断某参数不存在: 24[root@cham002 shell]# vim ifno123.sh 25#!/bin/bash 26if 27 ! grep -wq 'user10' /etc/passwd 28then 29 echo "no user1" 30fi 31 32[root@cham002 shell]# sh ifno123.sh 33no user1 34 35 36#!/bin/bash 37if 38 ! grep -wq 'user10' /etc/passwd 39then 40 useradd user10 41 echo "yes" 42fi 43 44[root@cham002 shell]# sh ifno123.sh 45useradd:警告:此主目录已经存在。 46不从 skel 目录里向其中复制任何文件。 47正在创建信箱文件: 文件已存在 48yes 49 50[root@cham002 shell]# sh -x ifno123.sh 51+ grep -wq user10 /etc/passwd 52+ useradd user10 53useradd:警告:此主目录已经存在。 54不从 skel 目录里向其中复制任何文件。 55正在创建信箱文件: 文件已存在 56+ echo yes 57yes 58
说明: grep中-w选项=Word,表示过滤一个单词;-q,表示不打印过滤的结果。判断某参数不存在时使用!表示取反。
20.8-20.9 case判断
格式:
1case 变量名 in 2 value1) 3 commond1 4 ;; 5 value2) 6 commod2 7 ;; 8 value3) 9 commod3 10 ;; 11esac
在case中,可以在条件中使用“|”,表示或的意思,如:
12|3) 2 commond 3 ;;
太晚了,记得case还没做!!!!!!!!!!!!!!!!!!!!!
