前言
工作中会经常写一些常用的 Shell 脚本,本文整理了一些常用的 Shell 脚本供大家学习使用:
IP 禁用
LNMP 搭建
mysql 数据库备份
nginx 日志分析
服务器系统配置初始化
检测网卡流量
批量创建用户
批量访问网站是否正常
查看服务器利用率
查看占用 CPU 和内存过高的进程
IP 禁用
#! /bin/bash
#Block-IPs-from-countries
Green="\033[32m"
Font="\033[0m"
#root权限
root_need(){
if [[ $EUID -ne 0 ]]; then
echo "Error:This script must be run as root!" 1>&2
exit 1
fi
}
#封禁ip
block_ipset(){
check_ipset
#添加ipset规则
echo -e "${Green}请输入需要封禁的国家代码,如cn(中国),注意字母为小写!${Font}"
read -p "请输入国家代码:" GEOIP
echo -e "${Green}正在下载IPs data...${Font}"
wget -P /tmp http://www.ipdeny.com/ipblocks/data/countries/$GEOIP.zone 2> /dev/null
#检查下载是否成功
if [ -f "/tmp/"$GEOIP".zone" ]; then
echo -e "${Green}IPs data下载成功!${Font}"
else
echo -e "${Green}下载失败,请检查你的输入!${Font}"
echo -e "${Green}代码查看地址:http://www.ipdeny.com/ipblocks/data/countries/${Font}"
exit 1
fi
#创建规则
ipset -N $GEOIP hash:net
for i in $(cat /tmp/$GEOIP.zone ); do ipset -A $GEOIP $i; done
rm -f /tmp/$GEOIP.zone
echo -e "${Green}规则添加成功,即将开始封禁ip!${Font}"
#开始封禁
iptables -I INPUT -p tcp -m set --match-set "$GEOIP" src -j DROP
iptables -I INPUT -p udp -m set --match-set "$GEOIP" src -j DROP
echo -e "${Green}所指定国家($GEOIP)的ip封禁成功!${Font}"
}
#解封ip
unblock_ipset(){
echo -e "${Green}请输入需要解封的国家代码,如cn(中国),注意字母为小写!${Font}"
read -p "请输入国家代码:" GEOIP
#判断是否有此国家的规则
lookuplist=`ipset list | grep "Name:" | grep "$GEOIP"`
if [ -n "$lookuplist" ]; then
iptables -D INPUT -p tcp -m set --match-set "$GEOIP" src -j DROP
iptables -D INPUT -p udp -m set --match-set "$GEOIP" src -j DROP
ipset destroy $GEOIP
echo -e "${Green}所指定国家($GEOIP)的ip解封成功,并删除其对应的规则!${Font}"
else
echo -e "${Green}解封失败,请确认你所输入的国家是否在封禁列表内!${Font}"
exit 1
fi
}
#查看封禁列表
block_list(){
iptables -L | grep match-set
}
#检查系统版本
check_release(){
if [ -f /etc/redhat-release ]; then
release="centos"
elif cat /etc/issue | grep -Eqi "debian"; then
release="debian"
elif cat /etc/issue | grep -Eqi "ubuntu"; then
release="ubuntu"
elif cat /etc/issue | grep -Eqi "centos|red hat|redhat"; then
release="centos"
elif cat /proc/version | grep -Eqi "debian"; then
release="debian"
elif cat /proc/version | grep -Eqi "ubuntu"; then
release="ubuntu"
elif cat /proc/version | grep -Eqi "centos|red hat|redhat"; then
release="centos"
fi
}
#检查ipset是否安装
check_ipset(){
if [ -f /sbin/ipset ]; then
echo -e "${Green}检测到ipset已存在,并跳过安装步骤!${Font}"
elif [ "${release}" == "centos" ]; then
yum -y install ipset
else
apt-get -y install ipset
fi
}
#开始菜单
main(){
root_need
check_release
clear
echo -e "———————————————————————————————————————"
echo -e "${Green}Linux VPS一键屏蔽指定国家所有的IP访问${Font}"
echo -e "${Green}1、封禁ip${Font}"
echo -e "${Green}2、解封iP${Font}"
echo -e "${Green}3、查看封禁列表${Font}"
echo -e "———————————————————————————————————————"
read -p "请输入数字 [1-3]:" num
case "$num" in
1)
block_ipset
;;
2)
unblock_ipset
;;
3)
block_list
;;
*)
clear
echo -e "${Green}请输入正确数字 [1-3]${Font}"
sleep 2s
main
;;
esac
}
main
LAMP 安装
#!bin/bash
NGINX_V=1.15.6
PHP_V=5.6.36
TMP_DIR=/tmp
INSTALL_DIR=/usr/local
PWD_C=$PWD
echo
echo -e "/tMenu\n0"
echo -e "1. Install Nginx"
echo -e "2. Install PHP"
echo -e "3. Install MySQL"
echo -e "4. Deploy LNMP"
echo -e "9. Quit"
function command_status_check() {
#打印上一个命令输出状态
if [ $? -ne 0 ]; then
echo $1
exit
fi
}
function install_nginx() {
cd ${TMP_DIR}
yum install -y gcc gcc-c++ make openssl-devel pcre-devel wget
wget http://nginx.org/download/nginx-${NGINX_V}.tar.gz
tar zxf nginx-${NGINX_V}.tar.gz
cd nginx-${NGINX_V}
./configure --prefix=$INSTALL_DIR/nginx \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-stream
command_status_check "Nginx - 平台环境检查失败!"
make -j 4
command_status_check "Nginx - 编译失败!"
make install
command_status_check "Nginx - 安装失败!"
mkdir -p $INSTALL_DIR/nginx/conf/vhost
alias cp=cp ; cp -rf $PWD_C/nginx.conf $INSTALL_DIR/nginx/conf
rm -rf $INSTALL_DIR/nginx/html/*
echo "ok" > $INSTALL_DIR/nginx/html/status.html
echo '<?php echo "ok"?>' > $INSTALL_DIR/nginx/html/status.php
$INSTALL_DIR/nginx/sbin/nginx
command_status_check "Nginx - 启动失败!"
}
function install_php() {
cd $TMP_DIR
yum install -y gcc gcc-c++ make gd-devel libxml2-devel \
libcurl-devel libjpeg-devel libpng-devel openssl-devel \
libmcrypt-devel libxslt-devel libtidy-devel
wget http://docs.php.net/distributions/php-${PHP_V}.tar.gz
tar zxf php-${PHP_V}.tar.gz
cd php-${PHP_V}.tar.gz
./configure --prefix=$INSTALL_DIR/php \
--with-config-file-path=$INSTALL_DIR/php/etc \
--enable-fpm --enable-opcache \
--with-mysql --with-mysqli -with-pdo-mysql \
--with-openssl --with-zlib --with-curl -with-gd \
--with-jpeg-dir --with-png-dir --with-freetype-dir \
--enable-mbstring --enable-hash
command_status_check "PHP - 平台环境监测失败!"
make -j4
command_status_check "PHP - 编译失败!"
make install
command_status_check "PHP - 安装失败!"
cp php.ini-production $INSTALL_DIR/php/etc/php.ini
cp sapi/fpm/php-fpm.conf $INSTALL_DIR/php/etc/php-fpm.conf
cp sapi/fpm.init.d.php-fpm /etc/init.d/php-fpm
chmod -x /etc/init.d/php-fpm
/etc/init.d/php-fpm start
command_status_check "PHP - 启动失败!"
}
read -p "请输入编号:" number
case $number in
1)
install_nginx;;
2)
install_php;;
3)
install_mysql;;
4)
install_nginx
install_php
;;
9)
exit;;
esac
mysql 数据备份
分库 分表
#-s 去掉边框
mysql -uroot -p密码 -s -e "show databases;"
#排除所有的系统库
mysql -uroot -p密码 -s -e "show databases;" | egrep -v "infor|perfor|sys|mysql"
分库备份
#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=localhost
USER=backup
PASS=密码
BACKUP_DIR=/data/db_backup
DB_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "show databases;" 2>/dev/null |egrep -v "Database|information_schema|mysql|performance_schema|sys")
for DB in $DB_LIST; do
BACKUP_NAME=$BACKUP_DIR/${DB}_${DATE}.sql
if ! mysqldump -h$HOST -u$USER -p$PASS -B $DB > $BACKUP_NAME 2>/dev/null; then
echo "$BACKUP_NAME 备份失败!"
fi
done
分表备份
#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=localhost
USER=backup
PASS=密码
BACKUP_DIR=/data/db_backup
DB_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "show databases;" 2>/dev/null |egrep -v "Database|information_schema|mysql|performance_schema|sys")
for DB in $DB_LIST; do
BACKUP_DB_DIR=$BACKUP_DIR/${DB}_${DATE}
[ ! -d $BACKUP_DB_DIR ] && mkdir -p $BACKUP_DB_DIR &>/dev/null
TABLE_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "use $DB;show tables;" 2>/dev/null)
for TABLE in $TABLE_LIST; do
BACKUP_NAME=$BACKUP_DB_DIR/${TABLE}.sql
if ! mysqldump -h$HOST -u$USER -p$PASS $DB $TABLE > $BACKUP_NAME 2>/dev/null; then
echo "$BACKUP_NAME 备份失败!"
fi
done
nginx 日志分析
访问最多的IP
访问最多的页面 CC攻击
访问页面状态码数量
根据时间段来访问最多的IP
#统计某列IP数量
awk '{a[$1]++}END{for(v in a)print v, a[v]}' /usr/local/nginx/logs/access.log
#!/bin/bash
LOG_FILE=$1
echo "统计访问最多的10个IP"
awk '{a[$1]++}END{print "UV:", length(a);for(v in a)print v, a[v]}' $LOG_FILE |sort -k2 -nr |head -10
echo "-----------------------------"
echo "统计时间段访问最多的IP"
awk '$4>="[01/Dec/2018:13:20:25" && $4<="[01/Dec/2018:16:20:25"{a[$1]++}END{for(v in a)print v, a[v]}' $LOG_FILE |sort -k2 -nr |head -10
echo "-----------------------------"
echo "统计访问最多的10个页面"
awk '{a[$7]++}END{print "PV:", length(a);for(v in a){if(a[v]>10)print v, a[v]}}' $LOG_FILE |sort -k2 -nr
echo "统计访问页面状态码数量"
awk '{a[$7" "$9]++}END{for(v in a){if(a[v]>5)print v, a[v]}}' $LOG_FILE |sort -k3 -nr
服务器系统配置初始化
背景:新购买的10台服务器并已安装Linux操作
需求:
1) 设置时区并同步时间
2) 禁用seLinux
3) 清空防火墙默认策略
4) 历史命令显示操作时间
5) 禁止root远程登录
6) 禁止定时任务发送邮件
7) 设置最大打开文件数
8) 减少Swap使用
9) 系统内核参数优化
10)安装系统性能分析工具及其他
#bin/bash
#设置时区并同步时间
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
#定时执行 2>&1 意思是把 标准错误输出 重定向到 标准输出.
if ! crontab -l | grep ntpdate &>/dev/null ;then
#最后的crontab -l是为了将追加的内容列出来,防止覆盖
(echo "* 1 * * * ntpdate time.windows.com >/dev/null 2>&1";crontab -l) |crontab
fi
#禁用selinux
sed -i '/SELINUX/{s/permissive/disabled/}' /etc/selinux/config
#关闭防火墙
if egrep "7.[0-9]" /etc/redhat-release &>/dev/null; then
systemctl stop firewalld
systemctl disable firewalld
elif egrep "6.[0-9]" /etc/redhat-release &>/dev/null; then
service iptables stop
chkconfig iptables off
fi
#历史命令显示操作时间 history
if ! grep HISTTIMEFORMAT /etc/bashrc; then
echo 'export HISTTIMEFORMAT="%F %T `whoami` "' >> /etc/bashrc
fi
#SSH超时时间
if ! grep "TMOUT=600" /etc/profile &>/dev/null; then
echo "export TMOUT=600" >> /etc/profile
fi
#禁止root远程登录
#sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
#禁止定时任务发送邮件
sed -i 's/^MAILTO=root/MAILTO=""/' /etc/crontab
#设置最大打开文件数
if ! grep "* soft nofile 65535" /etc/security/limits.conf &>/dev/null; then
cat >> /etc/security/limits.conf < * soft nofile 65535
* hard nofile 65535
EOF
fi
#系统内核优化
cat >> /etc/sysctl.conf <net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 20480
net.ipv4.tcp-max-syn_backlog = 20480
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_fin_timeout = 20
EOF
#减少SWAP使用
echo "0" > /proc/sys/vm/swappiness
检测网卡流量
#!/bin/bash
NIC=$1
echo In ------ Out
while true; do
OLD_IN=$(cat /proc/net/dev | awk '/eth0/{print $2}')
OLD_OUT=$(cat /proc/net/dev | awk '/eth0/{print $10}')
sleep 1
NEW_IN=$(cat /proc/net/dev | awk '/eth0/{print $2}')
NEW_OUT=$(cat /proc/net/dev | awk '/eth0/{print $10}')
IN=$(printf ""%.1f%s" $((($NEW_IN-$OLD_IN)/1024)), "KB/s")
OUT=$(printf ""%.1f%s" $((($NEW_OUT-$OLD_OUT)/1024)), "KB/s")
echo "$IN $OUT"
sleep 1
done
批量创建用户
#!/bin/bash
#$@接受用户输入的所有参数 $#表示所有参数的个数
USER_LIST=$@
USER_FILE=./user.info
for USER in $USER_LIST; do
if ! id $USER &>/dev/null; then
PASS=$(echo $RANDOM | md5sum |cur -c 1-8)
useradd $USER
echo $PASS | passwd --stdin $USER &>/dev/null
echo "$USER $PASS" >> $USER_FILE
echo "$USER User create sucessful."
else
echo "$USER User already exists!"
fi
done
批量访问网站是否正常
#!/bin/bash
URL_LIST="www.baidu.com www.vovomeet.com"
for URL in $URL_LIST; do
FAIL_COUNT=0
for((i-1;i<=3;i++)); do
HTTP_CODE=$(curl -o /dev/null --connect-timeout 3 -s -w "{http_code}" $URL)
if [ $HTTP_CODE -eq 200 ]; then
echo "${URL} ok"
break
else
let FAIL_COUNT++
fi
done
if [ $FAIL_COUNT -eq 3 ]; then
echo "Warining: $URL Access failure!"
fi
done
一件查看服务器利用率
1) CPU 60%以上
2) 内存 利用率
3) 硬盘 利用率
4) TCP连接状态 负载情况
#!/bin/bash
# awk更像是一个sql,有行有列
function cpu() {
util = $(vmstat |awk '{if(NR==3)print $13+$14}')
iowait=$(vmstat |awk '{if(NR==3)print $16}')
echo "CPU - 使用率:${util}%, 等待磁盘IO响应使用率:${iowait}%"
}
function memory() {
total=$(free -m| awk '{if(NR==2)printf "%.1fG", $2/1024}')
used=$(free -m| awk '{if(NR==2)printf "%.1fG", ($2-$NF)/1024}')
available=$(free -m| awk '{if(NR==2)printf "%.1fG", $NF/1024}')
echo "内存 -总大小: ${total}, 已使用: ${used}, 可用:${available}"
}
function disk() {
fs=$(df -h |awk '/^\/dev/{print $1}')
for p in $fs; do
mounted=$(df -h|awk -v p=$p '$1==p{print $NF}')
size=$(df -h|awk -v p=$p '$1==p{print $2}')
used=$(df -h|awk -v p=$p '$1==p{print $3}')
used_percent=$(df -h|awk -v p=$p '$1==p{print $5}')
echo "硬盘 -挂载点:$mounted, 总大小:$size 已使用:$used 使用率:$used_percent"
done
}
function tcp_stat() {
echo "TCP连接状态:"
netstat -antp |awk '{a[$6]++}END{for(i in a)print i,a[i]}'
}
占用 CPU 和 内存过高的进程
1) CPU 60%以上
2) 内存 利用率
3) 硬盘 利用率
4) TCP连接状态 负载情况
#!/bin/bash
# awk更像是一个sql,有行有列
function cpu() {
util = $(vmstat |awk '{if(NR==3)print $13+$14}')
iowait=$(vmstat |awk '{if(NR==3)print $16}')
echo "CPU - 使用率:${util}%, 等待磁盘IO响应使用率:${iowait}%"
}
function memory() {
total=$(free -m| awk '{if(NR==2)printf "%.1fG", $2/1024}')
used=$(free -m| awk '{if(NR==2)printf "%.1fG", ($2-$NF)/1024}')
available=$(free -m| awk '{if(NR==2)printf "%.1fG", $NF/1024}')
echo "内存 -总大小: ${total}, 已使用: ${used}, 可用:${available}"
}
function disk() {
fs=$(df -h |awk '/^\/dev/{print $1}')
for p in $fs; do
mounted=$(df -h|awk -v p=$p '$1==p{print $NF}')
size=$(df -h|awk -v p=$p '$1==p{print $2}')
used=$(df -h|awk -v p=$p '$1==p{print $3}')
used_percent=$(df -h|awk -v p=$p '$1==p{print $5}')
echo "硬盘 -挂载点:$mounted, 总大小:$size 已使用:$used 使用率:$used_percent"
done
}
function tcp_stat() {
echo "TCP连接状态:"
netstat -antp |awk '{a[$6]++}END{for(i in a)print i,a[i]}'
}