shell 最使用實戰(zhàn)整理

shell 實戰(zhàn)常用命令服務(wù)器系統(tǒng)一些配置初始化(centos7)
發(fā)送告警郵件
批量創(chuàng)建用戶
查看資源利用率
找出占用CPU/內(nèi)存過高的進程
查看網(wǎng)卡實時流量
監(jiān)控批量服務(wù)器磁盤利用率
--1.批量就需要免密登錄
--2.expec 免交互輸入密碼
檢測網(wǎng)站運行正常目錄文件變化和同步
mysql 備份監(jiān)控
MySQL 主從同步狀態(tài)
Nginx 訪問日志分析
自動屏蔽高訪問IP
LNMP環(huán)境搭建
python 調(diào)用shell 命令

服務(wù)器系統(tǒng)一些配置初始化(centos7)

> cat /proc/version
>
> Linux version 5.4.0-72-generic (buildd@lcy01-amd64-019) (gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)) #80-Ubuntu SMP Mon Apr 12 17:35:00 UTC 2021
>
> cat /etc/lsb-release
> DISTRIB_ID=Ubuntu
> DISTRIB_RELEASE=20.04
> DISTRIB_CODENAME=focal
> DISTRIB_DESCRIPTION="Ubuntu 20.04.2 LTS"
>
>  cat /etc/redhat-release
> CentOS Linux release 7.8.2003 (Core)
#/bin/bash

# 設(shè)置時區(qū)并同步時間
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 注意這種if 的寫法是可以的, 如果grep沒找到就返回Fasle虑凛, 還有可以用[] 做表達式
if ! crontab -l |grep ntpdate &>/dev/null ; then
    # 同步時間 ntpdate time.windows.com
    # () 內(nèi)作為一組去執(zhí)行
    # |crontab 可以將前面的輸入寫到文件中
    # crontab -l 可以把前面的命令以新增的方式寫入crontab, 不加他會覆蓋所有之前的crontab
    (echo "* 1 * * * ntpdate time.windows.com >/dev/null 2>&1";crontab -l) |crontab 
fi

# 禁用selinux, 不關(guān)閉可能會因為莫名其妙的權(quán)限問題導(dǎo)致服務(wù)不通
# 這里匹配到SELINUX 這一行锣披, 然后s/before/after 去替換雹仿, 和vim 里的:%s/before/after/g 一樣
sed -i '/SELINUX/{s/permissive/disabled/}' /etc/selinux/config

# 關(guān)閉防火墻
# egrep 后面接正則匹配胧辽, 匹配到就為True
# centos 7 用firewall 替代 iptables
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

# 歷史命令顯示操作時間, 只要設(shè)置這個系統(tǒng)變量HISTTIMEFORMAT 即可, %F日期奠骄, %T時間
# >> 增量寫入
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

# 禁止定時任務(wù)向發(fā)送郵件
# 如果定時任務(wù)沒有加到重定向為空  >/dev/null 2>&1, 它的標準輸出蝉绷、錯誤都會向當前用戶發(fā)送一封郵件辆床, 存到 /var/mail/
# mailto為空就不會發(fā)送
# s/before/after/  替換
sed -i 's/^MAILTO=root/MAILTO=""/' /etc/crontab 

# 設(shè)置最大打開文件數(shù)讼载, 默認是1024咨堤, 并發(fā)數(shù)高的時候很容易達到
# 將 soft hard 兩行內(nèi)容追加到 limits.conf中(*前面的空格也會寫進去)
# EOF 要頂?shù)筋^一喘, 否則會出錯
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
fi

# 系統(tǒng)內(nèi)核優(yōu)化
cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 20480
net.ipv4.tcp_max_syn_backlog = 20480  # 默認是128
net.core.netdev_max_backlog = 262144  # 網(wǎng)卡最大的隊列長度
net.ipv4.tcp_fin_timeout = 20         # 四次揮手斷開的一個超時時間
EOF

# 減少SWAP使用, 設(shè)置的是一個權(quán)重值闷沥, 值越大蚂维, 使用swap 的可能性越大,0 不使用
# swap 比物理內(nèi)存要慢很多览祖, 但是也不要關(guān)閉他
echo "0" > /proc/sys/vm/swappiness

# 安裝系統(tǒng)性能分析工具及其他
yum install gcc make autoconf vim sysstat net-tools iostat iftop iotp lrzsz -y

dos2unix

有時候 windows 編輯的shell 文件在linux 中可能有格式展蒂、語法錯誤
用dos2unix  轉(zhuǎn)一下
yum install dos2unix -y
dos2unix shell_file.sh

發(fā)送告警郵件

系統(tǒng)默認發(fā)送郵件锰悼,用sendmail , 顯示默認的發(fā)送人是主機名(會被當做垃圾郵件) 而且有延遲

所有丝里, 用外部郵箱服務(wù)器杯聚, 例如 163 (需要在郵箱設(shè)置中開啟 SMTP)

yum install mailx -y

# yum install mailx
# vi /etc/mail.rc  
set from=test@163.com smtp=smtp.163.com
set smtp-auth-user=test@163.com smtp-auth-password=123456
set smtp-auth=login

測試

echo "this is a test content" | mail -s "subject name" test@163.com

批量創(chuàng)建用戶

addusers.txt

user1 pwd1
user2 pwd2
#颁褂!/bin/bash

USERS_FILE=addusers.txt
USERADD=/usr/sbin/useradd
PASSWD=/usr/bin/passwd

# 循環(huán)讀文件
while read line
do
    # cut 通過 空格分隔, -f1 第一個
    USERNAME=`echo $line | cut -f1 -d ' '` 
    PASSWORD=`echo $line | cut -f2 -d ' '`
    $USERADD $USERNAME
    # $? 上一條命令的返回值, 0是 true, ne: not equal
    if [[ $? ne 0 ]]; then
        echo "$USERNAME has exited;skip set passwd"
    else
        echo "$PASSWORD | $PASSWD --stdin $USERNAME"
    fi
done <$USERS_FILE

if [ 1 -ne 1 ];then
...
fi
    -eq:等于
    -ne:不等于
    -le:小于等于
    -ge:大于等于
    -lt:小于
    -gt:大于
    
    
[root@VM-0-15-centos ~]# passwd --help
Usage: passwd [OPTION...] <accountName>
  -x, --maximum=DAYS      maximum password lifetime (root only)
  -n, --minimum=DAYS      minimum password lifetime (root only)
  -w, --warning=DAYS      number of days warning users receives before password expiration (root only)
  -i, --inactive=DAYS     number of days after password expiration when an account becomes disabled (root only)
  -S, --status            report password status on the named account (root only)
  --stdin                 read new tokens from stdin (root only)

升級版

#!/bin/bash
# 1.隨機密碼
# 2.用戶是否已經(jīng)存在

# 會接收所有的位置參數(shù)
USER_LIST=$@
USER_FILE=user.txt
for USER in $USER_LIST; do
    # 通過id 查看用戶是否存在
    if ! id $USER &>/dev/null; then
        # cut -c 
        PASS=$(echo $RANDOM |md5sum |cut -c 1-8)
        useradd $USER
        echo $PASS |passwd --stdin $USER &>/dev/null
        # 增量記錄到文件
        echo "$USER   $PASS" >> $USER_FILE
        echo "$USER User create successful."
    else
        echo "$USER User already exists!"
    fi
done

重點

[root@VM-0-15-centos ~]# id root
uid=0(root) gid=0(root) groups=0(root)
[root@VM-0-15-centos ~]# id ken
id: ken: no such user

# 生成隨機值, 然后取他的 md5
[root@VM-0-15-centos ~]# echo $RANDOM
18466
[root@VM-0-15-centos ~]# echo $RANDOM|md5sum
7841fac0faa769963c0ade1107ff3e80  -


[root@VM-0-15-centos ~]# echo "12345678" | cut -c 1-5
12345


# cut -d 通過空格分隔(其他分隔符也可以) 
# cut -c 截取字符
# -f1 取分隔后的第一個
cut -f1 -d ' '


[root@VM-0-15-centos ~]# echo {1..10}
1 2 3 4 5 6 7 8 9 10

grep

# 在當前目錄所有文件查詢關(guān)鍵字 modified
grep "modified" *

# 查看關(guān)鍵字前后10行
cat file_name.txt | grep "something" -C 10 

# 監(jiān)聽本機網(wǎng)卡 eth0 端口8299 的請求丰捷, 然后查看 User-Agent 前后10行
tcpdump -i eth0 -A  port 8299 |grep 'User-Agent' -C 10

grep 關(guān)鍵字 -A 10 查看關(guān)鍵字后10行
           -B 10 查看關(guān)鍵字前10行

查看資源利用率

1.cpu 60%

2.內(nèi)存 利用率

3.硬盤 利用率

4.TCP 連接狀態(tài) (查看并發(fā)情況)

可通過top 查看使用情況, 也可以使用vmstat

wa 表示I/O wait CPU等待磁盤相應(yīng)占用cpu 的百分比停巷, 如果到了3%~5% 當前機器讀寫就會很慢

[root@VM-0-15-centos ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 4  0      0 618712  45888 189752    0    0    13    25  187  404  1  0 99  0  0
netstat    
            -a all
            -t tcp
            -n numbric
            -p pid/name

ESTABLISHED  說明正在建立通信畔勤, 相當于并發(fā), 反應(yīng)這臺機器的網(wǎng)絡(luò)連接承載量
SYN_SENT        建立三次握手期間的狀態(tài)缸榛, 還沒正式建立完握手開始通信
LISTEN          本地監(jiān)聽的服務(wù)
[root@VM-0-15-centos ~]# netstat -atnp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      980/sshd
tcp        0     28 10.206.0.15:22          218.82.138.5:62795      ESTABLISHED 31974/sshd: root@pt
tcp        0      0 10.206.0.15:42786       169.254.0.55:5574       ESTABLISHED 1802/YDService
#!/bin/bash

function cpu() {
    NUM=1
    while [ $NUM -le 3 ]; do
        util=`vmstat |awk '{if(NR==3)print 100-$15"%"}'`
        user=`vmstat |awk '{if(NR==3)print $13"%"}'`
        sys=`vmstat |awk '{if(NR==3)print $14"%"}'`
        iowait=`vmstat |awk '{if(NR==3)print $16"%"}'`
        echo "CPU - 使用率: $util , 等待磁盤IO響應(yīng)使用率: $iowait"
        let NUM++
        sleep 1
    done
}

function memory() {
    # printf 格式化輸出 "%.1f" 保留一個小數(shù)點 后面要加逗號
    total=`free -m |awk '{if(NR==2)printf "%.1f",$2/1024}'`
    # $NF 表示最后一列
    used=`free -m |awk '{if(NR==2) printf "%.1f",($2-$NF)/1024}'`
    available=`free -m |awk '{if(NR==2) printf "%.1f",$NF/1024}'`
    echo "內(nèi)存 - 總大小: ${total}G , 使用: ${used}G , 剩余: ${available}G"
}

function disk() {
    # awk '/^\/dev/{print $1}' 先匹配在輸出敦腔, 匹配/dev開頭的 然后/需要\轉(zhuǎn)義
    fs=$(df -h |awk '/^\/dev/{print $1}')
    for p in $fs; do
        mounted=$(df -h |awk '$1=="'$p'"{print $NF}')
        size=$(df -h |awk '$1=="'$p'"{print $2}')
        used=$(df -h |awk '$1=="'$p'"{print $3}')
        
        used_percent=$(df -h |awk '$1=="'$p'"{print $5}')
        echo "硬盤 - 掛載點: $mounted , 總大小: $size , 使用: $used , 使用率: $used_percent"
    done
}

function tcp_status() {
    # awk [$6]++ 會把第六列的值作為key筒捺, 個數(shù)作為value系吭, 遇到一個就+1颗品, 然后++遍歷完所有的
    summary=(netstat -tanp |awk '{status[$6]++}END{for(i in status)printf i":"status[i]" "}')
    echo "TCP連接狀態(tài) - $summary"
}

# 調(diào)用函數(shù)
cpu
memory
disk
tcp_status

重點

awk
awk 的處理和數(shù)據(jù)庫比較類似
    列   $2 第二列
    行   NR==2  第二行
# 打印文件第二行第二列
cat users.txt | awk '{if (NR==2) print  $2}'

找出占用CPU/內(nèi)存過高的進程

ps

    -O format
        Like -o, but preloaded with some default columns.  Identical to -o                       pid,format,state,tname,time,command or -o pid,format,tname,time,cmd, see -o below.
   -e 
              

user 用戶名
uid 用戶號
pid 進程號
ppid 父進程號
size 內(nèi)存大小, Kbytes字節(jié).
vsize 總虛擬內(nèi)存大小, bytes字節(jié)(包含code+data+stack)
share 總共享頁數(shù)
nice 進程優(yōu)先級(缺省為0, 最大為-20)
priority(pri) 內(nèi)核調(diào)度優(yōu)先級
pmem 進程分享的物理內(nèi)存數(shù)的百分比
trs 程序執(zhí)行代碼駐留大小
rss 進程使用的總物理內(nèi)存數(shù), Kbytes字節(jié)
time 進程執(zhí)行起到現(xiàn)在總的CPU暫用時間
stat 進程狀態(tài)
cmd(args) 執(zhí)行命令的簡單格式

#!/bin/bash
echo "---------------- cpu top 10 ----------------------"
ps -eo user,pid,pcpu,pmem,args --sort=-pcpu  |head -n 10
echo "---------------- memory top 10 -------------------"
ps -eo user,pid,pcpu,pmem,args --sort=-pmem  |head -n 10

查看網(wǎng)卡實時流量

查看網(wǎng)卡有2個地方 , 可以看到從開機到現(xiàn)在收到和發(fā)出的流量

ifconfig

cat /proc/net/dev

?  cat /proc/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
  eth0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
  eth1:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0
#!/bin/bash
# 網(wǎng)卡名通過位置傳參, 因為每個機器網(wǎng)卡名可能不同
NIC=$1
echo -e " In ------ Out"
while true; do
    # $0~ 一整行 包含網(wǎng)卡名 $NIC, 下面還有一直用寫法躯枢, 上面用過
    OLD_IN=$(awk '$0~"'$NIC'"{print $2}' /proc/net/dev)
    # OLD_IN=$(cat /proc/net/dev | awk '/$NIC/{print $2}')
    OLD_OUT=$(awk '$0~"'$NIC'"{print $10}' /proc/net/dev)
    sleep 1
    NEW_IN=$(awk  '$0~"'$NIC'"{print $2}' /proc/net/dev)
    NEW_OUT=$(awk '$0~"'$NIC'"{print $10}' /proc/net/dev)
    # 開始計算和前一秒的差值
    # "%.1f%s"  保留一個小數(shù)點则吟, %s 是后面的值
    # (( ))  雙括號是計算
    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


監(jiān)控批量服務(wù)器磁盤利用率

前置知識

1.批量就需要免密登錄

# 1. 密鑰
ssh-keygen -t rsa

# this user must have sudo permission
ssh-copy-id -i ~/.ssh/id_rsa.pub username@192.168.91.135 

# 2.another way: 2 steps
$ scp ~/.ssh/id_rsa.pub root@<remote_ip>:pub_key //將文件拷貝至遠程服務(wù)器
$ cat ~/pub_key >>~/.ssh/authorized_keys //將內(nèi)容追加到authorized_keys文件中, 不過要登錄遠程服務(wù)器來執(zhí)行這條命令

3.將本地id_rsa.pub文件的內(nèi)容拷貝至遠程服務(wù)器的~/.ssh/authorized_keys文件中

然后 就可以免密碼登錄了
ssh -i .ssh/id_rsa username@192.168.91.135 
2.expec 免交互輸入密碼
# ssh 后面接命令就可以直接拿到執(zhí)行返回結(jié)果
ssh username@192.168.91.135 'df -h'
#!/bin/bash
HOST_INFO=host.info
# ^[^#] 去掉#開頭的
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)
    TMP_FILE=/tmp/disk.tmp
    ssh -p $PORT $USER@$IP 'df -h' > $TMP_FILE
    # int() 取整锄蹂,去掉20% 中的%
    USE_RATE_LIST=$(awk 'BEGIN{OFS="="}/^\/dev/{print $NF,int($5)}' $TMP_FILE)
    for USE_RATE in $USE_RATE_LIST; do
        PART_NAME=${USE_RATE%=*}
        USE_RATE=${USE_RATE#*=}
        if [ $USE_RATE -ge 80 ]; then
            echo "Warning: $PART_NAME Partition usage $USE_RATE%!"
        fi
    done
done


expect

#!/bin/bash
# 這里用 $* 因為要把bash 1.sh df -h sh后面的命令df -h作為一個整體
COMMAND=$*
HOST_INFO=host.info
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 {
       # \r 換行
          \"(yes/no)\" {send \"yes\r\"; exp_continue}
          \"password:\" {send \"$PASS\r\"; exp_continue}
          \"$USER@*\" {send \"$COMMAND\r exit\r\"; exp_continue}
       }
    "
    echo "-------------------"
done
也可以通過
#氓仲!/bin/bash

USERS_FILE=host.info

# 循環(huán)讀文件
while read line
do
HOST=`echo $line | cut -f1 -d ' '`
USER=`echo $line | cut -f2 -d ' '`
PORT=`echo $line | cut -f3 -d ' '`

echo "$HOST, $USER, $PORT"
done <$USERS_FILE

或者可以通過ansible 批量管理

檢測網(wǎng)站運行正常

#!/bin/bash  
URL_LIST="www.baidu.com www.jd.com"
for URL in $URL_LIST; do
    FAIL_COUNT=0
    for ((i=1;i<=3;i++)); do
        # curl -o  output FILE
        #      -s silent 不輸出任何內(nèi)容
        #      -w 輸出指定格式的內(nèi)容到標準輸出
        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
            echo "$URL retry $FAIL_COUNT"
            # FAIL_COUNT 加一
            let FAIL_COUNT++
        fi
    done
    if [ $FAIL_COUNT -eq 3 ]; then
        echo "Warning: $URL Access failure!"
    fi
done

目錄文件變化和同步

一些病毒(挖礦)會入侵系統(tǒng)后, 新建上傳文件得糜, 執(zhí)行腳本

/usr/bin

/wwwroot 串改, 注入

#!/bin/bash

# 需要先裝工具 yum install inotify-tools -y
# 這個工具可以監(jiān)控目錄下文件的增刪改
# -mrq 持續(xù)監(jiān)聽, 遞歸形式, 減少冗余信息輸出
# -e 監(jiān)聽的事件, 增刪改查等
MON_DIR=/opt
inotifywait -mqr --format %f -e create $MON_DIR |\
while read files; do
    # rsync 可以將2個目錄同步
   rsync -avz /opt /tmp/opt
   #echo "$(date +'%F %T') create $files" | mail -s "dir monitor" xxx@163.com
done

后臺運行

nohub bash monitor.sh &>/dev/null &

mysql 備份

備份庫

mysqldump -hxxx -uroot -pxxx -B DB_name > DB.sql

備份表

mysqldump -hxxx -uroot -pxxx DB_name table_name > table.sql

#!/bin/bash
# 時間格式
DATE=$(date +%F_%H-%M-%S)
HOST=localhost
# 備份就用一個最小權(quán)限的用戶 只能查看要備份的那部分捉超, 只讀
USER=backup
PASS=123.com
BACKUP_DIR=/data/db_backup
# egrep -v 過濾掉包含這些資源的行
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
    # -B 指定庫
    if ! mysqldump -h$HOST -u$USER -p$PASS -B $DB > $BACKUP_NAME 2>/dev/null; then
        echo "$BACKUP_NAME 備份失敗!"
    fi
done


# 分表備份
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
done

監(jiān)控MySQL 主從同步狀態(tài)

mysql -h$HOST -u$USER -p$PASSWD -e 'show slave status\G' 2>/dev/null |awk '/Slave_.*_Running:/{print $1$2}'

Slave_IO_Running: Connecting
Slave_SQL_Running: Yes
#!/bin/bash  
HOST=localhost
USER=root
PASSWD=123.com
IO_SQL_STATUS=$(mysql -h$HOST -u$USER -p$PASSWD -e 'show slave status\G' 2>/dev/null |awk '/Slave_.*_Running:/{print $1$2}')
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!" |mail -s "Master-Slave Staus" xxx@163.com
    fi
done

Nginx 訪問日志分析

#!/bin/bash
# 日志格式: $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"
LOG_FILE=$1
echo "統(tǒng)計訪問最多的10個IP"
# awk $1 第一個字段ip, 做count 統(tǒng)計, 然后排序
# sort -k2 按照第二列排序
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 "統(tǒng)計時間段訪問最多的IP"
# awk 中可以直接對時間進行比較穿香,分析某個時間段的日志
awk '$4>="[01/Dec/2018:13:20:25" && $4<="[27/Nov/2018:16:20:49"{a[$1]++}END{for(v in a)print v,a[v]}' $LOG_FILE |sort -k2 -nr|head -10
echo "----------------------"

echo "統(tǒng)計訪問最多的10個頁面"
# length(a) 去重后列表內(nèi)元素個數(shù)
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 "----------------------"

echo "統(tǒng)計訪問頁面狀態(tài)碼數(shù)量"
awk '{a[$7" "$9]++}END{for(v in a){if(a[v]>5)print v,a[v]}}' $LOG_FILE |sort -k3 -nr

自動屏蔽高訪問IP

這里是監(jiān)控nginx 訪問日志

#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
LOG_FILE=/usr/local/nginx/logs/demo2.access.log
# 訪問最后5000 條日志购公, 過濾ip出現(xiàn)10次以上的
ABNORMAL_IP=$(tail -n5000 $LOG_FILE |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>100)print i}')
for IP in $ABNORMAL_IP; do
    if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
        # 通過iptables 
        iptables -I INPUT -s $IP -j DROP
        echo "$(date +'%F_%T') $IP" >> /tmp/drop_ip.log
    fi
done

同樣 ssh 防暴力破解 也可以通過這種方式來屏蔽

/var/log/audit/audit.log 是系統(tǒng)審計日志较坛, 可以通過這個日志來統(tǒng)計

LNMP環(huán)境搭建

#!/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\n"
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
    # openssl-devel https
    # pcre-devel nginx 正則支持
    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
    # $1 相當于傳參
    command_status_check "Nginx - 平臺環(huán)境檢查失敗薛躬!"
    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}
    ./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 - 平臺環(huán)境檢查失斦晗场!"
    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
    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

bash -x test.sh 可以查看shell的執(zhí)行過程

#/bin/bash
echo $0(代表命令本身);
echo $1; (代表第幾個參數(shù))
echo $2;
 
[root@LocalWeb01 ~]# ./1.sh 2 3
./1.sh
2
3

$#代表參數(shù)個數(shù) 
$* 代表命令行的 所有參數(shù)代表一個整體
$@ 代表命令行的 所有參數(shù)代表一個整體缠黍,不過把每個參數(shù)區(qū)分對待
 
$? 上條命令執(zhí)行是否成功 0是成功
$$ 當前運行的進程號
$! 后臺運行的最后一條的進程號

python 調(diào)用shell 命令

import subprocess
return_code, res = subprocess.getstatusoutput('pwd')
print(return_code, res)

遇到比較復(fù)雜的shell 腳本惋砂, 也可以用python 處理源文件

然后生成shell 腳本镶苞, 執(zhí)行腳本

或者直接調(diào)用shell 命令

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市仑性,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巩剖,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異语稠,居然都是意外死亡莱坎,警方通過查閱死者的電腦和手機兑巾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門蒋歌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人委煤,你說我怎么就攤上這事堂油。” “怎么了碧绞?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵府框,是天一觀的道長。 經(jīng)常有香客問我讥邻,道長迫靖,這世上最難降的妖魔是什么院峡? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮系宜,結(jié)果婚禮上照激,老公的妹妹穿的比我還像新娘。我一直安慰自己盹牧,他們只是感情好俩垃,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著汰寓,像睡著了一般口柳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上踩寇,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天啄清,我揣著相機與錄音六水,去河邊找鬼俺孙。 笑死,一個胖子當著我的面吹牛掷贾,可吹牛的內(nèi)容都是我干的睛榄。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼想帅,長吁一口氣:“原來是場噩夢啊……” “哼场靴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起港准,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤旨剥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后浅缸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體轨帜,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年衩椒,在試婚紗的時候發(fā)現(xiàn)自己被綠了蚌父。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毛萌。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖膏秫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情做盅,我是刑警寧澤荔睹,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站宵距,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏吨拗。R本人自食惡果不足惜满哪,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望劝篷。 院中可真熱鬧娇妓,春花似錦、人聲如沸哈恰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荠医。三九已至,卻和暖如春彬向,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遍希。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工缕棵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留招驴,地道東北人。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓虱饿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親氮发。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容