15. Shell-案例之经典

服务器系统配置初始化

背景

新购买了10台服务器并已安装Linux操作系统,现在需要初始化服务器系统。

需求

  1. 设置时区并定期同步时间;
  2. 禁用selinux;
  3. 情况防火墙策略,并关闭防火墙;
  4. 设置历史命令显示操作时间;
  5. 禁止root用户远程登录
  6. 禁止定时任务发送邮件
  7. 设置最大打开文件数
  8. 减少swap使用
  9. 系统内核参数优化
  10. 安装系统性能分析工具

思路

  1. 设置时区并定期同步时间;
    1. 软连时区到“/etc/localtime”
    2. 定期同步任务需要使用的定时任务crontab
    3. crontab的写入需要免交互的方式
  2. 禁用selinux;
    1. 使用sed快速定位关键字
    2. 定位关键字后进行替换
  3. 关闭防火墙;
    1. 由于CentOS6和CentOS7的关闭命令不同,需要先判断系统版本
    2. 根据判断关闭防火墙(firewalld或iptables)
  4. 设置历史命令显示操作时间;
    1. 判断是否设置了历史命令显示操作
    2. 未设置则写入命令
  5. SSH超时时间
  6. 禁止root用户远程登录
    1. 禁止root用户登录之前需要先创建可以远程登录的普通用户
    2. 然后禁用root用户
  7. 禁止定时任务发送邮件
  8. 设置最大打开文件数
    1. 可以对命令结果进行判断,“!”表示结果取反
    2. EOF命令需要顶头写,是shell的命令格式
  9. 减少swap使用
  10. 系统内核参数优化
  11. 安装系统性能分析工具

实现

#!/bin/env bash

#1. 设置时区并定期同步时间
ls -l /etc/localtime &> /dev/null
if [[ $? != "0" ]]; then
    ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
else
    echo "时区 已设置"
fi

if ! crontab -l |grep ntpdate &> /dev/null; then
    (echo "* 1 * * * ntpdate ntp.aliyun.com  > /dev/null 2>&1"; crontab -l) | crontab
else 
    echo "定期同步时间 已设置"
fi

#2. 禁用selinux
sed -i '/SELINUX/{s/permissive/disabled/}' /etc/selinux/config

#3. 关闭防火墙
if grep -E "7.[0-9]" /etc/redhat-release &> /dev/null; then
    systemctl stop firewalld
    systemctl disable firewalld
elif grep -E "6.[0-9]" /etc/redhat-release &> /dev/null; then
    service iptables stop
    chkconfig iptables off
else
    echo "系统防火墙未能关闭"
    echo "此脚本仅适用于CentOS7和CentOS6版本的防火墙关停"
fi

#4. 历史命令显示操作时间
if ! grep HISTIMEFORMAT /etc/bashrc; then
    echo 'export HISTTIMEFORMAT="%F %T $(whoami) "' >> /etc/bashrc
    source /etc/bashrc > /dev/null 2&>1
else
    echo "历史命令显示操作时间 已设置"
fi

#5. SSH超时时间
if ! grep "TMOUT" /etc/profile > /dev/null 2&>1; then
    echo "export TMOUT=600" >> /etc/profile
else
    echo "SSH超时时间 已设置"
fi

#6. 禁止root用户远程登录
USER_NAME="r00t"
useradd $USER_NAME
echo "cmk521" | passwd --stdin $USER_NAME
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config

#7. 禁止定时任务发送邮件
sed -i 's/^MAILTO=root/MAILTO=""/' /etc/crontab

#8. 设置最大打开文件数
if ! grep "* soft nofile 65535" /etc/security/limits.conf &>/dev/null; then
cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
EOF
else
    echo "最大打开文件数 已设置"
fi

#9. 减少swap使用
echo "0" >> /proc/sys/vm/swappiness

#10. 系统内核参数优化
cat >> /etc/sysctl.conf << EOF
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

#11. 安装系统性能分析工具及其他工具
yum -y install gcc make autoconf vim sysstat net-tools iostat iftop iotp lrzsz > /dev/null 2&>1

总结

针对没有用的输出信息可以使用“> /dev/null 2&>1”或“&> /dev/null”使其不打印到屏幕上,更推荐使用“&> /dev/null”让代码更简介一点。

批量创建用户并设置密码

背景

公司新入职一批员工为员工批量创建用户并设置密码,假如入职10名新员工。

需求

  1. 创建的用户名从文件中读取;
  2. 用户的密码格式为:用户名@123;
  3. 创建的用户需要有家目录并且指定其用户组;
  4. 创建的用户指定各自的用户ID,用户ID为该组UID最大值+1;

思路

  1. 单独创建用户的操作流程;
  2. 单独为用户设置密码流程;
  3. 创建的用户、密码格式;

实现

  • 用户名单
cat > username_list.txt << EOF
王茗渠 男 wangmingqu
刘小伟 男 liuxiaowei
常有理 女 changyouli 
王岩茗 男 wangyanming
郭厅长 男 guotingzhang
王晓斌 男 wangxiaobin
郑弘汇 女 zhengnonghui
朱亚宗 男 zhuyazong
宋明辉 男 songminghui
车友聚 男 cheyouju
EOF
  • 脚本实现
#!/bin/bash

#根据用户列表批量创建用户并设置密码


#判断用户组是否存在,如不存在则创建
USERGROUP=yunwei
GROUPID=4040
grep ^$USERGROUP /etc/group >& /dev/null
if [ $? -eq 0 ]; then
	echo "用户组:$USERGROUP$GROUPID,已存在"
else
	echo "用户组:$USERGROUP$GROUPID,创建中..."
	groupadd -g $GROUPID $USERGROUP
  echo "用户组:$USERGROUP$GROUPID,创建完成"
fi

#用户组中现有UID最大值
cat /etc/passwd | awk -F':' '{print $3,$4}' | grep "$GROUPID"
if [ $? -eq 0 ]; then
	NUMBER=$(cat /etc/passwd | awk -F':' '{print $3,$4}' | grep "$GROUPID" | awk -F' ' '{print $1}' | sort -r -k1 | head -1)
else
	NUMBER=$GROUPID
  echo $NUMBER
fi

USERPID=$NUMBER
USERNAME_LIST=./username_list.txt
#循环创建用户、指定用户ID、指定用户组ID、指定用户家目录
for USERNAME in $(cat $USERNAME_LIST | awk -F' ' '{print $3}'); do
	USERPID=$[$USERPID+1]
  if ! id $USERNAME &> /dev/null; then
  	useradd -u $USERPID -g $USERGROUP -d /home/$USERNAME -m $USERNAME -s /bin/bash
  	echo "$USERNAME@123" | passwd --stdin $USERNAME
  else
    echo "$USERNAME 用户已存在"
  fi
done

echo "用户创建完毕"

一键查看服务器利用率

背景

用户反应公司web网站访问比较慢,在公司没有监控工具的情况下,需要排除服务器资源利用率、网络问题等。

需求

  1. 检查服务器利用率
  2. 检查网络情况

思路

  1. 查看服务器CPU(CPU利用率需要在60%以下);

image.png

  1. us:用户态利用率;sy:内核态利用率;(两者之和不能超过60%)
  2. ni:优先级利用率;id:空闲利用率;
  3. wa:磁盘等待响应百分比;
  4. 主要查看的是:us、sy、id、wa
  5. 查看服务器MEM(内存的利用率及剩余情况);

image.png

  1. Mem:物理内存使用情况;Swap:swap使用情况;
  2. total:总量;used:使用情况;free:剩余情况;
  3. buff/cache:缓存使用情况;available:可用的内存情况;
  4. 主要查看的是:used、free
  5. 查看服务器DISK(磁盘是否写满,如写满以后新的请求无法处理);

image.png

  1. Filesystem:系统文件名;Size:系统文件总计大小;Mounted on:磁盘挂载情况;
  2. Used:使用情况;Avail:可用情况;Use%使用占比;
  3. 主要查看的是:Use%、Mounted on
  4. 查看服务器TCP/UDP(TCP/UDP连接状态,从TCP/UDP连接状态可以反应出服务器并发情况);

image.png

  1. -autnp:a–>显示所有socket;t–>TCP连接;u–>UDP连接;n–>以数字形式显示;p–>显示程序名称
  2. Proto:使用协议;Local Address:本地地址和端口;Foreign Address:远程连接的地址和端口;State:监听的状态;PID/Program name:监听的进程名称;
  3. 主要查看的是:State(LISTEN:表示监听服务正常;ESTABLISHED:监听进程的并发监听;SYN_SENT:三次握手的一个过程监听)
  4. 查看服务器网络情况

image.png

  1. RX:接收的数据,packets:接收数据包个数,bytes:接收数据包大小,errors:接收包错误个数,dropped:接收包丢失个数;
  2. TX:发送的数据,packets:发送数据包个数,bytes:发送数据包大小,errors:发送包错误个数,dropped:发送包丢失个数;
  3. 主要查看的是:网卡个数、每个网卡的RX、TX情况

实现

  • 脚本实现
#!/bin/bash

function cpu(){
	USE_TOTAL=$(vmstat | awk -F' ' '{if(NR==3){print $(NF-5)+$(NF-4)}}')
  USE_IOWAIT=$(vmstat | awk -F' ' '{if(NR==3){print $(NF-1)}}')
  echo "CPU情况    使用情况:$USE_TOTAL%";磁盘IO等待情况:$USE_IOWAIT%
}

function cpu_top(){
	echo "进程的CPU使用率前五名"
	top -b -n 1 |tail -n +8 | awk -F' ' '{print "进程名称:"$NF";\t使用情况:"$(NF-3)}' | sort -k 1 -nr | head -5
}

function mem(){
	free -h | awk -F' ' '{if(NR==2){print "使用情况:"$3";剩余情况:"$4";使用百分比:"$3/$2"%;剩余百分比:"$4/$2"%"}}'
}

function mem_top(){
	echo "进程的MEM使用率前五名"
  top -b -n 1 |tail -n +8 | awk -F' ' '{print "进程名称:"$NF";\t使用情况:"$(NF-2)}' | sort -k 1 -nr | head -5
}

function disk_top(){
  echo "进程的DISK使用率前五名"
	df -h | tail -n +2 | awk -F' ' '/^\/dev/{print "磁盘名称:"$NF";磁盘使用情况:"$(NF-1)}' | sort -k 2 -nr | head -5
}

function tcp(){
	netstat -antp | awk '{a[$6]++}END{for(i in a)print i,a[i]}'
}

function network(){
	NEWORK_INTERFACE=ens32
  
	OLD_INPUT=$(ifconfig $NEWORK_INTERFACE | grep "RX" | head -1 | awk -F' ' '{print $5}')
  OLD_OUTPUT=$(ifconfig $NEWORK_INTERFACE | grep "TX" | head -1 | awk -F' ' '{print $5}')
  sleep 1

  NEW_INPUT=$(ifconfig $NEWORK_INTERFACE | grep "RX" | head -1 | awk -F' ' '{print $5}')
	NEW_OUTPUT=$(ifconfig $NEWORK_INTERFACE | grep "TX" | head -1 | awk -F' ' '{print $5}')

  INPUT_NETWORK=$[$[$NEW_INPUT-$OLD_INPUT]/1024/1024]
  OUTPUT_NETWORK=$[$[$NEW_OUTPUT-$OLD_OUTPUT]/1024/1024]

	INPUT_ERROR=$(ifconfig $NEWORK_INTERFACE | grep "RX" | grep "errors" | awk -F' ' '{print $3}')
  OUTPUT_ERROR=$(ifconfig $NEWORK_INTERFACE | grep "TX" | grep "errors" | awk -F' ' '{print $3}')

	echo "以下数据为 $NEWORK_INTERFACE 的收发情况"
  echo "接收量:$INPUT_NETWORK M/s;发送量:$OUTPUT_NETWORK M/s;"
  echo "接收错误个数:$INPUT_ERROR 个;发送错误个数:$OUTPUT_ERROR 个;"
}

cpu
cpu_top
mem
mem_top
disk_top
tcp
network

批量检查

批量监控磁盘利用率

背景

公司有100台主机,现在需要批量监控磁盘的利用率,当利用率达到80%时,要发邮件告警。

需求

  1. 主机IP地址文件输入;
  2. 当磁盘利用率超过80%时,发送邮件告警;
  3. 邮件告警要声明主机IP、哪块磁盘、磁盘使用情况等信息;
  4. 远程免密登录检查主机磁盘;

思路

  1. 使用for循环从主机列表文件读取要检测的IP地址、账号密码;
  2. 使用df -h列出磁盘超过80%的磁盘;
  3. 使用mail发送告警邮件;
  4. 使用expect实现免交互式登录;
  5. 使用crontab命令设置定时任务,实现自动监控;

实现

  • 主机列表
cat > ./host_ip_list.txt << EOF
主机名称        主机IP            端口号     账号密码         主机用途             备注
k8s-master      192.169.1.104     22        root/cmk521      k8s主机-master	
k8s-worker-1    192.169.1.130     22        root/cmk521      k8s主机-worker-1	
k8s-worker-2    192.169.1.128     22        root/cmk521      k8s主机-worker-2	
EOF
  • 脚本实现
#!/bin/env bash


#!/bin/env bash

#批量监控磁盘使用情况


#文件输入主机信息
HOST_IP_LIST_FILE=./host_ip_list.txt
#获取主机个数
HOST_LIST_NUMBER=$(cat $HOST_IP_LIST_FILE | tail -n +2 | wc -l)
#磁盘使用告警阀值
ALARM_THRESHOLD=2
#脚本使用临时文件
SCRIPT_TEMP_FILE=./df_temp.txt
touch $SCRIPT_TEMP_FILE
#指定告警发件人邮箱地址
MAIL_FROM_ADDRESS="1121935967@qq.com"
#指定告警发件人邮箱密码
MAIL_FROM_PASSWORD="ylcpgjzncjmoiggi"
#指定告警收件人
MAIL_RECIPIENT="15515190288@163.com"
#指定告警抄送人
MAIL_RECIPIENT_OTHER="15515190288@163.com,1121935967@qq.com"







#检查工具是否安装成功
function check_install(){
    if [ $? == "0" ]; then
        echo "应用工具 $TOOLS_NAME 安装完成"
    else
        echo "应用工具 $TOOLS_NAME 安装失败"
        exit 1
    fi
}


#QQ邮箱服务配置
function config_mailx_QQ(){
    grep "smtp-auth-user" /etc/mail.rc
    if [ $? == "0" ]; then
        echo "邮箱配置已存在,如邮件发送失败,需要手动检查"
    else
        cat >> /etc/mail.rc <<EOF
        # 设置发信人昵称
        set from=$MAIL_FROM_ADDRESS
        # 配置的第三方smtp服务器的地址及端口
        set smtp=smtp.qq.com
        # 发送邮件的邮箱账号
        set smtp-auth-user=$MAIL_FROM_ADDRESS
        # 发送邮件的客户端授权码
        set smtp-auth-password=$MAIL_FROM_PASSWORD
        # 认证方式
        set smtp-auth=login
EOF
    fi

}


#检查并安装脚本使用的工具
function install_tools(){
    TOOLS_NAME=$1
    rpm -qa | grep $TOOLS_NAME &>/dev/null
    if [ $? == "0" ]; then
        echo "应用工具 $TOOLS_NAME 已安装"
    else
        case $TOOLS_NAME in
            expect )
                echo "应用工具 $TOOLS_NAME 安装中..."
                yum -y install expect &>/dev/null
                check_install
                ;;
            sendmail )
                echo "应用工具 $TOOLS_NAME 安装中..."
                yum -y install expect &>/dev/null
                check_install
                ;;
            mailx )
                echo "应用工具 $TOOLS_NAME 安装中..."
                yum -y install mailx &>/dev/null
                check_install
                config_mailx_QQ
                ;;
        esac
    fi
}



#免密、免交互登录并获取磁盘数据
function login_host(){
expect << EOF
    set timeout 10
    spawn ssh -p $2 $3@$1 df -h > $SCRIPT_TEMP_FILE
    expect {
        "yes/no" {send "yes\n"; exp_continue}
        "password" {send "$4\n"}
    }
    expect "password" {send "$4\n"}
EOF
if [ $? != "0" ]; then
    LOGIN_ERROR="其中 $1 登录失败,请检查"
    continue
fi
}



#获取磁盘大小并判断否超出80%
function disk_use(){
    for ALL_PARAMS in $(cat $SCRIPT_TEMP_FILE | tail -n +2 | awk -F'[% ]+' '/^\/dev/{print $1"&"$(NF-1)"&"$NF}'); do
        USAGE_RATE=$(echo $ALL_PARAMS | awk -F'[%& ]+' '{print $2}')
        FILESYSTEM=$(echo $ALL_PARAMS | awk -F'[%& ]+' '{print $1}')
        MOUNTED=$(echo $ALL_PARAMS | awk -F'[%& ]+' '{print $3}')
        if [ $USAGE_RATE -gt $ALARM_THRESHOLD ]; then
            #echo "$HOST_IP 磁盘超过$ALARM_THRESHOLD%,已使用 $USAGE_RATE%"
            MAIL_MASSAGE="$HOST_IP 中磁盘超过$ALARM_THRESHOLD%,已使用 $USAGE_RATE%,文件系统 $FILESYSTEM,挂载点 $MOUNTED。"
        fi
    done
}


#如果磁盘高于80%发送邮件告警
function sed_mail(){
    HOST_NUMBER_MESSAGE="主机列表主机数量: $HOST_LIST_NUMBER 台; /\n 实际检查数量: $REALITY_NUMBER 台;"
    echo "$HOST_NUMBER_MESSAGE \n $LOGIN_ERROR \n $MAIL_MASSAGE" | mail -s "磁盘告警" -c "$MAIL_RECIPIENT_OTHER" $MAIL_RECIPIENT
}


#安装脚本使用的工具
install_tools expect
install_tools mailx
install_tools sendmail


#遍历登录主机
HOST_IP_PASSWORD=$(cat $HOST_IP_LIST_FILE | tail -n +2 | awk -F' ' '{print $2"&"$3"&"$4}')
REALITY_NUMBER=0
for IP_USERNAME_PASSWORD_PORT in $HOST_IP_PASSWORD; do
    HOST_IP=$(echo $IP_USERNAME_PASSWORD_PORT | awk -F'[& ]+' '{print $1}')
    HOST_PORT=$(echo $IP_USERNAME_PASSWORD_PORT | awk -F'[&/ ]+' '{print $2}')
    HOST_USERNAME=$(echo $IP_USERNAME_PASSWORD_PORT | awk -F'[&/ ]+' '{print $3}')
    HOST_PASSWORD=$(echo $IP_USERNAME_PASSWORD_PORT | awk -F'[&/ ]+' '{print $4}')
    login_host $HOST_IP $HOST_PORT $HOST_USERNAME $HOST_PASSWORD
    disk_use
    #计数检查主机的个数
    REALITY_NUMBER=$[REALITY_NUMBER+1]
done

#邮件发送
sed_mail

#删除临时目录
rm -f $SCRIPT_TEMP_FILE

批量检查网站是否异常

背景

公司有一批网站,需要监控,当发现网站不能正常登录时,可以发送邮件到运维处,实现快速处理。

需求

  1. 判断网站是否正常;
  2. 快速定位网站;
  3. 发送告警邮件;

思路

  1. 返回状态码;
    1. 使用curl获取网站状态码;
    2. -w “%{http_code}”:展示请求状态码;
    3. -o /dev/null:多余信息输出到/dev/null;
    4. -s:静默输出信息,只显示状态码;
    5. –connect-timeout:最大连接超时时间
    6. 举例:curl -o /dev/null --connect-timeout 3 -w “%{http_code}” -s www.baidu.com
  2. 状态码递增;
    1. 多次访问无效则返回错误;
    2. 使用let可以实现递增;
    3. 举例:a=1; let a++
  3. 发送邮件;

实现

  • 网站列表
cat > ./web_url_list.txt <<EOF
www.baidu.com
smbaexam.telfri-edu.com
www.learnin.com.cn
xihang.telfri-edu.com
EOF
  • 实现脚本
#!/bin/env bash

for url_one in $(cat web_url_list.txt); do
	ERROR_NUMBER=0
  for ((i=1;i<=3;i++)); do
  	HTTP_CODE=$(curl -o /dev/null --connect-timeout 5 -w "%{http_code}" -s $url_one)
    if [ $HTTP_CODE -eq 200 ]; then
    	break
    else
      let ERROR_NUMBER++
    fi
  done
  if [ $ERROR_NUMBER -eq 3 ]; then
    echo "网站无法访问:$url_one" | mail -s "网站告警" 15515190288@163.com
  fi
done

批量主机执行命令

背景

通过一些shell命令集中管理机器,深度理解expect命令。

需求

  1. 免交互登录主机;
  2. 批量执行命令;

思路

  1. 免交互;
    1. 使用expect命令实现免交互访问主机

实现

  • 主机列表文件
cat > ./host_list.txt <<EOF
#主机地址       主机用户   主机端口    主机密码
192.169.1.111   root      22          cmk521
192.169.1.104   root      22          cmk521
EOF
  • 实现脚本
#!/bin/env bash

COMMAND=$*

HOST_INFO=./host_list.txt
for IP in $(awk '/^[^#]/{print $1}' $HOST_INFO); do
	USER=$(awk -v ip=$IP 'ip==$1{print $2}' $HOST_INFO)
	PORT=$(awk -v ip=$IP 'ip==$1{print $3}' $HOST_INFO)
	PASS=$(awk -v ip=$IP 'ip==$1{print $4}' $HOST_INFO)

  expect -c "
    spawn ssh -p $PORT $USER@$IP
    expect {
      \"yes/no\" {send \"yes\r\"; exp_continue}
      \"password:\" {send \"$PASS\r\"; exp_continue}
      \"$USER@*~]#\" {send \"$COMMAND\r exit\r\"; exp_continue}
    }
  "
  echo "------------------------------------------------------"
done

总结

COMMAND=$*				#表示执行脚本传入参数的列表(不包括$0,$0是脚本本身)
for IP in $(awk '/^[^#]/{print $1}' $HOST_INFO); do					#使用awk的定位(/^[^#]/)可以去除文件中的注释内容
expect -c ""							#使用命令expect -c可以将expect语法融入shell语法中
\"$USER@*~]#\" {send \"$COMMAND\r exit\r\"; exp_continue}				#匹配(用户名@*)成后发送命令并退出

一键部署LNMP网站平台

背景

公司平台采用LNMP架构方式部署,现在需要新增一个平台。
LNMP架构:Linux–>Nginx–>MySQL–>PHP,主要适用于PHP项目的高性能web服务的组合。

需求

  1. 一键部署平台
  2. 自动配置Nginx、MySQL、PHP

思路

  1. 部署安装方式选择
    1. 源码编译安装
      1. 环境检测./configure
      2. 编译make
      3. 安装make install
    2. 二进制安装
    3. yum安装
  2. 使用函数模块化安装
    1. Nginx(安装、配置)
    2. MySQL(安装、配置)
    3. PHP(安装、配置)
  3. 菜单选择安装软件工具
    1. 选择安装的版本
    2. 选择安装的软件
    3. 选择安装的路径

实现

  • 简单版本
#!/bin/env bash

NGINX_V=1.22.1
PHP_V=7.4.32
MYSQL_V=5.7.44

TMP_DIR=/tmp

INSTALL_DIR=/usr/local

PWD_C=$PWD

echo
ehco -e '\tMenu\n'
echo -e '1. Install Nginx'
echo -e '2. Install PHP'
echo -e '3. Install MySQL (安装有些问题暂未解决)'
echo -e '4. Deploy LNMP'
echo -e '5. Quit'

function command_status_check(){
    if [ $? -ne 0 ]; then
        echo $1
        exit
    fi
}

function install_nginx(){
    cd $TMP_DIR
    yum -y install 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 -y install gcc gcc-c++ make gd-devel libxml2-devel \
        libcurl-devel libjpeg-devel libpng-devel openssl-devel \
        libmcrypt-devel libxslt-devel libtidy-devel sqlite-devel
    wget https://www.php.net/distributions/php-${PHP_V}.tar.gz --no-check-certificate
    tar zxf php-${PHP_V}.tar.gz
    cd php-${PHP_V}
    ./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 \
    --disable-mbregex --enable-hash
    command_status_check "PHP - 平台环境检测失败"
    make -j 4
    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
    cp $INSTALL_DIR/php/etc/php-fpm.d/www.conf.default $INSTALL_DIR/php/etc/php-fpm.d/www.conf
    chmod +x /etc/init.d/php-fpm
    /etc/init.d/php-fpm start
    command_status_check "PHP - 启动失败!"
}

function install_mysql(){
    cd $TMP_DIR
    yum -y install cmake openssl-devel \
        ncurses ncurses-devel bison gcc gcc-c++ make
    wget https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-boost-${MYSQL_V}.tar.gz
    tar zxf mysql-boost-${MYSQL_V}.tar.gz
    cd mysql-${MYSQL_V}
    mkdir -p $INSTALL_DIR/mysql/{etc,logs}
    cmake . \
    -DWITH_BOOST=boost/boost_1_59_0/ \
    -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR/mysql \
    -DSYSCONFDIR=$INSTALL_DIR/mysql/etc \
    -DMYSQL_DATADIR=$INSTALL_DIR/mysql/data \
    -DINSTALL_MANDIR=/usr/share/man \
    -DMYSQL_TCP_PORT=3306 \
    -DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
    -DDEFAULT_CHARSET=utf8 \
    -DEXTRA_CHARSETS=all \
    -DDEFAULT_COLLATION=utf8_general_ci \
    -DWITH_READLINE=1 \
    -DWITH_SSL=system \
    -DWITH_EMBEDDED_SERVER=1 \
    -DENABLED_LOCAL_INFILE=1 \
    -DWITH_INNOBASE_STORAGE_ENGINE=1
    command_status_check "MySQL - 平台环境检测失败"
    make -j 4
    command_status_check "MySQL - 编译失败!"
    make install
    command_status_check "MySQL - 安装失败!"
    cd $INSTALL_DIR/mysql
    useradd mysql
    chown -R mysql.mysql .
    ./bin/mysqld --initialize --user=mysql --basedir=$INSTALL_DIR/mysql --datadir=$INSTALL_DIR/mysql/data
    cat > $INSTALL_DIR/mysql/etc/my.cnf << EOF
    [client]
    port = 3306
    socket = /tmp/mysql.sock
    default-character-set = utf8
    
    [mysqld]
    port = 3306
    user = mysql
    basedir = /usr/local/mysql  //指定安装目录
    datadir = /usr/local/mysql/data  //指定数据存放目录
    socket = /tmp/mysql.sock
    character_set_server = utf8
    general_log_file = /usr/local/mysql/logs/mysql.log
EOF
    cd $INSTALL_DIR/mysql/
    ./bin/mysqld_safe --user=mysql &
    command_status_check "MySQL - 启动失败!"
}

read -p "请输入编号" number
case $number in
    1)
        install_nginx;;
    2)
        install_php;;
    3)
        install_mysql;;
    4)
        install_nginx
        install_php
        install_mysql;;
    5)
        exit;;
esac
  • 优化版本
#!/bin/env bash

function prompt_information(){
echo "=========================================="
echo -e "\t\t主菜单\n"
echo -e "选项:(1)安装Nginx(输入数字1)"
echo -e "选项:(2)安装MySQL(输入数字2)"
echo -e "选项:(3)安装MySQL(输入数字3)"
echo -e "选项:(4)部署LNMP(输入数字4)"
echo -e "选项:(5)检查LNMP(输入数字5)"
echo -e "选项:(6)退出脚本(输入quit)"
echo "=========================================="
}

function software_version_nginx(){
echo "=========================================="
echo -e "\t\tNginx版本信息\n"
echo -e "选项:(a)安装Nginx1.24.0(输入数字a)"
echo -e "选项:(b)安装Nginx1.22.1(输入数字b)"
echo -e "选项:(c)安装Nginx1.20.1(输入数字c)"
echo -e "选项:(d)退出脚本(输入quit)"
echo "=========================================="
}

function software_version_mysql(){
echo "=========================================="
echo -e "\t\tMySQL版本信息\n"
echo -e "选项:(a)安装MySQL8.0.35(输入数字a)"
echo -e "选项:(b)安装MySQL5.7.44(输入数字b)"
echo -e "选项:(c)安装MySQL5.6.51(输入数字c)"
echo -e "选项:(d)退出脚本(输入quit)"
echo "=========================================="
}

function software_version_php(){
echo "=========================================="
echo -e "\t\tPHP版本信息\n"
echo -e "选项:(a)安装PHP8.2.13(输入数字a)"
echo -e "选项:(b)安装PHP7.4.33(输入数字b)"
echo -e "选项:(c)安装PHP5.6.40(输入数字c)"
echo -e "选项:(d)退出脚本(输入quit)"
echo "=========================================="
}

function path_information(){
echo -e "是否指定软件安装路径,如未指定则默认安装路径为:/usr/local/"
read -p "请输入安装路径:" INSTALL_PATH
echo -e "您输入的安装路径为:$INSTALL_PATH"
read -p "输入“yes”确认,输入“no”终止安装:" CONFIRMATION_INFORMATION
}



MySQL相关

监控MySQL主从同步状态是否异常

  • 账号信息
cat > ./host_info.txt << EOF
#数据库地址				数据库用户		数据库密码
192.169.1.104     root        cmk521
EOF
  • 实现脚本
#!/bin/env bash

HOST_INFO=./host_info.txt
DB_HOST_IP=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)
DB_HOST_USER=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)
DB_HOST_PASSWD=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)

MYSQL_INFO=$(mysql -u$DB_HOST_USER -h$DB_HOST_IP -p$DB_HOST_PASSWD -e "show slave status\G")
SLAVE_IO=$(echo $MYSQL_INFO | awk -F'[: ]+' '/Slave_IO_Running:/{print $2}')
SLAVE_SQL=$(echo $MYSQL_INFO | awk -F'[: ]+' '/Slave_SQL_Running:/{print $2}')

if [[ $SLAVE_IO == "Yes" ]] && [[ $SLAVE_SQL == "Yes" ]]; then
	echo "MySQL主从同步连接正常"
else
	echo "MySQL主从同步检测失败"
fi

MySQL数据库备份

  • 账号信息
cat > ./host_info.txt << EOF
#数据库地址				数据库用户		数据库密码
192.169.1.104     root        cmk521
EOF
  • 实现脚本-分库备份
#!/bin/env bash

TIME_NOW=$(date +%F-%H-%S)
DATA_DIR=/data/backup

HOST_INFO=./host_info.txt
DB_HOST_IP=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)
DB_HOST_USER=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)
DB_HOST_PASSWD=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)

MYSQL_DB=$(mysql -u$DB_HOST_USER -h$DB_HOST_IP -p$DB_HOST_PASSWD -s -e "show databases;")
for DB_NAME in $MYSQL_DB; do
	if [[ $DB_NAME != "information_schema" ]] && [[ $DB_NAME != "mysql" ]] && [[ $DB_NAME != "sys" ]] && [[ $DB_NAME != "performance_shema" ]]; then
  	mysqldump -u$DB_HOST_USER -h$DB_HOST_IP -p$DB_HOST_PASSWD -B $DB_NAME > $DATA_DIR/$DB_NAME_$TIME_NOW.sql
    if [ $? -ne 0 ]; then
      echo "$DB_NAME 备份成功,正在打包..."
    	tar -cf $DATA_DIR/$DB_NAME_$TIME_NOW.sql.tgz $DATA_DIR/$DB_NAME_$TIME_NOW.sql
      if [ $? -ne 0 ]; then
        echo "$DB_NAME_$TIME_NOW.sql.tgz 打包成功!"
      else
        echo "$DB_NAME_$TIME_NOW.sql.tgz 打包失败!"
      fi
    else
      echo "$DB_NAME 备份失败!"
    fi
  fi
done

#sql文件保留3天
find $DATA_DIR -type f -mtime +3 -name *.sql -exec rm -f {} \;

#tgz文件保留7天
find $DATA_DIR -type f -mtime +7 -name *.tgz -exec rm -f {} \;
  • 实现脚本-分表备份
#!/bin/env bash

TIME_NOW=$(date +%F-%H-%S)
DATA_DIR=/data/backup

HOST_INFO=./host_info.txt
DB_HOST_IP=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)
DB_HOST_USER=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)
DB_HOST_PASSWD=$(awk -F' ' '!/^[#]/{print $1}' $HOST_INFO)

MYSQL_DB=$(mysql -u$DB_HOST_USER -h$DB_HOST_IP -p$DB_HOST_PASSWD -s -e "show databases;")
for DB_NAME in $MYSQL_DB; do
	if [[ $DB_NAME != "information_schema" ]] && [[ $DB_NAME != "mysql" ]] && [[ $DB_NAME != "sys" ]] && [[ $DB_NAME != "performance_shema" ]]; then
  	MYSQL_TABLE= $(mysql -u$DB_HOST_USER -h$DB_HOST_IP -p$DB_HOST_PASSWD -s -e "use $DB_NAME; show tables;")
    for TABLE_NAME in $MYSQL_TABLE; do
    	mysqldump -u$DB_HOST_USER -h$DB_HOST_IP -p$DB_HOST_PASSWD $DB_NAME.$TABLE_NAME > $DATA_DIR/$DB_NAME-$TABLE_NAME-$TIME_NOW.sql
      if [ $? -ne 0 ]; then
      	echo "$DB_NAME$MYSQL_TABLE 备份成功,正在打包..."
        tar -cf $DATA_DIR/$DB_NAME_$TIME_NOW.sql.tgz $DATA_DIR/$DB_NAME_$TIME_NOW.sql
        if [ $? -ne 0 ]; then
          echo "$DB_NAME_$TIME_NOW.sql.tgz 打包成功!"
        else
          echo "$DB_NAME_$TIME_NOW.sql.tgz 打包失败!"
        fi
      else
        echo "$DB_NAME 备份失败!"
      fi
    done
  fi
done

#sql文件保留3天
find $DATA_DIR -type f -mtime +3 -name *.sql -exec rm -f {} \;

#tgz文件保留7天
find $DATA_DIR -type f -mtime +7 -name *.tgz -exec rm -f {} \;

Nginx相关

Nginx访问日志分析

需求

  1. 访问最多的IP分析;
  2. 访问最多的页面分析;
  3. 访问页面状态码的数量;
  4. 访问时间段查看访问最多的IP;

思路

  1. 使用awk的数组,实现去重统计
    1. 格式:awk ‘{数组名称[索引值]}’
    2. awk ‘{number[$1]++}END{for}’

脚本实现

#!/bin/env bash

#日志格式:$remote_addr - $remote_usr [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"

LOG_FILE=$1

echo "统计访问最多的10个IP地址"
awk '{ADDRESS_LIST[$1]++}END{for(IP in ADDRESS_LIST){print ADDRESS_LIST[IP],IP}}' $LOG_FILE | sort -k2 -nr | head -10
echo "----------------------------------------------"

echo "统计某时间段内访问最多的IP"
START_TIME=[27/Nov/2023:10:00:00
STOP_TIME=[27/Nov/2023:11:00:00
awk '$4>="$START_TIME" && $4 <="$STOP_TIME"{ADDRESS_LIST[$1]++}END{for(IP in ADDRESS_LIST){print ADDRESS_LIST[IP],IP}}' $LOG_FILE | sort -k2 -nr | head -10
echo "----------------------------------------------"

echo "统计访问最多的10个页面"
awk '{PAGES_LIST[$7]++}END{for(PAGE in PAGES_LIST){print PAGES_LIST[PAGE],PAGE}}' $LOG_FILE | sort -k2 -nr | head -10
echo "----------------------------------------------"

echo "统计访问页面状态码数量"
awk '{PAGES_LIST[$7" " $9]++}END{for(PAGE in PAGES_LIST){print PAGES_LIST[PAGE],PAGE}}' $LOG_FILE | sort -k2 -nr | head -10
echo "----------------------------------------------"

Nginx访问日志自动按天切割

#!/bin/env bash

#指定原日志存放路径
LOG_DIR=/usr/local/nginx/logs
#指定Nginx的PID文件路径
PID_DIR=/var/run
#用于确定日志归档的日期
YESTERDAY_TIME=$(date -d "yesterday" +%F)
#每天的归档日志按照月份文件夹存储
LOG_MONTH_DIR=$LOG_DIR/$(date +"%Y-%m")
#指定要日志存放路径下要切割的文件名称列表
LOG_FILE_LIST="access.log error.log"

for LOG_FILE in $LOG_FILE_LIST; do
	[ ! -d $LOG_MONTH_DIR ] && mkdir -p $LOG_MONTH_DIR
  mv $LOG_DIR/$LOG_FILE $LOG_MONTH_DIR/${LOG_FILE}_${YESTERDAY_TIME}
done

kill -USR1 $(cat $PID_DIR/nginx.pid)
  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值