运行脚本
给予执行权限,通过具体的文件路径指定文件执行
直接运行解释器,将脚本作为解释器程序的参数运行
bash退出状态码
范围是0-255
脚本中一旦遇到exit命令,脚本会立即终止,终止退出状态取决于exit命令后面的数字
如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态
有效命名:
RUNOOB
LD_LIBRARY_PATH
_var
var2
无效命名:
?var=
user*name=runoob
语句给变量赋值
for file in `ls /etc`
或
for file in $(ls /etc)
定义变量:
your_name="eagles"
使用变量:
echo $your_name
echo ${your_name}
建议使用{}号作边界
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done
如果使用$skillScript,则将会输出空值
#!/bin/bash
myUrl="http://www.google.com"
readonly myUrl
myUrl="http://www.runoob.com"
执行脚本后,显示只读变量无法修改
#!/bin/sh
myUrl="http://www.runoob.com"
unset myUrl
echo $myUrl
$1,$2,…:对应调用第1,第2等参数
$0:命令本身
$*:传递给脚本的所有参数(把所有参数当作整体)
$@:传递给脚本的所有参数
$#:传递给脚本的参数的个数
案例1:
myecho.sh
#!/bin/bash
echo "命令本身是:$0"
echo "第一个参数是:$1"
echo "第二个参数是:$2"
echo "一共有$#个参数"
echo "所有参数是:$@"
案例2:判断所给文件的行数
linecount.sh
#!/bin/bash
linecount="$(wc -l $1|cut -d' ' -f1)"
echo "This file have ${linecount} lines"
语法格式:array_name=(value1 ... valuen)
示例:
my_array=(A B C D)
array_name[]=value0
array_name[]=value1
array_name[]=value2
读取数组:${array_name[index]}
获取数组中的所有元素:
my_array[]=A
my_array[]=B
my_array[]=C
my_array[]=D
echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"
获取数组的长度:
my_array[]=A
my_array[]=B
my_array[]=C
my_array[]=D
echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"
+ ‐ * / % ** ...
增强赋值:
+=,‐=,*=,/=,%=
乘法符号有些场景中需要转义 : *\
bash有内建随机数生成器:$RANDOM
() let var(变量名)=算术表达式
() var=$[算术表达式]
() var=$((算术表达式))
() var=$(expr arg1 arg2 arg3 …) var=$(expr + )
expr本身是一个命令,可以直接进行运算
[root@centos73 ~]# expr 1+2
+2
[root@centos73 ~]# expr 1 + 2注意要空格才可以进行运算。乘法符号有些场景中需要转义,如*。也就是expr这个命令后面跟的是3个参数
练习1:计算/etc/passwd文件中第10个用户的第20个用户的ID之和
练习2:传递两个文件路径参数给脚本,计算这两个文件之中所有空白行之和
练习3:统计/etc/,/var/,/usr/目录下有多少目录和文件
测试命令:test EXPERSSION
num1=
num2=
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
‐gt:是否大于
‐ge:是否大于等于
‐eq:是否等于
‐ne:是否不等于
‐lt:是否小于
‐le:是否小于等于
练习题,比较两个数的大小
[root@localhost ~]# cat diff.sh
#!/bin/bash
read -p "请输入两个整数" num1 num2
if [ $num1 -gt $num2 ];then
echo "$num1 > $num2"
elif [ $num1 -lt $num2 ];then
echo "$num1 < $num2"
else
echo "$num1 = $num2"
fi
==:是否等于
>:是否大于
<:是否小于
!=:是否不等于
=~:左侧字符串是否能够被右侧的PATTERN所匹配
Note:此表达式一般用于[[ ]]中
‐z “STRING”:测试字符串是否为空,空则为真,不空则为假
‐n “STRING”:测试字符串是否不空,不空则为真,空则为假
简单的存在性测试:
‐a FILE :文件存在性测试,存在为真,否则为假
存在性及类型测试:
‐b FLIE:是否存在且为块设备文件;
‐c FILE:是否存在且为字符设备文件;
‐d FILE:是否存在且为目录文件;
‐f FILE:是否存在且为普通文件;
‐h FILE 或 ‐L FILE : 存在且为符号链接文件;
‐p FIEL :是否存在且为命名管道文件;
‐S FILE:是否存在且为套接文件;
文件权限测试:
‐r FILE:是否存在且可读
‐w FILE:是否存在且可写
‐x FILE:是否存在可执行
文件特殊权限测试:
‐u FILE:是否存在且拥有suid权限;
‐g FILE:是否存在且拥有sgid权限;
‐k FILE:是否存在且拥有sticky权限;
文件大小测试:
‐s FILE:是否存在且非空
文件是否打开:
‐fd:fd表示文件描述符是否已经打开且与某终端相关
‐N FILE:文件自动上一次读取之后是否被修改过;
‐O FILE:当前用户是否为文件的属主;
‐G FILE:当前有效用户是否为文件数组;
双目测试:
FILE1 ‐ef FILE2 :FILE1与FILE2是否指向同一个设备上的相同inode
FILE1 ‐nt FILE2:FILE1是否新于FILE2
FILE1 ‐ot FILE2:FILE1是否旧于FILE2
逻辑运算符:
&&代表的意思是当前一个命令执行成功时会继续执行后续的命令,当前一个命令执行失败的时候不会执行后续的命令
||代表的意思是当前一个命令执行成功时不会继续执行后续的命令,当前一个命令执行失败的时候会执行后续的命令
第一种方式:
COMMAND1 && COMMAND2
COMMAND1 || COMMAND2
! COMMAND
第二种方式:
EXPRESSION1 ‐a EXPRESSION2
EXPRESSION1 ‐o EXPRESSION2
! EXPRESSION
Note:必须使用测试命令进行
if 判断条件;then
条件为真的分支代码
fi
if 判断条件;then
条件为真的分支代码
else
条件为假的分支代码
fi
if 判断条件;then
条件为真的分支代码
elif 判断条件;then
条件为真的分支代码
else
条件为假的分支代码
fi
练习1:判断两个数是否相等
Note:if经常会与test命令一起使用
练习2:判断用户是否存在,如果不存在添加用户,并设置密码和用户相同
# 练习2
#!bin/bash
read -p "请输入用户名:" user
id $user &> /dev/null
thing="$(echo $?)"
# echo $thing
if test $[thing] -eq
then
echo "用户已存在"
else
useradd $user
echo $user | passwd --stdin $user &>/dev/null
echo -e "账户已id成功创建\n"
echo "密码已更新为账户名"$user
fi
#!/bin/bash
read ‐p "input your name:" name
echo ${name}
exit
test.txt
aaa
bbb
ccc
for 变量名 in 列表;do
循环体
done
#!/bin/bash
for i in {..};do
mkdir /home/user$i
for i in (seq );do
touch /home/user$i/user$i.txt
done
done
练习题2:列出/var/目录下各个子目录占用磁盘大小
[root@localhost ~]# cat ping.sh
#!/bin/bash
for address in {..}
do
#echo $address
ping -c1 -W1 192.168.111.$address &>/dev/null
status="$(echo $?)"
if test $status -eq
then
echo "192.168.111.$address 目前在线"
else
echo "192.168.111.$address 目前不在线"
fi
done
while 测试条件;do
循环体
done
#!/bin/bash
while read a;do
echo $a
done < /datas/6files
#!/bin/bash
[root@localhost ~]# cat ran.sh
#!/bin/bash
num="$(echo $[RANDOM%100+1])"
count=
echo $num
while true
do
read -p "请猜一下这个数字:" guess
let count=${count}+1
echo $guess
if [ $guess -lt $num ];then
echo "你猜的小了,再猜一次吧"
elif [ $guess -gt $num ];then
echo "你猜的大了,再猜一次吧"
else
echo "你猜对了 总共猜了$count次"
breakh*+
done
until 条件测试;do
循环体
done
#while 写法 当判断条件为真则运行下面的内容
#!/bin/bash
first=
second=
while ((first <= ))
do
while ((second <= first))
do
let chicken=${first}*${second}
echo -n "${first}*${second}=${chicken} "
let second++
done
let first++
second=
echo ""
done
#until 写法 当判断条件为假则运行下面的内容
#!/bin/bash
first=
second=
until ((first > ))
do
until ((second > first))
do
let chicken=${first}*${second}
echo -n "${first}*${second}=${chicken} "
let second++
done
let first++
second=
echo ""
done
function FUNNAME(){
函数体
返回值
}
FUNNME #调用函数
#!/bin/bash
demoFun(){
echo '这是我的第一个 shell 函数!'
}
echo "‐‐‐‐‐函数开始执行‐‐‐‐‐"
demoFun
echo "‐‐‐‐‐函数执行完毕‐‐‐‐‐"
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
#可以使用$?来获取返回值
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam
注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=时,需要使用${n}来获取参数
#!/bin/bash
function disk_used(){
#获取磁盘使用率脚本
#2022/7/14
time=$(date "+%Y-%m-%d %H:%M:%S")
diskUsage=`df -h | sed -n '6p' | awk '{print $5}'`
disk=`echo "$diskUsage" | cut -d "%" -f `
disk_used=`df -h | sed -n '6p' | awk '{print $3}'`
disk_left=`df -h | sed -n '6p' | awk '{print $4}'`
disk_total=`df -h | sed -n '6p' | awk '{print $2}'`
echo "磁盘总量:$disk_total 磁盘使用量:$disk_used 磁盘剩余量:$disk_left"
echo "磁盘使用率:$disk%"
if [ $disk -gt ] #此处10可更改大小
then
echo "警告,您当前磁盘使用率${disk}%,已严重超标$time 标准最高使用量为70%"
else
exit
fi
}
function RAM_used(){
#获取内存相关信息的脚本
#2022/7/14
time=$(date "+%Y-%m-%d %H:%M:%S")
memoryUsed=`free -m | sed -n '2p' | awk '{printf "%f\n",($3)/$2*100}'`
memoryleft=`free -h | sed -n '2p' | awk '{print $4}'`
memorytotal=`free -h | sed -n '2p' | awk '{print $2}'`
echo "内存总量为$memorytotal 内存剩余量为$memoryleft"
echo "内存使用量:${memoryUsed}% ${time}"
memory=`echo "$memoryUsed" | cut -d "." -f `
if [ $memory -gt ]
then
echo "警告,您当前内存使用率${memoryUsed}%,已严重超标$time 标准最高使用率为70%"
else
return
fi
}
function CPU_used(){
#
#脚本功能描述:依据/proc/stat文件获取并计算CPU使用率
#
#CPU时间计算公式:CPU_TIME=user+system+nice+idle+iowait+irq+softirq
#CPU使用率计算公式:cpu_usage=(idle2-idle1)/(cpu2-cpu1)*100
#默认时间间隔
TIME_INTERVAL=
time=$(date "+%Y-%m-%d %H:%M:%S")
LAST_CPU_INFO=$(cat /proc/stat | grep -w cpu | awk '{print $2,$3,$4,$5,$6,$7,$8}')
LAST_SYS_IDLE=$(echo $LAST_CPU_INFO | awk '{print $4}')
LAST_TOTAL_CPU_T=$(echo $LAST_CPU_INFO | awk '{print $1+$2+$3+$4+$5+$6+$7}')
sleep ${TIME_INTERVAL}
NEXT_CPU_INFO=$(cat /proc/stat | grep -w cpu | awk '{print $2,$3,$4,$5,$6,$7,$8}')
NEXT_SYS_IDLE=$(echo $NEXT_CPU_INFO | awk '{print $4}')
NEXT_TOTAL_CPU_T=$(echo $NEXT_CPU_INFO | awk '{print $1+$2+$3+$4+$5+$6+$7}')
#系统空闲时间
SYSTEM_IDLE=`echo ${NEXT_SYS_IDLE} ${LAST_SYS_IDLE} | awk '{print $1-$2}'`
#CPU总时间
TOTAL_TIME=`echo ${NEXT_TOTAL_CPU_T} ${LAST_TOTAL_CPU_T} | awk '{print $1-$2}'`
CPU_USAGE=`echo ${SYSTEM_IDLE} ${TOTAL_TIME} | awk '{printf "%.2f", 100-$1/$2*100}'`
echo "CPU使用率:${CPU_USAGE}% "$time
cpu=`echo "$CPU_USAGE" | cut -d "." -f `
if [ $cpu -gt ]
then
echo "警告,您当前CPU使用率${CPU_USAGE}%,已严重超标"$time
else
return
fi
}
yum install -y net-tools &> /dev/null
wangka=`ip a | grep ens | head -1 | cut -d: -f2`
System=$(hostnamectl | grep System | awk '{print $3,$4,$5}')
Kernel=$(hostnamectl | grep Kernel | awk -F: '{print $2}')
Virtualization=$(hostnamectl | grep Virtualization| awk '{print $2}')
Statichostname=$(hostnamectl | grep Static|awk -F: '{print $2}')
Ens32=$(ifconfig $wangka | awk 'NR==2 {print $2}')
Lo=$(ifconfig lo0 | awk 'NR==2 {print $2}')
NetworkIp=$(curl -s icanhazip.com)
CPU_name=$(lscpu | grep 名称| awk -F" +" '{print $2}')
CPU_core=$(lscpu | grep CPU\(s\): | awk -F" +" '{print $2}')
echo "当前系统版本是:$System"
echo "当前系统内核是:$Kernel"
echo "当前虚拟平台是:$Virtualization"
echo "当前主机名是:$Statichostname"
echo "当前网卡$wangka的地址是:$Ens32"
echo "当前lo0接口的地址是:$Lo"
echo "当前公网地址是:$NetworkIp"
echo "当前使用的CPU型号为:$CPU_name"
echo "当前CPU核数为:$CPU_core"
CPU_used
RAM_used
disk_used
需求: 1.每隔10s监控mysql的进程数,若进程数大于等于500,则自动重启mysqld服务,并检测服务是 否重启成功 2.若未成功则需要再次启动,若重启5次依旧没有成功,则向管理员发送告警邮件(使用echo输 出已发送即可),并退出检测 3.如果启动成功,则等待1分钟后再次检测mysql进程数,若进程数正常,则恢复正常检测(10s 一次),否则放弃重启并向管理员发送告警邮件,并退出检测
# 代码可能不太对
#!/bin/bash
function check_mysqld_process_number() {
process_num=`ps -ef | grep mysql| wc -l`
if [ $process_num -gt ];then
systemctl restart mysqld &> /dev/null
# 重启五次mysqld确保服务启动
systemctl status mysqld &> /dev/null
num_restart_httpd= #定义一个变量进行重启次数的记录
if [ $? -ne ];then #如果重启后mysqld运行状态不正常
while true;do
let num_restart_mysqld++ #记录重启次数来确定最高循环五次
systemctl restart httpd &> /dev/null
systemctl status httpd &> /dev/null
[ $? -eq ] && break #如果有一次成功启动则不在重新执行重启
[ $num_restart_httpd -eq ] && break #重启次数达到6次不再尝试重启解决
done
fi
# 判断重启服务的结果
systemctl status httpd &> /dev/null
[ $? -ne ] && echo "apache未正常重启,已发送邮件给管理员" && return #发现重启无法解决 通知管理员
sleep
return
# 再次判断进程是否正常
process_num=`ps -ef | grep httpd| wc -l`
if [ $process_num -gt ] ;then
echo "apache经过重启进程数依然大于50"
return
else
return
fi
else
echo "进程数小于50"
sleep #10秒进行一次检测
return
fi
}
# 每十秒钟执行一次函数,检查进程是否正常
while true;do
check_mysqld_process_number
[ $? -eq ] && exit
done
#!/bin/bash
read -p "请输入第一个文件夹的路径:" DIR1
read -p "请输入第二个文件夹的路径:" DIR2
#echo $DIR1
#echo $DIR2
#用于读取 DIR1 中文件的数目
if [ ! -d $DIR1 ];then # 判断用户输入的路径是否正确,错误则直接退出程序
echo "没有 $DIR1 这个目录,程序退出"
exit
fi
count_1=`find $DIR1 |wc -l`
let count_1=${count_1}-1 #find命令第一行实际是查找的目录,减去第一行才是是实际的文件数
#echo $count_1
#echo $DIR1
#用于读取 DIR1 中文件的数目
if [ ! -d $DIR2 ];then # 判断用户输入的路径是否正确,错误则直接退出程序
echo "没有 $DIR2 这个目录,程序退出"
exit
fi
count_2=`find $DIR2 |wc -l`
let count_2=${count_2}-1 #find命令第一行实际是查找的目录,减去第一行才是是实际的文件数
#echo $count_2
#echo $DIR2
#将DIR1中的文件以“文件名 md5值”形式放入temp_1
time=
temp=
while [ $time -lt $count_1 ];do #利用DIR1中的文件数目控制循环
file_locate_1=`find $DIR1 | sed -n "${temp}p"` #取出文件名
#echo $temp
#echo $file_locate_1
file_first=`md5sum $file_locate_1 | awk -F[' ']+ '{print $1}'` #取出文件对应的md5值
#echo $file_first
echo "$file_locate_1 $file_first" >> /root/temp_1 #格式化输入文件
let time=${time}+1
let temp=${temp}+1
done
#将DIR2中的文件以“文件名 md5值”形式放入temp_2
time=
temp=
while [ $time -lt $count_2 ];do #利用DIR2中的文件数目控制循环
file_locate_2=`find $DIR2 | sed -n "${temp}p"` #取出文件名
#echo $temp
#echo $file_locate_2
file_second=`md5sum $file_locate_2 | awk -F[' ']+ '{print $1}'` #取出文件对应的md5值
#echo $file_second
echo "$file_locate_2 $file_second" >> /root/temp_2 #格式化输入文件
let time=${time}+1
let temp=${temp}+1
done
out=
in=
hang=
hang_2=
while [ $out -lt $count_1 ];do #外层循环由DIR1中的文件数目控制
file_name=`cat /root/temp_1 | sed -n "${hang}p" | awk -F" " '{print $1}'`
file_md5=`cat /root/temp_1 | sed -n "${hang}p" | awk -F" " '{print $2}'`
while [ $in -lt $count_2 ];do #内层循环由DIR2中的文件数目控制
file_name_2=`cat /root/temp_2 | sed -n "${hang_2}p" | awk -F" " '{print $1}'`
file_md5_2=`cat /root/temp_2 | sed -n "${hang_2}p" | awk -F" " '{print $2}'`
if [ "${file_md5}" = "${file_md5_2}" ];then #将文件的md5值进行对比
echo "$DIR1 中的 $file_name 与 $DIR2 中的 $file_name_2 为相同文件" #相同的则输出
flag=
echo "$file_name 1" >> /root/temp_3 #第一个文件夹的放入temp_3
echo "$file_name_2 1" >> /root/temp_4 #第二个文件夹的放入temp_4
else #[ $flag -eq 0 ];then #该组对比表示没有对比上
echo "$file_name 0" >> /root/temp_3 #第一个文件夹的放入temp_3
echo "$file_name_2 0" >> /root/temp_4 #第二个文件夹的放入temp_4
fi
let in=${in}+1
let hang_2=${hang_2}+1
flag=
done
hang_2=
in=
#echo $out
let out=${out}+1
let hang=${hang}+1
# echo $file_name
#echo $out
#echo $count_1
done
if [ -f /root/temp_3 ];then
echo "这是 $DIR1 中特有的文件"
sort -n /root/temp_3 | uniq | awk -F" " '{print $1}' | uniq -u #去除重复后取第一个元素后再次去掉重复行
# echo "这是 $DIR2 中特有的文件"
# sort -n /root/temp_4 | uniq
else
echo "$DIR1 中的每个文件都与 $DIR2 中相同"
fi
if [ -f /root/temp_4 ];then
echo "这是 $DIR2 中特有的文件"
sort -n /root/temp_4 | uniq | awk -F" " '{print $1}' | uniq -u #去除重复后取第一个元素后再次去掉重复行
else
echo "$DIR2 中的每个文件都与 $DIR1 中相同"
fi
rm -f /root/temp_{..}