别只敲命令了!用Shell脚本把openEuler日常操作自动化(附5个实用脚本)
别只敲命令了!用Shell脚本把openEuler日常操作自动化(附5个实用脚本)
在openEuler的日常运维中,重复性的命令行操作往往占据了大量时间。想象一下:每天手动检查服务状态、逐台服务器清理日志、反复输入相同的软件更新命令——这些操作不仅效率低下,还容易因人为疏忽导致错误。事实上,80%的日常运维工作都可以通过Shell脚本实现自动化,这正是本文要解决的核心问题。
对于已经掌握基础命令的中级用户而言,Shell脚本是将零散操作转化为标准化工具的关键跳板。不同于简单命令的堆砌,脚本化思维能实现条件判断、循环执行和错误处理的完整逻辑链。下面我们将通过5个典型场景的实战案例,展示如何用脚本将机械劳动转化为一键式智能操作。
1. 自动化运维的基石:Shell脚本核心语法
1.1 变量与参数传递
Shell脚本的威力始于变量的灵活运用。通过变量,我们可以将硬编码的值转化为可动态调整的参数:
#!/bin/bash # 定义备份目录变量 BACKUP_DIR="/var/backups" TODAY=$(date +%Y%m%d) # 获取当前日期 LOG_FILE="${BACKUP_DIR}/backup_${TODAY}.log"环境变量与位置参数的配合使用,能让脚本适应不同场景:
# 使用位置参数$1接收外部输入 target_dir=$1 if [ ! -d "$target_dir" ]; then echo "错误:目录 $target_dir 不存在" | tee -a $LOG_FILE exit 1 fi1.2 流程控制结构
条件判断和循环是自动化逻辑的核心构件。注意[ ]两侧的空格是语法必需:
# 多条件判断示例 if [ -f "/tmp/lockfile" ] && [ $(wc -l < /var/log/nginx/error.log) -gt 1000 ]; then echo "检测到错误日志过多且存在锁文件" >> $LOG_FILE # 触发告警逻辑... elif [ ! -f "/tmp/lockfile" ]; then touch /tmp/lockfile fi # 遍历目录的for循环 for conf_file in /etc/nginx/conf.d/*.conf; do if grep -q "ssl_certificate" "$conf_file"; then echo "发现SSL配置: $conf_file" fi done1.3 函数封装与模块化
将重复代码抽象为函数是专业脚本的标志:
# 定义日志函数 log_message() { local level=$1 local msg=$2 echo "[$(date '+%F %T')] [$level] $msg" | tee -a $LOG_FILE } # 调用示例 log_message "INFO" "开始执行备份流程"2. 实战案例一:智能日志清理脚本
2.1 场景痛点分析
系统日志的持续增长会快速耗尽磁盘空间。传统解决方案是手动执行rm命令或配置logrotate,但存在以下局限:
- 无法根据日志内容智能过滤
- 缺乏清理前的完整性检查
- 没有操作审计记录
2.2 脚本实现代码
以下脚本实现了按时间/大小双维度清理,并保留关键错误信息:
#!/bin/bash # 日志清理工具 v1.2 # 参数:$1=日志路径 $2=保留天数 $3=最大容量(MB) LOG_DIR=${1:-/var/log} KEEP_DAYS=${2:-30} MAX_SIZE=${3:-500} # 检查磁盘使用率 disk_usage=$(df -h $LOG_DIR | awk 'NR==2 {print $5}' | tr -d '%') [ $disk_usage -lt 90 ] || { echo "紧急:磁盘使用率已达${disk_usage}%,立即清理" >&2 MAX_SIZE=$((MAX_SIZE/2)) # 自动调低阈值 } # 主清理逻辑 find $LOG_DIR -type f -name "*.log" -mtime +$KEEP_DAYS -exec rm -v {} \; find $LOG_DIR -type f -size +${MAX_SIZE}M -exec truncate -s ${MAX_SIZE}M {} \; # 关键错误留存 grep -Ei "error|fail|critical" $LOG_DIR/*.log > $LOG_DIR/important_errors.log2.3 进阶技巧:日志轮转增强
结合crontab实现自动化调度:
# 每天凌晨执行清理 0 3 * * * /usr/local/bin/log_cleaner.sh /var/log 30 5003. 实战案例二:服务状态监控与自愈
3.1 服务监控原理
通过systemctl检测服务状态,当发现异常时:
- 尝试自动重启
- 重启失败则记录快照信息
- 通知管理员
3.2 完整实现脚本
#!/bin/bash # 服务守护脚本 SERVICES=("nginx" "mysql" "redis") for service in "${SERVICES[@]}"; do status=$(systemctl is-active $service) if [ "$status" != "active" ]; then echo "[$(date)] 服务 $service 异常 ($status)" >> /var/log/service_watcher.log # 尝试重启 systemctl restart $service sleep 5 # 验证重启结果 if [ $(systemctl is-active $service) == "active" ]; then echo "成功恢复 $service 服务" else # 收集诊断信息 journalctl -u $service -n 50 > /tmp/${service}_failure.log systemctl status $service >> /tmp/${service}_failure.log # 发送告警(需配置邮件或Webhook) send_alert "$service 服务恢复失败" /tmp/${service}_failure.log fi fi done3.3 监控指标扩展
可添加的性能监控维度:
| 指标类型 | 检查命令 | 阈值参考 |
|---|---|---|
| CPU使用率 | `top -bn1 | grep "Cpu(s)"` |
| 内存占用 | free -m | 剩余<10%告警 |
| 磁盘IO等待 | iostat -x 1 2 | await>50ms |
| 网络连接数 | ss -s | ESTAB>5000 |
4. 实战案例三:安全加固自动化脚本
4.1 典型加固项
- 密码策略强化
- 无用账户清理
- SSH安全配置
- 防火墙规则更新
4.2 一键加固实现
#!/bin/bash # 安全基线配置工具 # 备份原始配置 cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak cp /etc/login.defs /etc/login.defs.bak # SSH加固 sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config echo "AllowUsers admin" >> /etc/ssh/sshd_config # 密码策略 sed -i 's/PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/' /etc/login.defs sed -i 's/PASS_MIN_LEN.*/PASS_MIN_LEN 12/' /etc/login.defs # 清理无用账户 for user in games ftp; do if id "$user" &>/dev/null; then userdel -r "$user" fi done # 应用变更 systemctl restart sshd5. 实战案例四:批量软件更新与依赖检查
5.1 更新策略设计
- 先检查可更新软件包
- 排除内核等关键包
- 自动处理依赖关系
- 生成变更报告
5.2 智能更新脚本
#!/bin/bash # 安全更新工具 # 获取更新列表 UPDATES=$(dnf check-update -q | grep -v "kernel" | awk '{print $1}') if [ -z "$UPDATES" ]; then echo "没有待更新的软件包" exit 0 fi # 生成更新报告 REPORT_FILE="/var/log/update_report_$(date +%Y%m%d).log" echo "待更新软件包:" > $REPORT_FILE echo "$UPDATES" >> $REPORT_FILE # 交互式确认 read -p "发现 ${#UPDATES[@]} 个更新,是否继续?(y/n) " confirm if [[ $confirm != [yY] ]]; then exit 1 fi # 执行更新 dnf update -y ${UPDATES[@]} >> $REPORT_FILE 2>&1 # 检查依赖 echo -e "\n更新后依赖检查:" >> $REPORT_FILE dnf repoquery --unsatisfied >> $REPORT_FILE6. 实战案例五:跨服务器文件同步工具
6.1 同步方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| rsync | 增量同步、带宽优化 | 需配置SSH密钥 | 定期备份 |
| scp | 简单直接 | 全量传输 | 小文件快速传输 |
| inotify+rsync | 实时同步 | 系统资源占用高 | 关键目录实时镜像 |
6.2 智能同步脚本
#!/bin/bash # 跨服务器同步工具 SRC_DIR="/data/important" DST_SERVERS=("server1" "server2") EXCLUDE_FILE="/etc/sync_excludes" # 检查源目录 [ -d "$SRC_DIR" ] || { echo "错误:源目录不存在"; exit 1; } # 遍历目标服务器 for server in "${DST_SERVERS[@]}"; do echo "开始同步到 $server ..." # 使用rsync增量同步 rsync -avz --delete \ --exclude-from="$EXCLUDE_FILE" \ -e "ssh -p 22 -i /root/.ssh/sync_key" \ "$SRC_DIR/" "root@$server:$SRC_DIR/" # 校验结果 if [ $? -eq 0 ]; then echo "$server 同步成功" else echo "$server 同步失败" >&2 fi done7. 脚本优化与调试技巧
7.1 调试模式实践
使用set -x激活调试追踪:
#!/bin/bash set -x # 开启命令回显 DEBUG=${DEBUG:-false} # 默认关闭调试 $DEBUG && set -x # 条件调试 # 生产环境建议添加的错误处理 set -euo pipefail trap "echo '脚本被中断,执行清理...'; rm -f /tmp/lockfile" EXIT7.2 性能优化要点
- 减少子进程调用:用内置命令替代
awk/sed - 避免频繁文件IO:合并写操作
- 使用关联数组替代多文件处理
# 低效写法 for file in *.log; do grep "error" $file >> errors.txt done # 优化写法 grep "error" *.log > errors.txt8. 自动化运维体系进阶
当单个脚本无法满足需求时,需要考虑:
- 配置管理工具:Ansible剧本可管理脚本的版本和分发
- 任务调度系统:通过Kubernetes CronJob实现跨集群调度
- 监控集成:将脚本输出接入Prometheus等监控系统
# 示例:Ansible调用本地脚本 - name: 部署日志清理脚本 hosts: all tasks: - name: 推送脚本 copy: src: /local/scripts/log_cleaner.sh dest: /usr/local/bin/ mode: 0755 - name: 配置cron任务 cron: name: "每日日志清理" minute: "0" hour: "3" job: "/usr/local/bin/log_cleaner.sh >> /var/log/clean.log 2>&1"