diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..dabd2ac --- /dev/null +++ b/install.sh @@ -0,0 +1,296 @@ +#!/bin/bash +#==================================================== +# Swap Builder - Swap 管理工具 +# 夏日之瓜×仰望星辰工作室 出品 +#==================================================== + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' + +# 检查 root 权限 +check_root() { + if [ "$(id -u)" -ne 0 ]; then + echo -e "${RED}[错误] 此脚本需要 root 权限运行。${NC}" + echo -e "${YELLOW}请使用:curl -sSL swap.fangqihang.cn | sudo bash${NC}" + exit 1 + fi +} + +# 检查交互环境 +check_tty() { + if [ ! -e /dev/tty ]; then + echo -e "${RED}[错误] 无法访问 /dev/tty,请在终端中运行此脚本。${NC}" + exit 1 + fi +} + +# 打印横幅 +print_banner() { + echo -e "${CYAN}" + echo "==================================================" + echo " Swap Builder - Swap 管理工具" + echo "==================================================" + echo " 夏日之瓜×仰望星辰工作室 出品" + echo "==================================================" + echo -e "${NC}" +} + +# 显示当前状态 +show_status() { + echo -e "${BLUE}---------- 当前系统状态 ----------${NC}" + echo "" + + # Swap 设备信息 + if command -v swapon &>/dev/null; then + local swap_info=$(swapon --show 2>/dev/null) + if [ -n "$swap_info" ]; then + echo -e "${GREEN}[Swap 设备]${NC}" + echo "$swap_info" + else + echo -e "${YELLOW}[Swap 设备] 当前未启用 Swap${NC}" + fi + fi + + echo "" + + # 内存信息 + if command -v free &>/dev/null; then + echo -e "${GREEN}[内存使用]${NC}" + free -h 2>/dev/null || free -m 2>/dev/null + fi + + echo "" + + # swappiness + local current_swappiness=$(cat /proc/sys/vm/swappiness 2>/dev/null) + if [ -n "$current_swappiness" ]; then + echo -e "${GREEN}[swappiness] 当前值:${current_swappiness}${NC}" + fi + + echo "" + echo -e "${BLUE}-----------------------------------${NC}" + echo "" +} + +# 设置 Swap +set_swap() { + echo -e "${CYAN}【设置 Swap】${NC}" + echo "" + echo -e "请输入想要设置的 Swap 大小(单位:MB)" + echo -e "${YELLOW}建议:物理内存的 1~2 倍,例如 2048 = 2GB${NC}" + echo -e "${YELLOW}输入 0 可关闭 Swap${NC}" + echo "" + echo -n "Swap 大小 (MB): " + read swap_size < /dev/tty + echo "" + + # 输入校验 + if ! [[ "$swap_size" =~ ^[0-9]+$ ]]; then + echo -e "${RED}[错误] 请输入有效的数字!${NC}" + return 1 + fi + + # 关闭 Swap + if [ "$swap_size" -eq 0 ]; then + echo -e "${YELLOW}正在关闭 Swap...${NC}" + swapoff -a 2>/dev/null + + # 从 fstab 中移除 swap 条目(备份后操作) + if grep -q ' swap ' /etc/fstab 2>/dev/null; then + cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d%H%M%S) + sed -i '/ swap /d' /etc/fstab + echo -e "${GREEN}已备份 /etc/fstab 并移除 Swap 条目${NC}" + fi + + echo -e "${GREEN}Swap 已成功关闭!${NC}" + return 0 + fi + + # 范围检查 + if [ "$swap_size" -lt 128 ]; then + echo -e "${RED}[错误] Swap 大小不能小于 128MB!${NC}" + return 1 + fi + + if [ "$swap_size" -gt 65536 ]; then + echo -e "${RED}[错误] Swap 大小不能超过 65536MB (64GB)!${NC}" + return 1 + fi + + # 磁盘空间检查 + local available_mb=$(df -m / 2>/dev/null | awk 'NR==2 {print $4}') + local required_mb=$((swap_size + 1024)) + + if [ -z "$available_mb" ]; then + echo -e "${YELLOW}[警告] 无法检测磁盘空间,继续操作...${NC}" + elif [ "$available_mb" -lt "$required_mb" ]; then + echo -e "${RED}[错误] 磁盘空间不足!${NC}" + echo -e "${YELLOW}可用:${available_mb}MB | 需要:${required_mb}MB(含 1GB 余量)${NC}" + return 1 + fi + + # 确认操作 + echo -e "${YELLOW}即将创建 ${swap_size}MB 的 Swap 文件${NC}" + echo -n "确认继续?(y/n): " + read confirm < /dev/tty + echo "" + + if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then + echo -e "${YELLOW}操作已取消。${NC}" + return 0 + fi + + # 备份 fstab + cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d%H%M%S) 2>/dev/null + echo -e "${GREEN}已备份 /etc/fstab${NC}" + + # 关闭现有 swap + swapoff -a 2>/dev/null + + # 确定 swap 文件路径 + local swap_file="/swapfile" + if [ -d "/www" ]; then + swap_file="/www/swap" + fi + + # 移除旧文件(如果存在) + if [ -f "$swap_file" ]; then + rm -f "$swap_file" + fi + + # 创建 swap 文件 + echo -e "${YELLOW}正在创建 Swap 文件(${swap_size}MB)...${NC}" + + if command -v fallocate &>/dev/null; then + fallocate -l ${swap_size}M "$swap_file" 2>/dev/null + if [ $? -ne 0 ]; then + echo -e "${YELLOW}fallocate 不可用,使用 dd 创建...${NC}" + dd if=/dev/zero of="$swap_file" bs=1M count=$swap_size + fi + else + dd if=/dev/zero of="$swap_file" bs=1M count=$swap_size + fi + + # 检查文件是否创建成功 + if [ ! -f "$swap_file" ]; then + echo -e "${RED}[错误] Swap 文件创建失败!${NC}" + return 1 + fi + + # 设置权限 + chmod 600 "$swap_file" + + # 创建 swap 并启用 + mkswap "$swap_file" + swapon "$swap_file" + + if [ $? -ne 0 ]; then + echo -e "${RED}[错误] Swap 启用失败!${NC}" + return 1 + fi + + # 持久化到 fstab(先移除旧条目再添加) + sed -i '/ swap /d' /etc/fstab + echo "$swap_file none swap sw 0 0" >> /etc/fstab + + echo "" + echo -e "${GREEN}Swap 设置成功!${NC}" + echo "" + swapon --show 2>/dev/null + echo "" + free -h 2>/dev/null || free -m 2>/dev/null +} + +# 设置 swappiness +set_swappiness() { + echo -e "${CYAN}【设置 swappiness】${NC}" + echo "" + echo -e "swappiness 控制系统使用 Swap 的积极程度" + echo -e " ${YELLOW}0${NC} = 尽量不使用 Swap" + echo -e " ${YELLOW}100${NC} = 积极使用 Swap" + echo -e " ${YELLOW}建议${NC}:服务器推荐 10~30" + echo "" + + local current=$(cat /proc/sys/vm/swappiness 2>/dev/null) + echo -e "${GREEN}当前 swappiness 值:${current}${NC}" + echo "" + echo -n "请输入 swappiness 值 (0-100): " + read swappiness_val < /dev/tty + echo "" + + # 输入校验 + if ! [[ "$swappiness_val" =~ ^[0-9]+$ ]]; then + echo -e "${RED}[错误] 请输入有效的数字!${NC}" + return 1 + fi + + if [ "$swappiness_val" -gt 100 ]; then + echo -e "${RED}[错误] swappiness 值必须在 0~100 之间!${NC}" + return 1 + fi + + # 临时生效 + sysctl -w vm.swappiness=$swappiness_val + + # 持久化 + if grep -q "^vm.swappiness" /etc/sysctl.conf 2>/dev/null; then + sed -i "s/^vm.swappiness=.*/vm.swappiness=$swappiness_val/" /etc/sysctl.conf + else + echo "vm.swappiness=$swappiness_val" >> /etc/sysctl.conf + fi + + echo "" + echo -e "${GREEN}swappiness 已设置为 ${swappiness_val}(已持久化到 /etc/sysctl.conf)${NC}" +} + +# 主菜单 +main_menu() { + while true; do + clear 2>/dev/null + print_banner + show_status + + echo -e "${CYAN}请选择操作:${NC}" + echo -e " ${GREEN}1${NC}) 设置 Swap" + echo -e " ${GREEN}2${NC}) 设置优先度(swappiness)" + echo -e " ${GREEN}0${NC}) 退出" + echo "" + echo -n "请输入选项 [0-2]: " + read choice < /dev/tty + echo "" + + case $choice in + 1) + set_swap + ;; + 2) + set_swappiness + ;; + 0) + echo -e "${GREEN}感谢使用 Swap Builder!${NC}" + echo -e "${CYAN}—— 夏日之瓜×仰望星辰工作室 出品 ——${NC}" + exit 0 + ;; + *) + echo -e "${RED}无效选项,请重新输入!${NC}" + ;; + esac + + echo "" + echo -n "按回车键返回主菜单..." + read < /dev/tty + done +} + +# 捕获 Ctrl+C +trap 'echo ""; echo -e "${YELLOW}操作已中断。${NC}"; exit 1' INT + +# 入口 +check_root +check_tty +main_menu