【04-Shell 脚本】

【04-Shell 脚本】

批量有序重命名脚本

batch_rename() { local extension=$1 local prefix=$2 counter=1 for file in *."$extension"; do if [ -f "$file" ]; then mv "$file" "${prefix}_${counter}.${extension}" ((counter++)) fi done }

查找大文件

# 函数:查找指定目录下超过指定大小的文件,从大到小排序展示 # 使用方式: # find_large_files 默认查找当前目录大于1000M的文件 # find_large_files 200M 查找当前目录大于200M的文件 # find_large_files 1G /var 查找/var目录大于1G的文件 find_large_files(){ # 第一个参数:文件大小阈值,不传默认 1000M local size=${1:-1000M} # 第二个参数:搜索路径,不传默认当前目录 . local path=${2:-.} # 查找大于指定大小的普通文件,列出大小+路径,按容量倒序 find "$path" -type f -size +$size -exec ls -lh {} + | awk '{print $5 " " $9}' | sort -hr } # 程序入口:调用函数,查找当前目录大于 200M 的文件 find_large_files "$1" "$2"
  • ${1:-1000M}:参数默认值语法

    • 调用传了第一个参数 →size=$1

    • 不传参 → size 默认1000M(1GB)

  • -exec ls -lh {}+ :对每个找到的文件执行ls -lh,友好展示文件大小 :

    [root@iZbp18z01qkdujbrt0t8peZ docs]# find -name "*.jpg" -exec ls -l {} + -rw-r--r-- 1 root root 0 Jun 26 17:54 ./image_1.jpg -rw-r--r-- 1 root root 0 Jun 26 17:54 ./image_2.jpg -rw-r--r-- 1 root root 0 Jun 26 17:54 ./image_3.jpg -rw-r--r-- 1 root root 0 Jun 26 17:54 ./image_4.jpg
  • awk '{print $5 " " $9}'只保留第五列和第九列,精简输出。

文件权限批量修改

fix_permissions() { local dir=$1 find "$dir" -type d -exec chmod 755 {} + find "$dir" -type f -exec chmod 644 {} + find "$dir" -name "*.sh" -exec chmod +x {} + }

进程监控

# 函数:监控指定进程内存,超限告警 # 使用格式:monitor_process 进程名 [内存阈值KB] [检测间隔秒] monitor_process() { local process_name="$1" local max_memory="${2:-1000000}" # 默认阈值:1000000KB ≈ 976MB local check_interval="${3:-60}" # 默认检测间隔:60秒 # 参数合法性校验:阈值、间隔必须为纯数字 if ! [[ "$max_memory" =~ ^[0-9]+$ && "$check_interval" =~ ^[0-9]+$ ]]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] 参数错误:内存阈值、检测间隔必须为正整数" return 1 fi # 死循环持续巡检 while true; do # 获取所有匹配进程PID pids=$(pgrep "$process_name") # 进程不存在逻辑 if [[ -z "$pids" ]]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] 警告:进程【$process_name】当前未运行" sleep "${check_interval}" continue fi # 遍历所有PID,逐个检测内存 echo "${pids}" | while read -r pid; do [[ -z "${pid}" ]] && continue # 获取进程RSS物理内存,清除空格 memory=$(ps -o rss= -p "${pid}" | tr -d ' ') [[ -z "${memory}" ]] && continue # 内存超限判断 if (( memory > max_memory )); then mem_mb=$(( memory / 1024 )) max_mb=$(( max_memory / 1024 )) echo "=====================================================" echo "[$(date '+%Y-%m-%d %H:%M:%S')] 内存超限告警" echo "进程名称:${process_name} | PID:${pid}" echo "当前内存:${memory} KB (${mem_mb} MB)" echo "设定阈值:${max_memory} KB (${max_mb} MB)" echo "=====================================================" # 如需超限自动杀进程,取消下面两行注释 # kill "${pid}" # sleep 1 && kill -9 "${pid}" 2>/dev/null && echo "已强制终止超限PID: ${pid}" fi done sleep "${check_interval}" done } # ==================== 程序入口 ==================== # 判断是否传入进程名参数,无参数打印帮助 if [[ $# -lt 1 ]]; then echo "使用方法:" echo " $0 进程名 [内存阈值(KB)] [检测间隔(秒)]" echo "示例1:监控docker,默认阈值1000000KB,60秒检测一次" echo " $0 docker" echo "示例2:监控dockerd,阈值1500000KB,每30秒检测" echo " $0 dockerd 1500000 30" exit 1 fi # 启动监控 monitor_process "$1" "$2" "$3"
  • "KaTeX parse error: Expected group as argument to '\~' at position 17: …ax\_memory" =\~ ̲^\[0\-9\]\+: 先看 =~ 在bash中该运算符是正则表达运算符匹配成功为0(真) 匹配失败为非0 (假);^[0-9]+$
📣扩展
1️⃣锚点
2️⃣字符集(方括号[]
3️⃣量词(控制前面字符出现次数,x 代表任意字符 / 字符集)
4️⃣分组()与或|
5️⃣正则转义字符

.匹配任意单个字符\.小数点必须反斜杠转义,否则不是小数点。

6️⃣Bash[[ ]] =~正则匹配避坑对照表

服务状态查询

*# 服务状态检查* check_service() { local service=$1 **if **systemctl is-active --quiet "$service"; **then **** **echo "✅ $service is running"**return **0 **else **** **echo "❌ $service is not running"**return **1 **fi**}*# 批量服务检查* check_services() { local services=("nginx" "mysql" "redis" "docker") **for **service **in** "**${**services[@]**}**"; **do **** **check_service "$service" **done** }
  • systemctl is-active 服务名 --quiet :静默模式,只返回状态码。

服务正在运行 → 输出active,命令退出码0

停止 / 异常 / 不存在 → 输出inactive / failed,退出码非 0

📃 文本处理-三剑客之AWK

核心概念:

awk 默认按照空格/制表符进行分隔。

NR:表示当前行,NR>1跳过表头。

-F:指定自定义字符分隔符。

sub/gsub: 字符串替换(gsub全局替换)

#!/bin/bash # AWK 基础用法 awk_examples() { # 打印特定列 ps aux | awk '{print $1, $11}' # 条件过滤 awk '$3 > 1.0 {print $1, $3}' /proc/loadavg # 计算统计 df -h | awk 'NR>1{sub(/%/,"",$5);v=$5+0;if(v>5)print v}' # 字段分隔符 awk -F: '{print $1, $3}' /etc/passwd } # 日志分析脚本 analyze_log() { local log_file=$1 echo "=== Log Analysis for $log_file ===" # 总行数 echo "Total lines: $(wc -l < "$log_file")" # 错误统计 echo "Error count: $(grep -c "ERROR" "$log_file")" # IP 访问统计 echo "Top IPs:" awk '{print $1}' "$log_file" | sort | uniq -c | sort -nr | head -5 # 状态码统计 echo "Status codes:" awk '{print $9}' "$log_file" | sort | uniq -c | sort -nr # 访问时间分布 echo "Hourly distribution:" awk '{print substr($4, 14, 2)}' "$log_file" | sort | uniq -c | sort -k2n }
  • 打印特定列: ps aux | awk ‘{print $1, $11}’

  • 数值条件过滤:awk ‘$3 > 1.0 {print $1, $3}’ /proc/loadavg

  • 磁盘使用率过滤统计 : df -h | awk ‘NR>1{sub(/%/,“”,$5);v=$5+0;if(v>5)print v}’ v=$5+0 强制将字符串转换为数值类型,才能作为if(v>5) 的条件判断值。

  • 自定义分隔符-F:处理 /etc/passwd :awk -F: ‘{print $1 “---” $3}’ /etc/passwd

  • 访问 IP 排行 TOP5(高频攻击 / 爬虫排查):

    echo "Top IPs:" awk '{print $1}' "$log_file" | sort | uniq -c | sort -nr | head -5

uniq -c:统计每个 IP 出现次数(左侧是计数)

  • substr(字符串, 起始位置, 截取长度)字符串截取函数:

    awk '{print substr($4, 14, 2)}' "$log_file" | sort | uniq -c | sort -k2n
  • sort -k2n:按k2 指第二列 从小到大排序 用途判断业务高峰时段,做流量扩容、限流优化

🗒️ 文本处理-三剑客之SED

先说明两点关键前提:

  • Sed 默认是模式空间流式处理,默认只输出到终端,不修改源文件。

  • -i 参数才是原地修改文件。

  • s/匹配内容/替换内容/修饰符是sed替换语法核心。

sed_examples() { local file="example.txt" # 替换 sed 's/old/new/g' "$file" # 全局替换 sed 's/old/new/2' "$file" # 替换第2个匹配 sed '2,5s/old/new/g' "$file" # 指定行范围 # 删除 sed '/pattern/d' "$file" # 删除包含模式的行 sed '2,4d' "$file" # 删除第2-4行 sed '/^$/d' "$file" # 删除空行 # 插入 sed '2i\Insert this line' "$file" # 在第2行前插入 sed '2a\Append this line' "$file" # 在第2行后追加 sed '2c\Append this line' "$file" # 替换第二整行 # 打印 sed -n '2,5p' "$file" # 打印第2-5行 sed -n '/pattern/p' "$file" # 打印匹配行 } # 配置文件处理 update_config() { local config_file=$1 local key=$2 local value=$3 # 备份原文件 cp "$config_file" "${config_file}.bak" # 更新配置 if grep -q "^$key=" "$config_file"; then sed -i "s/^$key=.*/$key=$value/" "$config_file" else echo "$key=$value" >> "$config_file" fi }

📐正则表达式练习

regex_examples() { local text="Contact: john@example.com or call 123-456-7890" # 提取邮箱 if [[ $text =~ ([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}) ]]; then echo "Email found: ${BASH_REMATCH[1]}" fi # 提取电话号码 if [[ $text =~ ([0-9]{3}-[0-9]{3}-[0-9]{4}) ]]; then echo "Phone found: ${BASH_REMATCH[1]}" fi # 验证 IP 地址 validate_ip() { local ip=$1 local regex='^([0-9]{1,3}\.){3}[0-9]{1,3}$' if [[ $ip =~ $regex ]]; then echo "Valid IP format" else echo "Invalid IP format" fi } }