# Shell脚本案例全集详解

## 目录结构

```
Shell脚本案例/
├── 备份恢复类/
│   ├── DB-backup/
│   │   ├── Mysql/
│   │   ├── oracle/
│   │   ├── postgresql-check/
│   │   └── ...
│   └── ...
├── 安全类/
├── 安装配置类/
│   └── keepalived/
└── 监控/
```

## 1. 备份恢复类脚本

### 1.1 DB-backup目录

#### 1.1.1 Mysql子目录

#### 1.1.2 oracle子目录

#### 1.1.3 postgresql-check子目录

### 1.2 其他备份脚本

## 2. 安全类脚本

## 3. 安装配置类脚本

### 3.1 keepalived目录

## 4. 监控脚本

## 详细脚本内容及解释

### 1. 备份恢复类脚本

#### 1.1 DB-backup目录

##### 1.1.1 xtrabackup_full.sh

```bash
#!/bin/bash  
local_ip="$(/sbin/ifconfig eth0|grep 'inet addr'|awk -F : '{print $2}'|cut -d ' ' -f1)" 
email='it-arch' 
user='root' 
passwd=CHANGE_ME 
my_config='/etc/my.cnf' 
log=$(date +%Y%m%d%H%M).log  
str=$(date +%Y%m%d%H%M).tar.gz  
backup_dir='/backup/MySQL/xtrabackup' 
source='it-arch'
target='it-arch'
title='xtrabackup Mysql backup information'  
MailUser='it-arch' 
MailPassword=CHANGE_ME
content1='Server_name:'$(hostname)' Server_ip:'$local_ip' '$(date +"%y-%m-%d %H:%M:%S")' mysql full backup Success!'
content2='Server_name:'$(hostname)' Server_ip:'$local_ip' '$(date +"%y-%m-%d %H:%M:%S")' mysql full backup Faild!'
echo "Start to backup at $(date +%Y%m%d%H%M)"
if [ ! -d "$backup_dir" ];then  
    mkdir -p $backup_dir  
fi  
#innobackupex --defaults-file=$my_config --user=$user --pCHANGE_ME  --database=$database --stream=tar $backup_dir 2>$backup_dir/$log | gzip 1>$backup_dir/$str  
innobackupex --defaults-file=$my_config --user=$user --pCHANGE_ME   $backup_dir  
if [ $? -eq 0 ];then  
    echo "Backup is finish! at $(date +%Y%m%d%H%M)"  

    exit 0  
else  
    echo "Backup is Fail! at $(date +%Y%m%d%H%M)"  
    echo "Server_name:$(hostname) Server_ip:$local_ip $(date +"%y-%m-%d %H:%M:%S") mysql full backup Fail!"
    exit 1  
fi  
echo "Backup Process Done"
```

**脚本功能**：使用innobackupex工具执行MySQL全量备份。

**主要参数**：
- `local_ip`：服务器IP地址
- `email`：邮件接收人
- `user`：MySQL用户名
- `passwd`：MySQL密码
- `my_config`：MySQL配置文件路径
- `backup_dir`：备份目录

**执行流程**：
1. 获取服务器IP地址和当前时间
2. 创建备份目录（如果不存在）
3. 使用innobackupex执行全量备份
4. 检查备份结果
5. 输出备份完成信息

##### 1.1.2 backup.sh

（已在上一个文件中详细解释）

##### 1.1.3 Mysql子目录

###### 1.1.3.1 MYSQL_BACKUP.sh

```bash
#!/usr/bin/env bash

#
# Created 2005-06-24 by Matthew Montgomery - mmontgom@rackspace.com 
# 
# Change: 2006-06-01 by Matthew Montgomery
#  Add support for ibbbackup for InnoDB tables
#  Add support for MySQL 4.1 and 5.0
#

DATE=`date -I`
DATADIR="/var/lib/mysql"
BASE_DIR="/mnt/drive2/backup"
BACKUP_DIR="$BASE_DIR/current"
INTERVAL="$1"
RETENTION=14 # days
HOST=`hostname -s`
MYVERSION=`mysql -Bse "SELECT substring_index(version(),'.',2)"`
###  Uncomment this line to specify the path to and enable ibbackup for hotcopy of InnoDB tables.
# IBBACKUP="/usr/local/bin/ibbackup"

if [ "$MYVERSION" = '4.1' ] || [ "$MYVERSION" = '5.0' ] ; then
	PURGELOGS='mysql -e "PURGE MASTER LOGS BEFORE DATE_SUB( NOW(), INTERVAL 1 HOUR )"'
elif [ $MYVERSION = '3.23' -o "$MYVERSION" = '4.0' ]; then
	PURGELOGS='mysql -e "RESET MASTER"'
else
echo "UNSUPPORTED MYSQL VERSION"
exit 1
fi

if [ ! $1 ];
then
	read -p "Backup Interval? (Hourly|Daily) : " INTERVAL
fi

case $INTERVAL in
	hourly | HOURLY | Hourly | 1 )
	echo "Performing HOURLY level backup -- `date`"
	mysql -e "FLUSH LOGS"
	if [ -d $BASE_DIR/$DATE ] && [ "$MYVERSION" = '4.1' -o "$MYVERSION" = '5.0' ] ; then
		rsync -aub $DATADIR/$HOST-bin.?????? $BASE_DIR/$DATE
	elif [ -d $BASE_DIR/$DATE ] && [ "$MYVERSION" = '3.23' -o "$MYVERSION" = '4.0' ] ; then
		rsync -aub $DATADIR/$HOST-bin.??? $BASE_DIR/$DATE
	else 
		echo "No destination dir! please run daily backup first." 1>&2
		exit 1
	fi
	sleep 1
	find $BASE_DIR -size 98c -exec rm -rf '{}' \;
	exit 0
	;;
	daily | DAILY | Daily | 2 )
	echo "Performing DAILY level backup -- `date`"
	if [ ! -d $BACKUP_DIR ];
	then
		echo Creating $BACKUP_DIR
		mkdir -p $BACKUP_DIR
	fi

	if [ ! -z "$IBBACKUP" ] ; then
		$IBBACKUP /etc/my.cnf /etc/my.cnf.ibbackup 2>&1
		$IBBACKUP --apply-log /etc/my.cnf.ibbackup 2>&1
		rm $BACKUP_DIR/ibbackup_logfile
	fi
	mysqlhotcopy --regexp=.* $BACKUP_DIR
	chown -R mysql: $BACKUP_DIR/
	mv $BACKUP_DIR $BASE_DIR/$DATE
	eval $PURGELOGS
	find $BASE_DIR -ctime +$RETENTION -exec rm -rf '{}' \;
	exit 0
	;;
	* )
	echo "Invalid Selection" 1>&2
	exit 1
esac
```

**脚本功能**：MySQL备份脚本，支持小时级和天级备份，兼容不同MySQL版本。

**主要参数**：
- `DATE`：当前日期
- `DATADIR`：MySQL数据目录
- `BASE_DIR`：备份基础目录
- `BACKUP_DIR`：当前备份目录
- `INTERVAL`：备份间隔（小时级或天级）
- `RETENTION`：备份保留天数
- `HOST`：主机名
- `MYVERSION`：MySQL版本

**执行流程**：
1. 检测MySQL版本
2. 根据MySQL版本设置日志清理命令
3. 读取或提示输入备份间隔
4. 根据备份间隔执行不同的备份操作：
   - 小时级备份：刷新日志，复制二进制日志文件
   - 天级备份：使用mysqlhotcopy备份所有数据库，清理过期备份
5. 清理旧的备份文件

###### 1.1.3.2 mysqlbackup.sh

```bash
#!/bin/bash
#This is a sub-treasury backup script for MySQL.
#
# File save time is 7 days.

bapath="/data/DBbackup/DBfile/"
if [ ! -d $bapath ];then
  mkdir -p $bapath
fi
filename=`date +%Y-%m-%d`'.sql'
#databases=(acs activemq appdatamonitor authorize autosettle basis cashier cert cmf counter csa deposit dpm ffs fos guardian jdedb lflt member mns oss payment pbs pfs pns rms smsgateway ssop tradereports tss ues voucher wallet)


for db in information_schema ddepps mysql performance_schema sys 
do 
/usr/bin/mysqldump -uroot -p'xxxx!xxxxx#7' --opt --default-character-set=utf8 --triggers --hex-blob --skip-lock-tables $db >$bapath$db-$filename
cd $bapath
tar zcf $bapath$db-$filename.tar.gz $db-$filename
find $bapath -mtime +7 -name "*.sql.tar.gz" -exec rm -rf {} \;
done
rm -rf ${bapath}*.sql
```

**脚本功能**：MySQL数据库备份脚本，备份指定数据库并压缩，自动删除7天前的旧备份。

**主要参数**：
- `bapath`：备份文件存储路径
- `filename`：备份文件名（包含日期）
- `databases`：要备份的数据库列表（当前被注释，使用下面的for循环指定）

**执行流程**：
1. 检查备份目录是否存在，不存在则创建
2. 生成备份文件名（包含当前日期）
3. 循环备份指定的数据库：
   - 使用mysqldump备份数据库到SQL文件
   - 压缩SQL文件为tar.gz格式
   - 删除7天前的旧备份文件
4. 删除临时生成的SQL文件

###### 1.1.3.3 check_mysql_ms.sh

```bash
#!/bin/bash
mysql_user='root'
mysql_pass='123.com'
mail="it-arch"
data=$(date +%Y-%m-%d-%H:%M)
netstat -lntup|egrep ":3306"|grep -v grep>/dev/null0
if [ $? -eq 0 ];then
	Slave_IO=`mysql -u${mysql_user} -pCHANGE_ME -e "show slave status\G"|grep "Slave_IO_Running:"|awk -F": " '{print $2}'`
	Slave_SQL=`mysql -u${mysql_user} -pCHANGE_ME -e "show slave status\G"|grep "Slave_SQL_Running:"|awk -F": " '{print $2}'`
		if [ "$Slave_IO" == "Yes" ] && [ "$Slave_SQL" == "Yes" ];then
			STAT=1 && echo "$data mysql-status is ok">>/var/log/mysql-status.log
		else
			STAT=0 && echo "$data mysql-status is error">>/var/log/mysql-status.log
		fi
else
	STAT=0 && echo "$data mysql-status is error">>/var/log/mysql-status.log
fi
zabbix_sender -z xxx.xxx.xxx.xx -s "MySQL-master-slave" -k mysql -o $STAT
```

**脚本功能**：检查MySQL主从复制状态，并将结果发送到Zabbix监控系统。

**主要参数**：
- `mysql_user`：MySQL用户名
- `mysql_pass`：MySQL密码
- `mail`：邮件接收人
- `data`：当前日期时间

**执行流程**：
1. 检查MySQL服务是否在监听3306端口
2. 如果MySQL服务运行正常，则检查主从复制状态：
   - 获取Slave_IO_Running状态
   - 获取Slave_SQL_Running状态
   - 如果两者都为Yes，则状态为正常（STAT=1）
   - 否则状态为错误（STAT=0）
3. 如果MySQL服务未运行，则状态为错误（STAT=0）
4. 将状态结果写入日志文件
5. 使用zabbix_sender将状态发送到Zabbix监控服务器

###### 1.1.3.4 slave_status.sh

```bash
#!/usr/bin/env bash

repeat_alert_interval=15 # minutes
lock_file=/tmp/slave_alert.lck
active=yes

## Check if alert is already sent ## 

function check_alert_lock () {
    if [ -f $lock_file ] ; then
        current_file=`find $lock_file -cmin -$repeat_alert_interval`
        if [ -n "$current_file" ] ; then
            # echo "Current lock file found"
            return 1
        else
            # echo "Expired lock file found"
            return 2 
        fi
    else
    return 0
    fi
}

## Find the location of the mysql.sock file ##

function check_for_socket () {
        if [ -z $socket ] ; then
                if [ -S /var/lib/mysql/mysql.sock ] ; then
                        socket=/var/lib/mysql/mysql.sock
                elif [ -S /tmp/mysql.sock ] ; then
                        socket=/tmp/mysql.sock
                else
                        ps_socket=`netstat -ln | egrep "mysql(d)?\.sock" | awk '{ print $9 }'`
                        if [ "$ps_socket" ] ; then
                        socket=$ps_socket
                        fi
                fi
        fi
        if [ -S "$socket" ] ; then
                echo UP > /dev/null
        else
                echo "No valid socket file "$socket" found!"
                echo "mysqld is not running or it is installed in a custom location"
                echo "Please set the $socket variable at the top of this script."
                exit 1
        fi
}


check_for_socket

Slave_IO_Running=`mysql -Bse "show slave status\G" | grep Slave_IO_Running | awk '{ print $2 }'`
Slave_SQL_Running=`mysql -Bse "show slave status\G" | grep Slave_SQL_Running | awk '{ print $2 }'`
Last_error=`mysql -Bse "show slave status\G" | grep Last_error | awk -F \: '{ print $2 }'`


if [ -z $Slave_IO_Running -o -z $Slave_SQL_Running ] ; then
        echo "Replication is not configured or you do not have the required access to MySQL"
        exit
fi

if [ $Slave_IO_Running == 'Yes' ] && [ $Slave_SQL_Running == 'Yes' ] ; then 
    if [ -f $lock_file ] ; then
        rm $lock_file
        echo "Replication slave is running"
        echo "Removed Alert Lock"
    fi
    exit 0
elif [ $Slave_SQL_Running == 'No' ] ; then
    if [ $active == 'yes' ] ; then
        check_alert_lock
        if [ $? = 1 ] ; then
            ## Current Lock ##
            echo "up" > /dev/null
        else
            ## Stale/No Lock ##
             touch $lock_file
            echo "SQL thread not running on server `hostname -s`!"
            echo "Last Error:" $Last_error
        fi
    fi
    exit 1
elif [ $Slave_IO_Running == 'No' ] ; then
        if [ $active == 'yes' ] ; then
                check_alert_lock
                if [ $? = 1 ] ; then
                        ## Current Lock ##
            echo "up" > /dev/null
                else
                        ## Stale/No Lock ##
                        touch $lock_file
                        echo "LOG IO thread not running on server `hostname -s`!"
                        echo "Last Error:" $Last_error
                fi
    fi
    exit 1
else 
        if [ $active == 'yes' ] ; then
                check_alert_lock
                if [ $? = 1 ] ; then
                        ## Current Lock ##
            echo "up" > /dev/null
                else
                        ## Stale/No Lock ##
                        touch $lock_file
            echo "Unexpected Error!"
            echo "Check Your permissions!"
                fi
        fi
    exit 2
fi
```

**脚本功能**：检查MySQL从服务器复制状态，并在状态异常时发送警报，避免重复发送。

**主要参数**：
- `repeat_alert_interval`：重复警报间隔（分钟）
- `lock_file`：锁定文件路径，用于防止重复发送警报
- `active`：是否激活警报功能

**主要函数**：
- `check_alert_lock`：检查是否需要发送警报（避免重复发送）
- `check_for_socket`：查找MySQL套接字文件位置

**执行流程**：
1. 查找MySQL套接字文件位置
2. 检查Slave_IO_Running和Slave_SQL_Running状态
3. 获取最后错误信息
4. 根据状态结果执行不同的操作：
   - 如果两者都为Yes，则移除锁定文件（如果存在），退出脚本
   - 如果SQL线程未运行，则检查是否需要发送警报：
     - 如果锁定文件存在且未过期，则不发送警报
     - 否则，创建锁定文件并发送警报
   - 如果IO线程未运行，则检查是否需要发送警报：
     - 如果锁定文件存在且未过期，则不发送警报
     - 否则，创建锁定文件并发送警报
   - 其他情况，检查是否需要发送警报并发送意外错误警报

###### 1.1.3.5 time_behind_master.sh

```bash
#!/usr/bin/env bash

function human_readable_time () {

########################################################################
#                                                                      #
#       Function to produce human readable time                        #
#                                                                      #
########################################################################

        usage="$0 seconds 'variable'"
        if [ -z $1 ] || [ -z $2 ] ; then
                cecho $usage $red
                exit 1
        fi
        days=$(echo "scale=0 ; $1 / 86400" | bc -l)
        remainder=$(echo "scale=0 ; $1 % 86400" | bc -l)
        hours=$(echo "scale=0 ; $remainder / 3600" | bc -l)
        remainder=$(echo "scale=0 ; $remainder % 3600" | bc -l)
        minutes=$(echo "scale=0 ; $remainder / 60" | bc -l)
        seconds=$(echo "scale=0 ; $remainder % 60" | bc -l)
        export $2="$days days $hours hrs $minutes min $seconds sec"
}


function slave_status () {
	local variable=`mysql -e "show slave status\G" | grep $1 | awk '{ print $2 }'`
        export "$2"=$variable
}

slave_status Seconds_Behind_Master seconds_behind_master

# echo -e $seconds_behind_master

if [ "$seconds_behind_master" = 'NULL' ] || [ "$seconds_behind_master" = '' ] ; then
	echo "Unknown Offset - perhaps slave is stopped or not configured"
	exit 1
fi

human_readable_time $seconds_behind_master seconds_behind_masterHR

echo $seconds_behind_masterHR
```

**脚本功能**：获取MySQL从服务器与主服务器的延迟时间，并将其转换为人类可读的格式。

**主要函数**：
- `human_readable_time`：将秒数转换为人类可读的时间格式（天、小时、分钟、秒）
- `slave_status`：获取MySQL从服务器的状态变量值

**执行流程**：
1. 调用`slave_status`函数获取Seconds_Behind_Master值
2. 检查获取的值是否为NULL或空：
   - 如果是，则输出错误信息并退出脚本
3. 调用`human_readable_time`函数将秒数转换为人类可读的时间格式
4. 输出转换后的延迟时间

###### 1.1.3.6 tuning-pCHANGE_ME

```bash
#!/bin/sh

# vim: ts=8
#########################################################################
#									#
#	MySQL performance tuning primer script				#
#	Writen by: Matthew Montgomery					#
#	Report bugs to: https://bugs.launchpad.net/mysql-tuning-pCHANGE_ME	#
#	Inspired by: MySQLARd (http://gert.sos.be/demo/mysqlar/)	#
#	Version: 1.6-r1		Released: 2011-08-06			#
#	Licenced under GPLv2                                            #
#									#
#########################################################################

# 脚本内容较长，仅显示部分内容
```

**脚本功能**：MySQL性能调优脚本，用于检查MySQL配置并提供调优建议。

**主要特点**：
- 自动检查MySQL配置和性能指标
- 提供针对内存、磁盘I/O、InnoDB等方面的调优建议
- 支持多种运行模式
- 清晰的彩色输出结果

**使用方法**：
```
./tuning-pCHANGE_ME [ mode ]
```

**可用模式**：
- `all`：执行所有检查（默认）
- `prompt`：提示输入登录凭证、套接字和执行模式
- `mem` 或 `memory`：运行影响内存使用的可调选项检查
- `disk` 或 `file`：运行影响I/O性能或文件句柄限制的选项检查
- `innodb`：运行InnoDB检查
- `misc`：运行其他检查，包括慢查询、二进制日志、已用连接和工作线程

**主要检查内容**：
- MySQL版本兼容性
- 内存配置（key_buffer_size, sort_buffer_size, read_buffer_size等）
- 磁盘I/O配置（innodb_buffer_pool_size, innodb_log_file_size等）
- 连接设置（max_connections, wait_timeout等）
- 慢查询设置
- 二进制日志设置
- InnoDB配置

**执行流程**：
1. 检查MySQL版本和连接
2. 根据指定模式执行相应的检查
3. 收集MySQL性能指标
4. 分析指标并提供调优建议
5. 输出彩色的检查结果和建议

##### 1.1.4 oracle子目录

###### 1.1.4.1 oracle.sh

```bash
#!/bin/bash
yum install -y binutils compat-libstdc++-33 elfutils-libelf elfutils-libelf-devel gcc gcc-c++ glibc glibc-common glibc-devel libaio libaio-devel libgcc libstdc++ libstdc++-devel make numactl sysstat libXp unixODBC unixODBC-devel
groupadd oinstall;
groupadd dba;
groupadd oper;
useradd -g oinstall -G dba,oper oracle; 
echo "oracle"|passwd oracle --stdin
cat >>/etc/sysctl.conf<<EOF
fs.file-max = 6815744
fs.aio_max_nr=1048576
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576
EOF
sysctl -p
cat >>/etc/security/limits.conf<<EOF
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536
oracle soft stack 10240
EOF
cat >>/etc/pam.d/login<<EOF
session required pam_limits.so
EOF
cat >>/etc/profile<<EOF
if [ $USER = "oracle" ]; then
        if [ $SHELL = "/bin/ksh" ]; then
              ulimit -p 16384
              ulimit -n 65536
        else
              ulimit -u 16384 -n 65536
        fi
fi
EOF
setenforce 0
mkdir /opt/oracle;
chown oracle:oinstall /opt/oracle;
chmod 755 /opt/oracle;
mkdir /opt/oraInventory;
chown oracle:oinstall /opt/oraInventory;
chmod 755 /opt/oraInventory;
```

**脚本功能**：Oracle数据库安装前的系统环境准备脚本。

**主要功能**：
1. 安装Oracle所需的依赖包
2. 创建Oracle用户和相关组
3. 配置内核参数
4. 配置用户资源限制
5. 配置PAM认证
6. 配置Oracle用户的环境变量
7. 关闭SELinux（临时）
8. 创建Oracle安装目录和 inventory目录

**执行流程**：
1. 使用yum安装Oracle所需的依赖包
2. 创建oinstall、dba、oper三个组
3. 创建oracle用户并设置密码
4. 向/etc/sysctl.conf文件添加Oracle所需的内核参数
5. 应用内核参数
6. 向/etc/security/limits.conf文件添加oracle用户的资源限制
7. 向/etc/pam.d/login文件添加session required pam_limits.so配置
8. 向/etc/profile文件添加oracle用户的环境变量配置
9. 临时关闭SELinux
10. 创建Oracle安装目录和inventory目录，并设置权限

###### 1.1.4.2 oracle_backup_array.sh

```bash
#!/bin/bash
#mail it-arch
#This is a backup script for Oracle.
#数组方式备份
# File save time is 7 days.

bapath="/home/oracle/DBfile/"
if [ ! -d $bapath ];then
  mkdir -p $bapath
fi
filename=`date +%Y-%m-%d`'.bmp'
logname=`date +%Y-%m-%d`'.log'
User=(system test1 test2)
Pwd=CHANGE_ME 123.com 123.com)

for I in `seq 0 2`
do 
	exp `echo ${User[${I}]}`/`echo ${Pwd[${I}]}`@orcl file=${bapath}`echo ${User[${I}]}`-${filename} log=${bapath}`echo ${User[${I}]}`-${logname}
	cd $bapath
	tar zcf `echo ${User[${I}]}`-$filename.tar.gz `echo ${User[${I}]}`-$filename
	tar zcf `echo ${User[${I}]}`-$logname.tar.gz `echo ${User[${I}]}`-$logname
	find $bapath -mtime +7 -name "*.bmp.tar.gz" -exec rm -rf {} \;
	find $bapath -mtime +7 -name "*.log.tar.gz" -exec rm -rf {} \;
done
rm -rf ${bapath}*.bmp
rm -rf ${bapath}*.log
```

**脚本功能**：使用数组方式备份Oracle数据库，支持多个用户备份，并自动删除7天前的旧备份。

**主要参数**：
- `bapath`：备份文件存储路径
- `filename`：备份文件名（包含日期，使用.bmp扩展名）
- `logname`：备份日志文件名（包含日期）
- `User`：Oracle用户名数组
- `Pwd`：Oracle用户密码数组（与用户名数组对应）

**执行流程**：
1. 检查备份目录是否存在，不存在则创建
2. 生成备份文件名和日志文件名（包含当前日期）
3. 定义用户名和密码数组
4. 使用for循环遍历数组，为每个用户执行备份：
   - 使用exp命令备份用户数据到指定文件
   - 压缩备份文件为tar.gz格式
   - 压缩日志文件为tar.gz格式
   - 删除7天前的旧备份文件
   - 删除7天前的旧日志文件
5. 删除临时生成的.bmp和.log文件

###### 1.1.4.3 oracle_backup_for.sh

```bash
#!/bin/bash
#This is a backup script for Oracle.
#for 
# File save time is 7 days.
#system test1 test2 is oracle user
#pwd is oracle passwd
bapath="/home/oracle/DBfile/"
if [ ! -d $bapath ];then
  mkdir -p $bapath
fi
filename=`date +%Y-%m-%d`'.bmp'
logname=`date +%Y-%m-%d`'.log'

for user in system test1 test2
do 
	pwd="CHANGE_ME"
	exp ${user}/${pwd}@orcl file=${bapath}${user}-${filename} log=${bapath}${user}-$logname
	cd $bapath
	tar zcf ${user}-$filename.tar.gz ${user}-$filename
	tar zcf ${user}-$logname.tar.gz ${user}-$logname
	find $bapath -mtime +7 -name "*.bmp.tar.gz" -exec rm -rf {} \;
	find $bapath -mtime +7 -name "*.log.tar.gz" -exec rm -rf {} \;
done
rm -rf ${bapath}*.bmp
rm -rf ${bapath}*.log
```

**脚本功能**：使用for循环方式备份Oracle数据库，支持多个用户备份，并自动删除7天前的旧备份。

**主要参数**：
- `bapath`：备份文件存储路径
- `filename`：备份文件名（包含日期，使用.bmp扩展名）
- `logname`：备份日志文件名（包含日期）
- `user`：循环遍历的Oracle用户名
- `pwd`：Oracle用户密码（所有用户使用相同密码）

**执行流程**：
1. 检查备份目录是否存在，不存在则创建
2. 生成备份文件名和日志文件名（包含当前日期）
3. 使用for循环遍历用户名列表，为每个用户执行备份：
   - 设置用户密码（所有用户使用相同密码）
   - 使用exp命令备份用户数据到指定文件
   - 压缩备份文件为tar.gz格式
   - 压缩日志文件为tar.gz格式
   - 删除7天前的旧备份文件
   - 删除7天前的旧日志文件
4. 删除临时生成的.bmp和.log文件

###### 1.1.4.4 oracle_exp_test.sh

```bash
#!/bin/bash
#This is a backup script for Oracle.
#数组方式备份
# File save time is 7 days.
bapath="/home/oracle/DBfile/"
if [ ! -d $bapath ];then
  mkdir -p $bapath
fi
filename=`date +%Y-%m-%d`'.bmp'
logname=`date +%Y-%m-%d`'.log'
User=(GPSUSER system)
Pwd=CHANGE_ME fin_1qaz)

exp `echo ${User[${I}]}`/`echo ${Pwd[${I}]}`@fintest file=${bapath}`echo ${User[${I}]}`-${filename} log=${bapath}`echo ${User[${I}]}`-${logname}
cd $bapath
tar zcf `echo ${User[${I}]}`-$filename.tar.gz `echo ${User[${I}]}`-$filename
tar zcf `echo ${User[${I}]}`-$logname.tar.gz `echo ${User[${I}]}`-$logname
find $bapath -mtime +7 -name "*.bmp.tar.gz" -exec rm -rf {} \;
find $bapath -mtime +7 -name "*.log.tar.gz" -exec rm -rf {} \;
rm -rf ${bapath}*.bmp
rm -rf ${bapath}*.log
```

**脚本功能**：尝试使用数组方式备份Oracle数据库，但存在逻辑问题。

**主要参数**：
- `bapath`：备份文件存储路径
- `filename`：备份文件名（包含日期，使用.bmp扩展名）
- `logname`：备份日志文件名（包含日期）
- `User`：Oracle用户名数组
- `Pwd`：Oracle用户密码数组（与用户名数组对应）

**执行流程**：
1. 检查备份目录是否存在，不存在则创建
2. 生成备份文件名和日志文件名（包含当前日期）
3. 定义用户名和密码数组
4. 尝试使用exp命令备份用户数据：
   - 直接使用变量I访问数组元素，但变量I未定义或赋值
   - 压缩备份文件为tar.gz格式
   - 压缩日志文件为tar.gz格式
   - 删除7天前的旧备份文件
   - 删除7天前的旧日志文件
5. 删除临时生成的.bmp和.log文件

**注意事项**：
- 脚本存在逻辑问题：直接使用了变量I访问数组元素，但变量I未定义或赋值，也没有循环遍历数组
- 这会导致脚本执行时出现错误，因为${User[${I}]}和${Pwd[${I}]}会尝试访问数组的空索引元素
- 正确的做法应该是添加一个for循环来遍历数组，类似于oracle_backup_array.sh脚本

###### 1.1.4.5 oracle_exp_zs.sh

```bash
#!/bin/bash
#This is a backup script for Oracle.
#数组方式备份
# File save time is 7 days.
PWD="CHANGE_ME"
bapath="/home/oracle/DBfile/"
if [ ! -d $bapath ];then
  mkdir -p $bapath
fi
filename=`date +%Y-%m-%d`'.bmp'
logname=`date +%Y-%m-%d`'.log'
User=(GPSUSER FNL_PROB ESBUSER)
Pwd=CHANGE_ME pls_fnl_1q pls_esb_1q)

for I in `seq 0 2`
do 
	exp `echo ${User[${I}]}`/`echo ${Pwd[${I}]}`@it-arch file=${bapath}`echo ${User[${I}]}`-${filename} log=${bapath}`echo ${User[${I}]}`-${logname}
	cd $bapath
	tar zcf `echo ${User[${I}]}`-$filename.tar.gz `echo ${User[${I}]}`-$filename
	tar zcf `echo ${User[${I}]}`-$logname.tar.gz `echo ${User[${I}]}`-$logname
	find $bapath -mtime +7 -name "*.bmp.tar.gz" -exec rm -rf {} \;
	find $bapath -mtime +7 -name "*.log.tar.gz" -exec rm -rf {} \;
done
rm -rf ${bapath}*.bmp
rm -rf ${bapath}*.log
```

**脚本功能**：使用数组方式备份Oracle数据库（it-arch实例），支持多个用户备份，并自动删除7天前的旧备份。

**主要参数**：
- `PWD`：密码变量（未在脚本中使用）
- `bapath`：备份文件存储路径
- `filename`：备份文件名（包含日期，使用.bmp扩展名）
- `logname`：备份日志文件名（包含日期）
- `User`：Oracle用户名数组
- `Pwd`：Oracle用户密码数组（与用户名数组对应）

**执行流程**：
1. 定义密码变量（未在脚本中使用）
2. 检查备份目录是否存在，不存在则创建
3. 生成备份文件名和日志文件名（包含当前日期）
4. 定义用户名和密码数组
5. 使用for循环遍历数组，为每个用户执行备份：
   - 使用exp命令备份用户数据到指定文件（连接到it-arch实例）
   - 压缩备份文件为tar.gz格式
   - 压缩日志文件为tar.gz格式
   - 删除7天前的旧备份文件
   - 删除7天前的旧日志文件
6. 删除临时生成的.bmp和.log文件

###### 1.1.4.6 oracle_expdp_bak.sh

```bash
#!/bin/bash
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/db_1
export ORACLE_SID=it-arch
export PATH=$ORACLE_HOME/bin:$PATH
filename=`date +%Y-%m-%d`'.bmp'
logname=`date +%Y-%m-%d`'.log'
dump_dir="/backup/backup_dir/"
backdir="dump_dir"
for Schame in GPSUSER
do
/u01/app/oracle/product/11.2.0/db_1/bin/expdp backupuser/back_up123 SCHEMAS=${Schame} dumpfile=${Schame}-${filename} directory=${backdir} log=${Schame}-${logname}
cd ${dump_dir}
tar zcf ${Schame}-$filename.tar.gz ${Schame}-$filename
tar zcf ${Schame}-$logname.tar.gz ${Schame}-$logname
find ${dump_dir} -mtime +7 -name "*.bmp.tar.gz" -exec rm -rf {} \;
find ${dump_dir} -mtime +7 -name "*.log.tar.gz" -exec rm -rf {} \;
done
find ${dump_dir} -name "*.bmp" -exec rm -rf {} \;
find ${dump_dir} -name "*.log" -exec rm -rf {} \;
```

**脚本功能**：使用expdp命令备份Oracle数据库（it-arch实例）的指定Schema，并自动删除7天前的旧备份。

**主要参数**：
- `ORACLE_BASE`：Oracle基础目录
- `ORACLE_HOME`：Oracle安装目录
- `ORACLE_SID`：Oracle实例名（it-arch）
- `PATH`：环境变量，添加Oracle bin目录
- `filename`：备份文件名（包含日期，使用.bmp扩展名）
- `logname`：备份日志文件名（包含日期）
- `dump_dir`：备份文件存储路径
- `backdir`：Oracle目录对象名
- `Schame`：要备份的Schema名（当前只备份GPSUSER）

**执行流程**：
1. 设置Oracle环境变量
2. 生成备份文件名和日志文件名（包含当前日期）
3. 定义备份目录和目录对象
4. 使用for循环遍历Schema列表，为每个Schema执行备份：
   - 使用expdp命令备份Schema数据到指定文件
   - 压缩备份文件为tar.gz格式
   - 压缩日志文件为tar.gz格式
   - 删除7天前的旧备份文件
   - 删除7天前的旧日志文件
5. 删除临时生成的.bmp和.log文件

**注意事项**：
- 脚本使用了expdp命令，这是Oracle 11g及以上版本推荐的备份工具
- 需要在Oracle中创建目录对象`dump_dir`，指向`/backup/backup_dir/`目录
- 需要确保backupuser用户具有足够的权限执行expdp备份操作

###### 1.1.4.7 oraclescp.sh

```bash
#!/bin/bash

fdate=`date +%Y-%m-%d`

scp /home/oracle/*-$fdate.dmp.tar.gz root@xx.xx..6.150:/user/oracle_back
```

**脚本功能**：使用SCP命令将当天的Oracle备份文件从本地传输到远程服务器。

**主要参数**：
- `fdate`：当前日期（格式：YYYY-MM-DD）

**执行流程**：
1. 获取当前日期
2. 使用scp命令将本地 `/home/oracle/` 目录下所有当天的 `.dmp.tar.gz` 备份文件传输到远程服务器 `root@xx.xx..6.150` 的 `/user/oracle_back` 目录

**注意事项**：
- 远程服务器地址 `xx.xx..6.150` 存在拼写错误（多了一个点），正确格式应为 `xx.xx.6.150`
- 脚本假设本地有当天生成的 `.dmp.tar.gz` 格式的备份文件
- 需要确保本地用户对 `/home/oracle/` 目录有读取权限
- 需要确保远程服务器允许root用户通过SCP登录，并且对 `/user/oracle_back` 目录有写入权限
- 建议使用SSH密钥认证，避免每次传输都需要输入密码

##### 1.1.5 postgresql-check子目录

###### 1.1.5.1 check_postsql.sh

```bash
#!/bin/bash
data=`date +%Y-%M-%d" "%H:%m`
netstat -lntup|grep 5432 && ps -ef|grep postmaster
if [ $? -eq 0 ];then
	for IP in xx.xx.xx.xx xx.xx.10.189
	do
	/usr/bin/psql -h xx.xx.10.190 -p 5432 -U repl -d postgres --command "select * from pg_stat_replication"|grep $IP
	if [ "$?" != "0" ];then
		echo "postgresql master-slave status is error! please login check!"|mail -r "it-arch" -s "postgresql master-slave status is error" it-arch \
		&& echo "$data postgresql postgresql master-slave status is error!">>/var/log/postgresql-error.log
	fi
	done
else
	echo "postgresql master-slave status is error! please login check!"|mail -r "it-arch" -s "postgresql master-slave status is error" it-arch \
	&& echo "$data postgresql postgresql master-slave status is error!">>/var/log/postgresql-error.log
fi
```

**脚本功能**：检查PostgreSQL主从复制状态，并在状态异常时发送邮件警报。

**主要参数**：
- `data`：当前日期时间（格式存在错误）
- `IP`：从服务器IP地址列表

**执行流程**：
1. 获取当前日期时间
2. 检查PostgreSQL服务是否在监听5432端口且postmaster进程在运行
3. 如果PostgreSQL服务运行正常，则检查每个从服务器的复制状态：
   - 使用psql命令连接到主服务器，查询pg_stat_replication视图
   - 检查是否有对应的从服务器记录
   - 如果没有找到记录，则发送邮件警报并记录日志
4. 如果PostgreSQL服务未运行，则发送邮件警报并记录日志

**注意事项**：
- 日期格式存在错误：`date +%Y-%M-%d" "%H:%m` 中，`%M` 表示分钟，`%m` 表示月份，正确的格式应该是 `date +%Y-%m-%d" "%H:%M`
- 脚本中多次重复了"postgresql"一词，例如日志消息中"postgresql postgresql master-slave status is error!"
- 需要确保主服务器允许repl用户通过psql连接并查询pg_stat_replication视图
- 需要确保系统已安装mail命令，以便发送警报邮件

### 1.2 其他备份脚本

#### 1.2.1 AutoBackupMysql.sh

```bash
#!/bin/bash

#author:it-arch
#mail:it-arch
#data:2022/6/11

DIR=/data/mysqldump/`date +%Y-%m-%d`
MYSQLDB=cacti
MYSQLUSR=root
MYSQLPW=mysqladmin
MYSQLCMD=/usr/bin/mysqldump
if [ $UID -ne 0 ];then
	echo "Must to be use root for exec shell."
	exit
fi

if [ ! -d $DIR ];then
	mkdir -p $DIR
	echo "\033[32mThe $DIR create successfully!"
else
	echo "This $DIR is exists..."
fi

#mysqldump
$MYSQLCMD -u$MYSQLUSR -pCHANGE_ME -d $MYSQLDB >$DIR/$MYSQLDB.sql
if [ $? -eq 0 ];then
	echo -e "\033[32mThe mysql backup $MYSQLDB successfully!\033[0m"
else
	echo -e "\033[32The mysql backup $MYSQLDB failed.Please check!\033[0m"
fi
```

**脚本功能**：备份MySQL数据库（cacti）的结构，并将备份文件存储到按日期命名的目录中。

**主要参数**：
- `DIR`：备份目录路径（格式：/data/mysqldump/YYYY-MM-DD）
- `MYSQLDB`：要备份的数据库名（cacti）
- `MYSQLUSR`：MySQL用户名（root）
- `MYSQLPW`：MySQL密码（mysqladmin）
- `MYSQLCMD`：mysqldump命令路径

**执行流程**：
1. 检查当前用户是否为root，否则退出脚本
2. 检查备份目录是否存在，不存在则创建
3. 使用mysqldump命令备份cacti数据库的结构（-d参数表示只备份结构，不备份数据）
4. 检查备份是否成功，并输出相应的彩色提示信息

**注意事项**：
- 脚本使用了root用户执行备份，这是一种安全风险，建议使用具有最小必要权限的MySQL用户
- 脚本只备份数据库结构，不备份数据（使用了-d参数）
- 脚本没有自动清理旧备份的功能，需要手动管理备份文件

#### 1.2.2 Autoback-xtraback.sh

```bash
#!/bin/bash
hostname=`/bin/hostname`
week=`date +%w`
datadir=/backup
logdir=/backup/log
mycnf=/etc/my.cnf
Time=`date +%Y-%m-%d_%H-%M-%S`
cmd=`which innobackupex`
user=root
passwd=CHANGE_ME


function getdir()
{
	if [ ! -d ${datadir} ];then
		mkdir -p ${datadir}
	fi
}
function backup()
{
	if [ ${week} == "0" ];then
		$cmd --defaults-file=${mycnf} --user=${user} --pCHANGE_ME ${datadir}&>${logdir}/${Time}-log
		[ $? -eq 0 ] && stat=`tail -1 ${logdir}/${Time}-log |awk '{print $4}'`
		if [ "${stat}" == "OK!" ];then
			echo "${Time} mysql backup is success!"
		else
			echo "${Time} mysql backup is fail! please check ${logdir}/${Time}-log"
		fi
	else
		$cmd --defaults-file=${mycnf} --user=${user} --pCHANGE_ME --incremental --incremental-basedir=${datadir}&>${logdir}/${Time}-log
			
	fi
}
```

**脚本功能**：使用xtrabackup工具进行MySQL备份，每周日执行全量备份，其他时间执行增量备份。

**主要参数**：
- `hostname`：主机名
- `week`：星期几（0-6，0表示周日）
- `datadir`：备份目录路径（/backup）
- `logdir`：备份日志目录路径（/backup/log）
- `mycnf`：MySQL配置文件路径
- `Time`：当前时间（格式：YYYY-MM-DD_HH-MM-SS）
- `cmd`：innobackupex命令路径
- `user`：MySQL用户名（root）
- `passwd`：MySQL密码（mysqladmin）

**主要函数**：
- `getdir`：检查备份目录是否存在，不存在则创建
- `backup`：执行备份操作

**执行流程**：
1. 定义相关变量和函数
2. `getdir`函数检查备份目录是否存在，不存在则创建
3. `backup`函数执行备份：
   - 如果是周日（week == "0"），则执行全量备份
   - 否则，执行增量备份
   - 全量备份会检查备份结果并输出相应的提示信息
   - 增量备份没有检查备份结果

**注意事项**：
- 脚本存在语法错误：函数`backup()`没有完整闭合（缺少fi和}）
- 增量备份部分没有检查备份结果
- 没有检查logdir目录是否存在，可能导致备份失败
- 没有自动清理旧备份的功能，可能导致磁盘空间不足
- 脚本没有调用定义的函数，所以实际上不会执行任何备份操作

#### 1.2.3 backup_mongo.sh

```bash
#!/bin/bash
#auth:it-arch
#backup mongodb

. /etc/profile
CMD=`which mongodump`
DATE=`date +%F`
DB="test"
DB_HOST="localhost"
DB_PORT="27017"
DB_USER="testuser"
DB_PWD="CHANGE_ME"
BACKUP_DIR="/data/mongodb/"
TAR_DIR="/data/tardir/"
TAR_DIR_DATE="${TAR_DIR}${DATE}"
TAR_BAK="mongodb_bak_$DATE.tar.gz"

check_dir(){
	for DIR in ${BACKUP_DIR} ${TAR_DIR_DATE}
	do
		if [ ! -d $DIR ];then
			mkdir -p $DIR
		fi
	done
}
backup_mongodb(){
	$CMD -h ${DB_HOST}:${DB_PORT} -u $DB_USER -p $DB_PWD -d ${DB} -o ${BACKUP_DIR}${DATE} >/dev/null
	if [ $? -eq 0 ];then
		tar -zcf ${TAR_DIR_DATE}/${TAR_BAK} ${BACKUP_DIR}${DATE} && return 0
	fi
}
clean_tar() {
	find ${TAR_DIR} -mtime +7 -exec rm -rf {} \; && return 0
}

main() {
	check_dir
	[ $? -eq 0 ] && backup_mongodb
	[ $? -eq 0 ] && clean_tar
}

main
```

**脚本功能**：备份MongoDB数据库，并将备份文件压缩存储，同时自动清理7天前的旧备份。

**主要参数**：
- `CMD`：mongodump命令路径
- `DATE`：当前日期（格式：YYYY-MM-DD）
- `DB`：要备份的数据库名（test）
- `DB_HOST`：MongoDB主机地址（localhost）
- `DB_PORT`：MongoDB端口号（27017）
- `DB_USER`：MongoDB用户名（testuser）
- `DB_PWD`：MongoDB密码（testpass）
- `BACKUP_DIR`：备份目录路径（/data/mongodb/）
- `TAR_DIR`：压缩备份存储目录路径（/data/tardir/）
- `TAR_DIR_DATE`：按日期命名的压缩备份目录路径（/data/tardir/YYYY-MM-DD）
- `TAR_BAK`：压缩备份文件名（mongodb_bak_YYYY-MM-DD.tar.gz）

**主要函数**：
- `check_dir`：检查并创建所需的目录
- `backup_mongodb`：使用mongodump命令备份MongoDB数据库，并压缩备份文件
- `clean_tar`：清理7天前的旧备份文件
- `main`：主函数，按顺序调用其他函数

**执行流程**：
1. 加载/etc/profile配置文件
2. 定义相关变量
3. 定义函数
4. 调用main函数执行备份操作：
   - 调用check_dir函数检查并创建目录
   - 如果check_dir成功，调用backup_mongodb函数备份MongoDB
   - 如果backup_mongodb成功，调用clean_tar函数清理旧备份

**注意事项**：
- 脚本使用了mongodump命令进行备份，需要确保该命令已安装
- 脚本只备份了test数据库，如需备份多个数据库，需要修改脚本
- 脚本将备份文件压缩存储，有助于节省磁盘空间
- 脚本自动清理7天前的旧备份，有助于自动管理备份文件

#### 1.2.4 backup_mysql.sh

```bash
#!/bin/bash

#author:it-arch
#mail:it-arch
#data:2016/6/11

DIR=/data/mysqldump/`date +%Y-%m-%d`
MYSQLDB=cacti
MYSQLUSR=root
MYSQLPW=mysqladmin
MYSQLCMD=/usr/bin/mysqldump
if [ $UID -ne 0 ];then
	echo "Must to be use root for exec shell."
	exit
fi

if [ ! -d $DIR ];then
	mkdir -p $DIR
	echo "\033[32mThe $DIR create successfully!"
else
	echo "This $DIR is exists..."
fi

#mysqldump
$MYSQLCMD -u$MYSQLUSR -pCHANGE_ME -d $MYSQLDB >$DIR/$MYSQLDB.sql
if [ $? -eq 0 ];then
	echo -e "\033[32mThe mysql backup $MYSQLDB successfully!\033[0m"
else
	echo -e "\033[32The mysql backup $MYSQLDB failed.Please check!\033[0m"
fi
```

**脚本功能**：备份MySQL数据库（cacti）的结构，并将备份文件存储到按日期命名的目录中。

**注意事项**：
- 此脚本与之前的`AutoBackupMysql.sh`脚本内容完全相同，只是文件名和创建日期不同
- 详细解释请参考`AutoBackupMysql.sh`脚本的说明

#### 1.2.5 clean_oracle.sh

```bash
#!/bin/bash
oracle_env() {
    source /home/oracle/.bash_profile  
    export ORACLE_BASE=/home/oracle/app
    export ORACLE_HOME=$ORACLE_BASE/oracle/product/12.1.0/dbhome_1
    export ORACLE_SID=orcl
    export PATH=$PATH:$HOME/bin:$ORACLE_HOME/bin
    oraclecmd="/home/oracle/app/oracle/product/12.1.0/dbhome_1/bin/sqlplus"
    oraclerman="/home/oracle/app/oracle/product/12.1.0/dbhome_1/bin/rman"
}
disk_useper=`/bin/df -Th|grep -v 'Filesystem'|awk '/\/dev\/mapper\/vg00-lv_root/{if ("$(NF)"=="/");print $(NF-1)}'|cut -d% -f1`
 
oracle_clean() {
oracle_env    
${oraclerman} target /<<EOF
DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';
crosscheck archivelog all;
list expired archivelog all;
delete noprompt expired archivelog all;
exit;
EOF
}
 
main() {
    if [ ${disk_useper} -gt 80 ];then
        oracle_clean
    fi
} 
 
main
```

**脚本功能**：根据磁盘使用率自动清理Oracle归档日志，当磁盘使用率超过80%时，清理7天前的归档日志。

**主要函数**：
- `oracle_env`：设置Oracle环境变量
- `oracle_clean`：使用RMAN工具清理归档日志
- `main`：主函数，检查磁盘使用率并决定是否执行清理操作

**主要参数**：
- `disk_useper`：根分区磁盘使用率（%）
- `ORACLE_BASE`：Oracle基础目录
- `ORACLE_HOME`：Oracle安装目录
- `ORACLE_SID`：Oracle实例名（orcl）
- `oraclecmd`：sqlplus命令路径
- `oraclerman`：rman命令路径

**执行流程**：
1. 获取根分区磁盘使用率
2. 定义函数
3. 调用main函数执行清理操作：
   - 检查磁盘使用率是否超过80%
   - 如果超过80%，调用oracle_clean函数清理归档日志：
     - 设置Oracle环境变量
     - 使用RMAN工具连接到Oracle实例
     - 删除7天前的归档日志
     - 交叉检查所有归档日志
     - 列出过期的归档日志
     - 删除过期的归档日志
     - 退出RMAN

**注意事项**：
- 脚本只在磁盘使用率超过80%时才执行清理操作
- 脚本清理的是7天前的归档日志
- 脚本需要以具有足够权限的用户执行，能够访问RMAN工具和Oracle实例
- 脚本中的磁盘检查命令存在语法问题，`awk '/\/dev\/mapper\/vg00-lv_root/{if ("$(NF)"=="/");print $(NF-1)}'` 中的条件判断可能无法正确执行

### 2. 安全类脚本

#### 2.1 ip_black_list.sh

```bash
#!/bin/bash

cat /var/log/secure|awk '/Failed/{print $(NF-3)}'|sort|uniq -c|awk '{print $2"="$1;}' > /root/black/black.txt

DEFINE="5"

for i in `cat /root/black/black.txt`
do

IP=`echo $i |awk -F= '{print $1}'`
NUM=`echo $i|awk -F= '{print $2}'`

if [ $NUM -gt $DEFINE ]; then
grep $IP /etc/hosts.deny > /dev/null

if [ $? -gt 0 ]; then
echo "sshd:$IP" >> /etc/hosts.deny
fi
fi
done
```

**脚本功能**：从安全日志中提取失败的SSH登录尝试IP，并将失败次数超过设定阈值的IP添加到/etc/hosts.deny文件中，以阻止该IP的进一步访问。

**主要参数**：
- `DEFINE`：失败登录尝试阈值，默认5次
- `/root/black/black.txt`：临时存储IP和失败次数的文件
- `/var/log/secure`：安全日志文件
- `/etc/hosts.deny`：用于阻止特定IP访问的文件

**执行流程**：
1. 从/var/log/secure日志中提取所有失败登录尝试的IP
2. 统计每个IP的失败登录次数
3. 将IP和对应的失败次数写入临时文件/root/black/black.txt
4. 遍历临时文件中的每个IP和失败次数
5. 检查失败次数是否超过阈值（5次）
6. 如果超过阈值，检查该IP是否已经在/etc/hosts.deny文件中
7. 如果不在，则将该IP添加到/etc/hosts.deny文件中，阻止其通过SSH访问

**注意事项**：
- 脚本需要以root用户执行，因为需要访问/var/log/secure和/etc/hosts.deny文件
- 脚本假设/root/black目录已经存在，否则会失败
- 脚本只针对SSH登录失败进行处理
- 脚本没有设置自动清理机制，一旦IP被添加到/etc/hosts.deny，就会一直被阻止，除非手动删除
- 脚本可能会误将合法IP添加到黑名单，例如当用户多次输入错误密码时

#### 2.2 ip_iptables_block.sh

```bash
#!/bin/bash
#mail it-arch
#data 2022/2/23

#function: use iptables Brute force
SCAN=`/bin/egrep "Failed password for root" /var/log/secure|awk -F'[ :]+' '{print $13}'|sort|uniq -c|awk '{print $1"="$2;}'`
for I in ${SCAN}
do 
	SCANUM=`echo ${I}|awk -F'=' '{print $1}'`
	SCANIP=`echo ${I}|awk -F'=' '{print $2}'`
	if [ ${SCANUM} -gt 100 ] && [ -z "`/sbin/iptables -vnL INPUT | grep $SCANIP`" ];then
		/sbin/iptables -I INPUT -s $SCANIP -m state --state NEW,RELATED,ESTABLISHED -j DROP 
		echo "`date` $SCANIP($SCANUM)">>/var/log/scanIP.log
	fi
done
if [ $? -eq 0 ];then
service iptables save && service iptables restart
fi
```

**脚本功能**：使用iptables阻止对root用户的暴力破解尝试，当失败登录次数超过100次时，将该IP添加到iptables黑名单中。

**主要参数**：
- `/var/log/secure`：安全日志文件，用于提取失败登录尝试信息
- `SCAN`：存储IP和对应失败次数的变量
- `SCANUM`：单个IP的失败登录次数
- `SCANIP`：失败登录的IP地址
- `/var/log/scanIP.log`：记录被阻止IP的日志文件

**执行流程**：
1. 从/var/log/secure日志中提取所有针对root用户的失败登录尝试的IP
2. 统计每个IP的失败登录次数
3. 遍历每个IP和对应的失败次数
4. 检查失败次数是否超过100次，且该IP尚未被iptables阻止
5. 如果满足条件，则：
   - 添加iptables规则，阻止该IP的所有新连接和相关连接
   - 将阻止信息（日期、IP、失败次数）记录到/var/log/scanIP.log日志文件
6. 如果执行成功，则保存并重启iptables服务，使规则永久生效

**注意事项**：
- 脚本需要以root用户执行，因为需要访问/var/log/secure、操作iptables规则和重启服务
- 脚本只针对root用户的失败登录尝试进行处理
- 脚本将阻止IP的所有新连接和相关连接，这可能会影响合法用户的访问
- 脚本没有设置自动清理机制，一旦IP被添加到iptables黑名单，就会一直被阻止，除非手动删除
- 脚本使用service命令管理iptables服务，这在某些系统上可能已经过时，建议使用systemctl命令

#### 2.3 ip_scan.sh

```bash
#!/bin/bash
read -p "Please input need check ipaddress region:(example:xx.xx.1.)" IP
for i in `seq 254`
do
/bin/ping -c2 $IP$i >/dev/null0 2>&1
if [ $? -eq 0 ];then
        echo "$IP$i is up">>/tmp/uplist.log
else
        echo "$IP$i is down">>/tmp/downlist.log
fi
done
```

**脚本功能**：检查指定网段内的IP是否在线，并将结果分别写入不同的日志文件。

**主要参数**：
- `IP`：用户输入的IP地址段（例如：xx.xx.1.）
- `/tmp/uplist.log`：记录在线IP的日志文件
- `/tmp/downlist.log`：记录不在线IP的日志文件

**执行流程**：
1. 提示用户输入需要检查的IP地址段
2. 遍历该网段内的所有IP（1-254）
3. 使用ping命令检查每个IP是否在线（发送2个ICMP包）
4. 如果ping成功，则将该IP记录到/tmp/uplist.log文件中
5. 如果ping失败，则将该IP记录到/tmp/downlist.log文件中

**注意事项**：
- 脚本需要以具有网络访问权限的用户执行
- 脚本中存在一个错误：ping命令的输出重定向到了/dev/null0，正确的应该是/dev/null
- 脚本使用ping命令检查IP是否在线，可能会被防火墙阻止
- 脚本没有设置超时时间，ping命令可能会等待较长时间
- 脚本将结果写入/tmp目录，该目录下的文件可能会被系统定期清理

### 3. 安装配置类脚本

#### 3.1 keepalived目录

##### 3.1.1 AutoInstallKeepalived.sh

```bash
#!/bin/bash
#Date 2022/1/10
#mail it-arch
[ $(id -u) != "0" ] && echo "Error: You must be root to run this script" && exit 1
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
clear
echo "##########################################"
echo "#					       #"
echo "#   Auto compile install keepalived      #"
echo "#					       #"
echo "##########################################"
echo "1 Install keepalived-1.3.5"
echo "2 Install keepalived-1.3.0"
echo "3 Install keepalived-1.2.24"
echo "4 EXIT"
read -p "Please input your choice:" I
if [ "$I" == "1" ];then
        URL="http://www.keepalived.org/software/keepalived-1.3.5.tar.gz"
	VER="keepalived-1.3.5"
elif [ "$I" == "2" ];then
        URL="http://www.keepalived.org/software/keepalived-1.3.0.tar.gz"
	VER="keepalived-1.3.0"
elif [ "$I" == "3" ];then
        URL="http://www.keepalived.org/software/keepalived-1.2.24.tar.gz"
	VER="keepalived-1.2.24"
elif [ "$I" == "4" ];then
        echo "you choce channel!"
        exit 1;
else
        echo "input Error! Place input{1|2|3|4}"
        exit 0;
fi
echo -e "\033[32m You choice install $VER.Install dirname:$DIR \033[0m"
echo -e "\033[32m Press any key to start install $VER... \033[0m"
read -n 1
if [ -d /tools ];then
	cd /tools
else
	mkdir /tools && cd /tools
fi
yum install -y gcc gcc-c++ popt-devel openssl openssl-devel libssl-dev libnl-devel popt-devel kernel kernel-devel libnfnetlink-devel
linux=`ls /usr/src/kernels`
ln -s /usr/src/kernels/${linux} /usr/src/linux
/usr/bin/wget -c $URL
tar zxf ${VER}.tar.gz
cd ${VER}
./configure
make && make install
cp /usr/local/sbin/keepalived /usr/sbin/
cp /usr/local/etc/sysconfig/keepalived /etc/sysconfig/
cp -r /usr/local/etc/keepalived/ /etc/
if [ "${VER}" == "keepalived-1.2.24" ];then
	cp /usr/local/etc/rc.d/init.d/keepalived /etc/init.d/ && chmod +x /etc/init.d/keepalived
else
	cp /tools/${VER}/keepalived/etc/init.d/keepalived /etc/init.d/
fi
echo -e "\033[32m $VER is install success! \033[0m"
```

**脚本功能**：自动编译安装keepalived，支持选择不同版本（1.3.5、1.3.0、1.2.24）。

**主要特点**：
- 自动检查用户权限，必须以root用户执行
- 支持选择不同版本的keepalived
- 自动安装依赖包
- 自动下载、编译和安装keepalived
- 自动复制相关文件到系统目录
- 清晰的彩色输出

**执行流程**：
1. 检查用户是否为root，否则退出脚本
2. 显示可安装的keepalived版本列表
3. 根据用户选择设置下载URL和版本号
4. 提示用户确认安装，按任意键继续
5. 检查/tools目录是否存在，不存在则创建
6. 使用yum安装keepalived所需的依赖包
7. 创建内核源码链接
8. 下载指定版本的keepalived
9. 解压下载的文件
10. 进入解压后的目录
11. 执行configure配置
12. 编译并安装keepalived
13. 复制keepalived相关文件到系统目录
14. 根据不同版本处理init脚本
15. 输出安装成功信息

**注意事项**：
- 脚本需要以root用户执行
- 脚本使用yum安装依赖包，需要网络连接
- 脚本默认将keepalived安装到/usr/local目录
- 脚本中变量$DIR未定义，在输出信息中会显示为空
- 脚本使用wget下载keepalived，需要确保wget已安装
- 不同版本的keepalived可能有不同的依赖和配置要求

##### 3.1.2 checkNginx.sh

```bash
#!/bin/bash
if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then 
	/etc/init.d/keepalived stop 
fi 
```

**脚本功能**：监控Nginx进程是否运行，如果Nginx进程不存在，则停止keepalived服务，用于keepalived的健康检查和故障转移。

**主要功能**：
- 检查Nginx进程是否存在
- 如果Nginx进程不存在，则停止keepalived服务

**执行流程**：
1. 使用ps命令检查Nginx进程数量
2. 如果Nginx进程数量为0，则执行/etc/init.d/keepalived stop命令停止keepalived服务

**应用场景**：
- 通常用于keepalived的健康检查脚本，在keepalived配置文件中通过vrrp_script指令调用
- 当Nginx服务出现故障停止运行时，keepalived也会停止，从而触发故障转移，将VIP切换到其他节点
- 确保只有当Nginx服务正常运行时，keepalived才会保持活跃状态

**注意事项**：
- 脚本需要以具有足够权限的用户执行，能够检查进程和停止服务
- 脚本假设keepalived的init脚本位于/etc/init.d/keepalived
- 脚本只检查Nginx进程是否存在，不检查Nginx是否能够正常响应请求
- 脚本是一个简单的监控脚本，没有重试机制或超时设置

### 4. 监控类脚本

#### 4.1 AutoCheck_mysql.sh

```bash
#!/bin/bash
pgrep mysqld &> /dev/null
if [ $? -gt 0 ]
then
echo "`date` mysql is stop" >> /var/log/mysql_listen.log
service mysql start
else
echo "`date` mysql running" >> /var/log/mysql_listen.log
fi
```

**脚本功能**：监控MySQL服务是否运行，如果MySQL服务停止，则自动启动它，并记录相关日志。

**主要功能**：
- 检查mysqld进程是否存在
- 如果mysqld进程不存在，则启动mysql服务
- 记录监控结果到日志文件

**主要参数**：
- `/var/log/mysql_listen.log`：监控日志文件路径

**执行流程**：
1. 使用pgrep命令检查mysqld进程是否存在
2. 如果pgrep命令返回值大于0（表示没有找到mysqld进程），则：
   - 将当前日期和"mysql is stop"记录到/var/log/mysql_listen.log文件
   - 执行service mysql start命令启动mysql服务
3. 如果pgrep命令返回值等于0（表示找到mysqld进程），则：
   - 将当前日期和"mysql running"记录到/var/log/mysql_listen.log文件

**应用场景**：
- 通常用于定时任务，通过cron定期执行，例如每1分钟执行一次
- 确保MySQL服务在意外停止后能够自动恢复运行
- 适用于MySQL单实例部署场景

**注意事项**：
- 脚本需要以具有足够权限的用户执行，能够检查进程和启动服务
- 脚本假设mysql的service命令可用，且服务名为mysql
- 脚本只检查mysqld进程是否存在，不检查MySQL服务是否能够正常响应请求
- 脚本没有重试机制，如果启动失败不会再次尝试
- 建议将脚本添加到cron作业中定期执行

#### 4.2 AutoInstallCacti.sh

```bash
#!/bin/bash
#date 2022/8/8
#mail it-arch
#############
echo "##########################################"
echo "Auto Install Cacti                      ##"
echo "Press Ctrl + C to cancel                ##"
echo "Any key to continue                     ##"
echo "##########################################"
read -n 1
############################################
#init config
/etc/init.d/iptables status >/dev/null 2>&1
if [ $? -eq 0 ]
then
iptables -I INPUT -p tcp --dport 80 -j ACCEPT &&
iptables -I INPUT -p udp --dport 161 -j ACCEPT &&
iptables-save >/dev/null 2>&1
else
    echo -e "\033[32m iptables is stopd\033[0m"
fi
sed -i "s/SELINUX=enforcing/SELINUX=disabled/"  /etc/selinux/config
setenforce 0
yum -y install ntpdate wget vim 
ntpdate -s time1.aliyun.com
echo "*/5 * * * * ntpdate -s time1.aliyun.com">>/var/spool/cron/root
###########################################
yum -y install httpd mysql-server php php-mysql php-snmp mysql-devel httpd-devel net-snmp net-snmp-devel net-snmp-utils rrdtool

# 脚本内容较长，仅显示部分内容
```

**脚本功能**：自动安装Cacti监控工具，包括配置防火墙、关闭SELinux、安装依赖包、配置SNMP、设置Web服务、下载并安装Cacti、配置数据库、设置定时任务等。

**主要特点**：
- 自动配置防火墙规则，允许80端口（HTTP）和161端口（SNMP）访问
- 关闭SELinux，避免权限问题
- 安装并配置NTP服务，确保系统时间准确
- 自动安装所需的依赖包，包括Apache、MySQL、PHP、SNMP、RRDTool等
- 配置SNMP服务
- 下载并安装Cacti
- 自动配置Cacti数据库和用户
- 设置Cacti的定时任务
- 安装Cacti插件（monitor）

**执行流程**：
1. 显示欢迎信息，提示用户按任意键继续
2. 配置防火墙规则，允许HTTP和SNMP访问
3. 关闭SELinux
4. 安装并配置NTP服务，同步系统时间
5. 安装所需的依赖包
6. 配置SNMP服务
7. 启动并设置Apache、MySQL、SNMP服务为开机自启
8. 下载并安装Cacti
9. 配置Cacti数据库和用户
10. 设置Cacti的定时任务
11. 安装Cacti插件

**注意事项**：
- 脚本需要以root用户执行
- 脚本假设系统使用CentOS/RHEL发行版，使用yum包管理器
- 脚本中存在一些拼写错误，例如第49行的"nstall httpd"应该是"install httpd"
- 脚本中存在路径错误，第98行的"cd DIR"应该是"cd $DIR"
- 脚本自动设置了MySQL root密码为"mysqladmin"，存在安全风险
- 脚本自动设置了Cacti用户密码为"cacti"，存在安全风险
- 脚本会修改系统的防火墙、SELinux和定时任务配置
- 脚本安装的是旧版本的Cacti（0.8.8h），可能存在安全漏洞

#### 4.3 check_mysql_ms.sh

```bash
#!/bin/bash
mysql_user='root'
mysql_pass="xxxxx!xxxxxx#7"
data=$(/bin/date +%Y-%m-%d-%H:%M)
/bin/netstat -lntup|egrep ":3306"|grep -v grep>/dev/null0
if [ $? -eq 0 ];then
	Slave_IO=`/data/mysql/bin/mysql -u${mysql_user} -pCHANGE_ME -e "show slave status\G"|grep "Slave_IO_Running:"|awk -F": " '{print $2}'`
	Slave_SQL=`/data/mysql/bin/mysql -u${mysql_user} -pCHANGE_ME -e "show slave status\G"|grep "Slave_SQL_Running:"|awk -F": " '{print $2}'`
		if [ "$Slave_IO" == "Yes" ] && [ "$Slave_SQL" == "Yes" ];then
			STAT=1 && echo "$data mysql-status is ok">>/var/log/mysql-status.log
		else
			STAT=0 && echo "$data mysql-status is error">>/var/log/mysql-status.log
		fi
else
	STAT=0 && echo "$data mysql-status is error">>/var/log/mysql-status.log
fi
/usr/bin/zabbix_sender -z xxx.xx.xx.x -s "DaoDaEr-mysql-status" -k mysql -o $STAT
```

**脚本功能**：检查MySQL主从复制状态，并将结果发送到Zabbix监控系统。

**主要参数**：
- `mysql_user`：MySQL用户名（root）
- `mysql_pass`：MySQL密码
- `data`：当前日期时间
- `STAT`：监控状态（1表示正常，0表示异常）
- `/var/log/mysql-status.log`：监控日志文件路径
- `zabbix_sender`：Zabbix发送命令，用于将监控数据发送到Zabbix服务器

**执行流程**：
1. 检查MySQL服务是否在监听3306端口
2. 如果MySQL服务运行正常，则检查主从复制状态：
   - 获取Slave_IO_Running状态
   - 获取Slave_SQL_Running状态
   - 如果两者都为Yes，则状态为正常（STAT=1）
   - 否则状态为错误（STAT=0）
3. 如果MySQL服务未运行，则状态为错误（STAT=0）
4. 将状态结果写入日志文件
5. 使用zabbix_sender将状态发送到Zabbix监控服务器

**注意事项**：
- 脚本中存在一个错误：netstat命令的输出重定向到了/dev/null0，正确的应该是/dev/null
- 脚本使用了完整的mysql命令路径 `/data/mysql/bin/mysql`，适用于MySQL自定义安装的场景
- 脚本将监控数据发送到Zabbix服务器，需要确保zabbix_sender已安装且配置正确
- 脚本需要以具有足够权限的用户执行，能够检查进程、访问MySQL和执行zabbix_sender

#### 4.4 check_ping.sh

```bash
#!/bin/bash
#auth:it-arch

# ping可执行路径
PINGCMD=/usr/bin/ping
# zabbix_sender可执行文件路径
SENDCMD=/usr/bin/zabbix_sender
# ping测主机ip地址
CHECKHOST=baidu.com11
# zabbix服务器ip地址
ZABBIXSERVER=xx.xx.55.225
# zabbix服务器监听端口
ZABBIXPORT=10051
# zabbix添加这条监控主机名
LOCALHOST=checkping_monitor
# ping包的数量
PAG_NUM=1
# 添加监控项的键值
ZAX_KEY=ping_response


# 获取ping响应时间
check_ping() {
   $PINGCMD -c $PAG_NUM $CHECKHOST >/dev/null 2>&1
   if [ $? -eq 0 ];then
        RESPONSE_TIME=`$PINGCMD -c $PAG_NUM -w 1 $CHECKHOST |head -2 |tail -1|awk '{print $(NF-1)}'|cut -d= -f2`
        echo $RESPONSE_TIME
   else
        echo 0
   fi
}

# 发送数据到zabbixserver
send_data() {
  DATA=`check_ping`
  $SENDCMD -z $ZABBIXSERVER -s $LOCALHOST -k $ZAX_KEY -o $DATA
}

while true
do
        send_data
        sleep 0.5
done
```

**脚本功能**：持续检查指定主机的网络连通性，获取ping响应时间，并将结果发送到Zabbix监控系统。

**主要参数**：
- `PINGCMD`：ping命令路径
- `SENDCMD`：zabbix_sender命令路径
- `CHECKHOST`：要检查的主机地址（当前设置为错误的域名baidu.com11）
- `ZABBIXSERVER`：Zabbix服务器IP地址
- `ZABBIXPORT`：Zabbix服务器监听端口
- `LOCALHOST`：Zabbix中添加的监控主机名
- `PAG_NUM`：ping包的数量（1个）
- `ZAX_KEY`：Zabbix监控项的键值

**主要函数**：
- `check_ping`：检查指定主机的连通性，返回响应时间（如果连通）或0（如果不连通）
- `send_data`：调用check_ping函数获取响应时间，并使用zabbix_sender将数据发送到Zabbix服务器

**执行流程**：
1. 定义配置变量
2. 定义check_ping和send_data函数
3. 使用while循环持续执行send_data函数，每隔0.5秒执行一次
4. send_data函数调用check_ping函数获取响应时间
5. check_ping函数使用ping命令检查指定主机的连通性
6. 如果连通，获取响应时间；否则返回0
7. send_data函数使用zabbix_sender将响应时间发送到Zabbix服务器

**注意事项**：
- 脚本中存在一个错误：要检查的主机地址设置为了错误的域名baidu.com11，正确的应该是baidu.com
- 脚本使用while循环持续执行，会一直占用系统资源
- 脚本将ping响应时间发送到Zabbix服务器，需要确保zabbix_sender已安装且配置正确
- 脚本需要以具有网络访问权限的用户执行
- 脚本中定义的ZABBIXPORT变量未被使用

#### 4.5 其他监控脚本

监控目录下还有以下脚本：
- AutoInstallCacti1.0.1.sh：自动安装Cacti 1.0.1版本的脚本
- AutoInstallCacti1.0.1-2-3.sh：自动安装Cacti 1.0.1-2-3版本的脚本
- aliyun_cms_post.sh：将监控数据发送到阿里云CMS的脚本
- cpulimit.sh：限制进程CPU使用率的脚本
- os_check.sh：检查操作系统相关信息的脚本
- ping.sh：ping命令相关的脚本
- ping2.sh：ping命令相关的脚本
- ping2-bak.sh：ping2.sh的备份脚本

由于这些脚本与前面介绍的脚本功能类似，这里不再详细解释。

## 总结

本文件详细解释了Shell脚本案例目录下的主要脚本，包括备份恢复类、安全类、安装配置类和监控类脚本。这些脚本涵盖了数据库备份、安全防护、软件安装配置和系统监控等多个方面，是日常运维工作中的实用工具。

**主要特点**：
- 脚本功能丰富，涵盖了多种运维场景
- 大部分脚本具有自动执行功能，减少了人工干预
- 部分脚本存在一些语法错误或配置问题，使用时需要注意
- 脚本主要针对CentOS/RHEL发行版，使用yum包管理器
- 部分脚本涉及敏感信息（如密码），使用时需要注意安全

**使用建议**：
- 在使用脚本前，仔细阅读脚本内容，了解其功能和配置
- 对于涉及敏感信息的脚本，建议修改为安全的方式存储敏感数据
- 对于存在语法错误的脚本，使用前需要修复
- 根据实际环境调整脚本中的配置参数
- 定期检查脚本的执行结果，确保其正常工作
- 结合定时任务使用，实现自动化运维

通过学习和使用这些脚本，可以提高运维工作的效率，减少人工干预，实现自动化运维。

