01-shell的基本概述与变量的定义
Shell的基本概述
shell是一个命令解释器,它在操作系统的最外层,负责连接与用户进行对话,将用户输入的命令翻译给操作系
统,并将处理结果输出至屏幕
shell命令是存在交互式、和非交互式的两种方式
什么是shell???
1)将系统命令堆积在一起,顺序执行(简称:系统命令堆积)
2)特定的格式+特定的语法+系统命令=文件
Shell能做什么(shell其实就是基于标准化之上的-->脚本工具)
1)基础配置:系统初始化操作,系统更新,内核调整,网络,时区,ssh优化
2)安装服务:LNMP,LAMP,MySQL,nginx,redis,
3)配置变更:nginx conf,PHP conf,MySQL conf,redis conf
4)业务部署:shell配合git、jenkins、实现自动化部署,php、java、代码,以及代码回滚
5)日常备份:使用shell脚本对mysql进行每晚的全备与增量备份
6)信息采集:zallix+shell,硬件,系统,服务,网络,等等
7)日志分析:取值-->排序-->去重-->统计-->分析
8)服务扩容:扩容:监控服务器集群cpu,如cpu负载持续80% + 触发动作(脚本),脚本:调用api开通云主机,
-->初始化环境-->加入集群-->对外提供
9)服务缩容:监控服务器集群cpu使用率,-->低于20%-->检测当前有多少web节点,-->判断是否超过预设-->缩
减对应的预设状态-->变更负载的配置
注意:shell脚本主要的作用是简化操作步骤,提高效率,减少人为干预,减少系统故障
学习shell脚本需要哪些预备知识,如何才能学好shell脚本
1)熟悉使用vim编辑器
2)熟练使用linux
3)熟练使用linux三剑客
注意:如果我们对命令使用不熟练,对基本服务也不会手动搭建,那么一定学不会shell
那么我们究竟如何才能学好shell脚本,基础命令+基础服务+经常练习+思路!!!
Shell的基本规范
1)脚本存放固定目录/scripts
2)开头加!/bin/bash 作用:告诉我脚本使用哪种命令解析器,如不指定shell,默认以bash执行
#!/usr/bin/bash
1. 脚本如果以./方式执行,需要拥有执行权限
2. 直接使用解析器命令执行脚本时,不需要执行权限也可以执行脚本
3)附带作者及版权信息
Auther:chenyun
4)脚本扩展名用.sh
check_nginx.sh
5)脚本中尽量不要用中文
6)成对的符号一次书写完成
7)循环格式一次性输入完成
Shell的脚本变量
1)shell变量概述
2)shell变量赋值
3)shell变量替换
4)shell变量运算
5)shell变量案例
什么是变量?
变量是一个传递数据的一种方法,简单理解,就是用一个固定的字符串去表示不固定的值,便于后续引用
变量命名规范
变量定义时名称要求:字母、数字、下划线几个组成,尽量用字母开头,{变量名最好具备一定的含义,但不要与系统命令冲突}
如 Hostname_ip=$(hostname -i),
等号是赋值,需要注意:等号两边不能有空格,其次定义的变量不要与系统命令相冲突
Shell变量定义的方式
1)用户自定义变量:人为定义变量名称
2)系统环境变量:保存的是和系统环境相关的数据
3)位置参数变量:向脚本中进行参数传参,变量名不能自定义,变量作用是固定的
4)预定义的变量:是bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的
Shell变量定义实践
1. 用户定义变量示例,当前shell有效
1)定义变量,变量名=变量值中不能出现“-”横杠命名
[root@shell ~]# var="hello world" 定义变量有空格时一定要有用""号,让它们输出时是一个整体
2)引用变量,$变量 或 ${变量}
[root@shell ~]# echo $var_log $var_log当做一个整体
[root@shell ~]# echo ${var}_log ${var}_log var变量加后缀_log
3)查看变量,set显示所有变量,包括自定义变量和环境变量
[root@shell ~]# set | grep var 查看自定义变量
[root@shell ~]#echo $PATH 查看环境变量
4)取消变量,只在当前shell中生效
unset var
5)注意事项,引用变量时注意事项,""双引号属于弱引用,''单引号属于强引用
a 在定义变量的时候,比如:var="$(var)"
b 在引用变量的时候,尽可能的使用双引号 echo "$var"
c 在我们使用echo输出的时候,如果输出的字符串中有特殊的符号,建议使用单引号 echo '#$123'
echo "$var is good is \$500"
$var被解析
$500前使用\转译符,这里$500不被解析
-------------------------------------------------------------------
1. 如何定义变量
2. 变量的命名规范,不要与系统命令冲突,不要太随意
3. 使用变量需要注意$var_log 以及"" '' 带来的问题
2. 系统环境变量示例,在当前shell和子shell都有效
1)定义环境变量,export变量,将自定义变量转换成环境变量
[root@shell ~]# export JAVA_HOME=/usr/local/jdk 将变量转为环境变量
[root@shell ~]# echo $JAVA_HOME
/usr/local/jdk
2)使用已定义好的系统变量
[root@shell ~]# echo $SSH_CLIENT 使用系统已定义好变量
10.0.0.1 49741 22
echo $HOME:打印用户当前家目录
echo $HOMENAME:打印主机名
echo $PWD:打印当前所在路径
echo $SSH_CONNECTION:打印当前连接服务器使用的地址和端口
3. 预先定义变量参数示例,系统内置变量的使用方法。需要注意:$*和$@的区别
echo $0:当前shell脚本的文件名
echo $1:第一个shell脚本位置参数
echo $2:第二个shell脚本位置参数
echo $3:第三个shell脚本位置参数
echo $*:所有传递的位置参数
echo $@:所有传递的位置参数
echo $#:总共传递的参数个数
echo $$:当前程序运行的PID
echp $?:上一个命令执行的返回结果
$*和$#的区别
$*和$@在没有加引号时,两者都是返回传入的参数,但加了引号后
$*把参数作为一个字符串整体(单字符串)返回
$@把每个参数作为一个一个字符串返回
----------------------------------------------------------
位置参数是什么?在执行脚本的时候,在脚本后面写入内容,按空格分隔
[root@shell ~]# /etc/init.d/network start #start就算第一个位置参数
4. 补充:将命令执行结果传递给变量(命令替换)
# 根据系统时间打印明年时间
echo $(date +%Y -d +"1year") 或
echo $(($(date +%Y)+1))
2021
# 打包/root下面所有的.txt的文件
[root@shell ~]# tar -zcf /root/data.tar.gz $(find /root -type f -name "*.txt")
[root@shell ~]# tar -tf data.tar.gz
./3.txt
./4.txt
Shell的变量赋值
1. read示例语法
#!/bin/bash
read -p "请输入你要备份的目录:" file
cd /
tar -zcf backup.tar.gz .$file
echo ".......... backup $file ................"
echo ".......... backup $file end ............"
[root@shell scripts]# /bin/bash read.sh
请输入你要备份的目录:/tmp
............ backup /tmp .....................
............. backup /tmp end .................
[root@shell scripts]# tar -tf backup.tar.gz
tmp/
tmp/.X11-unix/
示例2:
编写一个测试用户IP能否拼通的脚本
要求:拼通返回IP正常拼通,不通返回IP无法正常拼通
思路:第一,执行时提示输入IP read -p
第二,让IP只拼一次 ping -c1
第三,指定超时时间 ping -W1
第四,返回命令执行结果 echo $?
-----------------------------------------------
[root@shell scripts]#vim /scripts/ping.sh
#!/bin/bash
read -p "请您输入测试IP:" IP
ping -W1 -c1 $IP >/dev/null
rc=$?
if [ $rc == 0 ];then
echo "IP可以正常拼通"
else
echo "IP无法拼通"
fi
[root@shell scripts]# /bin/bash ping.sh
请您输入测试IP:10.0.0.1
IP可以正常拼通
[root@shell scripts]# /bin/bash ping.sh
请您输入测试IP:10.0.0.2
IP无法拼通
示例3:
使用read命令写一个脚本修改主机名和IP地址
思路:1. 提示用户输入修改主机名称或IP
2. 提示用户是否确认此操作
3. 真的执行修改
#!/bin/bash
#1. 提示用户输入要修改的主机名称,然后打印主机名称
read -p "请输入您想要修改的主机名称" HostName
echo "您要修改的主机名称为$HostName"
#2. 询问用户是否确认修改,如果确认执行shell,否则退出
read -p "您确认要修改如下主机名称[y|n]" rc
#3. 判断用户输入是y还n
if [ $rc == y ];then
hostnamectl set-hostname $HostName
else
exit
fi
Shell变量替换
$(变量#匹配规则) 从头开始匹配,最短删除
$(变量##匹配规则) 从头开始匹配,最长删除
$(变量%匹配规则) 从尾开始匹配,最短删除
$(变量%%匹配规则) 从尾开始匹配,最长删除
$(变量/旧字符串/新字符串) 替换变量内的旧字符串为新字符串,只替换一个
$(变量//旧字符串/新字符串) 替换变量内的旧字符串为新字符串,全部替换
1)从尾往前删除变量内容
最短删除
[root@shell scripts]# url=www.sina.com.cn
[root@shell scripts]# echo ${url%.*}
最长删除
[root@shell scripts]# echo ${url%%.*}
www
2)从前往尾删除变量内容
最短删除
[root@shell scripts]# echo ${url#*.}
最长删除
[root@shell scripts]# echo ${url##*.}
cn
[root@shell scripts]# free=$(free -m|grep ^M|awk '{print $3/$2*100}')
[root@shell scripts]# echo $free
12.1399
[root@shell scripts]# echo ${free%.*}
12
3)变量内容替换
[root@shell scripts]# echo $url
[root@shell scripts]# echo ${url/n/N} 只替换一个
[root@shell scripts]# echo ${url//n/N} 全部替换
应用场景
1. 查看内存/当前使用状态,如果使用率超过80%,则发送报警邮件
2. 场景实践,在/backup下创建10个.txt的文件,找到/backup目录下所后缀名为.txt的文件
1)批量修改txt为txt.bak
2)把所有的.bak文件打包压缩为123.tar.gz
3)批量还原文件的名字,及把增加的.bak再删除
3. 使用shell脚本打印、系统版本、内核版本平台、虚拟平台、静态化平台、eth0网卡IP地址、lo网卡IP地址
当前外网IP地址
4. 需求描述:变量string="Bigdata process is Hadoop,Hadoop is open source project",执行脚本后,
打印输出string字符串变量,并给用户以下选项
1)打印string长度
2)删除字符串中所有的Hadoop
3)替换第一个Hadoop为Linux
4)替换全部Hadoop为Linux
用户输入数字1|2|3|4,可以执行对应项的功能,输入q|Q则退出交互模式
问答题:
1. 用shell或者python编写一个脚本,要求如下
在每个月第一天备份并压缩/etc/目录下所有内容,存放在/root/bak目录里,文件名为如下形式yymmd_etc,yy为年,mm为月,脚本名称为filebck存放在root 目录下
思路:
1. 备份什么? 源 /etc
2. 备份到哪? 目标 /root/bak
3. 使用什么方式备份 压缩 tar
3. 备份的周期? 每月第一天,如何每月第一天,crond
--------------------------------------------------------------------
[root@shell scripts]# vim /scripts/fileback.sh
#/bin/bash
####################################################
# 脚本要求: #
# 1)每个月第一天备份并压缩/etc/目录下所有内容 #
# 2)存放在/root/bak目录里 #
# 3)文件名为如下形式yymmd_etc #
# 4)脚本名称为filebck存放在root目录下 #
###################################################
DestPath=/root/bak
Date=$(date +%Y_%m_%d)
# 1. 准备目标位置
[ ! -d $DestPath ] && mkdir -p $DestPath
# 2. 备份到目标位置
cd /
tar -zchf $DestPath/${Date}_etc.tar.gz ./etc
[root@shell scripts]# crontab -e
0 1 1 * * /bin/bash /scripts/fileback.sh &>/dev/null
2. 场景实践,查看内存/当前使用状态,如果使用率超过80%,则发送报警邮件
1)如何查看内存 free -m
2)如何查看内存百分比 使用的内存 / 总的内存 *100=使用百分比
free -m|awk '/Mem/ {print $3/$2*100}'
[root@shell ~]# vim /scripts/free_use.sh
#!/bin/bash
##################################
# 查看内存使用率 #
##################################
free_use=$(free -m|awk '/Mem/ {print $3/$2*100}')
if [ ${free_use%.*} -gt 80 ];then
echo "你的内存使用率超过了80%,当前内存使用率是${free_us}%"
else
echo "当前内存使用率是${free_use}%"
fi
3. 场景实践,在/backup下创建10个.txt的文件,找到/backup目录下所后缀名为.txt的文件
1)批量修改txt为txt.bak
2)把所有的.bak文件打包压缩为123.tar.gz
3)批量还原文件的名字,及把增加的.bak再删除
rename txt txt.bak *.txt
要修改的类型 修改成什么类型 操作的对象
方法一:rename重命名
[root@shell scripts]# vim rename.sh
#!/bin/bash
#批量修改文件名
#定义变量
T=txt
B=bak
#把/backup目录下的.txt结尾的文件修改为.txt.bak
cd /backup && rename $T $T\.$B *.txt
#打包
tar zcf /backup/123.tar.gz $(find /backup/ -type f -iname "*.bak")
#还原
rename $T\.$B $T *
方法二:sed重命名
[root@shell scripts]# vim /scripts/sed_name.sh
#!/bin/bash
#批量修改文件名
#1. 将文件批量重命名
find /backup/ -type f -iname "*.txt"|sed -r 's#(.*)#mv \1 \1.bak#g'|bash
#2. 打包
tar -zcf /backup/123.tar.gz $(find /backup/ -type f -iname "*.bak")
#3. 还原
find /backup/ -type f -iname "*.bak"|sed -r 's#(.*).bak#mv \1.bak \1#g'|bash
方法三:使用变量替换
[root@shell scripts]# vim /scripts/for_name.sh
#!/bin/bash
###########################
# 批量修改文件名 #
###########################
File_txt=$(find /backup/ -type f -iname "*.txt"|xargs >/backup/txt.tt)
for i in $(cat /backup/txt.tt)
do
mv $i $i.bak
done
tar czf /backup/123.tar.gz ./*.bak
File_bak=$(find /backup/ -type f -iname "*.bak" >/backup/tar.tt)
for j in $(cat /backup/tar.tt)
do
mv $j ${j%.*}
done
Shell变量运算
1)整数运算,expr $(()) $[] ,不支持小数运算
+ 加
- 减
* 乘
/ 除
% 余
[root@shell backup]# expr $num + $num1
30
[root@shell backup]# expr $num - $num1
-10
[root@shell backup]# expr $num \* $num1
200
[root@shell backup]# expr $num / $num1
0
[root@shell backup]# expr $num % $num1
10
[root@shell backup]# echo $(( num + num1 ))
[root@shell backup]# echo $[ num + num1 ]
2)小数运算bc,用的不是很多,了解即可
[root@shell backup]# yum -y install bc
[root@shell backup]# echo 2 \* 4|bc
8
[root@shell backup]# echo 7 % 4|bc
3
[root@shell backup]# echo "scale=2;7 / 4"|bc
1.75
[root@shell backup]# awk 'BEGIN{print 1/2}'
0.5
Shell变量案例
1)使用shell脚本打印,系统版本、内核版本平台、虚拟平台、静态主机名、ens33网卡、IP地址、lo网卡IP
[root@shell scripts]# vim system.sh
#!/bin/bash
System=$(hostnamectl | grep System|awk '{print $3,$4,$5}')
Kernel=$(hostnamectl | grep Kernel|awk '{print $2,$3}')
Vt=$(hostnamectl | grep Virtualization|awk '{print $2}')
Statichostname=$(hostnamectl | grep "Static hostname"|awk '{print $3}')
Ens33=$(ifconfig ens33|awk 'NR==2{print $2}')
Lo=$(ifconfig lo|awk 'NR==2{print $2}')
echo "当前系统版本是:$System"
echo "当前系统内核版本是:$Kernel"
echo "当前虚拟平台是:$Vt"
echo "当前静态主机名是:$Statichostname"
echo "当前ens33网卡IP是:$Ens33"
echo "当前lo网卡IP是:$Lo"
[root@shell scripts]# sh +x /scripts/system.sh
当前系统版本是:CentOS Linux 7
当前系统内核版本是:Linux 3.10.0-1062.el7.x86_64
当前虚拟平台是:vmware
当前静态主机名是:shell
当前ens33网卡IP是:172.16.1.100
当前lo网卡IP是:127.0.0.1
2)需求描述:变量string="Bigdata process is Hadoop, Hadoop is open source project",执行脚本后,打印输出string字符串变量,并给出用户以下选项:
-
打印string长度
[root@shell ~]# echo $string | wc -c
[root@shell ~]# echo ${#string}
-
删除字符串中所有的Hadoop
[root@shell ~]# echo ${string//Hadoop/}
Bigdata process is , is open source project
-
替换第一个Hadoop为Linux
echo ${string/Hadoop/Linux}
Bigdata process is Linux, Hadoop is open source project
-
替换全部Hadoop为Linux
[root@shell ~]# echo ${string//Hadoop/Linux}
Bigdata process is Linux, Linux is open source project
用户输入数字1| 2| 3| 4|,可以执行对应项的功能,输入q|Q则退出交互模式
[root@shell scripts]# vim string.sh
#!/bin/bash
#打印字符串,并列出操作选项,执行对应操作
string="Bigdata process is Hadoop, Hadoop is open source project"
echo $string
cat <<EOF
1. 打印string长度
2. 删除字符串中所有的Hadoop
3. 替换第一个Hadoop为Linux
4. 替换全部Hadoop为Linux
EOF
read -p "输入数字1| 2| 3| 4|,或输入q|Q则退出交互模式:" var
if [ $var -eq 1 ];then
echo "当前string字符长度是:${#string}"
fi
if [ $var -eq 2 ];then
echo ${string//Hadoop/}
fi
if [ $var -eq 3 ];then
echo ${string/Hadoop/Linux}
fi
if [ $var -eq 4 ];then
echo ${string//Hadoop/Linux}
fi
if [ $var == q ];then
exit
fi