Skip to content

Instantly share code, notes, and snippets.

@lainbo
Last active June 10, 2025 14:45
Show Gist options
  • Select an option

  • Save lainbo/b8de16e1ed5dc9ab9cc0f8b8ee756d00 to your computer and use it in GitHub Desktop.

Select an option

Save lainbo/b8de16e1ed5dc9ab9cc0f8b8ee756d00 to your computer and use it in GitHub Desktop.
服务器脚本
#!/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
#!/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
#!/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 "--- 所有操作已完成 ---"
#!/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