搬砖 Shell 脚本整理

✨ 这是一篇关于Shell脚本的整理文章,其中包括了一些实用的Shell脚本和命令组合,以及它们的用法和作用说明。文章内容涵盖了删除备份文件、批量重命名文件、变量替换、去除换行符、统计匹配行数、分析Nginx日志、DDoS攻击防范、解压缩脚本、Git修改历史commit信息、以及一些网络连接和Docker容器日志的清空操作。

此处整理收集一些会用到的 Shell 脚本/命令组合,方便查阅

  • 删除n天前的备份文件
# 删除7天前备份文件!
find ${dir_path:=/data/back_data/} -name '*.tar.gz' -type f -mtime +7 |xargs rm -rf
  • 批量重命名文件
# 去除所有文件名中lalala
for fname in $(ls *lalala.jpg); do
    mv $fname $(echo ${fname//lalala/})
done
此处使用了 Shell 中的变量替换,详细可参见http://cn.linux.vbird.org/linux_basic/0320bash_2.php#variable_other

主要为如下内容:

变量形式作用说明
${变量#关键词} ${变量##关键词}若变量内容从头开始的数据符合『关键词』,则将符合的最短数据删除 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据删除
${变量%关键词} ${变量 %% 关键词}若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据删除 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据删除
${变量/旧字符串/新字符串} ${变量//旧字符串/新字符串}若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串取代』 若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串取代』

  • 去除换行符
sed -i ':a;N;$!ba;s/\n/ /g'
  • 统计匹配行数
ps -ef | grep java | wc -l
# 或者 grep -c
ps -ef | grep -c java
  • 分析 Nginx 日志,统计同一IP访问次数并排序
# 使用`awk`命令对输入的每一行进行处理。`{d[$1]++}`表示以每行的第一个字段(IP地址)作为索引,将该字段的值作为数组`d`的键,并将该键对应的值加1。`END {for (i in d) print d[i],i}`表示在处理完所有行后,遍历数组`d`中的键值对,并按照格式输出键值对,即IP地址和出现次数。

cat access.log | awk '{d[$1]++} END {for (i in d) print d[i],i}' | sort -nr | head
#!/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 "统计访问最多的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<="[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 "统计访问最多的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 "----------------------"

echo "统计访问页面状态码数量"
awk '{a[$7" "$9]++}END{for(v in a){if(a[v]>5)print v,a[v]}}'
  • DDoS 攻击防范(自动封禁IP)
#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
LOG_FILE=/usr/local/nginx/logs/test.access.log
ABNORMAL_IP=$(tail -n5000 $LOG_FILE |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>10)print i}')
for IP in $ABNORMAL_IP; do
    if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
        iptables -I INPUT -s $IP -j DROP
        echo "$(date +'%F_%T') $IP" >> /tmp/drop_ip.log
    fi
done
  • ssh_config 配置
Host *
	  StrictHostKeyChecking no
    UserKnownHostsFile=/dev/null
    ForwardAgent yes
    ServerAliveInterval 10
    ServerAliveCountMax 10000
    TCPKeepAlive no
    ControlMaster auto
    ControlPath ~/.ssh/session/%h-%p-%r
    ControlPersist 12h

Host server
    Hostname 192.168.0.1
    Port 22
    User root
    IdentityFile ~/.ssh/id_rsa
  • 解压缩脚本
#!/bin/bash
# function Extract for common file formats

function extract {
 if [ -z "$1" ]; then
    # display usage if no parameters given
    echo "Usage: extract <path/file_name>.<zip|rar|bz2|gz|tar|tbz2|tgz|Z|7z|xz|ex|tar.bz2|tar.gz|tar.xz>"
 else
    if [ -f "$1" ] ; then
        NAME=${1%.*}
        #mkdir $NAME && cd $NAME
        case "$1" in
          *.tar.bz2)   tar xvjf ./"$1"    ;;
          *.tar.gz)    tar xvzf ./"$1"    ;;
          *.tar.xz)    tar xvJf ./"$1"    ;;
          *.lzma)      unlzma ./"$1"      ;;
          *.bz2)       bunzip2 ./"$1"     ;;
          *.rar)       unrar x -ad ./"$1" ;;
          *.gz)        gunzip ./"$1"      ;;
          *.tar)       tar xvf ./"$1"     ;;
          *.tbz2)      tar xvjf ./"$1"    ;;
          *.tgz)       tar xvzf ./"$1"    ;;
          *.zip)       unzip ./"$1"       ;;
          *.Z)         uncompress ./"$1"  ;;
          *.7z)        7z x ./"$1"        ;;
          *.xz)        unxz ./"$1"        ;;
          *.exe)       cabextract ./"$1"  ;;
          *)           echo "extract: '$1' - unknown archive method" ;;
        esac
    else
        echo "'$1' - file does not exist"
    fi
fi
}
  • Git 修改历史commit信息
git filter-branch --commit-filter '
    if [ "$GIT_COMMITTER_EMAIL" = "a@example.com" ];
    then
            GIT_COMMITTER_NAME="Test";
            GIT_AUTHOR_NAME="Test";

            GIT_COMMITTER_EMAIL="b@example.com";
            GIT_AUTHOR_EMAIL="b@example.com";

            git commit-tree "$@";
    else
            git commit-tree "$@";
    fi' 
HEAD
  • 查找请求数前20个IP(请求来源):
netstat -anlp|grep 80|grep tcp|awk '{print $5}'|awk -F: '{print $1}'|sort|uniq -c|sort -nr|head -n20

netstat -ant |awk '/:80/{split($5,ip,”:”);++A[ip[1]]}END{for(i in A) print A[i],i}' |sort -rn|head -n20
  • 查找较多time_wait连接
netstat -n|grep TIME_WAIT|awk '{print $5}'|sort|uniq -c|sort -rn|head -n20
  • 找查较多的SYN连接
netstat -an | grep SYN | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr | more
  • 根据端口列进程
netstat -ntlp | grep 80 | awk '{print $7}' | cut -d/ -f1
  • 清空 Docker 容器日志
#!/bin/bash 
# 治标  
logs=$(find /var/lib/docker/containers/ -name *-json.log)  
  
for log in $logs  
        do  
                echo "clean logs : $log"  
                cat /dev/null > $log  
        done  
  • 查看占用内存最高的进程 — topmem
alias topmem='ps aux --sort=-%mem | awk '\\''NR==1 {printf "%-10s %-6s %s %s %s\\n", $2, $4, "MEM", $11, $12; next} {printf "%-10s %-6s %.2fMB %s %s\\n", $2, $4, $6/1024, $11, substr($12,1,20)}'\\'' | head -n 30'