目录
前言
本篇文章借鉴《跟老男孩学Linux运维—shell编程实战》一书,下面文章题目全部出自此书,感兴趣的小伙伴可以购买阅读,很适合入门。
一、题目
1、批量生成文件名
使用for循环在/oldboy目录下批量创建10个html文件,其中每个文件需要包含10个随机小写字母加固定字符串oldboy
注意随机数生成的方法:
1、openssl rand -base64 + (生成的随机数位数)
2、$RAND (范围是0-32767) 【可以通过md5sum进行加密】
3、date +%s%N
4、head /dev/urandomIcksum
#脚本实现
[root@any /server/scripts/mianshiti]#cat 1_piliangwenjian.sh
#!bin/bash
#######################################################
#Author:any
#Blog:http://xxx.com
#Time:2020-10-26 22:39:25
#Name:1_piliangwenjian.sh
#Version:VI.0
#Discription:To
#######################################################
[ -d /opt ] || mkdir /opt
for n in {1…10}
do
rand=openssl rand -base64 30|sed "s#[^a-z]##g"|cut -c 2-10
touch /opt/any_${rand}.html
done
## 2、批量更改文件名
将题目一所得文件名中的oldboy字符串全部改成oldgirl (最好用for循环实现),并且将扩展名html全部改成大写。
```bash
[root@any /server/scripts/mianshiti]#cat 2_gaiming.sh
#!bin/bash
#######################################################
#Author:any
#Blog:http://xxx.com
#Time:2020-10-26 22:56:00
#Name:2_gaiming.sh
#Version:VI.0
#Discription:To
#######################################################
#第一种方法:renamea专业的名字更改命令更改
rename (原名) (将要改成的名称) (文件)
rename "any" "ANY" /opt/*
rename "html" "HTML" /opt/*
# =========================================
#第二种方法:
dir=/opt/
if [ -d $dir ]
then
cd $dir
for n in `ls`
do
name=`echo $n|awk -F "[_.]" '{print "ANY_"$2".HTML"}'`
mv $n $name
done
else
exit 1
fi
# =========================================
#第三种方法:awk拼接
ls|awk -F "[_.]" '{print "mv",$0,"ANY_"$2".HTML"}'|bash
3、批量创建用户
批量创建10个系统账号any01-10并设置密码(密码为随机数,要求是字符和数字等的混合)。
[root@any /server/scripts/mianshiti]#cat 3_useradd.sh
#!bin/bash
#######################################################
#Author:any
#Blog:http://xxx.com
#Time:2020-10-27 08:53:59
#Name:3_useradd.sh
#Version:VI.0
#Discription:To
#######################################################
. /etc/init.d/functions #引用库函数
for n in {1..10}
do
rand=`openssl rand -base64 30|sed "s#[^a-z1-9]##g"|cut -c 2-11`
id any$n &>/dev/null
if [ $? -ne 0 ]
then
useradd any$n
echo "$rand"|passwd --stdin $n 2>/dev/null #指定随机密码
echo -e "any$n\t$rand" >>/tmp/user.txt #注意要输出密码
action "user any$n is exist!" /bin/true #引用库函数下面的action函数
else
action "user any$n is already exist!" /bin/false
continue
fi
done
4、扫描网段内存活的IP
写一个Shell脚本,判断10.0.0.0/24网络里,当前在线的IP有哪些?
方法一:
[root@any /server/scripts/mianshiti]#cat 4_wangduan.sh
#!bin/bash
#######################################################
#Author:any
#Blog:http://xxx.com
#Time:2020-10-27 10:38:36
#Name:4_wangduan.sh
#Version:VI.0
#Discription:To
#######################################################
. /etc/init.d/functions
cmd='ping -c 2 -W 2' #-c 尝试次数,-W超时时间
ip='10.0.0.'
for n in {1..255}
do
$cmd ${ip}$n &>/dev/null
if [ $? -eq 0 ]
then
action "Url ${ip}$n is ok" /bin/true
else
action "Url ${ip}$n is error" /bin/false
fi
done
方法二:
#使用nmap命令
nmap - 网络探测工具和安全/端口扫描器
-sP:进行ping扫描 (主机发现),然后打印出对扫描做出响应的那些主机。 没有进一步的测试(如端口扫描或者操作系统探测)。
-sS:TCP SYN扫描,只扫描不进行连接,在一个没有入侵防火墙的快速网络上,每秒钟可以扫描数千个端口。
CMD="nmap -sP "
Ip="10.0.0.0/24"
CMD2 ="nmap -sS"
$CMD $Ip|awk '/Nmap scan report for/ {print $NF}'
5、解决DOS攻击
写一个Shell脚本以解决DOS攻击生产的问题。
请根据Web日志或网络连接数,监控当某个IP并发连接数或短时内PV达到100(读者可根据实际情况来设定)时,即调用防火墙命令封掉对应的IP。防火墙命令为:
“iptables -I INPUT -s IP -j DROP” (IP 为要封的地址)。
分析:
先分析Web日志,可以每分钟或每小时分析一次,这里给出按小时处理的方法。可以将日志按小时进行分割,分成不同的文件,根据分析结果把PV数高的单IP封掉。例如,每小时单IP的PV数超过500,则即刻封掉,这里简单地把日志的每一行近似看作一个PV,实际工作中需要计算实际页面的数量,而不是请求页面元素的数量,另外,很多公司都是以NAT形式上网的,因此每小时单IP的PV数超过多少就会被封掉,还要根据具体的情况具体分析,本题仅给出一个实现的案例,读者使用时需要考虑自身网站的业务去使用。
iptables -L -n:查看ip的访问情况
uniq 用于报告或者忽略重复行
-c:count,在该行显示重复连接的次数
-d:仅显示重复出现的行列
-u:仅显示出现一次的行列
sort 对文本文件内容进行排序,可以针对文件的内容按照单位进行排序
-r:以相反的顺序来排序
-b:忽略每行前面开始出现的空行
-c:检查文件是否已经按照顺序排序
-n:按照数值大小排序
-o:将排序后的内容结果指定到文件当中
-t:分个字符,指定排序时所用的栏位分隔字符
[root@any /server/scripts]#cat DDOS.sh
#!bin/bash
#######################################################
#Author:any
#Blog:http://xxx.com
#Time:2020-10-24 16:17:33
#Name:DDOS.sh
#Version:VI.0
#Discription:To
#######################################################
#网站监测
abc(){
#对文件进行处理,把外网访问的所有的ip地址进行分类按,访问次数进行排名,导入到一个临时的文件,然后对这个临时文件进行提取ip和次数
awk -F "[ :]+" '/ESTABLISHED/{print $(NF-3)}' /tmp/netstat.log|sort|uniq -c|sort -rn|head -10 >/tmp/ip.log
while read line
do
ip=`echo $line|awk '{print $2}'`
count=`echo $line|awk '{print $1}'`
if [ $count -gt 10 ] && [`iptables -nL|grep "$ip"|wc -l` -lt 1]
then
echo "$ip is degrous"
iptables -I INPUT -s $ip -j DROP #>>>封杀ip
echo "$ip is dropped" >>/tmp/droplist_$(date +%F).log #把处理日志导出,方便检查
else
echo "$ip is safy"
fi
done </tmp/ip.log
}
main(){
while true
do
abc
sleep 5
done
}
main
6、数据库备份(库备份、表备份)
分库备份:
PATH="/application/mysql/bin/mysqld:$PATH"
backup='/tmp/mysql'
master='root'
passwd='any123'
#进入到数据库中并且打开库列表
mysql=`$PATH -u${master} -p${passwd} -e show databases|sed "1d"|egrep -v "_achema"`
for n in $mysql
do
mysqldump -u$master -p$passwd -B $n 2>/devnull|gzip >${backup}/${date+%T%F}.sql.gz
done
每个库里面的每一个表备份:
backup='/tmp/mysql/'
master='root'
passwd='any123'
database=`mysql -u${master} -p${passwd} -e "show databases;" 2>/dev/null|sed "1d"|egrep -v "_schema"`
for n in $database
do
mkdir -p ${backup}${n}_$(date +%F)
tables=`mysql -u$master -p$passwd -e "show tables from $n;"|sed "1d"|egrep -v "mysql|schema"` #删选表
for tab in $tables #双重for循环,每个库进入库里面列表当中
do
mysqldump -u$master -p$passwd -B $tab 2>/devnull|gzip >${backup}${n}_$(date +%F)/${n}_${table}.sql.gz #备份库下面的所有表
done
done
7、筛选合适长度的单词
给一段字符串:I am oldboy teacher welcome to oldboy training class,从中筛选长度不大于6的单词
#运用数组
arr=(I am oldboy teacher welcome to oldboy training class)
for n in ${#arr[*]}
do
if [ ${#arr[n]} -le 6 ]
then
echo "${arr[n]}"
fi
done
8、比较两个整数的大小
输入两个整数,并且输出大小的比较
usage(){
echo "请正确输入!!"
exit
}
compare(){
read -p "请输入两个数:" a b
expr $a + $b + 10 &>/dev/null
if [ $? -ne 0 ]
then
usage
else
if [ $a -gt $b ]
then
echo 'a>b'
elif [ $a -lt $b ]
then
echo 'a<b'
else
echo 'a=b'
fi
fi
}
compare
8、打印菜单选项
把选项列出来,然后根据需要,选择合适的选项
cat <END
1.[蔡徐坤]
2.[詹姆斯]
3.[科比]
4.[韦德]
5.[exit]
END
while true
do
read -p "Plaese input the num:" n
case a in $n
1)
echo "you love 蔡徐坤!"
;;
2)
echo "you love 詹姆斯!"
;;
3)
echo "you love 科比!"
;;
4)
echo "you love 韦德!"
;;
5)
exit
;;
*)
echo "you are SB!"
exit
esac
done
9、网站入侵检测
分析:
一、篡改
1、恶意篡改,顾名思义就是未经过允许修改网页内容
2、文件的大小,内容,修改时间会变化
二、采用md5sum指纹校验方法,建立进本的指纹库,以用来与源文件进行比对数据
三、检测文件内容和数量的变化
1、用md5sum来检测文件内容的变化:md5sum -c -quiet
2、因为md5sum无法检测新的文件,所以用diff来比对检测
#先给网站下面的所有的目录文件进行指纹的索取,索取之后,如果网站下面的文件内容有篡改,则用"md5sum -c " 命令就会检测出来
[root@web02 /server/scripts]#find =/application/nginx/html -type f|xargs md5sum >$zhiwen
#先复制源文件到指定目录之下,相当于先备份,然后如果源文件被篡改,则把备份文件与源文件进行对比之后就会查出被篡改的文件
[root@web02 /server/scripts]#find =/application/nginx/html -type f >$wenjian_yuan
[root@web02 /server/scripts]#cat check_web.sh
web_dir=/application/nginx/html
zhiwen=/opt/zhiwen.db.ori
wenjian_yuan=/opt/wenjian.db.ori
wenjian_check=/opt/wenjian.db.ori_bak
#错误文件查看目录
error=/opt/web_error.log
[ -e $web_dir ] || exit
echo '#md5sum -c --quiet /opt/zhiwen.db.ori' >$error
md5sum -c --quiet $zhiwen &>>$error
if [ $? -ne 0 ]
then
echo 'error! Please check the error file in /opt/web_error.log!'
echo "find $web_dir -type f >$wenjian_check" >>$error
find $web_dir -type f >$wenjian_check
diff /opt/wenjian.db* >>$error
if [ $? -ne 0 ]
then
echo 'error! Please check the error file in /opt/web_error.log!'
fi
else
echo 'file is ok!'
fi
10、nginx启动脚本
CentOS 6版本下的自启动:
CentOS6实现chconfig管理注意
chk --list #查看服务
chkconfig [服务] off #关闭服务
chkconfig [服务] on #开启服务
自启动运行脚本开头必须要加上:
chkconfig:2345 90 60 (2345是默认运行级别同时处理;90:开始启动服务顺序;60:停止关闭服务顺序;都可以自定义)
如下所示启动脚本文件:
[root@any ~]#cat /etc/init.d/nginx #nginx启动脚本必须要在/etc/init.d/目录下面
#!/bin/bash
#chkconfig:2345 90 60 #必须要加,可以自定义启动和关闭的顺序
#decription:nginx #可加可不加
function usage(){
echo "Usage:$0 {start|restart|stop|reload}"
exit 0
}
function start(){
/application/nginx/sbin/nginx
sleep 2
if [ `netstat -lntup|grep nginx|wc -l` -ne 0 ]
then
echo 'nginx is starting'
exit 1
fi
}
function stop(){
/application/nginx/sbin/nginx -s stop &>/dev/null
sleep 1
if [ `netstat -lntup|grep nginx|wc -l` -eq 0 ]
then
echo 'nginx is down'
exit 1
fi
}
function reload(){
/application/nginx/sbin/nginx -s reload &>/dev/null
if [ `netstat -lntup|grep nginx|wc -l` -ne 0 ]
then
echo 'nginx is reload'
exit
else
echo 'nginx is dead!'
fi
}
main(){
if [ $# -eq 0 ]
then
usage
fi
if [ "$1" = "start" ]
then
start
elif [ "$1" = "stop" ]
then
stop
elif [ "$1" = "reload" ]
then
reload
elif [ "$1" = "restart" ]
then
stop
sleep 1
start
else
usage
fi
}
main $*
编写好脚本之后开始配置chkconfig
首先确定自启动脚本文件在不在目录/etc/init.d/下面,不在的添加进来
然后
#赋予脚本的执行权限
chmod +x /etc/init.d/nginx
#添加到自启动服务当中
chkconfig --add nginx
#查看服务是否已经添加
chkconfig --list nginx
#启动服务
chkconfig nginx on
#关闭服务
chkconfig nginx off
CentOS 7 systemctl 自启动管理
systemctl知识简介
从CentOS7 Linux开始,系统里的网络服务启动已经从传统的service改成了systemctl(一个systemd工具,主要负责控制systemd系统和服务管理器。),管理开机自启动的命令也从chkconfig改为了systemctl,由systemctl一个命令代替了CentOS7以前系统中的service和chkconfig两个命令。系统服务的脚本也从传统的路径的/etc/init.d(/etc/rc.d/init.d/),改了/usr/lib/systemd(除此之外还有/etc/systemd/system),需要自启动运行的程序,一般存在这个系统服务目录下,即:/usr/lib/systemd/system目录,每一个服务以“服务名.service”结尾,该文件的内容一般分为3部分:即[Unit]、[Service]和[Install]
CentOS7:
#systemctl管理的nginx服务配置说明
#确定配置服务的目录必须要在/usr/lib/systemd/system/nginx.service目录之下
[root@any ~]#cat /usr/lib/systemd/system/nginx.service
[Unit]
Description=Nginx service
After=network.target
[Service]
Type=forking #<==后台运行。
PIDFile=/var/run/nginx.pid #<==PID路径。
ExecStart=/etc/rc.d/init.d/nginx start #<==启动服务脚本,介绍在下文。
ExecReload=/etc/rc.d/init.d/nginx restart #<==重启服务脚本,介绍在下文。
ExecStop=/etc/rc.d/init.d/nginx stop #<==兼容停止服务脚本,介绍在下文。
PrivateTmp=true #<==开启独立的空间。
[Install]
WantedBy=multi-user.target #<==这里为设置多用户级别。
============================================================
nginx自启动脚本:
#!/bin/bash
#Author:any
#Blog:http://xxx.com
#Time:2020-10-22 10:57:08
#Name:nginx.sh
#Version:VI.
. /etc/init.d/functions #初始化库函数
pid='/application/nginx/logs/nginx.pid'
path='/application/nginx/sbin'
function usage(){
echo "Usage:$0 {start|restart|stop|reload}"
exit 0
}
function start(){
if [ ! -f $pid ]
then
$path/nginx
sleep 1
action 'nginx is starting' /bin/true #调用库函数当中的action 提示函数
retval=$?
else
echo 'nginx is on!!!'
exit 1
fi
return $retval
}
function stop(){
if [ -f $pid ]
then
$path/nginx -s stop
sleep 1
action 'nginx is off' /bin/true
retval=$?
else
echo 'nginx is off!!!'
exit 1
fi
return $retval
}
function reload(){
if [ -f $pid ]
then
$path/nginx -s stop
$path/nginx
sleep 1
action 'nginx is reload' /bin/true
retval=$?
else
echo 'nginx is dead!!!'
fi
return $retval
}
main(){
if [ $# -ne 1 ]
then
usage
fi
case $1 in
start)
start
retval=$?
;;
stop)
stop
retval=$?
;;
reload)
reload
retval=$?
;;
*)
usage
;;
esac
}
main $*
11、抓阄脚本
每一个人随机对应1-99中的一个数,定向到一个文件当中,然后从文件当中选出三个人以及对应的数字。
抓阄分析:
1、输入一个人的名字,判断这个名字在name_file文件当中是否存在,如存在则表示该同学已经抽过,否则随机生成一个数(1-99),放nemae_file文件当中保留。
2、判断随机数是否重复,如果重复则要重新生成随机数使用while循环实现一直输入名字。
root@any /server/scripts]#cat zhajiu.sh
#!bin/bash
#######################################################
#Author:any
#Blog:http://xxx.com
#Time:2020-10-29 14:43:12
#Name:zhajiu.sh
#Version:VI.0
#Discription:To
#######################################################
name_file=/opt/zhuajiu.log
[ -f $name_file ] || touch $name_file
usage(){
echo "输入错误,请正确输入!!"
}
check_name(){
while true
do
read -p "请输入你的名字:" name
if [ ${#name} -eq 0 ]
then
usage
else
if [ `grep -w $name $name_file|wc -l` -eq 0 ]
then
num=`expr $RANDOM % 99 + 1`
if [ `grep $num $name_file|wc -l` -eq 0 ]
then
echo "$name,your number is $num!"|tee -a $name_file
fi
else
echo "your name is already exit!"
echo "`grep $name $name_file`"
fi
fi
done
}
check_name
12、破解RANDON随机数
有一窜数字是md5sum加密之后在截取的内容是:
21029299
00205d1c
a3da1677
1f6d12dd
890684b
问原来的数值时多少?
分析:
RANDOM随机数的范围是0-32767,把这所有的数md5sum处理之后的都列出来,再比对就好了
#!bin/bash
#######################################################
#Author:any
#Blog:http://xxx.com
#Time:2020-10-26 09:23:07
#Name:pojie.sh
#Version:VI.0
#Discription:To
#######################################################
arr=(
21029299
00205d1c
a3da1677
1f6d12dd
890684b
)
>/tmp/md5.txt
getmd5sum(){
for n in {1..32767}
do
{
stat="echo $n|md5sum|cut -c 1-8"
echo "$stat $n" >>/tmp/md5sum.txt
}& #括号内命令并行(一同)执行
done
}
findmd5(){
#取出元素数组并且用“|”分隔开
#word="${arr[*]}|tr ' ' '\n'"
word="${arr[*]}|sed -r 's# #|#g'" #取出数组元素并且用"|"分隔开
egrep "$word" /tmp/md5sum.txt #同时过滤出不同字符串的内容
}
if [ ! -s /tmp/md5sum.txt ]
then
getmd5sum
else
findmd5dum
fi
13、批量查看多个网址是否是正常
1、把网站定义成一个数组
2、wget或者curl判断网站是否正常,不正常则报警
[root@any /server/scripts]#vim a.sh
#Blog:http://xxx.com
#Time:2020-10-29 15:56:46
#Name:a.sh
#Version:VI.0
#Discription:To
#######################################################
. /etc/init.d/functions #引用库函数
arr=(
www.baidu.com
blog.etiantian.com
www.jd.com
10.0.0.61
)
usage(){
echo "usage:$0 url"
exit 0
}
url(){
for ((i=0;i<${#arr[*]};i++))
do
wget -T 2 --tries 2 -q ${arr[i]} &>/dev/null
if [ $? -eq 0 ]
then
action "${arr[i]} is ok." /bin/true
else
action "${arr[i]} is error." /bin/false
fi
done
exit 0
}
url
14、字符串去重排序
给一段字符串或者文本进行数量排序:
[root@any ~]#vim 2.txt
I am any,I think there where is a way,there is a will
方法1:tr替换与awk删选
#tr ‘ ,.’ ‘\n’ <2.txt|awk ‘{S[$1]++}END{for(key in S) print S[key],key}’|sort -rn
tr ‘ ,.’ ‘\n’ <2.txt|awk ‘{S[$1]++}END{for(key in S) print S[key],key|"sort -rn"}’ 2.txt
方法2:tr替换与sort、uniq 排序
tr ‘ ,.’ ‘\n’ <2.txt|sort|uniq -c|sort -rn
方法3:awk删选
#awk -F '[ ,.]+' ‘{for(i=1;i<=NF;i++)S[$i]++}END{for(key in S) print S[key],key|"sort -rn"}' 2.txt
awk -F '[ ,.]+' '{for(i=1;i<=NF;i++)S[$i]++}END{for(key in S) print S[key],key}' 2.txt
=======================================================================================================================
分成单个字母排序
方法1:
awk -F "" '{for(i=1;i<=NF ;i++)S[$i]++}END{for(key in S) print S[key],key}' 2.txt|sort -rn
方法2:
grep -o :--仅匹配只打印匹配行的匹配(非空)部分,每个匹配部分都在单独的输出行上
grep -o '[^ ,.]' 2.txt|sort|uniq -c|sort -rn
15 、web以及mysql服务异常监测
端口检测:
netstat -lntup|grep
pe -ef|grep
lsof -i :
web获取:
wget -o --timeout 2 --tries 2 --spider (网站)
-o:所有的消息记录到日志文件
--timeout:超时时间
--tries:尝试次数
--spider:模拟爬取文件
curl -o /dev/null (ip)
-o /dev/null :输出定向到空
检测数据库:
#if [ `nestat -lntup|grep mysqld|wc -l` -gt 0 ]
#if [ `lsof -i :80|wc -l` -gt 0 ]
if [ `ps -ef|grep mysqld|wc -l` -lt 1 ]
then
echo “mysql is alived!”
else
echo “mysql is dead”
systemctl start mysql #此命令是必须要配置好mysql的启动脚本之后才能执行
fi
检测web网站:
[root@any /server/scripts]#cat check_url.sh
#!/bin/bash
#Author:any
#Blog:http://xxx.com
#Time:2020-10-22 14:31:54
#Name:url.sh
#Version:VI.0
. /etc/init.d/functions #引用库函数
usage(){
echo "usage:$0 url"
exit 0
}
url(){
wget -q $1 &>/dev/null
if [ $? -eq 0 ]
then
action "$1 is ok." /bin/true
exit 0
else
action "$1 is error." /bin/true
exit 0
fi
}
main(){
if [ $# -eq 0 ]
then
usage
else
url $1
fi
}
main $*