Compare commits
6
Commits
main
...
833b33e042
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
833b33e042 | ||
|
|
50d51b328f | ||
|
|
e031bd0c6d | ||
|
|
6fa2891d41 | ||
|
|
f8ddfa48a4 | ||
|
|
3999760d02 |
Executable
+263
@@ -0,0 +1,263 @@
|
||||
#!/bin/bash
|
||||
# cleanup-server - Dọn dẹp + nâng cấp server (Ubuntu/Arch), interactive, tuần tự.
|
||||
# Cách dùng:
|
||||
# cleanup-server # hiện menu chọn target (local hoặc server alias)
|
||||
# cleanup-server --run-steps # (nội bộ) chạy thẳng 6 bước trên máy hiện tại
|
||||
|
||||
# -----------------------------
|
||||
# Color helpers (tự tắt khi không phải TTY)
|
||||
# -----------------------------
|
||||
if [ -t 1 ]; then
|
||||
C_RESET=$'\033[0m'
|
||||
C_TITLE=$'\033[1;36m' # tiêu đề
|
||||
C_OK=$'\033[1;32m' # thành công
|
||||
C_DEL=$'\033[1;31m' # sẽ xóa / lỗi
|
||||
C_WARN=$'\033[1;33m' # cảnh báo
|
||||
else
|
||||
C_RESET=""; C_TITLE=""; C_OK=""; C_DEL=""; C_WARN=""
|
||||
fi
|
||||
|
||||
# -----------------------------
|
||||
# Banner rainbow (giống style `cleanup`)
|
||||
# -----------------------------
|
||||
print_banner() {
|
||||
local use_color=0 reset="" i=0 line
|
||||
local -a lines=(
|
||||
' ██████╗██╗ ██╗ ██████╗██╗ ██╗██╗ ██╗██████╗ ███████╗███╗ ██╗ ██████╗██╗ ██╗'
|
||||
' ██╔════╝██║ ██║██╔════╝██║ ██║██║ ██║██╔══██╗ ██╔════╝████╗ ██║██╔═══██╗╚██╗██╔╝'
|
||||
' ██║ ██║ ██║██║ ███████║██║ ██║██║ ██║ █████╗ ██╔██╗ ██║██║ ██║ ╚███╔╝ '
|
||||
' ██║ ██║ ██║██║ ██╔══██║██║ ██║██║ ██║ ██╔══╝ ██║╚██╗██║██║ ██║ ██╔██╗ '
|
||||
' ╚██████╗╚██████╔╝╚██████╗██║ ██║╚██████╔╝██████╔╝ ███████╗██║ ╚████║╚██████╔╝██╔╝ ██╗'
|
||||
' ╚═════╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝'
|
||||
)
|
||||
local -a colors=()
|
||||
if [ -t 1 ]; then
|
||||
use_color=1
|
||||
reset=$'\033[0m'
|
||||
colors=(
|
||||
$'\033[1;38;5;51m' $'\033[1;38;5;87m' $'\033[1;38;5;123m'
|
||||
$'\033[1;38;5;159m' $'\033[1;38;5;220m' $'\033[1;38;5;214m'
|
||||
)
|
||||
fi
|
||||
echo ""
|
||||
for line in "${lines[@]}"; do
|
||||
if [ "$use_color" -eq 1 ]; then
|
||||
printf '%b%s%b\n' "${colors[$i]}" "$line" "$reset"
|
||||
else
|
||||
printf '%s\n' "$line"
|
||||
fi
|
||||
i=$((i + 1))
|
||||
done
|
||||
echo ""
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Phát hiện distro qua /etc/os-release → debian | arch | unknown
|
||||
# -----------------------------
|
||||
detect_distro() {
|
||||
[ -r /etc/os-release ] || { echo unknown; return; }
|
||||
local id id_like
|
||||
. /etc/os-release 2>/dev/null
|
||||
id="${ID:-}"; id_like="${ID_LIKE:-}"
|
||||
case "$id $id_like" in
|
||||
*arch*) echo arch ;;
|
||||
*debian*) echo debian ;;
|
||||
*ubuntu*) echo debian ;;
|
||||
*) echo unknown ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Hỏi Y/n (Enter = Yes). Trả về 0 = đồng ý, 1 = hủy.
|
||||
# -----------------------------
|
||||
confirm_yn() {
|
||||
local prompt="$1" confirm
|
||||
read -r -p " ${prompt} (Y/n): " confirm
|
||||
if [[ -n "$confirm" && ! "$confirm" =~ ^([yY]|[yY][eE][sS])$ ]]; then
|
||||
echo " Đã hủy."
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Danh sách target fix cứng (alias từ ~/.ssh/config)
|
||||
# -----------------------------
|
||||
TARGETS=("local" "ta" "toc" "oc" "cse" "vrc" "aws" "tk" "od")
|
||||
TARGET_CURSOR=0
|
||||
TARGET=""
|
||||
|
||||
# Vẽ menu single-select
|
||||
draw_target_menu() {
|
||||
if [ "$1" = "redraw" ]; then
|
||||
printf '\033[%dA' "$(( ${#TARGETS[@]} + 2 ))"
|
||||
fi
|
||||
echo " Chọn target (↑↓: di chuyển | Enter: chọn):"
|
||||
echo ""
|
||||
local i
|
||||
for ((i = 0; i < ${#TARGETS[@]}; i++)); do
|
||||
local prefix=" "
|
||||
if [ "$i" -eq "$TARGET_CURSOR" ]; then
|
||||
prefix="${C_TITLE}▸ ${C_RESET}"
|
||||
fi
|
||||
printf '\r\033[K%s%s\n' "$prefix" "${TARGETS[$i]}"
|
||||
done
|
||||
}
|
||||
|
||||
# Chạy menu, đặt biến toàn cục TARGET
|
||||
select_target() {
|
||||
draw_target_menu
|
||||
while true; do
|
||||
IFS= read -rsn1 key
|
||||
case "$key" in
|
||||
$'\x1b')
|
||||
read -rsn2 seq
|
||||
case "$seq" in
|
||||
'[A') TARGET_CURSOR=$(( (TARGET_CURSOR - 1 + ${#TARGETS[@]}) % ${#TARGETS[@]} ));;
|
||||
'[B') TARGET_CURSOR=$(( (TARGET_CURSOR + 1) % ${#TARGETS[@]} ));;
|
||||
esac
|
||||
;;
|
||||
'') # Enter
|
||||
echo ""
|
||||
TARGET="${TARGETS[$TARGET_CURSOR]}"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
draw_target_menu "redraw"
|
||||
done
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Bước 1: Nâng cấp hệ thống theo distro
|
||||
# -----------------------------
|
||||
step_upgrade() {
|
||||
echo "${C_TITLE}--- [System Upgrade] ---${C_RESET}"
|
||||
local distro
|
||||
distro=$(detect_distro)
|
||||
case "$distro" in
|
||||
debian)
|
||||
echo " Distro: Debian/Ubuntu (apt)."
|
||||
sudo apt-get update || { echo "${C_DEL} ✗ apt-get update thất bại.${C_RESET}"; echo ""; return; }
|
||||
local upgradable
|
||||
upgradable=$(apt list --upgradable 2>/dev/null | grep -c 'upgradable')
|
||||
echo " ${C_WARN}✗ ${upgradable} package có thể nâng cấp.${C_RESET}"
|
||||
if confirm_yn "Upgrade + autoremove?"; then
|
||||
sudo apt-get upgrade -y
|
||||
sudo apt-get autoremove --purge -y
|
||||
echo "${C_OK} ✓ Đã nâng cấp xong.${C_RESET}"
|
||||
fi
|
||||
;;
|
||||
arch)
|
||||
echo " Distro: Arch (pacman)."
|
||||
local helper=""
|
||||
command -v paru >/dev/null 2>&1 && helper="paru"
|
||||
[ -z "$helper" ] && command -v yay >/dev/null 2>&1 && helper="yay"
|
||||
[ -z "$helper" ] && helper="sudo pacman"
|
||||
echo " Helper: $helper"
|
||||
if confirm_yn "Chạy $helper -Syu?"; then
|
||||
$helper -Syu
|
||||
echo "${C_OK} ✓ Đã nâng cấp xong.${C_RESET}"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "${C_WARN} ⚠ Distro không hỗ trợ upgrade, bỏ qua.${C_RESET}"
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Chọn 'docker' hoặc 'sudo docker' tùy permission
|
||||
# Trả về chuỗi lệnh qua echo (gán: DC=$(docker_cmd))
|
||||
# -----------------------------
|
||||
docker_cmd() {
|
||||
if docker info >/dev/null 2>&1; then
|
||||
echo "docker"
|
||||
elif sudo -n docker info >/dev/null 2>&1; then
|
||||
echo "sudo docker"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Bước 2: Docker — df rồi prune từng loại
|
||||
# -----------------------------
|
||||
step_docker() {
|
||||
echo "${C_TITLE}--- [Docker] ---${C_RESET}"
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "${C_WARN} ⚠ docker command not found.${C_RESET}"
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
local DC
|
||||
DC=$(docker_cmd)
|
||||
if [ -z "$DC" ]; then
|
||||
echo "${C_WARN} ⚠ Không có quyền truy cập docker (cần group docker hoặc sudo).${C_RESET}"
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
echo " Lệnh: $DC"
|
||||
$DC system df
|
||||
echo ""
|
||||
confirm_yn "Prune images (-a)?" && $DC image prune -a -f
|
||||
confirm_yn "Prune containers?" && $DC container prune -f
|
||||
confirm_yn "Prune volumes?" && $DC volume prune -f
|
||||
confirm_yn "Prune build cache?" && $DC builder prune -f
|
||||
confirm_yn "Prune networks?" && $DC network prune -f
|
||||
echo "${C_OK} ✓ Docker cleanup xong.${C_RESET}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Chạy tuần tự 6 bước (stub — các bước thêm ở Task 4-9)
|
||||
# -----------------------------
|
||||
run_all_steps() {
|
||||
step_upgrade
|
||||
step_docker
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Chạy trên target đã chọn.
|
||||
# local → chạy tại chỗ.
|
||||
# alias → self-bootstrap: base64 script qua argv, giữ stdin=terminal
|
||||
# để read/màu tương tác hoạt động qua PTY của `ssh -t`.
|
||||
# -----------------------------
|
||||
run_on_target() {
|
||||
local target="$1"
|
||||
if [ "$target" = "local" ]; then
|
||||
run_all_steps
|
||||
return $?
|
||||
fi
|
||||
local b64
|
||||
b64=$(base64 < "$0" | tr -d '\n') || {
|
||||
echo "${C_DEL} ✗ Không mã hóa được script.${C_RESET}"
|
||||
return 1
|
||||
}
|
||||
# Giải mã ra file tạm trên remote rồi chạy; stdin không bị redirect → read OK.
|
||||
ssh -t "$target" \
|
||||
"umask 077; t=\$(mktemp); printf '%s' '$b64' | base64 -d > \"\$t\" && bash \"\$t\" --run-steps; r=\$?; rm -f \"\$t\"; exit \$r" \
|
||||
|| { echo "${C_DEL} ✗ ssh tới $target thất bại.${C_RESET}"; return 1; }
|
||||
}
|
||||
|
||||
# -----------------------------
|
||||
# Main (phân nhánh theo argv)
|
||||
# -----------------------------
|
||||
main() {
|
||||
if [ "${1:-}" = "--run-steps" ]; then
|
||||
echo "${C_TITLE}===== 🧹 Cleanup-server (--run-steps) =====${C_RESET}"
|
||||
echo ""
|
||||
run_all_steps
|
||||
echo ""
|
||||
echo "${C_OK}===== ✅ Cleanup-server hoàn tất =====${C_RESET}"
|
||||
return
|
||||
fi
|
||||
print_banner
|
||||
echo "${C_TITLE}===== 🧹 Cleanup-server =====${C_RESET}"
|
||||
echo ""
|
||||
select_target
|
||||
echo ""
|
||||
run_on_target "$TARGET"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -24,7 +24,6 @@ run_ssh() {
|
||||
# Run SSH commands for each server
|
||||
run_ssh "oc" 'sudo apt-get upgrade -y'
|
||||
run_ssh "tk" 'sudo apt-get upgrade -y'
|
||||
run_ssh "cc" 'sudo apt-get upgrade -y'
|
||||
run_ssh "rpi3" 'sudo apt-get upgrade -y'
|
||||
run_ssh "cse-z" 'sudo apt-get upgrade -y'
|
||||
run_ssh "hp" 'sudo apt-get upgrade -y'
|
||||
|
||||
Reference in New Issue
Block a user