当前位置: 首页 > news >正文

Shell脚本实战:从入门到自动化运维

1. Shell脚本入门:从"Hello World"到实用工具

刚接触Shell脚本时,很多人会被各种符号和命令吓到。但就像学骑自行车一样,一旦掌握了基本平衡,剩下的就是不断练习了。我刚开始写Shell脚本时,最头疼的就是那个神秘的#!/bin/bash——它到底有什么用?后来才发现,这就像给剧本指定导演,告诉系统该用哪个解释器来执行这个脚本。

让我们从最基础的脚本开始。创建一个hello.sh文件,内容如下:

#!/bin/bash echo "Hello World"

保存后,你可以用三种方式运行它:

  1. bash hello.sh(直接调用解释器)
  2. sh hello.sh(使用sh解释器)
  3. chmod +x hello.sh && ./hello.sh(赋予执行权限后直接运行)

提示:新手常犯的错误是忘记给脚本执行权限就直接运行。如果看到"Permission denied"错误,记得先用chmod +x命令授权。

变量是Shell脚本的基石。定义变量时要注意:等号两边不能有空格,变量名建议全大写。比如:

SERVER_IP="192.168.1.1" echo "正在连接服务器 $SERVER_IP..."

这里有个实用技巧:用readonly声明不可修改的常量,用export将变量提升为全局环境变量。我在实际项目中就吃过亏——一个测试脚本意外修改了生产环境配置,就是因为变量没加readonly限制。

2. 条件判断与循环控制:让脚本学会做决策

真实的运维场景中,脚本需要根据不同条件执行不同操作。比如检查磁盘空间时,超过90%就该报警,否则只需记录日志。这就是条件判断的用武之地。

Shell提供了两种条件判断语法:

  • test命令:test -f /path/to/file
  • 方括号:[ -f /path/to/file ](注意括号内外的空格!)

常用判断条件包括:

  • 文件检测:-e(存在)、-f(是文件)、-d(是目录)
  • 数值比较:-eq(等于)、-gt(大于)
  • 字符串比较:=(相等)、!=(不等)

来看个实际案例——自动备份数据库前检查磁盘空间:

#!/bin/bash FREE_SPACE=$(df -h /backup | awk 'NR==2 {print $5}' | tr -d '%') WARNING_THRESHOLD=90 if [ $FREE_SPACE -ge $WARNING_THRESHOLD ]; then echo "警告:备份分区剩余空间不足!当前使用率: ${FREE_SPACE}%" exit 1 else echo "磁盘空间正常,开始备份..." # 这里放备份命令 fi

循环则是处理批量任务的利器。比如批量检查服务器连通性:

#!/bin/bash SERVERS=("192.168.1.10" "192.168.1.11" "192.168.1.12") for IP in "${SERVERS[@]}"; do if ping -c 1 $IP &> /dev/null; then echo "$IP 在线" else echo "$IP 离线!" >&2 fi done

注意:for循环处理带空格的字符串时会出问题。安全做法是用数组和双引号包裹变量,就像上面例子那样。

3. 函数与参数处理:打造可复用的脚本组件

当脚本超过50行时,就该考虑用函数来组织代码了。函数不仅能提高可读性,还能避免重复代码。Shell中定义函数有两种方式:

# 方式一 function check_disk() { local threshold=$1 # local表示局部变量 # 函数体 } # 方式二 check_memory() { # 函数体 }

关键技巧:

  1. local声明局部变量,避免污染全局命名空间
  2. 通过$1$2等获取参数
  3. return返回退出状态码(0表示成功)

分享一个实用的日志函数,我在多个项目中都复用这个组件:

#!/bin/bash LOG_FILE="/var/log/my_script.log" log() { local level=$1 local message=$2 local timestamp=$(date "+%Y-%m-%d %H:%M:%S") case $level in INFO) echo "[$timestamp] INFO: $message" >> $LOG_FILE ;; WARN) echo "[$timestamp] WARN: $message" >> $LOG_FILE ;; ERROR) echo "[$timestamp] ERROR: $message" >> $LOG_FILE >&2 ;; esac } log INFO "脚本启动" # 业务逻辑... log WARN "磁盘空间接近阈值"

参数处理是另一个重点。特殊变量如$#(参数个数)、$@(所有参数)非常有用。这里有个处理命令行选项的模板:

while getopts "u:p:h" opt; do case $opt in u) USERNAME=$OPTARG ;; p) PASSWORD=$OPTARG ;; h) echo "用法: $0 -u 用户名 -p 密码"; exit 0 ;; *) echo "无效选项"; exit 1 ;; esac done

4. 实战案例:自动化运维三剑客

现在我们把前面学的知识综合运用,实现三个经典运维场景。

4.1 日志分析报警系统

这个脚本会:

  1. 扫描指定日志文件
  2. 匹配错误关键词
  3. 超过阈值就发邮件报警
#!/bin/bash LOG_FILE="/var/log/nginx/error.log" ERROR_KEYWORDS=("502 Bad Gateway" "404 Not Found") THRESHOLD=10 EMAIL="admin@example.com" analyze_log() { local keyword=$1 local count=$(grep -c "$keyword" $LOG_FILE) if [ $count -gt $THRESHOLD ]; then send_alert "$keyword 出现 $count 次" fi } send_alert() { local content=$1 echo "$content" | mail -s "日志报警" $EMAIL } for keyword in "${ERROR_KEYWORDS[@]}"; do analyze_log "$keyword" done

4.2 自动化备份方案

这个备份脚本特点:

  • 保留最近7天备份
  • 自动压缩
  • 校验备份完整性
#!/bin/bash BACKUP_DIR="/backup" DB_USER="root" DB_PASS="password" DATE=$(date +%Y%m%d) KEEP_DAYS=7 # 创建备份目录 [ -d $BACKUP_DIR ] || mkdir -p $BACKUP_DIR # MySQL备份 mysqldump -u$DB_USER -p$DB_PASS --all-databases | gzip > $BACKUP_DIR/db_$DATE.sql.gz # 校验备份 if [ ${PIPESTATUS[0]} -ne 0 ]; then echo "数据库备份失败!" >&2 exit 1 fi # 清理旧备份 find $BACKUP_DIR -name "*.sql.gz" -mtime +$KEEP_DAYS -delete

4.3 服务监控与自愈

这个脚本监控Nginx服务,异常时自动重启:

#!/bin/bash SERVICE="nginx" MAX_RETRY=3 LOG="/var/log/service_monitor.log" check_service() { if ! systemctl is-active --quiet $SERVICE; then echo "$(date) - $SERVICE 服务停止" >> $LOG restart_service fi } restart_service() { local retry=0 while [ $retry -lt $MAX_RETRY ]; do systemctl restart $SERVICE sleep 5 if systemctl is-active --quiet $SERVICE; then echo "$(date) - 重启成功" >> $LOG return 0 fi ((retry++)) done echo "$(date) - 重启失败,已达最大重试次数" >> $LOG send_alert "$SERVICE 服务无法启动" } check_service

5. 高级技巧与避坑指南

5.1 安全防护要点

写生产环境脚本时,安全必须放在第一位:

  • set -e让脚本遇到错误立即退出
  • set -u防止使用未定义变量
  • set -o pipefail确保管道命令中任意失败都会终止脚本

完整的安全头部应该这样写:

#!/bin/bash set -euo pipefail IFS=$'\n\t'

5.2 性能优化技巧

处理大文件或循环时,这些技巧能显著提升性能:

  1. 避免在循环中调用外部命令,改用Shell内置功能
  2. 使用awk/sed代替grep+cut组合
  3. 批量操作时尽量减少文件IO

比如统计日志中IP访问次数,低效写法:

cat access.log | cut -d' ' -f1 | sort | uniq -c

高效写法:

awk '{ips[$1]++} END {for(ip in ips) print ips[ip], ip}' access.log | sort -nr

5.3 调试与排错

调试Shell脚本的几种方法:

  1. 打印调试信息:set -x开启调试模式
  2. 检查退出状态:echo $?
  3. 使用ShellCheck在线工具检查语法

这是我常用的调试模板:

#!/bin/bash set -x # 开启调试 # 业务代码... set +x # 关闭调试

遇到复杂问题时,可以分段调试:

  1. 在可疑代码前加set -x
  2. 在可疑代码后加set +x
  3. 使用trap命令捕获信号进行清理

6. 实战项目:从零构建自动化运维系统

让我们用所学知识构建一个完整的自动化运维系统,包含以下功能:

  • 定时执行批量任务
  • 集中管理多台服务器
  • 可视化报告生成

6.1 架构设计

├── bin/ │ ├── deploy.sh # 部署脚本 │ ├── monitor.sh # 监控脚本 │ └── backup.sh # 备份脚本 ├── config/ │ └── servers.list # 服务器列表 ├── lib/ │ └── utils.sh # 通用函数库 └── logs/ # 日志目录

6.2 核心实现

lib/utils.sh通用函数库:

#!/bin/bash # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' NC='\033[0m' # No Color # 日志函数 log() { local level=$1 shift local message=$@ local timestamp=$(date "+%Y-%m-%d %H:%M:%S") case $level in INFO) echo -e "${GREEN}[$timestamp] INFO: $message${NC}" ;; ERROR) echo -e "${RED}[$timestamp] ERROR: $message${NC}" >&2 ;; esac } # 远程执行命令 remote_exec() { local server=$1 local cmd=$2 ssh -o ConnectTimeout=5 $server "$cmd" return $? }

bin/monitor.sh监控脚本:

#!/bin/bash source ../lib/utils.sh SERVER_LIST="../config/servers.list" while read server; do log INFO "检查服务器: $server" # 检查磁盘 disk_usage=$(remote_exec $server "df -h / | awk 'NR==2 {print \$5}'") if [[ $disk_usage =~ ([0-9]+)% ]]; then usage=${BASH_REMATCH[1]} if [ $usage -gt 90 ]; then log ERROR "$server 磁盘使用率过高: $usage%" fi fi # 检查内存 mem_free=$(remote_exec $server "free -m | awk '/Mem/{print \$4}'") [ $mem_free -lt 100 ] && log WARN "$server 内存不足,剩余: ${mem_free}MB" done < $SERVER_LIST

6.3 部署与调度

用crontab设置定时任务:

# 每天凌晨执行备份 0 0 * * * /opt/ops/bin/backup.sh # 每5分钟执行监控 */5 * * * * /opt/ops/bin/monitor.sh # 每周一执行安全更新 0 3 * * 1 /opt/ops/bin/update.sh

7. 从脚本到系统:工程化实践

当脚本越来越多时,就需要考虑工程化管理了。以下是我总结的最佳实践:

  1. 版本控制:所有脚本必须纳入Git管理
  2. 代码审查:重要的脚本变更需要同行评审
  3. 单元测试:用bats框架为关键函数写测试
  4. 文档规范:每个脚本头部要有标准注释:
#!/bin/bash # 名称: monitor.sh # 描述: 服务器健康状态监控 # 作者: Your Name # 版本: 1.0 # 参数: 无 # 返回值: 0-成功 1-失败
  1. 配置分离:将配置项抽离到单独文件
  2. 日志规范:统一日志格式和存储位置
  3. 报警集成:对接企业微信/钉钉/Slack等IM工具

分享一个通过企业微信发送报警的实用函数:

send_wechat() { local corp_id="YOUR_CORP_ID" local corp_secret="YOUR_SECRET" local agent_id="YOUR_AGENT_ID" local msg=$1 # 获取access_token token=$(curl -s "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$corp_id&corpsecret=$corp_secret" | jq -r .access_token) # 发送消息 curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$token" \ -H "Content-Type: application/json" \ -d '{ "touser": "@all", "msgtype": "text", "agentid": "'$agent_id'", "text": { "content": "'"$msg"'" }, "safe": 0 }' }

8. 性能监控脚本深度优化

让我们深入优化一个服务器性能监控脚本,使其具备:

  • 实时监控CPU、内存、磁盘
  • 历史数据存储
  • 自动生成报告

优化后的脚本架构:

#!/bin/bash # 性能监控v2.0 # 加载库 source ./lib/metrics.sh source ./lib/report.sh # 主循环 while true; do # 采集数据 cpu_usage=$(get_cpu_usage) mem_usage=$(get_mem_usage) disk_usage=$(get_disk_usage) # 存储数据 store_metrics "$cpu_usage" "$mem_usage" "$disk_usage" # 检查阈值 check_thresholds "$cpu_usage" "$mem_usage" "$disk_usage" # 间隔60秒 sleep 60 done

lib/metrics.sh采集函数:

#!/bin/bash # 获取CPU使用率(取1秒内的平均值) get_cpu_usage() { local cpu=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}') printf "%.1f" $cpu } # 获取内存使用率 get_mem_usage() { local total=$(free -m | awk '/Mem/{print $2}') local used=$(free -m | awk '/Mem/{print $3}') local percent=$(awk "BEGIN {printf \"%.1f\", $used/$total*100}") echo $percent } # 获取磁盘使用率 get_disk_usage() { df -h / | awk 'NR==2 {print $5}' | tr -d '%' }

数据存储采用CSV格式,便于后续分析:

2023-08-01 12:00:00,25.5,68.3,45 2023-08-01 12:01:00,26.1,67.9,45

报告生成使用gnuplot绘制趋势图:

#!/bin/bash generate_report() { local data_file="$1" local output_img="$2" gnuplot <<- EOF set terminal png size 1000,600 set output "$output_img" set xdata time set timefmt "%Y-%m-%d %H:%M:%S" set format x "%H:%M" set xlabel "时间" set ylabel "使用率(%)" set title "服务器性能监控报告 - $(date +%Y-%m-%d)" plot "$data_file" using 1:2 with lines title "CPU", \ "$data_file" using 1:3 with lines title "内存", \ "$data_file" using 1:4 with lines title "磁盘" EOF }

9. 错误处理与日志收集系统

健壮的运维系统必须有完善的错误处理和日志收集机制。以下是一个分布式日志收集方案:

  1. 客户端脚本(部署在各服务器上):
#!/bin/bash # log_collector.sh LOG_DIR="/var/log/app" CENTRAL_SERVER="logserver.example.com" ARCHIVE_DIR="/backup/logs" # 发送日志到中心服务器 send_logs() { local log_file=$1 local server=$2 if ! scp $log_file ops@$server:/collector/raw/; then echo "日志传输失败: $log_file" >&2 return 1 fi # 传输成功后归档 mv $log_file $ARCHIVE_DIR/ } # 处理旧日志 for old_log in $(find $LOG_DIR -name "*.log" -mtime +1); do gzip $old_log send_logs "${old_log}.gz" $CENTRAL_SERVER done
  1. 服务端处理脚本(日志中心服务器):
#!/bin/bash # log_processor.sh RAW_DIR="/collector/raw" PROCESSED_DIR="/collector/processed" REPORT_DIR="/collector/reports" process_log() { local log_file=$1 local server_name=$(basename $log_file | cut -d'_' -f1) # 错误统计 local errors=$(zgrep -c "ERROR" $log_file) local warnings=$(zgrep -c "WARN" $log_file) # 生成报告 echo "$server_name,$(date +%Y-%m-%d),$errors,$warnings" >> $REPORT_DIR/daily_report.csv # 移动已处理文件 mv $log_file $PROCESSED_DIR/ } # 主循环 while true; do for new_log in $(find $RAW_DIR -name "*.log.gz"); do process_log $new_log done sleep 300 done
  1. 日志分析报表生成:
#!/bin/bash # report_generator.sh REPORT_DATA="$REPORT_DIR/daily_report.csv" HTML_REPORT="$REPORT_DIR/latest.html" generate_html_report() { echo "<html><body><h1>服务器日志分析报告</h1>" > $HTML_REPORT echo "<table border=1><tr><th>服务器</th><th>日期</th><th>错误数</th><th>警告数</th></tr>" >> $HTML_REPORT while IFS=, read -r server date errors warnings; do echo "<tr><td>$server</td><td>$date</td><td>$errors</td><td>$warnings</td></tr>" >> $HTML_REPORT done < $REPORT_DATA echo "</table></body></html>" >> $HTML_REPORT }

10. 安全加固与权限管理

生产环境中的Shell脚本必须考虑安全性。以下是关键防护措施:

  1. 最小权限原则:为脚本创建专用用户
# 创建运维专用用户 sudo useradd -m -s /bin/bash opsadmin sudo passwd opsadmin # 设置sudo权限(/etc/sudoers) opsadmin ALL=(ALL) NOPASSWD: /opt/scripts/*
  1. 敏感信息保护:不要硬编码密码
# 错误做法 DB_PASS="123456" # 正确做法 # 从加密文件读取 DB_PASS=$(gpg --decrypt secrets.gpg) # 或者使用环境变量 export DB_PASS=$(vault kv get -field=password secret/db)
  1. 输入验证:防止命令注入
# 危险!可能被注入 read -p "输入服务器IP: " IP ping $IP # 安全做法 read -p "输入服务器IP: " IP if [[ $IP =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then ping -c 1 $IP else echo "非法IP地址" fi
  1. 日志审计:记录关键操作
# 记录谁在什么时候执行了什么 log_audit() { local user=$(whoami) local timestamp=$(date "+%Y-%m-%d %H:%M:%S") local action=$1 echo "$timestamp $user $action" >> /var/log/audit.log } # 使用示例 log_audit "执行了数据库备份"
  1. 文件完整性检查:防止脚本被篡改
#!/bin/bash # verify_script.sh SCRIPT="/opt/scripts/backup.sh" KNOWN_HASH="a1b2c3d4e5f6..." current_hash=$(sha256sum $SCRIPT | awk '{print $1}') if [ "$current_hash" != "$KNOWN_HASH" ]; then echo "警告:脚本已被修改!" exit 1 fi

11. 跨平台兼容性处理

不同Linux发行版甚至Unix-like系统之间,Shell语法和工具链可能存在差异。以下是保证兼容性的技巧:

  1. 指定解释器版本
#!/bin/bash --posix # 使用POSIX模式
  1. 工具检测与替代方案
# 检测工具是否存在 if ! command -v jq &> /dev/null; then echo "错误:需要jq但未安装" exit 1 fi # 替代方案示例:如果没有awk使用sed if command -v awk &> /dev/null; then CPU_USAGE=$(top -bn1 | awk '/Cpu/{print $2}') else CPU_USAGE=$(top -bn1 | sed -n '/Cpu/s/.*, *\([0-9.]*\)%* id.*/\1/p') fi
  1. 路径处理兼容性
# 获取脚本所在目录(兼容各种系统) SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd) # 路径拼接使用变量 CONFIG_FILE="$SCRIPT_DIR/../config/settings.cfg"
  1. 系统类型判断
case "$(uname -s)" in Linux*) SYSTEM="Linux" ;; Darwin*) SYSTEM="Mac" ;; CYGWIN*) SYSTEM="Cygwin" ;; MINGW*) SYSTEM="MinGw" ;; *) SYSTEM="Unknown" ;; esac if [ "$SYSTEM" = "Linux" ]; then # Linux特有命令 PKG_MANAGER="apt-get" elif [ "$SYSTEM" = "Mac" ]; then # Mac特有命令 PKG_MANAGER="brew" fi
  1. 时间处理兼容方案
# GNU date和BSD date参数不同 if date --version &> /dev/null; then # GNU date TIMESTAMP=$(date -d "1 day ago" "+%Y-%m-%d") else # BSD date (Mac) TIMESTAMP=$(date -v-1d "+%Y-%m-%d") fi

12. 性能敏感场景的优化策略

当脚本需要处理大量数据或高频执行时,性能优化就变得至关重要。以下是我在实战中总结的优化技巧:

  1. 减少子进程创建
# 低效:每次循环都调用date for i in {1..1000}; do echo "$(date +%s) - $i" done # 高效:只调用一次date now=$(date +%s) for i in {1..1000}; do echo "$now - $i" done
  1. 使用内置字符串操作代替外部命令
# 低效:使用cut echo "hello:world" | cut -d: -f1 # 高效:使用Shell内置 str="hello:world" echo "${str%:*}"
  1. 批量处理代替逐行处理
# 低效:逐行处理 while read line; do process "$line" done < file.txt # 高效:批量读取 mapfile -t lines < file.txt for line in "${lines[@]}"; do process "$line" done
  1. 使用更快的文本处理工具
# 处理GB级日志文件时 # grep+awk组合:约30秒 grep "ERROR" huge.log | awk '{print $3}' # 单独使用awk:约15秒 awk '/ERROR/{print $3}' huge.log # 使用ripgrep(rg):约5秒 rg "ERROR" huge.log -o | awk '{print $3}'
  1. 并行处理加速
# 串行处理 for server in "${SERVERS[@]}"; do check_status $server done # 并行处理(使用GNU parallel或xargs) printf "%s\n" "${SERVERS[@]}" | xargs -P 4 -I {} bash -c 'check_status "$@"' _ {}
  1. 内存优化技巧
# 处理大文件时避免全部读入内存 while IFS= read -r line; do process_line "$line" done < <(grep "pattern" huge_file.txt) # 使用临时文件代替变量存储中间结果 awk '{print $1}' big_file.txt > temp_file1 awk '{print $2}' big_file.txt > temp_file2 # 而不是 # col1=$(awk '{print $1}' big_file.txt) # col2=$(awk '{print $2}' big_file.txt)

13. 与现代运维工具集成

传统Shell脚本可以很好地与现代运维工具链集成,发挥更大价值:

  1. 与Ansible集成
#!/bin/bash # 动态生成Ansible inventory echo "[web]" aws ec2 describe-instances \ --filters "Name=tag:Role,Values=web" \ --query "Reservations[].Instances[].PrivateIpAddress" \ --output text | tr '\t' '\n' echo "[db]" aws ec2 describe-instances \ --filters "Name=tag:Role,Values=db" \ --query "Reservations[].Instances[].PrivateIpAddress" \ --output text | tr '\t' '\n'
  1. 与Docker/Kubernetes集成
#!/bin/bash # 自动部署容器并检查状态 DEPLOYMENT="myapp" IMAGE_VERSION="v1.2.3" NAMESPACE="production" # 部署 kubectl set image deployment/$DEPLOYMENT *=myrepo/myapp:$IMAGE_VERSION -n $NAMESPACE # 等待就绪 for i in {1..30}; do ready=$(kubectl get deploy $DEPLOYMENT -n $NAMESPACE -o jsonpath='{.status.readyReplicas}') if [ "$ready" -eq 3 ]; then echo "部署成功" exit 0 fi sleep 5 done echo "部署超时" exit 1
  1. 与CI/CD管道集成
#!/bin/bash # GitLab CI Runner脚本 # 构建阶段 build() { docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA } # 测试阶段 test() { docker run --rm $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA npm test } # 部署阶段 deploy() { kubectl set image deployment/myapp *=myapp:$CI_COMMIT_SHA -n production } case $1 in build) build ;; test) test ;; deploy) deploy ;; *) echo "无效阶段" ;; esac
  1. 与监控系统集成
#!/bin/bash # 向Prometheus Pushgateway提交指标 PUSHGATEWAY="prometheus.example.com:9091" JOB_NAME="custom_metrics" # 收集指标 cpu_temp=$(sensors | awk '/Package/{print $4}' | tr -d '+°C') disk_usage=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%') # 推送指标 cat <<EOF | curl --data-binary @- http://$PUSHGATEWAY/metrics/job/$JOB_NAME # TYPE cpu_temperature gauge cpu_temperature $cpu_temp # TYPE disk_usage_percent gauge disk_usage_percent $disk_usage EOF

14. 复杂文本处理实战

Shell脚本配合文本处理工具可以高效解决复杂日志分析需求:

  1. 多维度日志分析
#!/bin/bash # 分析Nginx日志:统计状态码、热门URL、客户端IP LOG_FILE="/var/log/nginx/access.log" # 状态码统计 echo "状态码统计:" awk '{print $9}' $LOG_FILE | sort | uniq -c | sort -nr # 热门URL echo -e "\n热门URL:" awk -F'"' '{print $2}' $LOG_FILE | awk '{print $2}' | sort | uniq -c | sort -nr | head -10 # 客户端IP统计 echo -e "\n客户端IP统计:" awk '{print $1}' $LOG_FILE | sort | uniq -c | sort -nr | head -20
  1. 实时日志监控
#!/bin/bash # 实时监控错误日志并报警 LOG_FILE="/var/log/app/error.log" ALERT_THRESHOLD=5 ALERT_EMAIL="admin@example.com" tail -Fn0 $LOG_FILE | \ while read line; do if echo "$line" | grep -q "ERROR"; then echo "$line" >> /tmp/error_buffer.log error_count=$(wc -l < /tmp/error_buffer.log) if [ $error_count -ge $ALERT_THRESHOLD ]; then mail -s "应用错误报警" $ALERT_EMAIL < /tmp/error_buffer.log > /tmp/error_buffer.log fi fi done
  1. CSV文件处理
#!/bin/bash # 处理员工薪资CSV文件 INPUT="employees.csv" OUTPUT="report.txt" # 计算各部门平均薪资 awk -F, ' NR>1 { dept[$3] += $4 count[$3]++ } END { for(d in dept) { avg = dept[d]/count[d] printf "%s: %.2f\n", d, avg } }' $INPUT | sort -k2 -nr > $OUTPUT # 添加报表头部 sed -i '1i 部门平均薪资报告\n=================' $OUTPUT
  1. JSON数据处理
#!/bin/bash # 处理API返回的JSON数据 API_URL="https://api.example.com/data" TEMP_FILE="/tmp/api_response.json" # 获取并处理JSON curl -s $API_URL | jq '.' > $TEMP_FILE # 提取关键信息 total_items=$(jq '.pagination.total' $TEMP_FILE) first_item=$(jq '.data[0].name' $TEMP_FILE) echo "共 $total_items 条记录,第一条: $first_item" # 复杂处理:过滤并转换数据 jq -r '.data[] | select(.value > 100) | "\(.name):\(.value)"' $TEMP_FILE | \ while IFS=: read -r name value; do echo "高价值项目: $name (值: $value)" done

15. 系统管理自动化合集

分享几个我在日常运维中积累的实用脚本:

  1. 用户账户批量管理
#!/bin/bash # 批量创建用户并设置随机密码 USER_LIST="users.txt" PASSWORD_LENGTH=12 while IFS=: read -r username groups; do # 创建用户 if ! id "$username" &>/dev/null; then useradd -m -s /bin/bash "$username" # 设置组 if [ -n "$groups" ]; then usermod -aG "$groups" "$username" fi # 生成随机密码 password=$(tr -dc A-Za-z0-9 </dev/urandom | head -c $PASSWORD_LENGTH) echo "$username:$password" | chpasswd # 记录密码(实际环境应该使用密钥或密码管理器) echo "$username:$password:$groups" >> created_users.log else echo "用户 $username 已存在" >&2 fi done < "$USER_LIST"
  1. SSL证书监控
#!/bin/bash # 检查证书过期时间 DOMAINS=("example.com" "api.example.com" "blog.example.com") WARNING_DAYS=30 for domain in "${DOMAINS[@]}"; do # 获取证书过期时间 expiry_date=$(echo | openssl s_client -connect $domain:443 2>/dev/null | \ openssl x509 -noout -dates | grep '^notAfter' | cut -d= -f2) # 转换为时间戳 expiry_epoch=$(date -d "$expiry_date" +%s) now_epoch=$(date +%s) days_left=$(( (expiry_epoch - now_epoch) / 86400 )) # 判断是否需要报警 if [ $days_left -le $WARNING_DAYS ]; then echo "警告: $
http://www.jsqmd.com/news/1187249/

相关文章:

  • 3分钟学会无损视频剪辑:LosslessCut 终极使用指南
  • 积家官方服务项目及价格查询|权威信息公示(2026年7月最新) - 积家官方维修中心
  • GitHub CSV Tools错误排查指南:常见问题解决方法和调试技巧
  • 时间序列建模实战语言地图:从平稳性、自相关到残差诊断的可操作指南
  • 从ERROR 1698到安全登录:深入解析MySQL root身份验证插件的演变与配置
  • 图像识别:从像素到智能的演进之路
  • 汽车电子MCU选型实战:MSPM0Lx22x如何以单芯片方案满足功能安全与低功耗需求
  • Dialog源码架构解析:理解BaseDialog与ModalBaseDialog的设计思想
  • 嵌入式毕业设计实战项目精选30例(附技术路线与源码解析)
  • 告别Electron臃肿:基于WebView2的轻量化HTML转EXE方案实战
  • 如何在43秒内解锁星露谷物语所有XNB资源:StardewXnbHack完全指南
  • 高效数据输入输出:readr、data.table与fst性能对比终极指南 [特殊字符]
  • YOLOv7目标检测架构革新与实战优化
  • HMCL启动器服务器配置:终极Minecraft服务器搭建指南
  • 基于STM32单片机指纹考勤签到刷卡门禁无线WiFi/蓝牙APP设计DIY-T127
  • 树莓派搭建ArduSub地面站:从写卡到视频流的完整实践指南
  • DRA829引脚复用配置详解:从信号表到硬件设计的实战指南
  • YOLOv8手写数字与符号识别实战指南
  • STM32F303K8与A89307实现高效FOC电机控制方案
  • 焊缝缺陷视觉质检系统:YOLOv8工业场景数据集与训练全栈实战
  • 3步找回加密文件密码:免费压缩包密码恢复工具完整指南
  • RedisFullCheck 与 RedisShake 集成:数据迁移后的完整性验证最佳实践
  • 面试官:介绍一下 Java 异常!99% 的人都答不全(附异常体系图)
  • 终极指南:OpCore-Simplify如何让黑苹果配置从3天缩短到30分钟
  • Java 转大模型开发:用一次交付过程做复盘
  • WIN+R 进阶指南:解锁隐藏的系统管理工具
  • 视觉原语:从特征提取到可解释视觉推理的新范式
  • terminal-portfolio性能优化秘籍:让你的终端网站加载速度提升60%
  • 八大核心深度学习算法详解:CNN、RNN、Transformer等原理与实战
  • yada高级特性探索:自定义中间件和扩展的实用技巧