一. Shell介绍
Shell的作用
系统服务的启动脚本 服务管理方式使用shell编程
脚本作用: 减少重复性工作
-
安装操作系统 通过cobbler kickstart批量自动化安装工具 批量安装操作系统 底层使用Shell编程
-
操作系统优化 优化内容:
a.修改ssh默认连接端口 禁止DNS解析 禁止root远程登录 创建普通用户 jumpserver
b.加大文件描述符 最大文件打开数量
c.时间同步
d.关闭Selinux
c.关闭NetworkManger
f.优化firewalld防火墙
g.修改默认的YUM仓库为国内速度较快的仓库 安装epel源
h.安装常用的命令软件
内核层面优化
通过脚本进行系统优化CentOS6.x CentOS7.x -
安装部署服务
需求: 每天安装的PHP版本不同 5.4 7.1 7.2
通过脚本部署不同的PHP(服务)版本1. PHP5.4 2. PHP7.1 3. PHP7.2 请选择安装的版本: 2
-
服务优化 通过脚本优化(Ansible)
-
启动服务 通过Shell脚本启动
企业自己研发 自研程序
使用python写了一个业务程序 运行程序[root@shell ~]#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
-
日志管理
ELK 通过Shell脚本处理日志
日志切割(防止日志单个文件容量过大)
1.mv 移动
2.重载服务
3.日志统计分析 -
监控
zabbix
底层硬件 磁盘 内存 IO 网络 负载 风扇转速 温度 湿度
系统运行状态 日志情况 系统日志 登录日志
系统服务运行状态 端口 PID方式 Nginx状态 PHP状态 MySQL状态
系统服务状态码1天的状态码 访问URL次数
业务层面 api接口 业务数据
取值---->监控
8)处理重复性问题 脚本+定时任务
9)通过脚本对接业务 实现业务功能(大保健 点餐案例)
二. 什么是Shell
-
命令解释器
Linux操作系统默认的解释器是: bash
交互式: 和人交互 人输入命令 解释器解释 返回结果给人
非交互式 执行shell脚本 -
什么是Shell脚本
命令的集合
将可执行命令写入文本中(并且脚本中包含变量 判断 循环等语句) 文本称为shell脚本Shell语法: 解释型语言 脚本语言 执行一次解释一次 慢
C语言: 编译型语言 一次编译终身执行 快
Shell和python区别
Shell处理底层 启动 停止 优化 统计数据
Python处理数据 页面CMDB运维平台 日志统计平台
三. Shell脚本的规范
-
shell脚本必须以.sh结尾 给我们自己看的
-
脚本的以#!/bin/bash或者 #!/bin/sh开头 指定shell解释器
-
Shell存放位置统一
[root@shell ~]# mkdir /server/scripts -p
-
脚本尽量写注释信息
脚本作用 脚本作者 脚本版本号(和业务对应) 脚本创建时间 -
成对的符号和语句一次性书写完毕 注意中英文问题
‘’ “” `` [] {} [[[]] {{}} . <>
‘’ “” ·· 【】 。《》 -
脚本注释尽量不用中文(大嘘)
四. 第一个Shell脚本
[root@shell scripts]# cat test.sh
#!/bin/bash
echo "Hello World!!"
执行脚本的方式:
第一种执行方式: 使用sh或者bash执行
[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=ahui
[root@shell scripts]# sh test.sh
Hello World!!
[root@shell scripts]# echo $name
[root@shell scripts]#
使用surce执行:
[root@shell scripts]# source test.sh
Hello World!!
[root@shell scripts]# echo $name
ahui
脚本的其他执行方式:
[root@shell scripts]# cat test.sh
#!/bin/bash
echo "Hello World!!"
name=ahui
[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!!
五.变量
什么是变量? x=1 y=x+1
用一个固定的值来表示任意不固定的值称为变量
例如:
name=ahui
age=18
变量的分类:
环境变量(全局变量) 对所有bash生效
普通变量(局部变量) 只对当前的bash生效
全局变量: 系统默认的变量 为了满足用户正常使用操作系统定义的
PATH
PS1
LANG
普通变量: 用户自定义变量 常用变量(写在脚本中的变量 只针对脚本生效)
查看全局变量: env
变量相关的配置文件
第一种方式: 按照开机启动加载文件的顺序排序
1. /etc/profile
2. .bash_profile
3. .bashrc
4. /etc/bashrc
第二种方式: 按照生效顺序排序
最后一个执行的就是优先生效的 称为重复赋值
1. /etc/bashrc
2. .bashrc
3. .bash_profile
4. /etc/profile
变量按照生命周期划分:
永久变量: 写入配置文件 写入脚本的
/etc/profile
test.sh
临时变量: 使用export声明即可
在当前命令行测试的变量
变量加export和不加export的区别:
加export对当前窗口的所有bash生效
不加export值针对当前的bash生效
案例:
执行以下脚本结果为: 空
[root@shell ~]# cat test.sh
I=`whoami`
[root@shell ~]# sh test.sh
[root@shell ~]# echo $I
变量名的定义方式
- 名称见名知其意
- 名称只能以下划线和字母开头 不能以数字和-开头
- 等号的两端不允许有空格
- 名称的书写方式:
NAME_AGE= # 全部大写 系统变量名称默认全部大写的
name_age= # 全部小写
Name_Age= # 单词的首字母大写 大驼峰语法
name_Age= # 小驼峰语法
临时取消变量:
[root@shell ~]# unset name
变量值的定义方式
第一种: 值为字符串
特点:
连续的字符串
如果不连续需要用引号括起来
双引号 可以解析变量
单引号 不解析变量 所见即所得
直接定义name=ahui
变量调用变量:
[root@shell ~]# name=ahui
[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
ahui_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双数以上需要使用{}括起来为一个整体 ※※※※※
$? 获取上一次执行命令的结果 0为成功 非0失败 ※※※※※
$# 表示脚本传参的个数 ※※※※
$! 获取上一次在后台执行脚本的PID号 脚本测试使用 调试脚本使用 ※※※
$* 表示所有脚本传参的参数 在使用循环语法不同 需加双引号 ※※
$@ 表示所有单个脚本传参的参数 在使用循环语法不同 需加双引号 类似数组 ※※
$$ 获取脚本的PID ※※
$_ 获取最后的字符串 ※※
$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=ahui
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 ahui 18
ahui 18
案例:序列传参
[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 ahui
必须传两个参数
[root@shell scripts]# sh test.sh ahui 18 test
必须传两个参数
[root@shell scripts]# sh test.sh ahui 18
ahui
18
$* $@ 获取传参的所有的参数
在循环中加双引号有区别
[root@shell ~]# set -- "I am" ahui blogger
[root@shell ~]# echo $*
I am ahui blogger
[root@shell ~]# echo $@
I am ahui blogger
[root@shell ~]# for i in "$*";do echo $i;done
I am ahui blogger
[root@shell ~]# for i in "$@";do echo $i;done
I am
ahui
blogger
案例: 将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
七. 变量子串知识
变量的切片
[root@shell ~]# test="I am ahui"
[root@shell ~]# echo $test
I am ahui
[root@shell ~]# echo ${test:2:3}
am
[root@shell ~]# echo ${test:3:3}
m l
统计字符串的长度
第一种方式:
[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 ahui I am 18
[root@shell ~]# cat test.sh
#!/bin/bash
for i in I am ahui 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 ahui I am 18
do
[ ${#i} -gt 3 ] && echo $i
done
[root@shell ~]# sh test.sh
ahui
第二种方式: 通过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}'
ahui
awk进阶方式:
[root@shell ~]# echo $test
I am ahui I am 18
[root@shell ~]#
[root@shell ~]# echo $test|awk '{for(i=1;i<=NF;i++)if(length($i)>3)print $i}'
ahui
[root@shell ~]# echo $test|awk '{for(i=1;i<=NF;i++)if(length($i)<3)print $i}'
I
am
I
am
18
变量子串删除
从前往后删除使用# ## 贪婪匹配
[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
变量子串替换
替换使用// 贪婪匹配使用///
[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
小结:
-
脚本的执行方式
sh bash
source .
./script 路径方式执行
cat test.sh|bash
bash < test.sh -
变量定义
字符串定义
数值定义
命令定义(反引号和单引号使用方式) 时间案例
双引号和单引号的区别
永久变量写入/etc/profile 针对全局生效
脚本中定义普通变量 局部变量
临时变量export -
特殊位置变量
重点: $0 $n $# $?
了解: $$ $! $_ $* $@ -
变量子串
笔试题 切片 awk取值
统计字符串的长度
统计字符串小于3的单词
子串删除 替换