跳到主要内容

Shell 脚本自动化

脚本编写规范

script-template.sh
#!/usr/bin/env bash
set -euo pipefail # e:出错退出 u:未定义变量报错 o pipefail:管道错误
IFS=$'\n\t'

# ========== 变量 ==========
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_FILE="/var/log/my-script.log"
LOCK_FILE="/tmp/my-script.lock"

# ========== 函数 ==========
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

cleanup() {
rm -f "$LOCK_FILE"
log "Script finished"
}
trap cleanup EXIT

# ========== 文件锁(防重复执行) ==========
if [ -f "$LOCK_FILE" ]; then
log "ERROR: Script already running (lock: $LOCK_FILE)"
exit 1
fi
echo $$ > "$LOCK_FILE"

# ========== 主逻辑 ==========
log "Script started"
# ... your code here ...
提示

set -euo pipefail 是 Shell 脚本的安全三件套,生产环境脚本必须加上。

常用自动化场景

日志清理

clean-logs.sh
#!/usr/bin/env bash
set -euo pipefail

LOG_DIRS=("/var/log/app" "/data/logs")
KEEP_DAYS=30

for dir in "${LOG_DIRS[@]}"; do
if [ -d "$dir" ]; then
count=$(find "$dir" -name "*.log" -mtime +${KEEP_DAYS} | wc -l)
find "$dir" -name "*.log" -mtime +${KEEP_DAYS} -delete
echo "Cleaned $count files in $dir (older than ${KEEP_DAYS} days)"
fi
done

批量服务器操作

batch-exec.sh
#!/usr/bin/env bash
set -euo pipefail

HOSTS_FILE="hosts.txt" # 每行一个 IP
CMD="$*"

while IFS= read -r host; do
echo "=== $host ==="
ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no \
"$host" "$CMD" 2>&1 || echo "FAILED: $host"
done < "$HOSTS_FILE"

服务器初始化

init-server.sh
#!/usr/bin/env bash
set -euo pipefail

# 时区
timedatectl set-timezone Asia/Shanghai

# 关闭 SELinux
setenforce 0 || true
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

# 内核参数
cat > /etc/sysctl.d/99-init.conf << 'EOF'
net.core.somaxconn = 65535
fs.file-max = 2097152
vm.swappiness = 10
net.ipv4.tcp_tw_reuse = 1
EOF
sysctl -p /etc/sysctl.d/99-init.conf

# ulimit
cat > /etc/security/limits.d/99-limits.conf << 'EOF'
* soft nofile 65535
* hard nofile 65535
EOF

echo "Server initialized successfully"

Crontab 定时任务

# 编辑定时任务
crontab -e

# 格式:分 时 日 月 周 命令
# 每天凌晨 2 点清理日志
0 2 * * * /opt/scripts/clean-logs.sh >> /var/log/cron-clean.log 2>&1

# 每 5 分钟健康检查
*/5 * * * * /opt/scripts/health-check.sh >> /var/log/cron-health.log 2>&1

# 每周一 9 点发送巡检报告
0 9 * * 1 /opt/scripts/weekly-report.sh
警告

Crontab 环境变量与交互式 Shell 不同,脚本中要使用绝对路径,并在 crontab 开头声明 PATH


常见面试问题

Q1: 如何确保 Shell 脚本的安全性和健壮性?

答案

  1. set -euo pipefail:出错即止、未定义变量报错、管道错误传递
  2. 文件锁:防止脚本重复执行
  3. trap cleanup EXIT:异常退出时清理临时文件
  4. 日志记录:操作过程可追溯
  5. 变量加引号"$var" 防止空格/特殊字符问题
  6. 使用 ShellCheck:静态分析工具检查常见错误

相关链接