20.1 shell脚本介绍
什么是shell
- shell是一种脚本语言,写shell不是说要怎么样去写,而是当拿到一个需求时,要有一个思路,没有思路的话是写不出来的.
- shell脚本语言和传统的编程语言C、PHP、Python相比,shell还是比较简单的.
- 在liunx系统当中随便写一些命令,其实是可以把这些命令组成一个shell脚本.
- shell有自己的语法规则,比如可以使用逻辑判断(if)去做一个判断,也可以使用for、while这样的循环,和C有点像,但它们的语法又有区别.
- shell是系统命令的集合,例如要求在凌晨两点的时候,去执行若干条命令,首先是把数据库做一个备份,然后把备份出来的sql文件做一个压缩,压缩完后再放到指定的目录里去,或者是压缩后的文件还需传输到远程的一台服务器上去. 按命令去执行可能没什么问题,可在每天凌晨去做这些事情的话,还是有一定的难度,所以就可以把这些一步步执行的命令集合在shell脚本里,然后一个任务计划就搞定,这就是shell.
- 日常工作中可能会做很多重复性的工作,例如安装了一个操作系统,安装完了操作系统,更改各种配置,搭建各种环境,若是一两台还可以手动操作,若是几百台,那么就可以使用脚本,把系统拿过来,执行一下脚本,同步进行,这样的话可以增加运维工作效率.
20.2 shell脚本结构和执行
shell脚本结构
在写shell脚本的往往第一行是写 #! /bin/bash,那么这第一行的作用是什么呢?
若是在本机上执行这个脚本,可以不用这第一行,因为它知道能够在这台机器上识别以及被解析,被执行.
但当换一台机器的时候就不一定能够被识别、解析、执行,所以在文件头的第一行需要加上 #! /bin/bash
演示:
[root@quandong sbin]# vim 01.sh
#! /bin/bash
echo "this is test"
free
ls
[root@quandong sbin]# sh 01.sh
this is test
total used free shared buff/cache available
Mem: 1016412 500228 69996 348 446188 357444
Swap: 0 0 0
01.sh
#把开头第一行删除,得出的结果与有开头第一行得出来的结果是一样的.
[root@quandong sbin]# vim 01.sh
#! /bin/bash
echo "this is test"
free
ls
[root@quandong sbin]# sh 01.sh
this is test
total used free shared buff/cache available
Mem: 1016412 500300 69872 348 446240 357408
Swap: 0 0 0
01.sh
shell脚本执行
接下来运行的命令是通过哪个解析器操作的? 通常都是/bin/bash
说明在刚在01.sh脚本写的free、ls都是通过/bin/bash这个解析器来执行的
所以#! /bin/bash的作用就在于此.
#给01.sh执行权限
[root@quandong sbin]# chmod a+x 01.sh
#加了权限后就可以./01.sh去执行这个脚本,说明这个脚本已经被/bin/bash这个文件识别,解析了.
./是相对路径,也可以使用绝对路径/usr/local/sbin/01.sh
[root@quandong sbin]#./01.sh
this is test
total used free shared buff/cache available
Mem: 1016412 500228 69848 348 446336 357456
Swap: 0 0 0
01.sh
[root@quandong ~]# /usr/local/sbin/01.sh
this is test
total used free shared buff/cache available
Mem: 1016412 502956 66612 380 446844 354576
Swap: 0 0 0
1.txt vps
#可以看到/bin/sh 和/bin/bash是同一个文件,所以才可以./01.sh执行脚本
要是没有/bin/sh文件,可以使用/bin/bash 01.sh执行脚本
[root@quandong sbin]# /bin/bash 01.sh
this is test
total used free shared buff/cache available
Mem: 1016412 500204 69856 348 446352 357496
Swap: 0 0 0
01.sh
[root@quandong sbin]# ls -l /bin/bash
-rwxr-xr-x 1 root root 960472 Dec 7 2016 /bin/bash
[root@quandong sbin]# ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 24 2017 /bin/sh -> bash
开头需要加#!/bin/bash
以#开头的行作为解释说明
脚本的名字以.sh结尾,作用是为了更好的区分,也可以不以.sh结尾
[root@quandong sbin]# vim 01.sh
#! /bin/bash
#This is the script for the demo
#by Anna
#2017-09-12
echo "this is test"
free
ls
说明:以#开头的是解释说明脚本的作用,谁写的,日期.
查看脚本执行过程
说明:sh -x选项 可以查看执行过程,每一个+ 表示一个操作
[root@quandong ~]# cd /usr/local/sbin/
[root@quandong sbin]# ls
01.sh
[root@quandong sbin]# sh -x 01.sh
+ echo 'this is test'
this is test
+ free
total used free shared buff/cache available
Mem: 1016412 503072 66480 380 446860 354452
Swap: 0 0 0
+ ls
01.sh
检查脚本错误
说明:sh -n选项可以检查脚本的语法错误,有输出表示有错误,没有输出就说明没有问题
[root@quandong sbin]# vim 01.sh
#! /bin/bash
#This is the script for the demo
#by Anna
#2017-09-12
echo "this is test"
free
ls
for i in `sep 1 10`
do
echo $i
[root@quandong sbin]# sh 01.sh
this is test
total used free shared buff/cache available
Mem: 1016412 502984 66480 380 446948 354536
Swap: 0 0 0
01.sh
01.sh: line 12: syntax error: unexpected end of file
#提示12行有错误,因为没有加done结束符,使用for 循环,最后都是需要加上done结束符.
20.3 date命令用法
单纯敲date显示系统当前的日期以及时间
[root@quandong ~]# date
Tue Sep 12 14:55:21 CST 2017
#date +%Y 表示4位的年
[root@quandong ~]# date +%Y
2017
#date +%y 表示2位的年
[root@quandong ~]# date +%y
17
#date +%m 表示月份
[root@quandong ~]# date +%m
09
#date +%m 表示分钟
[root@quandong ~]# date +%M
04
#date +%d 表示日
[root@quandong ~]# date +%d
12
#date +%D 表示年月日
[root@quandong ~]# date +%D
09/12/17
#把 大写Y、小写的m、小写的d组合在一起就是年月日
[root@quandong ~]# date +%Y%m%d
20170912
#另外一种表示年月日,大写的F,带横杆的
[root@quandong ~]# date +%F
2017-09-12
#date +%H 表示小时
[root@quandong ~]# date +%H
15
#date +%h 表示英文的月
[root@quandong ~]# date +%h
Sep
#date +%S 表示秒
[root@quandong ~]# date +%S
16
#date +%s 表示时间戳
[root@quandong ~]# date +%s
1505200351
说明:时间戳是距离1979年1月1日到现在过去1505200351秒
#date +%T 表示时间(时:分钟:秒)
[root@quandong ~]# date +%T
15:16:16
#把 大写H、大写的M、大写的S组合在一起就是一个时间
[root@quandong ~]# date +%H:%M:%S
15:22:46
说明:date +%H:%M:%S等同于date +%T
#date +%w 表示周(现在周二)
[root@quandong ~]# date +%w
2
#date +%W 表示今年的第几周 (现在是今年的第37周)
[root@quandong ~]# date +%W
37
#cal 显示日历
[root@quandong ~]# cal
September 2017
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
#例如在nginx日志切割的时候,今天是2017-9-12,在9月12日的凌晨要做日志切割,在9月12日零点零分之前是9月11日,日志需要加一个日期的标记的话,应该是标记9月11日的日期,本来就是9月11日的日志,所以要会使用date -d "-1 day" 标记昨天的日期
[root@quandong ~]# date -d "-1 day"
Mon Sep 11 15:35:01 CST 2017
[root@quandong ~]# date -d "-1 day" +%F
2017-09-11
#表示上个月
[root@quandong ~]# date -d "-1 month" +%F
2017-08-12
#表示上一年
[root@quandong ~]# date -d "-1 year" +%F
2016-09-12
#表示一小时前
[root@quandong ~]# date -d "-1 hour" +%T
14:38:51
#表示一分钟前
[root@quandong ~]# date -d "-1 min" +%T
15:39:36
#把时间换算成时间戳
[root@quandong ~]# date +%s -d "2017-09-12 15:43:13"
1505202193
#把时间戳换算成时间
[root@quandong ~]# date -d @1505202193
Tue Sep 12 15:43:13 CST 2017
20.4 shell脚本中的变量
在Linux shell脚本编程中,我们使用两种类型的变量:系统定义的变量和用户定义的变量
shell 脚本中的变量是用来调用一个数值或者字符串的手段.
什么时候会使用到脚本中变量呢?
当脚本中使用某个字符串比较繁琐并字符串长度很长时就应该使用变量代替.
#把时间和人名做一个变量,输出结果时引用变量
[root@quandong sbin]# cat 02.sh
#! /bin/bash
days=`date -d "-2 hour" +%T`
guest="Anna"
echo "$guest checked in $days days ago"
days=`date -d "-5 hour" +%T`
guest="quandong"
echo "$guest checked in $days days ago"
[root@quandong sbin]# sh 02.sh
Anna checked in 14:08:40 days ago
quandong checked in 11:08:40 days ago
#引用某个命令的结果,使用变量代替
[root@quandong sbin]# vim 03.sh
#! /bin/bash
n=`cat 1.txt`
echo "$n"
[root@quandong sbin]# sh 03.sh
The is the test
Bend the rules
Can you just bend the rules a little?
I was only 2 minutes late.
Will not bend the rules.
Don't think about it.
#内置变量$0,$1,$2....等等,其中$0表示脚本本身,$1 表示第一个参数,$# 表示第二个参数 ....
演示:
[root@quandong sbin]# cat 03.sh
#! /bin/bash
head -2 /usr/local/sbin/1.txt |awk '{print $0}'
[root@quandong sbin]# sh 03.sh
The is the test
Bend the rules
说明:在这里$0 表示打印所有