Last active
June 10, 2025 14:45
-
-
Save lainbo/b8de16e1ed5dc9ab9cc0f8b8ee756d00 to your computer and use it in GitHub Desktop.
服务器脚本
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Title: add-swap-debian-ubuntu.sh | |
| # Description: A streamlined script to add a swap file on Debian/Ubuntu systems. | |
| # Interactively asks for size, with a 2x RAM default. | |
| # Date: 2025-06-10 | |
| # Exit immediately if a command exits with a non-zero status. | |
| set -e | |
| # --- Helper Functions & Variables --- | |
| # Colors for pretty printing | |
| RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; BLUE="\033[34m"; NC='\033[0m'; | |
| # Logging functions | |
| success() { printf "${GREEN}✔ %s${NC} ${@:2}\n" "$1"; } | |
| info() { printf "${BLUE}ℹ %s${NC} ${@:2}\n" "$1"; } | |
| danger() { printf "${RED}✖ %s${NC}\n" "$@" >&2; } | |
| warn() { printf "${YELLOW}⚠ %s${NC}\n" "$@"; } | |
| # --- Main Logic --- | |
| create_swap() { | |
| # 1. Check for root privileges | |
| if [[ $EUID -ne 0 ]]; then | |
| danger "此脚本必须以 root 用户身份运行。" | |
| danger "请尝试使用: sudo bash <(curl -Lso- ...)" | |
| exit 1 | |
| fi | |
| # 2. Display current system status for context | |
| info "--- 当前系统状态 ---" | |
| free -h | |
| swapon --show | |
| echo | |
| # 3. Handle any pre-existing /swapfile for a clean slate | |
| if grep -q "/swapfile" /proc/swaps; then | |
| warn "检测到已激活的 /swapfile,将先进行移除..." | |
| swapoff /swapfile | |
| rm -f /swapfile | |
| # Clean up the fstab entry as well | |
| sed -i '/\/swapfile/d' /etc/fstab | |
| success "旧的 /swapfile 已成功移除。" | |
| elif [ -f /swapfile ]; then | |
| warn "检测到未激活的 /swapfile 文件,将进行移除..." | |
| rm -f /swapfile | |
| success "旧的 /swapfile 文件已成功移除。" | |
| fi | |
| # 4. Get user input for swap size, with a smart default | |
| local default_swap_mb=$(($(free -m | awk '/^Mem:/{print $2}') * 2)) | |
| local swap_size_mb | |
| read -p "请输入要创建的 Swap 大小 (单位: MB) [默认为内存的两倍: ${default_swap_mb}MB]: " swap_size_mb | |
| # If the input is empty, use the default value | |
| swap_size_mb=${swap_size_mb:-$default_swap_mb} | |
| # Validate that the input is a number | |
| if ! [[ "$swap_size_mb" =~ ^[0-9]+$ ]]; then | |
| danger "输入无效。请输入一个纯数字。" | |
| exit 1 | |
| fi | |
| # 5. Check for sufficient disk space before proceeding | |
| info "正在检查磁盘剩余空间..." | |
| local available_space_kb=$(df -k / | awk 'NR==2 {print $4}') | |
| local requested_space_kb=$((swap_size_mb * 1024)) | |
| if (( requested_space_kb > available_space_kb )); then | |
| danger "磁盘空间不足!" | |
| danger "请求创建 ${swap_size_mb}MB Swap, 但根目录 (/) 仅剩约 $((available_space_kb / 1024))MB 空间。" | |
| exit 1 | |
| fi | |
| success "磁盘空间充足。" | |
| # 6. Create the new swap file using the most efficient method | |
| info "正在创建新的 Swap 文件: /swapfile, 大小: ${swap_size_mb}MB..." | |
| if fallocate -l "${swap_size_mb}M" /swapfile &>/dev/null; then | |
| success "使用 fallocate 快速创建文件成功。" | |
| else | |
| warn "fallocate 失败, 自动切换到 dd 命令 (可能会慢一些)..." | |
| dd if=/dev/zero of=/swapfile bs=1M count=${swap_size_mb} &>/dev/null | |
| success "使用 dd 创建文件成功。" | |
| fi | |
| # 7. Set permissions, format, and activate the swap file | |
| info "正在设置权限、格式化并激活 Swap..." | |
| chmod 600 /swapfile | |
| mkswap /swapfile | |
| swapon /swapfile | |
| # 8. Make the swap file permanent across reboots | |
| info "正在将 Swap 配置写入 /etc/fstab 以便开机自启..." | |
| echo "/swapfile swap swap defaults 0 0" >> /etc/fstab | |
| # 9. Final confirmation | |
| echo | |
| success "--- Swap 添加成功! ---" | |
| info "--- 操作完成后的系统状态 ---" | |
| free -h | |
| swapon --show | |
| } | |
| # --- Execute the script --- | |
| create_swap | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # 一个自包含的、交互式修改 SSH 端口的函数 | |
| # [v3 - 最终修正版] 使用最可靠的端口监听状态进行验证 | |
| change_ssh_port_interactive() { | |
| local port | |
| local ssh_config_file="/etc/ssh/sshd_config" | |
| # 1. 获取并验证用户输入 | |
| read -p "请输入新的 SSH 端口号 (1-65535),或按 Enter 取消: " port | |
| if [[ -z "$port" ]]; then | |
| echo "操作已取消。" | |
| return 0 | |
| fi | |
| if ! [[ "$port" =~ ^[0-9]+$ ]] || ! [ "$port" -ge 1 ] || ! [ "$port" -le 65535 ]; then | |
| echo "❌ 错误: 输入的不是一个有效的端口号 (1-65535)。" >&2 | |
| return 1 | |
| fi | |
| # 预检查端口是否被占用 | |
| if ss -tlpn | grep -q ":$port\b"; then | |
| echo "❌ 错误: 端口 $port 已被占用。" >&2 | |
| return 1 | |
| fi | |
| # 2. 备份并修改配置文件 | |
| echo "⚙️ 正在备份和修改 SSH 配置文件..." | |
| cp "$ssh_config_file" "${ssh_config_file}.bak_$(date +%F)_$(date +%T)" | |
| # 使用-E参数支持扩展正则表达式,\s匹配空白字符,更健壮 | |
| sed -i.bak -E "s/^[#\s]*Port\s+.*/Port $port/" "$ssh_config_file" | |
| if ! grep -q "^Port $port" "$ssh_config_file"; then | |
| echo "❌ 错误: 修改配置文件 $ssh_config_file 失败。" >&2 | |
| return 1 | |
| fi | |
| echo "✅ 配置文件已修改,新端口为: $port" | |
| # 3. 重启 SSH 服务 | |
| echo "🔄 正在重启 SSH 服务..." | |
| systemctl restart ssh | |
| # 4. 最终验证 (使用最简单的端口监听检查) | |
| echo "🔍 正在验证服务状态..." | |
| local retries=5 | |
| local success=0 | |
| for ((i=1; i<=retries; i++)); do | |
| # 核心验证:检查服务是否活跃,并且目标端口是否在监听 | |
| if systemctl is-active --quiet ssh && ss -tlpn | grep -q ":$port\b"; then | |
| echo "✅ SSH 服务已启动,并成功监听在端口 $port。" | |
| success=1 | |
| break | |
| fi | |
| echo " 等待服务响应... (尝试 $i/$retries)" | |
| sleep 1 | |
| done | |
| if [[ "$success" -eq 0 ]]; then | |
| echo "❌ 严重错误: 未能验证 SSH 在新端口 $port 上监听!请手动检查!" >&2 | |
| echo " - 检查服务状态: systemctl status ssh" >&2 | |
| echo " - 检查服务日志: journalctl -u ssh" >&2 | |
| echo " - 检查监听端口: ss -tlpn | grep ssh" >&2 | |
| return 1 | |
| fi | |
| # 5. 显示最终的重要警告 | |
| echo "" | |
| echo "============================= ⚠️ 重要提醒 ⚠️ =============================" | |
| echo "操作已成功,但你随时可能被锁定!在断开当前连接之前,请务必:" | |
| echo "为新端口 '$port' 配置防火墙!" | |
| echo "在确认新连接成功后,才能安全地断开当前会话!" | |
| echo "==========================================================================" | |
| } | |
| # 调用函数开始执行 | |
| change_ssh_port_interactive |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # | |
| # Title: prefer-ipv4.sh | |
| # Description: A standalone script to set the system to prefer IPv4 over IPv6 for outbound connections. | |
| # Date: 2025-06-10 | |
| # Exit immediately if a command exits with a non-zero status. | |
| set -e | |
| # --- Pre-flight Checks --- | |
| # Check if curl is installed, as it's needed for verification. | |
| if ! command -v curl >/dev/null 2>&1; then | |
| echo "错误: 未找到 curl 命令,请先安装。" >&2 | |
| exit 1 | |
| fi | |
| # --- Helper Functions & Variables --- | |
| # Colors for pretty printing | |
| RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; BLUE="\033[34m"; NC='\033[0m'; | |
| # Logging functions | |
| success() { printf "${GREEN}✔ %s${NC} ${@:2}\n" "$1"; } | |
| info() { printf "${BLUE}ℹ %s${NC} ${@:2}\n" "$1"; } | |
| danger() { printf "${RED}✖ %s${NC}\n" "$@" >&2; } # Errors to stderr | |
| warn() { printf "${YELLOW}⚠ %s${NC}\n" "$@"; } | |
| # Configuration variables | |
| GAICONF=/etc/gai.conf | |
| # Using a specific mark to avoid conflicts with the original script | |
| MARK="# vpsDance-prefer-ipv4" | |
| # Function to run commands with sudo if not already root | |
| # It ensures that all necessary functions and variables are available in the sudo context. | |
| with_sudo() { | |
| if ! command -v sudo >/dev/null 2>&1; then | |
| danger "错误: 未找到 sudo 命令。请以 root 用户运行此脚本,或先安装 sudo。" | |
| return 1 | |
| fi | |
| local cmd | |
| # This clever part packages up the necessary functions and variables to be available inside the 'sudo bash -c' environment | |
| if [[ "$(type -t "$1")" == "function" ]]; then | |
| local declare_vars="$(declare -p GAICONF MARK RED GREEN YELLOW BLUE NC 2>/dev/null)" | |
| local declare_funcs="$(declare -f success info danger warn restore_ip46 prefer_ipv4 check_ip46)" | |
| cmd="$declare_vars; $declare_funcs; $1 "'"${@:2}"' | |
| else | |
| # Fallback for simple commands | |
| cmd="$1 "'"${@:2}"' | |
| fi | |
| if [[ $EUID -ne 0 ]]; then | |
| info "此操作需要 root 权限,将使用 sudo 执行..." | |
| sudo bash -c "$cmd" -- "$@" < /dev/tty | |
| else | |
| bash -c "$cmd" -- "$@" | |
| fi | |
| } | |
| # --- Core Logic --- | |
| # Restores the gai.conf file to its default state by removing our marked lines. | |
| # This prevents duplicate entries on subsequent runs. | |
| restore_ip46() { | |
| info "正在清理旧的配置..." | |
| # Check if the file exists and is a regular file | |
| if [[ -f $GAICONF ]]; then | |
| # Use sed to remove any lines containing our specific mark | |
| sed -i "/$MARK/d" $GAICONF | |
| fi | |
| } | |
| # Sets the system to prefer IPv4 by modifying /etc/gai.conf. | |
| prefer_ipv4() { | |
| info "正在配置系统为 IPv4 优先..." | |
| # First, clean up any previous configurations made by this script. | |
| restore_ip46 | |
| # Add the precedence rule to gai.conf. | |
| # This rule gives IPv4-mapped IPv6 addresses (::ffff:0:0/96) a high precedence value (100), | |
| # effectively making the system prefer IPv4 for connections when both are available. | |
| echo "precedence ::ffff:0:0/96 100 $MARK" >>$GAICONF | |
| success "配置文件 /etc/gai.conf 已更新。" | |
| # Verify the change. | |
| check_ip46 | |
| } | |
| # Checks the current public IP address to verify which protocol is being preferred. | |
| check_ip46() { | |
| info "正在检测当前网络访问优先级..." | |
| warn "(如果下方显示 IPv4 地址, 则代表已成功设为 IPv4 优先)" | |
| printf "检测结果: " | |
| # Use curl to fetch the public IP. If it returns an IPv4 address, the setting is working. | |
| # Added a fallback for detection. | |
| curl -sS --max-time 5 ip.sb || curl -sS --max-time 5 ifconfig.me || echo "检测失败,请手动验证" | |
| echo | |
| } | |
| # --- Main Execution --- | |
| info "--- 开始设置网络为 IPv4 优先 ---" | |
| # Call the main function with sudo wrapper to handle permissions. | |
| with_sudo prefer_ipv4 | |
| success "--- 所有操作已完成 ---" | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Colors | |
| gl_lan="\033[36m" | |
| gl_bai="\033[96m" | |
| gl_end="\033[0m" | |
| # Helper Functions | |
| current_timezone() { | |
| timedatectl 2>/dev/null | awk '/Time zone:/ {print $3}' || date +%Z | |
| } | |
| ip_address() { | |
| ipv4_address=$(curl -s4 ip.sb 2>/dev/null || curl -s4 ifconfig.me) | |
| ipv6_address=$(curl -s6 ip.sb 2>/dev/null || curl -s6 ifconfig.me) | |
| } | |
| output_status() { | |
| output="" | |
| if systemctl is-active docker >/dev/null 2>&1; then | |
| output="${output}Docker: 运行中 " | |
| fi | |
| if systemctl is-active nginx >/dev/null 2>&1; then | |
| output="${output}Nginx: 运行中 " | |
| fi | |
| } | |
| linux_ps() { | |
| clear | |
| ip_address | |
| local cpu_info=$(lscpu | awk -F': +' '/Model name:/ {print $2; exit}') | |
| local cpu_usage_percent=$(awk '{u=$2+$4; t=$2+$4+$5; if (NR==1){u1=u; t1=t;} else printf "%.0f\n", (($2+$4-u1) * 100 / (t-t1))}' \ | |
| <(grep 'cpu ' /proc/stat) <(sleep 1; grep 'cpu ' /proc/stat)) | |
| local cpu_cores=$(nproc) | |
| local cpu_freq=$(cat /proc/cpuinfo | grep "MHz" | head -n 1 | awk '{printf "%.1f GHz\n", $4/1000}') | |
| local mem_info=$(free -b | awk 'NR==2{printf "%.2f/%.2f MB (%.2f%%)", $3/1024/1024, $2/1024/1024, $3*100/$2}') | |
| local disk_info=$(df -h | awk '$NF=="/"{printf "%s/%s (%s)", $3, $2, $5}') | |
| local ipinfo=$(curl -s ipinfo.io) | |
| local country=$(echo "$ipinfo" | grep 'country' | awk -F': ' '{print $2}' | tr -d '",') | |
| local city=$(echo "$ipinfo" | grep 'city' | awk -F': ' '{print $2}' | tr -d '",') | |
| local isp_info=$(echo "$ipinfo" | grep 'org' | awk -F': ' '{print $2}' | tr -d '",') | |
| local load=$(uptime | awk '{print $(NF-2), $(NF-1), $NF}') | |
| local dns_addresses=$(awk '/^nameserver/{printf "%s ", $2} END {print ""}' /etc/resolv.conf) | |
| local cpu_arch=$(uname -m) | |
| local hostname=$(uname -n) | |
| local kernel_version=$(uname -r) | |
| local congestion_algorithm=$(sysctl -n net.ipv4.tcp_congestion_control) | |
| local queue_algorithm=$(sysctl -n net.core.default_qdisc) | |
| local os_info=$(grep PRETTY_NAME /etc/os-release | cut -d '=' -f2 | tr -d '"') | |
| output_status | |
| local current_time=$(date "+%Y-%m-%d %I:%M %p") | |
| local swap_info=$(free -m | awk 'NR==3{used=$3; total=$2; if (total == 0) {percentage=0} else {percentage=used*100/total}; printf "%dMB/%dMB (%d%%)", used, total, percentage}') | |
| local runtime=$(cat /proc/uptime | awk -F. '{run_days=int($1 / 86400);run_hours=int(($1 % 86400) / 3600);run_minutes=int(($1 % 3600) / 60); if (run_days > 0) printf("%d天 ", run_days); if (run_hours > 0) printf("%d时 ", run_hours); printf("%d分\n", run_minutes)}') | |
| local timezone=$(current_timezone) | |
| echo "" | |
| echo -e "系统信息查询" | |
| echo -e "${gl_lan}-------------" | |
| echo -e "${gl_lan}主机名: ${gl_bai}$hostname" | |
| echo -e "${gl_lan}系统版本: ${gl_bai}$os_info" | |
| echo -e "${gl_lan}Linux版本: ${gl_bai}$kernel_version" | |
| echo -e "${gl_lan}-------------" | |
| echo -e "${gl_lan}CPU架构: ${gl_bai}$cpu_arch" | |
| echo -e "${gl_lan}CPU型号: ${gl_bai}$cpu_info" | |
| echo -e "${gl_lan}CPU核心数: ${gl_bai}$cpu_cores" | |
| echo -e "${gl_lan}CPU频率: ${gl_bai}$cpu_freq" | |
| echo -e "${gl_lan}-------------" | |
| echo -e "${gl_lan}CPU占用: ${gl_bai}$cpu_usage_percent%" | |
| echo -e "${gl_lan}系统负载: ${gl_bai}$load" | |
| echo -e "${gl_lan}物理内存: ${gl_bai}$mem_info" | |
| echo -e "${gl_lan}虚拟内存: ${gl_bai}$swap_info" | |
| echo -e "${gl_lan}硬盘占用: ${gl_bai}$disk_info" | |
| echo -e "${gl_lan}-------------" | |
| echo -e "${gl_lan}$output" | |
| echo -e "${gl_lan}-------------" | |
| echo -e "${gl_lan}网络算法: ${gl_bai}$congestion_algorithm $queue_algorithm" | |
| echo -e "${gl_lan}-------------" | |
| echo -e "${gl_lan}运营商: ${gl_bai}$isp_info" | |
| if [ -n "$ipv4_address" ]; then | |
| echo -e "${gl_lan}IPv4地址: ${gl_bai}$ipv4_address" | |
| fi | |
| if [ -n "$ipv6_address" ]; then | |
| echo -e "${gl_lan}IPv6地址: ${gl_bai}$ipv6_address" | |
| fi | |
| echo -e "${gl_lan}DNS地址: ${gl_bai}$dns_addresses" | |
| echo -e "${gl_lan}地理位置: ${gl_bai}$country $city" | |
| echo -e "${gl_lan}系统时间: ${gl_bai}$timezone $current_time" | |
| echo -e "${gl_lan}-------------" | |
| echo -e "${gl_lan}运行时长: ${gl_bai}$runtime" | |
| echo | |
| } | |
| # Execute the main function | |
| linux_ps |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment