在Linux終端實現批量刪除OpenStack實例,支持并發刪除、安全確認、重試機制、優先清理運行中實例
#!/bin/bash
# ======================================================================
# 增強版 OpenStack 刪除實例腳本
# 功能:支持并發刪除、安全確認、重試機制、優先清理運行中實例
# 更新:2025年4月30日
# ======================================================================#######################################
# 配置區(用戶可自定義參數)
#######################################
delete_InstanceMAX_RETRY=20 # 最大嘗試次數(刪除失敗時嘗試再次刪除實例)
CHECK_INTERVAL=5 # 實例狀態檢測間隔(單位:秒)
no_InstanceMAX_RETRY_TIME=20 # 實例列表為空,連續監測實例列表都是空的次數
CONCURRENCY=2 # 并發刪除線程數(建議不超過 API 限制)
MAX_WAIT_TIME=3600 # 最大等待超時時間(單位:秒,60 分鐘)LOG_FILE="./log_instance_delete_$(date +%Y%m%d).log" # 日志文件路徑(自動按日期生成)# 統計變量
TOTAL_DELETED_INSTANCES=0 # 已刪除實例總數統計
DELETED_INSTANCES_FILE="/tmp/deleted_instances.txt" # 已刪除實例ID臨時記錄文件# 顏色定義(終端輸出美化)
RED='\033[0;31m' # 紅色 - 錯誤/危險操作
GREEN='\033[0;32m' # 綠色 - 成功/正常狀態
YELLOW='\033[0;33m' # 黃色 - 警告/等待狀態
BLUE='\033[0;34m' # 藍色 - 執行中/進度信息
NC='\033[0m' # 無顏色 - 重置終端顏色#######################################
# 函數:帶重試機制的實例刪除
# 參數:
# $1 : 實例ID(必填)
# 返回值:
# 0 - 刪除成功 | 1 - 刪除失敗
# 描述:
# 使用指數退避策略重試刪除,最多嘗試 delete_InstanceMAX_RETRY 次刪除實例
#######################################
retry_delete() {local instance_id=$1for ((i=1; i<=delete_InstanceMAX_RETRY; i++)); dolog "${BLUE}嘗試刪除實例 [ID: $instance_id] (第 $i 次嘗試)...${NC}"if nova force-delete "$instance_id"; thenlog "${GREEN}刪除實例成功: $instance_id${NC}"echo "$instance_id" >> "$DELETED_INSTANCES_FILE"return 0fisleep $((i*2)) # 指數退避等待donelog "${RED}錯誤:刪除實例 $instance_id 失敗,已達最大重試次數(${delete_InstanceMAX_RETRY} 次)${NC}"return 1
}#######################################
# 函數:安全獲取實例列表
# 參數:
# $1 : 實例狀態(默認 ACTIVE)
# 返回值:
# 實例ID列表(格式:每行一個ID)
# 描述:
# 過濾無效字符并格式化輸出,避免臟數據干擾
#######################################
safe_get_instances() {local status=${1:-"ACTIVE"}nova list --status $status | awk -F '|' '/[0-9a-f]{8}-/ {gsub(/ /, "", $2);if ($4 ~ status) print $2}' status="$status"
}#######################################
# 函數:日志記錄
# 參數:
# $1 : 日志信息(支持顏色代碼)
# 描述:
# 自動添加時間戳,并同時輸出到終端和日志文件
#######################################
log() {local msg="$1"echo -e "$(date '+%Y-%m-%d %T') - $msg" | tee -a "$LOG_FILE"
}# 導出函數到子 Shell(確保并發調用時可用)
export -f log retry_delete#######################################
# 主流程
######################################## 解析命令行參數
while getopts "s:i:c:l:" opt; docase $opt ins) STATUS=$OPTARG;; # 指定目標實例狀態(如 ACTIVE/BUILD)i) CHECK_INTERVAL=$OPTARG;; # 自定義檢測間隔時間c) CONCURRENCY=$OPTARG;; # 調整并發線程數l) LOG_FILE=$OPTARG;; # 指定日志文件路徑*) echo -e "${RED}用法: $0 [-s 狀態] [-i 間隔] [-c 并發數] [-l 日志路徑]${NC}"exit 1;;esac
done# 初始化 OpenStack 環境
source /openstack/admin-openrc.sh || { log "${RED}錯誤:環境變量加載失敗,請檢查 admin-openrc.sh 文件權限或路徑${NC}"exit 1
}# 檢查日志目錄可寫性
if [ ! -w "$(dirname "$LOG_FILE")" ]; thenecho -e "${RED}錯誤:日志目錄不可寫 [路徑: $(dirname "$LOG_FILE")]${NC}" >&2exit 1
fi# 初始化臨時文件(記錄已刪除實例)
> "$DELETED_INSTANCES_FILE"# 進程鎖檢查(防止重復運行)
LOCK_FILE="/tmp/os_clean.lock"
if [ -e "$LOCK_FILE" ]; thenlog "${YELLOW}警告:檢測到已有清理進程運行中 [PID: $(cat $LOCK_FILE)]${NC}"exit 1
fi
echo $$ > "$LOCK_FILE"
trap 'rm -f "$LOCK_FILE"; TOTAL_DELETED_INSTANCES=$(wc -l < "$DELETED_INSTANCES_FILE"); log "${GREEN}===== 腳本進程中斷退出,已刪除實例數: $TOTAL_DELETED_INSTANCES ====="; rm -f "$DELETED_INSTANCES_FILE"' EXIT# 安全確認(確保轉義符被解析)
if [[ -t 0 ]]; thenread -p "$(printf "${YELLOW}危險操作:是否確認執行刪除實例?(y/N): ${NC}")" -n 1 confirm[[ $confirm != "y" ]] && { log "操作已取消"; exit; }echo
fi# 主循環(狀態檢測與刪除)
log "\n${GREEN}===== 開始刪除實例 [時間: $(date +%T)] ====="
start_time=$(date +%s)
empty_count=0 # 連續空檢測計數器while :; do# 超時檢查(防止無限等待)if (( $(date +%s) - start_time > MAX_WAIT_TIME )); thenlog "${RED}錯誤:操作超時,已超過最大等待時間(${MAX_WAIT_TIME} 秒)${NC}"exit 1fi# 獲取目標實例列表instances=$(safe_get_instances "${STATUS:-ACTIVE}")creating_instances=$(safe_get_instances "BUILD")# 優先刪除運行中的實例if [ -n "$instances" ]; thenlog "檢測到 ${#instances[@]} 個運行中實例,啟動并發刪除..."printf "%s\n" "${instances[@]}" | xargs -P $CONCURRENCY -I {} bash -c "delete_InstanceMAX_RETRY='$delete_InstanceMAX_RETRY'LOG_FILE='$LOG_FILE'DELETED_INSTANCES_FILE='$DELETED_INSTANCES_FILE'$(declare -f log retry_delete)retry_delete \"{}\""sleep $((CHECK_INTERVAL/2)) # 降低 API 請求頻率continuefi# 處理創建中的實例(等待后重試)if [ -n "$creating_instances" ]; thenlog "${YELLOW}提示:檢測到 ${#creating_instances[@]} 個創建中實例,等待 ${CHECK_INTERVAL} 秒...${NC}"sleep $CHECK_INTERVALcontinuefi# 空狀態處理(連續檢測退出機制)if [ -z "$instances" ]; thenlog "${YELLOW}提示:未發現可操作實例,等待 ${CHECK_INTERVAL} 秒后重試,至多重試${no_InstanceMAX_RETRY_TIME}次...${NC}"sleep $CHECK_INTERVAL# 連續${no_InstanceMAX_RETRY_TIME} 次空檢測則退出if (( empty_count++ >= ${no_InstanceMAX_RETRY_TIME} )); thenTOTAL_DELETED_INSTANCES=$(wc -l < "$DELETED_INSTANCES_FILE")log "${GREEN}===== 腳本運行清理完成,已刪除實例總數: ${TOTAL_DELETED_INSTANCES} ====="exit 0ficontinuefiempty_count=0 # 重置空檢測計數器
done