Shell脚本实例一
1. 每隔3秒调用一次
2. 批量远程主机软件部署程序
3. 批量创建用户
4. 告警内存使用率大于80%
5. ftp自动批量下载文件
6. 检测千台服务器ping连接性
7. 屏蔽每分钟访问超过200的IP
8. 屏蔽每分钟SSH暴力破解超过10次的IP
9. 检查MySQL主从同步状态
10. MySQL数据库备份
- 1.编写脚本每隔3秒调用自己一次,但是该进程会一直增加
#!/bin/bash
# exec $$(可以理解为脚本的pid,有没有运行可以在/proc下找到该pid就时有运行,没有则没有)可以联想到kill 关闭进程
echo $$
sleep 3
./test.sh
- 2.批量远程主机软件部署程序
[root@linux ~]# ./test.sh nginx
#!/bin/bash
username=tony
/usr/bin/expect <<EOF
set timeout 10
spawn ssh $username@192.168.233.201
expect {
"*yes/no" { send "yes\r" }
"*password:" { send "123\r" }
}
expect "]#"
send "yum install $1 -y\r"
expect eof
EOF
- 3.批量创建用户
#!/bin/bash
echo_color(){
if [ $1 =="green" ]; then
echo -e "\033[32;40m$2\033[0m"
elif [ $1 == "red" ]; then
echo -e "\033[31;40m$2\033[0m"
fi
}
for ((i=1;i<=5;i++)); do
if id user$i; then
echo_color red "user$i already exists!"
else
echo "create user$i"
useradd user$i
echo 123 | passwd --stdin user$i &>/dev/null #给用户正确格式的输入密码
echo_color green "create successful"
fi
done
- 4.根分区剩余空间小于20%
(已用80%)或内存的已用空间大于80%,向root用户发送告警邮件,邮件内容包含使用率相关信息
[root@linux ~]# vim test.sh
#!/bin/bash
mem=`free -m | awk '/Mem/{printf("%d\n"),$3/$2*100}'`
io=`df -h | awk '/\/$/{printf("%d\n"),$5}'`
if [ ${mem} -ge 80 ]
then
echo "xxx" | mail -s "mem warning" root@localhost
fi
if [ ${io} -ge 80 ]
then
echo "xxx" | mail -s "io warning" root@localhost
fi
- 5.ftp自动批量下载文件
#####从ftp服务器上的/data/localacc 到 本地的/data/localacc####
#!/bin/bash
ftp -n<<!
open 192.168.233.201
user sfhc sfhc1234
binary
cd /data/localacc
lcd /data/localacc
prompt
mget *.gz
close
bye
!
命令详解:
-n是不使用ftp的自动登录
open host[port]:建立指定ftp服务器连接,可指定连接端口
user username password:向远程主机表明自己的身份,需要口令时,必须输入口令,如:user anonymous my@email
binary:设置文件传输模式为binary,缺省为ascii。binary模式不会对数据进行任何处理,ascii模式会将回车换行转换为本机的回车字符。关于binary和ascii传输模式的区别请看: FTP的ASCII和Binary传输模式
cd remote-dir:进入远程主机目录remote-dir
lcd local-dir:将本地工作目录切换至local-dir
prompt:设置多个文件传输时的交互提示(默认为提示,批量下载在每个文件都会提示,输入Y才能进行下一文件的传输,prompt可取消交互提示)
mget remote-files:下载多个远程文件
close:中断与远程服务器的ftp会话
bye:退出ftp会话过程
!:在本地机器执行交互shell,exit回到ftp环境
- 6.检测千台服务器ping连接性
#!/bin/bash
data=`date +%c`
export data
cat /opt/ping/1000.txt | while read line
do
ping -c 1 $line &> /dev/null
if [ $? -eq 0 ]
then
echo "$data" >> /var/log/ping/ping-status-right.log
echo -e " $line is ok" >> /var/log/ping/ping-status-right.log
else
echo "$data" >> /var/log/ping/ping-status-wrong.log
echo -e " $line is not ok" >>/var/log/ping/ping-status-wrong.log
fi
done
- 7.屏蔽每分钟访问超过200的IP
方法1:以Nginx日志作为测试
#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
ABNORMAL_IP=$(tail -n5000 /var/log/nginx/access.log | grep $DATE | awk '{a[$1]++}END{for(i in a)if(a[i]>100)print i}')
#先tail防止文件过大,读取慢,数字可调整每分钟最大的访问量。awk不能直接过滤日志,因为包含特殊字符。
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
方法2:通过建立连接数
ABNORMAL_IP=$(netstat -an | awk '$4~/:80$/ && $6~/ESTABLISHED/{gsub(/:[0-9]+/,"",$5);{a[$5]++}}END{for(i in a)if(a[i]>100)print i}')
#gsub是将第五列(客户端IP)的冒号和端口去掉
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
- 8.屏蔽每分钟SSH暴力破解超过10次的IP
方法1:通过lastb获取登录状态:
DATE=$(date +"%a %b %e %H:%M") #星期月天时分 %e单数字时显示7,而%d显示07
ABNORMAL_IP=$(lastb | grep "$DATE" | awk '{a[$3]++}END{for(i in a)if(a[i]>10)print i}')
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
方法2:通过日志获取登录状态
DATE=$(date +"%b %d %H")
ABNORMAL_IP="$(tail -n10000 /var/log/auth.log |grep "$DATE" |awk '/Failed/{a[$(NF-3)]++}END{for(i in a)if(a[i]>5)print i}')"
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -A INPUT -s $IP -j DROP
echo "$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >>~/ssh-login-limit.log
fi
done
- 9.检查MySQL主从同步状态
#!/bin/bash
USER=bak
PASSWD=123456
IO_SQL_STATUS=$(mysql -u$USER -p$PASSWD -e 'show slave status\G' |awk -F: '/Slave_.*_Running/{gsub(": ",":");print $0}') #gsub去除冒号后面的空格
for i in $IO_SQL_STATUS; do
THREAD_STATUS_NAME=${i%:*}
THREAD_STATUS=${i#*:}
if [ "$THREAD_STATUS" != "Yes" ]; then
echo "Error: MySQL Master-Slave $THREAD_STATUS_NAME status is $THREAD_STATUS!"
fi
done
- 10.MySQL数据库备份
#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=192.168.1.120
DB=test
USER=bak
PASS=123456
MAIL="zhangsan@example.com lisi@example.com"
BACKUP_DIR=/data/db_backup
SQL_FILE=${DB}_full_$DATE.sql
BAK_FILE=${DB}_full_$DATE.zip
cd $BACKUP_DIR
if mysqldump -h$HOST -u$USER -p$PASS --single-transaction --routines --triggers -B $DB > $SQL_FILE; then
zip $BAK_FILE $SQL_FILE && rm -f $SQL_FILE
if [ ! -s $BAK_FILE ]; then
echo "$DATE 内容" | mail -s "主题" $MAIL
fi
else
echo "$DATE 内容" | mail -s "主题" $MAIL
fi
find $BACKUP_DIR -name '*.zip' -ctime +14 -exec rm {} \;