#!/bin/bash VERSION="v5.0.1" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' RESET='\033[0m' get_system_type() { if [ -f /etc/debian_version ]; then echo "debian" elif [ -f /etc/redhat-release ]; then echo "centos" elif [ -f /etc/arch-release ]; then echo "archlinux" else echo "unknown" fi } wait_for_package_manager() { local system_type=$(get_system_type) if [ "$system_type" = "debian" ]; then while fuser /var/lib/dpkg/lock >/dev/null 2>&1 || fuser /var/lib/apt/lists/lock >/dev/null 2>&1 || fuser /var/cache/apt/archives/lock >/dev/null 2>&1; do echo -e "${YELLOW}等待其他 apt 进程完成${RESET}" sleep 1 done fi } install_required_packages() { local system_type=$(get_system_type) echo -e "${GREEN}安装必要软件包${RESET}" if [ "$system_type" = "debian" ]; then apt update apt install -y wget unzip curl elif [ "$system_type" = "centos" ]; then yum -y update yum -y install wget unzip curl elif [ "$system_type" = "archlinux" ]; then pacman -Sy pacman -S wget unzip curl else echo -e "${RED}不支持的系统类型${RESET}" exit 1 fi } check_root() { if [ "$(id -u)" != "0" ]; then echo -e "${RED}请以 root 权限运行此脚本.${RESET}" exit 1 fi } check_snell_installed() { if command -v snell-server &> /dev/null; then return 0 else return 1 fi } check_snell_running() { systemctl is-active --quiet "snell.service" return $? } start_snell() { systemctl start "snell.service" if [ $? -eq 0 ]; then echo -e "${GREEN}Snell 启动成功${RESET}" else echo -e "${RED}Snell 启动失败${RESET}" fi } stop_snell() { systemctl stop "snell.service" if [ $? -eq 0 ]; then echo -e "${GREEN}Snell 停止成功${RESET}" else echo -e "${RED}Snell 停止失败${RESET}" fi } install_snell() { echo -e "${GREEN}正在安装 Snell${RESET}" wait_for_package_manager install_required_packages || { echo -e "${RED}安装必要软件包失败${RESET}" exit 1 } ARCH=$(arch) if [[ ${ARCH} == "aarch64" ]]; then SNELL_URL="https://dl.nssurge.com/snell/snell-server-${VERSION}-linux-aarch64.zip" else SNELL_URL="https://dl.nssurge.com/snell/snell-server-${VERSION}-linux-amd64.zip" fi wget ${SNELL_URL} -O snell-server.zip || { echo -e "${RED}下载 Snell 失败。${RESET}" exit 1 } unzip -o snell-server.zip -d /usr/local/bin || { echo -e "${RED}解压缩 Snell 失败。${RESET}" exit 1 } rm snell-server.zip chmod +x /usr/local/bin/snell-server RANDOM_PORT=$(shuf -i 30000-65000 -n 1) RANDOM_PSK=$(tr -dc A-Za-z0-9 /dev/null; then useradd -r -s /usr/sbin/nologin snell fi mkdir -p /etc/snell cat > /etc/snell/snell-server.conf << EOF [snell-server] listen = ::0:${RANDOM_PORT} psk = ${RANDOM_PSK} ipv6 = true EOF cat > /etc/systemd/system/snell.service << EOF [Unit] Description=Snell Proxy Service After=network.target [Service] Type=simple User=snell Group=snell ExecStart=/usr/local/bin/snell-server -c /etc/snell/snell-server.conf AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN CAP_NET_RAW CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_ADMIN CAP_NET_RAW LimitNOFILE=32768 Restart=on-failure StandardOutput=journal StandardError=journal SyslogIdentifier=snell-server [Install] WantedBy=multi-user.target EOF echo -e "${GREEN}Snell 安装成功${RESET}" systemctl daemon-reload && systemctl enable snell && systemctl start snell sleep 3 && journalctl -u snell.service -n 8 --no-pager HOST_IP=$(curl -s http://checkip.amazonaws.com) IP_COUNTRY=$(curl -s http://ipinfo.io/${HOST_IP}/country) echo -e "${GREEN}Snell 示例配置,项目地址: https://github.com/passeway/Snell${RESET}" cat << EOF > /etc/snell/config.txt ${IP_COUNTRY} = snell, ${HOST_IP}, ${RANDOM_PORT}, psk = ${RANDOM_PSK}, version = 5, reuse = true EOF cat /etc/snell/config.txt } update_snell() { if [ ! -f "/usr/local/bin/snell-server" ]; then echo -e "${YELLOW}Snell 未安装,跳过更新${RESET}" return fi echo -e "${GREEN}Snell 正在更新${RESET}" systemctl stop snell wait_for_package_manager install_required_packages ARCH=$(arch) if [[ ${ARCH} == "aarch64" ]]; then SNELL_URL="https://dl.nssurge.com/snell/snell-server-${VERSION}-linux-aarch64.zip" else SNELL_URL="https://dl.nssurge.com/snell/snell-server-${VERSION}-linux-amd64.zip" fi wget ${SNELL_URL} -O snell-server.zip unzip -o snell-server.zip -d /usr/local/bin rm snell-server.zip chmod +x /usr/local/bin/snell-server systemctl restart snell echo -e "${GREEN}Snell 更新成功${RESET}" sleep 3 && journalctl -u snell.service -n 8 --no-pager echo -e "${GREEN}Snell 示例配置,项目地址: https://github.com/passeway/Snell${RESET}" cat /etc/snell/config.txt } uninstall_snell() { echo -e "${GREEN}正在卸载 Snell${RESET}" systemctl stop snell systemctl disable snell rm /etc/systemd/system/snell.service systemctl daemon-reload rm /usr/local/bin/snell-server rm -rf /etc/snell echo -e "${GREEN}Snell 卸载成功${RESET}" } show_menu() { clear check_snell_installed snell_installed=$? check_snell_running snell_running=$? if [ $snell_installed -eq 0 ]; then installation_status="${GREEN}已安装${RESET}" if version_output=$(/usr/local/bin/snell-server -version 2>&1); then snell_version=$(echo "$version_output" | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+') if [ -n "$snell_version" ]; then version_status="${GREEN}${snell_version}${RESET}" else version_status="${RED}未知版本${RESET}" fi else version_status="${RED}未知版本${RESET}" fi if [ $snell_running -eq 0 ]; then running_status="${GREEN}已启动${RESET}" else running_status="${RED}未启动${RESET}" fi else installation_status="${RED}未安装${RESET}" running_status="${RED}未启动${RESET}" version_status="—" fi echo -e "${GREEN}=== Snell 管理工具 ===${RESET}" echo -e "安装状态: ${installation_status}" echo -e "运行状态: ${running_status}" echo -e "运行版本: ${version_status}" echo "" echo "1. 安装 Snell 服务" echo "2. 卸载 Snell 服务" if [ $snell_installed -eq 0 ]; then if [ $snell_running -eq 0 ]; then echo "3. 停止 Snell 服务" else echo "3. 启动 Snell 服务" fi fi echo "4. 更新 Snell 服务" echo "5. 重启 Snell 服务" echo "6. 查看 Snell 服务" echo "7. 查看 Snell 配置" echo "0. 退出" echo -e "${GREEN}======================${RESET}" read -p "请输入选项编号: " choice export choice echo "" } trap 'echo -e "${RED}已取消操作${RESET}"; exit' INT main() { check_root while true; do show_menu case "${choice}" in 1) install_snell ;; 2) if [ $snell_installed -eq 0 ]; then uninstall_snell else echo -e "${RED}Snell 尚未安装${RESET}" fi ;; 3) if [ $snell_installed -eq 0 ]; then if [ $snell_running -eq 0 ]; then stop_snell else start_snell fi else echo -e "${RED}Snell 尚未安装${RESET}" fi ;; 4) update_snell ;; 5) systemctl restart snell ;; 6) systemctl status snell ;; 7) if [ -f /etc/snell/config.txt ]; then cat /etc/snell/config.txt else echo -e "${RED}配置文件不存在${RESET}" fi ;; 0) echo -e "${GREEN}已退出 Snell 管理工具${RESET}" exit 0 ;; *) echo -e "${RED}无效的选项${RESET}" ;; esac read -p "按 enter 键继续..." done } main