shell脚本实例(二)

【脚本12】批量更改文件名

需求:

找到/123目录下所有后缀名为.txt的文件
批量修改.txt为.txt.bak
把所有.bak文件打包压缩为123.tar.gz
批量还原文件的名字,即把增加的.bak再删除
代码:

#!/bin/bash
now=`date +%F_%T`
mkdir /tmp/123_$now
for txt in `ls /123/*.txt`
do
  mv $txt $txt.bak
  for f in $txt
  do
    cp $txt.bak /tmp/123_$now
  done
done

cd /tmp/
tar czf 123.tar.gz 123_$now/

for txt in `ls /123/*.txt.bak`
do
  name=`echo $txt |awk -F '.' '{OFS="."} {print $1,$2}'`
  mv $txt $name
done

【脚本13】监控80端口

需求:
写一个脚本,判断本机的80端口(假如服务为httpd)是否开启着,如果开启着什么都不做,如果发现端口不存在,那么重启一下httpd服务,并发邮件通知你自己。脚本写好后,可以每一分钟执行一次,也可以写一个死循环的脚本,30s检测一次。
发邮件的脚本参考【脚本11】的示例代码。
代码:

#!/bin/bash
email="user@example.com"
if netstat -lntp |grep ':80' |grep 'httpd'
then
   echo "80 port no problem"
   exit
else
   /usr/local/apache2.4/bin/apachectl restart
   python mail.py $email "check_80port" "The 80 port is down."
   n=`ps aux |grep httpd|grep -cv grep`

   if [ $n -eq 0 ]
   then
      /usr/local/apache2/bin/apachectl start 2>/tmp/apache_start.err
   fi

   if [ -s /tmp/apache_start.err ]
     then
      python mail.py  $mail 'apache_start_error' `cat /tmp/apache_start.err`
   fi
fi

【脚本14】备份数据库

需求:

设计一个shell脚本来备份数据库,首先在本地服务器上保存一份数据,然后再远程拷贝一份,本地保存一周的数据,远程保存一个月。

假定,我们知道mysql root账号的密码,要备份的库为discuz,本地备份目录为/bak/mysql, 远程服务器ip为192.168.123.30,远程提供了一个rsync服务,备份的地址是 192.168.123.30::backup . 写完脚本后,需要加入到cron中,每天凌晨3点执行。
脚本代码:

#!/bin/bash
PATH=$PATHi:/usr/local/mysql/bin
week=`date +%w`
today=`date +d`
passwd="123456"
backdir="/data/mysql"
r_backupIP="192.168.123.30::backup"

exec 1>/var/log/mysqlbak.log 2>/var/log/mysqlbak.log
echo "mysql backup begin at `date +%F %T`."

# 本地备份
mysqldump -uroot -p$passwd --default-character-set=utf8 discuz >$backdir/$week.sql
# 同步备份到远程机器
rsync -az $backdir/$week.sql $r_backupIP/$today.sql

echo "mysql backup end at `date +%F %T`."
然后加入cron
0 3 * * * /bin/bash /usr/local/sbin/mysqlbak.sh

【脚本15】自动重启php-fpm服务

服务器上跑的是LNMP环境,近期总是有502现象。502为网站访问的状态码,200正常,502错误是nginx最为普通的错误状态码。由于502只是暂时的,并且只要一重启php-fpm服务则502消失,但不重启的话,则会一直持续很长时间。所以有必要写一个监控脚本,监控访问日志的状态码,一旦发生502,则自动重启一下php-fpm。

我们设定:

access_log /data/log/access.log
脚本死循环,每10s检测一次(假设每10s钟的日志条数为300左右)
重启php-fpm的方法是 /etc/init.d/php-fpm restart
脚本代码:

#!/bin/bash
access_log="/data/log/access.log"
N=10
while :
do
   # 因为10秒大概产生300条日志记录
   tail -n300 $access_log > /tmp/log
   # 拿出log中包含502的日志行数
   n_502=`grep -c "502" /tmp/log`
   # 如果行数大于10
   if [ $n_502 -ge $N ]
   then
      # 就记录一下系统状态
      top -bn1 > /tmp/`date +%H%M%S`-top.log
      vmstat 1 5 > /tmp/`date +%H%M%S`-vm.log
      # 然后才重启服务,并把错误信息重定向
      /etc/init.d/php-fpm restart 2> /dev/null
      # 重启php-fpm服务后,应先暂缓1分钟,而后继续每隔10s检测一次
      sleep(60)
   fi
   sleep(10)
done

【脚本16】文本替换

将memcached里的数据导出到文件中,然后再导入memcached里却发现数据过期了,这是因为导出的数据是带有一个时间戳的,这个时间戳就是该条数据过期的时间点,如果当前时间已经超过该时间戳,那么是导入不进去的。不过可以修改文件中的时间戳来保证导入时数据的有效期。可以写一个简单的脚本批量替换这些文件中的时间戳:

#!/bin/bash
hour=`date -d "+1 hour" +%s`  # 一个小时之后的时间戳
data_time=`cat data.txt |grep add |awk '{print $4}' |sort -n |uniq`
for i in $data_time
do
   sed -i "s/$i/$hour/g" `grep $i -rl /root/data.txt`
done

【脚本17】启动容器

docker每次关闭都会连带着将运行中的容器关闭,所以每次启动docker后都需要逐个去启动容器,很麻烦,由于是实验用的虚拟机不是线上的机器,所以就直接写了一个很简单的循环来启动容器:

#!/bin/bash
/usr/bin/systemctl start docker

for i in `docker ps -a |grep 'Exited' |awk '{print $1}'`
do
  /usr/bin/docker start $i
done

【脚本18】删除文本中的字母

要求:把一个文本文档的前5行中包含字母的行删除掉,同时把6到10行中的全部字母删除掉。

参考答案:假设文本名字叫做1.txt,并且文本行数大于10,脚本如下:

#!/bin/bash

## 先获取该文本的行数
rows=`wc -l 1.txt |awk '{print $1}'`

## 对前5行进行处理
for i in `seq 1 5`
do
  ## 使用sed把每一行的内容赋值给变量
  row=`sed -n "$i"p 1.txt`
  ## 用grep 判定是否匹配字母,-v取反,-q不输出内容
  if echo $row |grep -vq '[a-zA-Z]'
  then
     echo $row
  fi
done

## 对6-10行做删除字母处理
for i in `seq 6 10`
do
  row=`sed -n "$i"p 1.txt`
  echo $row |sed 's/[a-zA-Z]//g'
done

## 剩余的直接输出
for i in `seq 11 $rows`
do
  sed -n "$i"p 1.txt
done

##若想把更改内容写入到1.txt,还需要把以上内容重定向到一个文本中,然后删除1.txt,再把刚刚重定向的文件更名为1.txt

【脚本19】查找字母数小于6的单词

用shell打印下面这句话中字母数小于6的单词。
Bash also interprets a number of multi-character options.

  • 脚本如下:
#!/bin/bash
for s in Bash also interprets a number of multi-character options
do
  n=`echo $s |wc -c`
  if [ $n -lt 6 ]
  then
     echo $s
  fi
done

【脚本20】输入数字执行对应命令

写一个脚本实现如下功能: 输入一个数字,然后运行对应的一个命令。显示命令如下:

cmd meau* 1—date 2–ls 3–who 4–pwd
当输入1时,会运行date, 输入2时运行ls, 依此类推。

实现脚本如下:

#!/bin/bash
echo "*cmd meau**  1—date 2–ls 3–who 4–pwd"

read -p "please input a number 1-4: " n
case $n in
   1)
      date
   ;;
   2)
      ls
   ;;
   3)
      who
   ;;
   4)
      pwd
   ;;
   *)
      echo "Please input a number: 1-4"
   ;;
esac

【脚本21】批量创建用户并设置密码

用shell脚本实现如下需求:
添加user_00 – user_09 10个用户,并且给他们设置一个随机密码,密码要求10位包含大小写字母以及数字,注意需要把每个用户的密码记录到一个日志文件里。

  • 提示:

随机密码使用命令 mkpasswd
在脚本中给用户设置密码,可以使用echo 然后管道passwd命令
实现脚本如下:

#!/bin/bash
for i in `seq 00 09`
do
   useradd user_$i
   p=`mkpasswd -s 0 -l 10`
   echo "user_$i $p" >> /tmp/user0_9.pw
   echo $p |passwd -stdin user_$i
done

#【脚本22】监控httpd进程

在服务器上,写一个监控脚本。

每隔10s去检测一次服务器上的httpd进程数,如果大于等于500的时候,就需要自动重启一下apache服务,并检测启动是否成功?
若没有正常启动还需再一次启动,最大不成功数超过5次则需要理解发邮件通知管理员,并且以后不需要再检测!
如果启动成功后,1分钟后再次检测httpd进程数,若正常则重复之前操作(每隔10s检测一次),若还是大于等于500,那放弃重启并需要发邮件给管理员,然后自动退出该脚本。假设其中发邮件脚本为mail.py

  • 实现脚本如下:
    #!/bin/bash
    

check_service(){
n=0
for i in seq 1 5
do
# apachectl命令所在路径
/usr/local/apache2/bin/apachectl restart 2> /tmp/apache.err
if [$? -ne 0 ]
then
n=$[$n-1]
else
break
fi

done

if [ $n -eq 5 ]
then
## mail.py的内容参考https://coding.net/u/aminglinux/p/aminglinux-book/git/blob/master/D22Z/mail.py
python mail.py “123@qq.com“ “httpd service down” cat /tmp/apache.err
exit

fi
}

while :
do
t_n=ps -C httpd --no-heading |wc -l
if [ $t_n -ge 500 ]
then
/usr/local/apache2/bin/apachectl restart
if [ $? -ne 0 ]
then
check_service
fi
sleep 60
t_n=ps -C httpd --no-heading |wc -l
if [ $t_n -ge 500]
then
python mail.py “123@qq.com“ “httpd service somth wrong” “the httpd process is budy.”
exit
fi
fi
sleep 10
done


# 【脚本23】封ip

- 需求: 
根据web服务器上的访问日志,把一些请求量非常高的ip给拒绝掉!

- 分析: 
我们要做的,不仅是要找到哪些ip请求量不合法,并且还要每隔一段时间把之前封掉的ip(若不再继续请求了)给解封。 所以该脚本的关键点在于定一个合适的时间段和阈值。

比如, 我们可以每一分钟去查看一下日志,把上一分钟的日志给过滤出来分析,并且只要请求的ip数量超过100次那么就直接封掉。 而解封的时间又规定为每半小时分析一次,把几乎没有请求量的ip给解封!

- 参考日志文件片段:

157.55.39.107 [20/Mar/2015:00:01:24 +0800] www.aminglinux.com “/bbs/thread-5622-3-1.html” 200 “-” “Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)”
61.240.150.37 [20/Mar/2015:00:01:34 +0800] www.aminglinux.com “/bbs/search.php?mod=forum&srchtxt=LNMP&formhash=8f0c7da9&searchsubmit=true&source=hotsearch” 200 “-” “Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)”

- 脚本实现如下:

``` bash
#!/bin/bash
## 日志文件路径
log_file="/home/logs/client/access.log"
## 当前时间减一分钟的时间
d1=`date -d "-1 minute" +%H:%M`
## 当前时间的分钟段
d2=`date +%M`
## iptables命令所在的路径
ipt="/sbin/iptables"
## 用于存储访问日志里的ip
ips="/tmp/ips.txt"

## 封ip
block(){
   ## 把日志文件中的ip过滤出来,去掉重复的ip,并统计ip的重复次数以及对ip进行排序,最后将结果写到一个文件中
   grep "$d1:" $log_file |awk '{print $1}' |sort -n |uniq -c |sort -n > $ips
   ## 将文件里重复次数大于100的ip迭代出来
   for ip in `awk '$1 > 100 {print $2}' $ips`
   do
      ## 通过防火墙规则对这些ip进行封禁
      $ipt -I INPUT -p -tcp --dport 80 -s $ip -j REJECT
      ## 将已经封禁的ip输出到一个文件里存储
      echo "`date +%F-%T` $ip" >> /tmp/badip.txt
   done
}

## 解封ip
unblock(){
   ## 将流量小于15的规则索引过滤出来
   for i in `$ipt -nvL --line-number |grep '0.0.0.0/0' |awk '$2 < 15 {print $1}' |sort -nr`
   do
      ## 通过索引来删除规则
      $ipt -D INPUT $i
   done
   ## 清空规则中的数据包计算器和字节计数器
   $ipt -Z
}

## 为整点或30分钟就是过了半个小时,就需要再进行分析
if [ $d2 == "00" ] || [ $d2 == "30" ]
then
   unblock
   block
else
   block
fi

【脚本24】部署前端项目

最近做了一个web前端的项目,需要编写一个脚本完成项目的上线。

  • 脚本实现如下:
#!/bin/bash

#
# 使用方法:
# mmall:front_deploy.sh mmall-fe
# admin:front_deploy.sh admin-fe
#

GIT_HOME=/developer/git-repository/   # 从git仓库拉取下来的源码的存放路径
DEST_PATH=/product/frontend/    # 项目打包后的发布路径

# cd dir
if [ ! -n "$1" ]
then
    echo -e "请输入要发布的项目!"
    exit
fi 

if [ $1 = "mmall-fe" ]
then
    echo -e "===========Enter mall-fe============="
    cd $GIT_HOME$1
elif [ $1 = "admin-fe" ]
then
    echo -e "===========Enter mall-fe============="
    cd $GIT_HOME$1
else 
    echo -e "输入的项目名没有找到!"
    exit
fi

# clear git dist
echo -e "===========Clear Git Dist============="
rm -rf ./dist

# git操作
echo -e "===========git checkout master============="
git checkout master

echo -e "===========git pull============="
git pull

# npm install
echo -e "===========npm install============="
npm install --registry=https://registry.npm.taobao.org

# npm run dist
echo -e "===========npm run dist============="
npm run dist

if [ -d "./dist" ]
then
    # backup dest
    echo -e "===========dest backup============="
    mv $DEST_PATH$1/dist $DEST_PATH$1/dist.bak

    # copy
    echo -e "===========copy============="
    cp -R ./dist $DEST_PATH$1

    # echo result
    echo -e "===========Deploy Success============="
else
    echo -e "===========Deploy Error============="
fi

   转载规则


《shell脚本实例(二)》 helen 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录