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 脚本的安全性和健壮性?
答案:
set -euo pipefail:出错即止、未定义变量报错、管道错误传递- 文件锁:防止脚本重复执行
trap cleanup EXIT:异常退出时清理临时文件- 日志记录:操作过程可追溯
- 变量加引号:
"$var"防止空格/特殊字符问题 - 使用 ShellCheck:静态分析工具检查常见错误