Shell编程:
1.了解入门
2.变量 变量子串知识
3.特殊位置变量
4.脚本的执行方式
5.脚本传参
6.数值运算
7.数值比较
8.字符串比较
9.正则比较方式
10.条件控制语句
if
while
for
case
break
continue
exit
11.数组
12.案例
一. Shell介绍
Shell的作用
系统服务的启动脚本 服务管理方式使用shell编程
脚本作用: 减少重复性工作
1)安装操作系统 通过cobbler kickstart批量自动化安装工具 批量安装操作系统 底层使用Shell编程
2)操作系统优化 优化内容:
a.修改ssh默认连接端口 禁止DNS解析 禁止root远程登录 创建普通用户 jumpserver
b.加大文件描述符 最大文件打开数量
c.时间同步
d.关闭Selinux
c.关闭NetworkManger
f.优化firewalld防火墙
g.修改默认的YUM仓库为国内速度较快的仓库 安装epel源
h.安装常用的命令软件
内核层面优化
通过脚本进行系统优化CentOS6.x CentOS7.x
3)安装部署服务
需求: 每天安装的PHP版本不同 5.4 7.1 7.2
通过脚本部署不同的PHP(服务)版本
1. PHP5.4
2. PHP7.1
3. PHP7.2
请选择安装的版本: 2
4)服务优化 通过脚本优化(Ansible)
5)启动服务 通过Shell脚本启动
企业自己研发 自研程序
使用python写了一个业务程序 运行程序
cat test.sh
nohup python test.py --mysql-ip --mysql-ip --mysql-user= --mysql-password= &
nohup python test.py --mysql-ip --mysql-ip --mysql-user= --mysql-password= &
nohup python test.py --mysql-ip --mysql-ip --mysql-user= --mysql-password= &
sh test.sh start
sh test.sh stop
[root@shell ~]# ps axu|grep 1.sh|grep -v grep|awk '{print $2}'|xargs kill -9
6)日志管理
ELK 通过Shell脚本处理日志
日志切割(防止日志单个文件容量过大)
1. mv 移动
2. 重载服务
3. 日志统计分析
7)监控
zabbix
底层硬件 磁盘 内存 IO 网络 负载 风扇转速 温度 湿度
系统运行状态 日志情况 系统日志 登录日志
系统服务运行状态 端口 PID方式 Nginx状态 PHP状态 MySQL状态
系统服务状态码1天的状态码 访问URL次数
业务层面 api接口 业务数据
取值---->监控
8)处理重复性问题 脚本+定时任务
9)通过脚本对接业务 实现业务功能(大保健 点餐案例)
二. 学习Shell必须掌握的知识
1)远程连接工具xshell crt
2)基础命令 常用命令必须掌握60个左右
3)vim快捷键 快捷方式 vim是vi的高级版本
4)awk sed grep find
awk -F "-:." "[-:.]+"
三. 如何学好Shell编程
1)掌握必会知识点
2)掌握Shell基础部分
变量
数值运算
整数比较
字符串比较
文件判断
正则比对
3)Shell语法结构
if [ ]
for
case
while
数组
4)能读懂 能修改 独立书写小的案例 多花时间(购买老男孩Shell编程)
5)不要看着感觉会了 切记拿来既用(模仿)
四. 什么是Shell
1)命令解释器
Linux操作系统默认的解释器是: bash
交互式: 和人交互 人输入命令 解释器解释 返回结果给人
非交互式 执行shell脚本
2)什么是Shell脚本
命令的集合
将可执行命令写入文本中(并且脚本中包含变量 判断 循环等语句) 文本称为shell脚本
Shell语法: 解释型语言 脚本语言 执行一次解释一次 慢
C语言: 编译型语言 一次编译终身执行 快
python go ruby html java javascript
Shell和python区别
Shell处理底层 启动 停止 优化 统计数据
Python处理数据 页面CMDB运维平台 日志统计平台
五. Shell脚本的规范
1)shell脚本必须以.sh结尾 给我们自己看的
2)脚本的以#!/bin/bash或者 #!/bin/sh开头 指定shell解释器
3)Shell存放位置统一
[root@shell ~]# mkdir /server/scripts -p
4)脚本尽量写注释信息
脚本作用 脚本作者 脚本版本号(和业务对应) 脚本创建时间
5)成对的符号和语句一次性书写完毕 注意中英文问题
'' "" `` [] {} [[[]] {{}} . <>
‘’ “” ·· 【】 。《》
6)脚本注释尽量不用中文
六. 第一个Shell脚本
[root@shell scripts]# cat test.sh
#!/bin/bash
echo "Hello World!!"
执行脚本的方式:
第一种执行方式: 使用sh或者bash执行
以子shell方式运行
[root@shell scripts]# sh test.sh
Hello World!!
[root@shell scripts]# bash test.sh
Hello World!!
[root@shell ~]# sh /server/scripts/test.sh
Hello World!!
第二种执行方式: 使用路径方式执行 需要执行x权限
以子shell方式运行
相对路径:./
[root@shell scripts]# ./test.sh
-bash: ./test.sh: Permission denied
[root@shell scripts]# chmod +x test.sh
[root@shell scripts]# ll
total 4
-rwxr-xr-x 1 root root 33 Aug 1 11:22 test.sh
[root@shell scripts]# ./test.sh
Hello World!!
绝对路径:
[root@shell ~]# /server/scripts/test.sh
Hello World!!
第三种执行方式: 使用. 或者source执行
在父shell中执行
[root@shell scripts]# . test.sh
Hello World!!
[root@shell scripts]# source test.sh
Hello World!!
第二种执行方式和第三种执行方式的区别:
使用sh或者bash执行:
[root@shell scripts]# cat test.sh
#!/bin/bash
echo "Hello World!!"
name=oldboy
[root@shell scripts]# sh test.sh
Hello World!!
[root@shell scripts]# echo $name
[root@shell scripts]#
使用source执行:
[root@shell scripts]# source test.sh
Hello World!!
[root@shell scripts]# echo $name
oldboy
脚本的其他执行方式:
[root@shell scripts]# cat test.sh
#!/bin/bash
echo "Hello World!!"
name=oldboy
[root@shell scripts]# cat test.sh |bash
Hello World!!
[root@shell scripts]# echo pwd
pwd
[root@shell scripts]# echo pwd|bash
/server/scripts
[root@shell scripts]# sh < test.sh
Hello World!!
七.变量
1)什么是变量? x=1 y=x+1
用一个固定的值来表示任意不固定的值称为变量
例如:
name=oldboy
age=18
变量的分类:
环境变量(全局变量) 对所有bash生效
普通变量(局部变量) 只对当前的bash生效
全局变量: 系统默认的变量 为了满足用户正常使用操作系统定义的
PATH
PS1
LANG
普通变量: 用户自定义变量 常用变量(写在脚本中的变量 只针对脚本生效)
查看全局变量: env
2)变量相关的配置文件
第一种方式: 按照开机启动加载文件的顺序排序
1. /etc/profile
2. .bash_profile
3. .bashrc
4. /etc/bashrc
第二种方式: 按照生效顺序排序
最后一个执行的就是优先生效的 称为重复赋值
1. /etc/bashrc
2. .bashrc
3. .bash_profile
4. /etc/profile
3)变量按照生命周期划分:
永久变量: 写入配置文件 写入脚本的
/etc/profile
test.sh
临时变量: 使用export声明即可
在当前命令行测试的变量
变量加export和不加export的区别:
加export对当前窗口的所有bash生效
不加export值针对当前的bash生效
笔试题:
执行以下脚本结果为: 空
[root@shell ~]# cat test.sh
oldboy=`whoami`
[root@shell ~]# sh test.sh
[root@shell ~]# echo $oldboy
4)变量名的定义方式
1. 名称见名知其意
2. 名称只能以下划线和字母开头 不能以数字和-开头
3. 等号的两端不允许有空格
4. 名称的书写方式:
NAME_AGE= # 全部大写 系统变量名称默认全部大写的
name_age= # 全部小写
Name_Age= # 单词的首字母大写 大驼峰语法
name_Age= # 小驼峰语法
临时取消变量:
[root@shell ~]# unset name
5)变量值的定义方式
第一种: 值为字符串
特点:
连续的字符串
如果不连续需要用引号括起来
双引号 可以解析变量
单引号 不解析变量 所见即所得
name=oldboy
变量调用变量:
[root@shell ~]# name=oldboy
[root@shell ~]# test='$name_age'
[root@shell ~]# echo $test
$name_age
[root@shell ~]# test="$name_age"
[root@shell ~]# echo $test
[root@shell ~]# test="${name}_age"
[root@shell ~]# echo $test
oldboy_age
[root@shell ~]# test='${name}_age'
[root@shell ~]# echo $test
${name}_age
案例: 字符串定义
定义代码路径
第二种: 值为数字
特点:
连续的数字
[root@shell ~]# age=12 323
-bash: 323: command not found
[root@shell ~]# age=12323
[root@shell ~]# age='12 3 2 3'
[root@shell ~]# echo $age
12 3 2 3
第三种: 值为命令
如果值为命令必须加反引号或者$()
[root@shell ~]# test=`ls`
[root@shell ~]# echo $test
1 data.txt passwd test.sh
[root@shell ~]# date +%F-%H-%M-%S
2022-08-01-15-20-38
[root@shell ~]# time=`date +%F-%H-%M-%S`
[root@shell ~]# echo $time
2022-08-01-15-20-53
[root@shell ~]# echo $time
2022-08-01-15-20-53
[root@shell ~]# time=`date +%F-%H-%M-%S`
[root@shell ~]# echo $time
2022-08-01-15-22-00
需求: 每次调用time变量让时间发生变化
[root@shell ~]# cat test.sh
time='date +%F-%H-%M-%S'
echo `$time`
sleep 5
echo `$time`
sleep 5
echo `$time`
[root@shell ~]# sh test.sh
2022-08-01-15-25-37
2022-08-01-15-25-42
2022-08-01-15-25-47
八. 特殊位置变量
$0 表示脚本的名称 如果全路径执行则带全路径 *****
$n 表示脚本的第n个参数 从$1开始 表示第1个参数 $10 $11双数以上需要使用{}括起来为一个整体 *****
$# 表示脚本传参的个数 *****
$* 表示脚本传参的参数 在使用循环语法不同 加双引号 了解 **
$@ 表示脚本传参的参数 在使用循环语法不同 了解 **
$$ 获取脚本的PID **
$! 获取上一次在后台执行脚本的PID号 脚本测试使用 调试脚本使用 ***
$_ 获取最后的字符串 了解 **
$? 获取上一次执行命令的结果 0为成功 非0失败 *****
$0 输出脚本名称
[root@shell scripts]# cat test.sh
#!/bin/bash
echo $0
[root@shell scripts]# sh test.sh
test.sh
[root@shell scripts]# cd
[root@shell ~]# sh /server/scripts/test.sh
/server/scripts/test.sh
案例: 提示用户使用方法
[root@shell scripts]# cat test.sh
#!/bin/bash
name=oldboy
echo "Usage: $0 [start|stop|restart|reload|status]"
[root@shell scripts]# sh test.sh
Usage: test.sh [start|stop|restart|reload|status]
[root@shell scripts]#
单独取脚本名称:
[root@shell ~]# basename /server/scripts/test.sh
test.sh
[root@shell ~]# basename /etc/sysconfig/network-scripts/ifcfg-eth0
ifcfg-eth0
$n 表示脚本的第n个参数
[root@shell scripts]# cat test.sh
#!/bin/bash
name=$1
age=$2
echo $name $age
[root@shell scripts]# sh test.sh oldboy 20
oldboy 20
序列传参
[root@shell scripts]# cat test.sh
#!/bin/bash
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
[root@shell scripts]# sh test.sh {a..z}
a b c d e f g h i j k
$# 控制用户传参的个数
[root@shell scripts]# cat test.sh
#!/bin/bash
[ $# -ne 2 ] && echo "必须传两个参数" && exit
echo $1
echo $2
[root@shell scripts]# sh test.sh
必须传两个参数
[root@shell scripts]# sh test.sh oldboy
必须传两个参数
[root@shell scripts]# sh test.sh oldboy 18 test
必须传两个参数
[root@shell scripts]# sh test.sh oldboy 18
oldboy
18
$* $@ 获取传参的所有的参数
在循环中加双引号有区别
[root@shell ~]# set -- "I am" lizhenya teacher
[root@shell ~]# echo $*
I am lizhenya teacher
[root@shell ~]# echo $@
I am lizhenya teacher
[root@shell ~]# for i in "$*";do echo $i;done
I am lizhenya teacher
[root@shell ~]# for i in "$@";do echo $i;done
I am
lizhenya
teacher
案例: 将ping的结果定向到空
通过$?判断网站是否能ping通
[root@shell scripts]# cat ping.sh
#!/bin/bash
ping -c1 -W1 $1 &>/dev/null
[ $? -eq 0 ] && echo "$1 ok" || echo "$1 error"
[root@shell scripts]# sh ping.sh www.baidu.com
www.baidu.com ok
[root@shell scripts]# sh ping.sh www.baiduddd.com
www.baiduddd.com ok
[root@shell scripts]# sh ping.sh www.baiducccc.com
www.baiducccc.com error
九. 变量子串知识
1)变量的切片
[root@shell ~]# test="I am lizhenya"
[root@shell ~]# echo $test
I am lizhenya
[root@shell ~]# echo ${test:2:3}
am
[root@shell ~]# echo ${test:3:3}
m l
2)统计字符串的长度 笔试题
第一种方式:
[root@shell ~]# echo $test|wc -L
13
第二种方式:
[root@shell ~]# expr length "${test}"
13
第三种方式:
[root@shell ~]# echo $test|awk '{print length}'
13
第四种方式: 子串知识统计
[root@shell ~]# echo ${#test}
13
笔试题: 取出字符串小于3的单词
[root@shell ~]# echo $test
I am lizhenya I am 18
[root@shell ~]# cat test.sh
#!/bin/bash
for i in I am lizhenya I am 18
do
echo ${#i}
done
[root@shell ~]# sh test.sh
1
2
8
1
2
2
第一种方式: 使用for循环+判断
[root@shell ~]# cat test.sh
#!/bin/bash
for i in I am lizhenya I am 18
do
[ ${#i} -gt 3 ] && echo $i
done
[root@shell ~]# sh test.sh
lizhenya
第二种方式: 通过awk判断
[root@shell ~]# echo $test|xargs -n1|awk '{if(length<3)print}'
I
am
I
am
18
[root@shell ~]# echo $test|xargs -n1|awk '{if(length>3)print}'
lizhenya
awk进阶方式:
[root@shell ~]# echo $test
I am lizhenya I am 18
[root@shell ~]#
[root@shell ~]# echo $test|awk '{for(i=1;i<=NF;i++)if(length($i)>3)print $i}'
lizhenya
[root@shell ~]# echo $test|awk '{for(i=1;i<=NF;i++)if(length($i)<3)print $i}'
I
am
I
am
18
笔试题: 取出文章中所有的字母 并且统计出现的次数
取出文件中所有的单词 并且统计单词出现的次数
3)变量子串删除
从前往后删除使用# ## 贪婪匹配
[root@shell ~]# echo $url
www.baidu.com
[root@shell ~]# echo ${url#www.}
baidu.com
[root@shell ~]# echo ${url#*.}
baidu.com
[root@shell ~]# echo ${url#*.baidu.}
com
[root@shell ~]# echo ${url#*.*.}
com
[root@shell ~]# echo ${url##*.}
com
从后往前删除使用% %% 贪婪匹配
[root@shell ~]# echo ${url%.*}
www.baidu
[root@shell ~]# echo ${url%.*.*}
www
[root@shell ~]# echo ${url%%.*}
www
案例: 获取磁盘使用率 使用子串删除%
[root@shell ~]# df -h|grep /$|awk '{print $(NF-1)}'
11%
[root@shell ~]# use_disk=`df -h|grep /$|awk '{print $(NF-1)}'`
[root@shell ~]# echo $use_disk
11%
[root@shell ~]# echo $use_disk
11%
[root@shell ~]# echo ${use_disk%\%}
11
4)变量子串替换
替换使用// 贪婪匹配使用///
[root@shell ~]# echo $url
www.baidu.com
[root@shell ~]# echo ${url/w/a}
aww.baidu.com
[root@shell ~]# echo ${url/ww/aa}
aaw.baidu.com
[root@shell ~]# echo ${url/w/aa}
aaww.baidu.com
[root@shell ~]# echo ${url/baidu/sina}
www.sina.com
[root@shell ~]# echo ${url/w/W}
Www.baidu.com
[root@shell ~]# echo ${url//w/W}
WWW.baidu.com
小结:
1. 脚本的执行方式
sh bash
source .
./script 路径方式执行
cat test.sh|bash
bash < test.sh
2. 变量定义
字符串定义
数值定义
命令定义(反引号和单引号使用方式) 时间案例
双引号和单引号的区别
永久变量写入/etc/profile 针对全局生效
脚本中定义普通变量 局部变量
临时变量export
3. 特殊位置变量
$0 $n $# $?
$$ $! $_ $* $@ 了解
4. 变量子串
笔试题 切片 awk取值
统计字符串的长度
统计字符串小于3的单词
了解: 子串删除 替换
下次内容:
1. 变量的传参方式
2. 数值运算
3. 条件表达式
整数比较
多整数比较
字符串比较
正则比较