(京峰教育-内部资料)
第 17 章 Shell 企业编程基础
说到 Shell 编程,很多从事 Linux 运维工作的朋友都不陌生,都对 Shell 有基本的了解,
读者可能刚开始接触 Shell 的时候,有各种想法,感觉编程非常困难,SHELL 编程是所有编
程语言中最容易上手,最容易学习的编程脚本语言。
本章向读者介绍 Shell 编程入门、Shell 编程变量、If、While、For、Case、Select 基本语
句案例演练及 Shell 编程四剑客 Find、Grep、Awk、Sed 深度剖析等。
17.1 SHELL 编程入门简介
曾经有人说过,学习 Linux 不知道 Shell 编程,那就是不懂 Linux,现在细细品味确实
是这样。Shell 是操作系统的最外层,Shell 可以合并编程语言以控制进程和文件,以及启动
和控制其它程序。
Shell 通过提示您输入,向操作系统解释该输入,然后处理来自操作系统的任何结果输
出,简单来说 Shell 就是一个用户跟操作系统之间的一个命令解释器。
Shell 是用户与 Linux 操作系统之间沟通的桥梁,用户可以输入命令执行,又可以利用
Shell 脚本编程去运行,如图 17-1 所示:
图 17-1 Shell、用户及 Kernel 位置关系
Linux Shell 种类非常多,常见的 SHELL 如下:
Bourne Shell(/usr/bin/sh 或/bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh)
不同的 Shell 语言的语法有所不同,一般不能交换使用,最常用的 shell 是 Bash,也就
是 Bourne Again Shell。Bash 由于易用和免费,在日常工作中被广泛使用,也是大多数 Linux
操作系统默认的 Shell 环境。
Shell、Shell 编程、Shell 脚本、Shell 命令之前都有什么区别呢?简单来说 Shell 是一个
整体的概念,Shell 编程与 Shell 脚本统称为 Shell 编程,Shell 命令是 Shell 编程底层具体的
语句和实现方法。
17.2 SHELL 脚本及 Hello World
要熟练掌握 Shell 编程语言,需要大量的练习,初学者可以用 Shell 打印“Hello World”
字符,寓意着开始新的启程!
Shell 脚本编程需要如下几个事项:
Shell 脚本名称命名一般为英文、大写、小写;
不能使用特殊符号、空格来命名;
Shell 脚本后缀以.sh 结尾;
不建议 Shell 命名为纯数字,一般以脚本功能命名。
Shell 脚本内容首行需以#!/bin/bash 开头;
Shell 脚本中变量名称尽量使用大写字母,字母间不能使用“-”,可以使用“_”;
Shell 脚本变量名称不能以数字、特殊符号开头。
如下为第一个 Shell 编程脚本,脚本名称为:first_shell.sh,代码内容如下:
#!/bin/bash
#This is my First shell
#By author jfedu.net 2017
echo “Hello World ”
First_shell.sh 脚本内容详解如下:
#!/bin/bash
固定格式,定义该脚本所使用的 Shell 类型;
#This is my First shell
#号表示注释,没有任何的意义,SHELL 不会解析它;
#By author jfedu.net 2017 表示脚本创建人,#号表示注解;
echo “Hello World !” Shell 脚本主命令,执行该脚本呈现的内容。
Shell 脚本编写完毕,如果运行该脚本,运行用户需要有执行权限,可以使用 chmod o+x
first_shell.sh 赋予可执行权限。然后./first_shell.sh 执行即可,还可以直接使用命令执行: /bin/sh
first_shell.sh 直接运行脚本,不需要执行权限,最终脚本执行显示效果一样。
初学者学习 Shell 编程,可以将在 Shell 终端运行的各种命令依次写入到脚本内容中,
可以把 Shell 脚本当成是 Shell 命令的堆积。
17.3 Shell 编程之变量详解
Shell 编程是非类型的解释型语言,不像 C++、JAVA 语言编程时需要事先声明变量,Shell
给一个变量赋值,实际上就是定义了变量,在 Linux 支持的所有 shell 中,都可以用赋值符
号(=)为变量赋值,Shell 变量为弱类型,定义变量不需要声明类型,但在使用时需要明确变
量的类型,可以使用 Declare 指定类型,Declare 常见参数有:
+/-
"-"可用来指定变量的属性,"+"为取消变量所设的属性;
-f 仅显示函数;
r 将变量设置为只读;
x 指定的变量会成为环境变量,可供 shell 以外的程序来使用;
i 指定类型为数值,字符串或运算式。
Shell 编程中变量分为三种,分别是系统变量、环境变量和用户变量,其中系统变量在
对参数判断和命令返回值判断时使用,而环境变量则主要是在程序运行时需要设置,用户变
量又称为局部变量,多使用在 Shell 脚本内部或者临时局部使用。
Shell 变量名在定义时,首个字符必须为字母(a-z,A-Z),不能以数字开头,中间不能
有空格,可以使用下划线(_),不能使用(-),也不能使用标点符号等。
例如定义变量 A=jfedu.net,定义这样一个变量,A 为变量名,jfedu.net 是变量的值,变
量名有格式规范,变量的值可以随意指定。变量定义完成,如需要引用变量,可以使用$A。
如下脚本 var.sh 脚本内容如下:
#!/bin/bash
#By author jfedu.net 2017
A=123
echo “Printf variables is $A.”
执行该 Shell 脚本,结果将会显示:Printf variables is jfedu.net。Shell 常见的系统变量、
环境变量、用户变量详解如下:
(1) SHELL 编程常见系统变量:
$0
$n
$*
$#
$?
$$
当前脚本的名称;
当前脚本的第 n 个参数,n=1,2,…9;
当前脚本的所有参数(不包括程序本身);
当前脚本的参数个数(不包括程序本身);
命令或程序执行完后的状态,返回 0 表示执行成功;
程序本身的 PID 号。
(2) SHELL 编程常见环境变量:
PATH
HOME
SHELL
USER
ID
PWD
TERM
HOSTNAME
(3) SHELL 编程用户变量:
命令所示路径,以冒号为分割;
打印用户家目录;
显示当前 Shell 类型;
打印当前用户名;
打印当前用户 id 信息;
显示当前所在路径;
打印当前终端类型;
显示当前主机名。
A=jfedu.net
自定义变量 A;
N_SOFT=nginx-1.12.0.tar.gz
自定义变量 N_SOFT;
BACK_DIR=/data/backup/
自定义变量 BACK_DIR;
IP1=192.168.1.11
IP2=192.168.1.12
自定义变量 IP1;
自定义变量 IP2。
创建 Echo 打印菜单 Shell 脚本,脚本代码如下:
#!/bin/bash
#auto install httpd
#By author jfedu.net 2017
echo -e '\033[32m-----------------------------\033[0m'
FILE=httpd-2.2.31.tar.bz2
URL=http://mirrors.cnnic.cn/apache/httpd/
PREFIX=/usr/local/apache2/
echo -e "\033[36mPlease Select Install Menu:\033[0m"
echo
echo "1)官方下载 Httpd 文件包."
echo "2)解压 apache 源码包."
echo "3)编译安装 Httpd 服务器."
echo "4)启动 HTTPD 服务器."
echo -e '\033[32m-----------------------------\033[0m'
sleep 20
运行脚本,执行结果如图 17-2 所示:
图 17-2 Echo 打印菜单脚本
17.4 If 条件语句实战
Linux Shell 编程中,if、for、while、case 等条件流程控制语句用的非常多,熟练掌握以
上流程控制语句及语法的实验,对编写 Shel 脚本有非常大的益处。
If 条件判断语句,通常以 if 开头,fi 结尾。也可加入 else 或者 elif 进行多条件的判断,
if 表达式如下:
if
(表达式)
语句 1
else
fi
语句 2
If 语句 Shell 脚本编程案例如下:
(1) 比较两个整数大小。
#!/bin/bash
#By author jfedu.net 2017
NUM=100
if
(( $NUM > 4 )) ;then
echo “The Num $NUM more
than 4.”
echo “The Num $NUM less
than 4.”
else
fi
(2) 判断系统目录是否存在。
#!/bin/bash
#judge DIR or Files
#By author jfedu.net 2017
if
[
!
-d
/data/20140515 -a
!
-d
/tmp/2017/
];then
mkdir
-p
/data/20140515
fi
-f
-d
-eq
-ne
-lt
-gt
If 常见判断逻辑运算符详解:
判断文件是否存在 eg: if [ -f filename ];
判断目录是否存在 eg: if [ -d dir
];
等于,应用于整型比较 equal;
不等于,应用于整型比较 not equal;
小于,应用于整型比较 letter;
大于,应用于整型比较 greater;
-le
-ge
-a
-o
-z
||
&&
小于或等于,应用于整型比较;
大于或等于,应用于整型比较;
双方都成立(and) 逻辑表达式 –a 逻辑表达式;
单方成立(or) 逻辑表达式 –o 逻辑表达式;
空字符串;
单方成立;
双方都成立表达式。
(3) if 多个条件测试分数判断。
#!/bin/bash
#By author jfedu.net 2017
scores=$1
if
[[ $scores -eq 100 ]]; then
echo "very good!";
elif [[ $scores -gt 85 ]]; then
echo "good!";
elif [[ $scores -gt 60 ]]; then
echo "pass!";
elif [[ $scores -lt 60 ]]; then
echo "no pass!"
fi
17.5 If 判断括号区别
在使用 if 语句时,经常会使用()、(())、[]、[[]]、{}等括号,如下为几种括号简单区别
对比:
(
)
用于多个命令组、命令替换、初始化数组;
(( ))
整数扩展、运算符、重定义变量值,算术运算比较;
[]
bash 内部命令,[与 test 是等同的,正则字符范围、引用数组元素编号,不支持+-*/数学运
算符,逻辑测试使用-a、-o。
[[ ]]
bash 程序语言的关键字,不是一个命令,[[ ]]结构比[ ]结构更加通用,不支持+-*/数学运算
符,逻辑测试使用&&、||。
{}
主要用于命令集合或者范围,例如 mkdir
-p
/data/201{7,8}/
17.6 MySQL 数据库备份脚本
MySQL 数据库备份是运维工程师的工作之一,如下为自动备份 Mysql 数据库脚本。
#!/bin/bash
#auto backup mysql
#By author jfedu.net 2017
#Define PATH 定义变量
BAKDIR=/data/backup/mysql/`date +%Y-%m-%d`
MYSQLDB=webapp
MYSQLPW=backup
MYSQLUSR=backup
#must use root user run scripts 必须使用 root 用户运行,$UID 为系统变量
If
[ $UID -ne 0 ];then
echo This script must use the root user ! ! !
sleep 2
exit
fi
#Define DIR and mkdir DIR 判断目录是否存在,不存在则新建
if
[ ! -d
$BAKDIR ];then