Add modular install and uninstall scripts

This commit is contained in:
爱喝水的木子
2026-03-19 14:32:48 +08:00
parent c04724a533
commit 6fa49aabee
9 changed files with 1274 additions and 412 deletions

114
README.md Normal file
View File

@@ -0,0 +1,114 @@
# 环境安装与卸载脚本
这个仓库提供了一组独立的 Shell 脚本,用于安装和卸载常见开发环境工具,适合在 Linux 和 macOS 上快速初始化开发机器。
## 文件说明
- `install.sh`:总安装入口,支持交互式选择或命令行按需安装。
- `install-docker.sh`:单独安装 Docker。
- `install-nvm.sh`:单独安装 NVM并自动安装 Node.js LTS。
- `install-mambaconda.sh`:单独安装 Mambaconda默认安装到 `$HOME/mambaconda`
- `uninstall.sh`:总卸载入口,支持交互式选择或命令行按需卸载。
- `uninstall-docker.sh`:单独卸载 Docker默认保留 Docker 数据。
- `uninstall-nvm.sh`:单独卸载 NVM并清理脚本追加的 Shell 初始化配置。
- `uninstall-mambaconda.sh`:单独卸载 Mambaconda并清理脚本追加的 Shell 初始化配置。
## 支持平台
- Linux
- macOS
## 安装用法
总入口安装:
```bash
bash install.sh
```
常见用法:
```bash
bash install.sh all
bash install.sh docker
bash install.sh nvm mambaconda
```
也可以直接执行单独脚本:
```bash
bash install-docker.sh
bash install-nvm.sh
bash install-mambaconda.sh
```
`install.sh` 支持以下模式:
- 不带参数:交互式选择安装项
- `all`:安装全部工具
- `docker` / `nvm` / `mambaconda`:安装指定工具
- 多个参数组合:安装多个指定工具
## 卸载用法
总入口卸载:
```bash
bash uninstall.sh
```
常见用法:
```bash
bash uninstall.sh all
bash uninstall.sh docker
bash uninstall.sh nvm mambaconda
```
也可以直接执行单独脚本:
```bash
bash uninstall-docker.sh
bash uninstall-nvm.sh
bash uninstall-mambaconda.sh
```
`uninstall.sh` 支持以下模式:
- 不带参数:交互式选择卸载项
- `all`:卸载全部工具
- `docker` / `nvm` / `mambaconda`:卸载指定工具
- 多个参数组合:卸载多个指定工具
## 默认行为说明
- `install-nvm.sh` 会配置 Node.js 国内镜像和 npm 国内源。
- `install-mambaconda.sh` 会写入 `~/.condarc`,并使用国内镜像源。
- `install-mambaconda.sh` 默认会安装 Python 3.10。
- `uninstall-docker.sh` 默认不会删除 Docker 数据目录。
如果需要在卸载 Docker 时同时删除数据,可使用:
```bash
REMOVE_DOCKER_DATA=1 bash uninstall-docker.sh
```
## 安装后验证
```bash
docker --version
docker compose version
nvm --version && node --version && npm --version
conda --version && python --version
```
## 输出风格
现在所有入口脚本和子脚本都会使用统一的输出格式:
- `INFO`:普通步骤提示
- `WARN`:非阻断警告
- `ERROR`:错误并退出
- `DONE`:当前脚本执行完成
同时会显示阶段标题,便于在安装或卸载过程中快速定位当前步骤。

171
install-docker.sh Normal file
View File

@@ -0,0 +1,171 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
OS_TYPE=""
info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
success() {
echo -e "${BLUE}[DONE]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
section() {
echo
echo -e "${BOLD}${BLUE}== $1 ==${NC}"
}
detect_system() {
case "${OSTYPE:-}" in
linux-gnu*) OS_TYPE="linux" ;;
darwin*) OS_TYPE="macos" ;;
*) error "不支持的操作系统: ${OSTYPE:-unknown},仅支持 Linux 和 macOS。" ;;
esac
info "检测到系统: $OS_TYPE"
}
run_privileged() {
if [[ "$(id -u)" -eq 0 ]]; then
"$@"
elif command -v sudo >/dev/null 2>&1; then
sudo "$@"
else
error "该步骤需要 root 权限,请安装 sudo 或以 root 身份运行。"
fi
}
ensure_homebrew() {
if command -v brew >/dev/null 2>&1; then
return
fi
info "未检测到 Homebrew开始安装..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
}
install_dependencies() {
section "安装依赖"
if [[ "$OS_TYPE" == "linux" ]]; then
if command -v apt-get >/dev/null 2>&1; then
run_privileged apt-get update
run_privileged apt-get install -y ca-certificates curl
elif command -v dnf >/dev/null 2>&1; then
run_privileged dnf install -y ca-certificates curl
elif command -v yum >/dev/null 2>&1; then
run_privileged yum install -y ca-certificates curl
else
error "当前 Linux 包管理器不受支持,请手动安装 curl 和 ca-certificates。"
fi
else
ensure_homebrew
fi
}
install_docker_linux() {
if command -v docker >/dev/null 2>&1; then
warn "检测到 Docker CLI 已存在,跳过下载安装。"
else
local tmp_script
tmp_script="$(mktemp "/tmp/get-docker.XXXXXX.sh")"
info "下载 Docker 官方安装脚本..."
curl -fsSL https://get.docker.com -o "$tmp_script"
run_privileged sh "$tmp_script"
rm -f "$tmp_script"
fi
run_privileged systemctl enable docker || true
run_privileged systemctl start docker || true
if [[ "$(id -u)" -ne 0 ]] && ! id -nG "$USER" | grep -qw docker; then
info "将用户 $USER 加入 docker 用户组..."
run_privileged usermod -aG docker "$USER" || warn "加入 docker 用户组失败。"
fi
}
install_docker_macos() {
if brew list --cask docker >/dev/null 2>&1; then
warn "检测到 Docker Desktop 已安装,跳过安装。"
return
fi
info "安装 Docker Desktop..."
brew install --cask docker
}
install_docker() {
section "安装 Docker"
if [[ "$OS_TYPE" == "linux" ]]; then
install_docker_linux
else
install_docker_macos
fi
}
verify_installation() {
section "校验安装结果"
if ! command -v docker >/dev/null 2>&1; then
error "安装完成后仍未找到 docker 命令。"
fi
info "Docker 版本: $(docker --version)"
if docker compose version >/dev/null 2>&1; then
info "Docker Compose 版本: $(docker compose version)"
else
warn "当前尚未检测到 docker compose 插件。"
fi
if ! docker info >/dev/null 2>&1; then
warn "暂时无法连接 Docker daemon。Linux 可能需要重新登录macOS 需要先启动 Docker Desktop。"
fi
}
finalize() {
section "完成"
if [[ "$OS_TYPE" == "linux" ]]; then
echo "如果刚加入 docker 用户组,请重新登录后再无 sudo 使用 Docker。"
else
echo "首次使用前请先手动启动一次 Docker Desktop。"
fi
echo "可执行以下命令快速验证:"
echo " docker --version && docker compose version"
success "Docker 安装流程结束。"
}
main() {
section "Docker 安装脚本"
detect_system
install_dependencies
install_docker
verify_installation
finalize
}
main "$@"

274
install-mambaconda.sh Normal file
View File

@@ -0,0 +1,274 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
OS_TYPE=""
ARCH_TYPE=""
CONDA_PATH="${CONDA_PATH:-$HOME/mambaconda}"
LATEST_CONDA_VERSION=""
info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
success() {
echo -e "${BLUE}[DONE]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
section() {
echo
echo -e "${BOLD}${BLUE}== $1 ==${NC}"
}
detect_system() {
section "检测系统信息"
case "${OSTYPE:-}" in
linux-gnu*) OS_TYPE="linux" ;;
darwin*) OS_TYPE="macos" ;;
*) error "不支持的操作系统: ${OSTYPE:-unknown},仅支持 Linux 和 macOS。" ;;
esac
case "$(uname -m)" in
x86_64|amd64) ARCH_TYPE="x86_64" ;;
arm64|aarch64)
if [[ "$OS_TYPE" == "macos" ]]; then
ARCH_TYPE="arm64"
else
ARCH_TYPE="aarch64"
fi
;;
*) error "不支持的系统架构: $(uname -m)" ;;
esac
info "检测到平台: $OS_TYPE $ARCH_TYPE"
}
run_privileged() {
if [[ "$(id -u)" -eq 0 ]]; then
"$@"
elif command -v sudo >/dev/null 2>&1; then
sudo "$@"
else
error "该步骤需要 root 权限,请安装 sudo 或以 root 身份运行。"
fi
}
ensure_homebrew() {
if command -v brew >/dev/null 2>&1; then
return
fi
info "未检测到 Homebrew开始安装..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
}
install_dependencies() {
section "安装依赖"
if [[ "$OS_TYPE" == "linux" ]]; then
if command -v apt-get >/dev/null 2>&1; then
run_privileged apt-get update
run_privileged apt-get install -y curl wget ca-certificates bzip2
elif command -v dnf >/dev/null 2>&1; then
run_privileged dnf install -y curl wget ca-certificates bzip2
elif command -v yum >/dev/null 2>&1; then
run_privileged yum install -y curl wget ca-certificates bzip2
else
error "当前 Linux 包管理器不受支持,请手动安装 curl、wget、ca-certificates 和 bzip2。"
fi
else
ensure_homebrew
brew install curl wget
fi
}
get_latest_version() {
section "获取版本信息"
local api_url="https://api.github.com/repos/conda-forge/miniforge/releases/latest"
LATEST_CONDA_VERSION="$(curl -fsSL "$api_url" | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p' | head -n1)"
if [[ -z "$LATEST_CONDA_VERSION" ]]; then
error "无法获取最新的 Miniforge 版本。"
fi
info "最新 Miniforge 版本: $LATEST_CONDA_VERSION"
}
append_block_if_missing() {
local file="$1"
local marker="$2"
local block="$3"
touch "$file"
if ! grep -qF "$marker" "$file"; then
printf '\n%s\n' "$block" >> "$file"
fi
}
configure_shells() {
section "配置 Shell 环境"
local bash_block zsh_block
bash_block=$(cat <<EOF
# >>> mambaconda initialize >>>
__conda_setup="\$('$CONDA_PATH/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ \$? -eq 0 ]; then
eval "\$__conda_setup"
else
if [ -f "$CONDA_PATH/etc/profile.d/conda.sh" ]; then
. "$CONDA_PATH/etc/profile.d/conda.sh"
else
export PATH="$CONDA_PATH/bin:\$PATH"
fi
fi
unset __conda_setup
# <<< mambaconda initialize <<<
EOF
)
zsh_block=$(cat <<EOF
# >>> mambaconda initialize >>>
__conda_setup="\$('$CONDA_PATH/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ \$? -eq 0 ]; then
eval "\$__conda_setup"
else
if [ -f "$CONDA_PATH/etc/profile.d/conda.sh" ]; then
. "$CONDA_PATH/etc/profile.d/conda.sh"
else
export PATH="$CONDA_PATH/bin:\$PATH"
fi
fi
unset __conda_setup
# <<< mambaconda initialize <<<
EOF
)
append_block_if_missing "$HOME/.bashrc" "# >>> mambaconda initialize >>>" "$bash_block"
append_block_if_missing "$HOME/.zshrc" "# >>> mambaconda initialize >>>" "$zsh_block"
export PATH="$CONDA_PATH/bin:$PATH"
}
write_condarc() {
section "写入 Conda 配置"
info "生成 ~/.condarc 并写入镜像配置..."
cat > "$HOME/.condarc" <<'EOF'
channels:
- conda-forge
- defaults
show_channel_urls: true
channel_priority: flexible
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
EOF
}
install_mambaconda() {
section "安装 Mambaconda"
info "安装目录: $CONDA_PATH"
if [[ -x "$CONDA_PATH/bin/conda" ]]; then
warn "检测到已有 Conda 安装,跳过下载安装。"
else
local package_name=""
local tmp_script=""
local github_url=""
local mirror_url=""
if [[ "$OS_TYPE" == "linux" ]]; then
package_name="Miniforge3-${LATEST_CONDA_VERSION}-Linux-${ARCH_TYPE}.sh"
else
package_name="Miniforge3-${LATEST_CONDA_VERSION}-MacOSX-${ARCH_TYPE}.sh"
fi
github_url="https://github.com/conda-forge/miniforge/releases/download/${LATEST_CONDA_VERSION}/${package_name}"
mirror_url="https://mirrors.ustc.edu.cn/github-release/conda-forge/miniforge/${LATEST_CONDA_VERSION}/${package_name}"
tmp_script="$(mktemp "/tmp/${package_name}.XXXXXX")"
info "下载 Mambaconda 安装脚本..."
if ! curl -fL "$mirror_url" -o "$tmp_script"; then
warn "中科大镜像下载失败,尝试从 GitHub 下载..."
curl -fL "$github_url" -o "$tmp_script"
fi
bash "$tmp_script" -b -p "$CONDA_PATH"
rm -f "$tmp_script"
fi
configure_shells
write_condarc
# shellcheck disable=SC1091
source "$CONDA_PATH/etc/profile.d/conda.sh"
info "安装 Python 3.10..."
conda install -y python=3.10
}
verify_installation() {
section "校验安装结果"
if [[ ! -x "$CONDA_PATH/bin/conda" ]]; then
error "未在 $CONDA_PATH/bin/conda 找到 conda 可执行文件"
fi
# shellcheck disable=SC1091
source "$CONDA_PATH/etc/profile.d/conda.sh"
info "Conda 版本: $(conda --version)"
info "Python 版本: $(python --version 2>&1)"
}
finalize() {
section "完成"
echo "下一步可执行:"
echo " source \"$HOME/.bashrc\" # 或 source \"$HOME/.zshrc\""
echo "可执行以下命令快速验证:"
echo " conda --version && python --version"
success "Mambaconda 安装流程结束。"
}
main() {
section "Mambaconda 安装脚本"
detect_system
install_dependencies
get_latest_version
install_mambaconda
verify_installation
finalize
}
main "$@"

215
install-nvm.sh Normal file
View File

@@ -0,0 +1,215 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
OS_TYPE=""
LATEST_NVM_VERSION=""
info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
success() {
echo -e "${BLUE}[DONE]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
section() {
echo
echo -e "${BOLD}${BLUE}== $1 ==${NC}"
}
detect_system() {
case "${OSTYPE:-}" in
linux-gnu*) OS_TYPE="linux" ;;
darwin*) OS_TYPE="macos" ;;
*) error "不支持的操作系统: ${OSTYPE:-unknown},仅支持 Linux 和 macOS。" ;;
esac
info "检测到系统: $OS_TYPE"
}
run_privileged() {
if [[ "$(id -u)" -eq 0 ]]; then
"$@"
elif command -v sudo >/dev/null 2>&1; then
sudo "$@"
else
error "该步骤需要 root 权限,请安装 sudo 或以 root 身份运行。"
fi
}
ensure_homebrew() {
if command -v brew >/dev/null 2>&1; then
return
fi
info "未检测到 Homebrew开始安装..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
if [[ -x /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -x /usr/local/bin/brew ]]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
}
install_dependencies() {
section "安装依赖"
if [[ "$OS_TYPE" == "linux" ]]; then
if command -v apt-get >/dev/null 2>&1; then
run_privileged apt-get update
run_privileged apt-get install -y curl ca-certificates
elif command -v dnf >/dev/null 2>&1; then
run_privileged dnf install -y curl ca-certificates
elif command -v yum >/dev/null 2>&1; then
run_privileged yum install -y curl ca-certificates
else
error "当前 Linux 包管理器不受支持,请手动安装 curl 和 ca-certificates。"
fi
else
ensure_homebrew
brew install curl
fi
}
get_latest_version() {
section "获取版本信息"
local api_url="https://api.github.com/repos/nvm-sh/nvm/releases/latest"
LATEST_NVM_VERSION="$(curl -fsSL "$api_url" | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p' | head -n1)"
if [[ -z "$LATEST_NVM_VERSION" ]]; then
LATEST_NVM_VERSION="v0.39.7"
warn "获取最新版本失败,回退到 $LATEST_NVM_VERSION"
fi
info "使用的 NVM 版本: $LATEST_NVM_VERSION"
}
append_block_if_missing() {
local file="$1"
local marker="$2"
local block="$3"
touch "$file"
if ! grep -qF "$marker" "$file"; then
printf '\n%s\n' "$block" >> "$file"
fi
}
append_line_if_missing() {
local file="$1"
local line="$2"
touch "$file"
if ! grep -qxF "$line" "$file"; then
printf '%s\n' "$line" >> "$file"
fi
}
configure_shells() {
section "配置 Shell 环境"
local init_block
init_block=$(cat <<'EOF'
# >>> nvm initialize >>>
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"
export NVM_NODEJS_ORG_MIRROR="https://npmmirror.com/mirrors/node"
# <<< nvm initialize <<<
EOF
)
append_block_if_missing "$HOME/.bashrc" "# >>> nvm initialize >>>" "$init_block"
append_block_if_missing "$HOME/.zshrc" "# >>> nvm initialize >>>" "$init_block"
append_line_if_missing "$HOME/.profile" 'export NVM_DIR="$HOME/.nvm"'
export NVM_DIR="$HOME/.nvm"
export NVM_NODEJS_ORG_MIRROR="https://npmmirror.com/mirrors/node"
}
install_nvm() {
section "安装 NVM"
if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
warn "检测到 NVM 已存在,跳过下载安装。"
else
local primary_url="https://raw.githubusercontent.com/nvm-sh/nvm/${LATEST_NVM_VERSION}/install.sh"
local mirror_url="https://cdn.jsdelivr.net/gh/nvm-sh/nvm@${LATEST_NVM_VERSION}/install.sh"
local tmp_script
tmp_script="$(mktemp "/tmp/install_nvm.XXXXXX.sh")"
info "下载 NVM 安装脚本..."
if ! curl -fL "$mirror_url" -o "$tmp_script"; then
warn "镜像下载失败,尝试从 GitHub 下载..."
curl -fL "$primary_url" -o "$tmp_script"
fi
bash "$tmp_script"
rm -f "$tmp_script"
fi
configure_shells
# shellcheck disable=SC1091
source "$HOME/.nvm/nvm.sh"
info "安装最新 LTS 版本 Node.js..."
nvm install --lts
nvm alias default 'lts/*'
npm config set registry https://registry.npmmirror.com/
}
verify_installation() {
section "校验安装结果"
if [[ ! -s "$HOME/.nvm/nvm.sh" ]]; then
error "$HOME/.nvm 下未找到 nvm.sh"
fi
# shellcheck disable=SC1091
source "$HOME/.nvm/nvm.sh"
info "NVM 版本: $(nvm --version)"
info "Node 版本: $(node --version)"
info "npm 源: $(npm config get registry)"
}
finalize() {
section "完成"
echo "下一步可执行:"
echo " source \"$HOME/.bashrc\" # 或 source \"$HOME/.zshrc\""
echo "可执行以下命令快速验证:"
echo " nvm --version && node --version && npm --version"
success "NVM 安装流程结束。"
}
main() {
section "NVM 安装脚本"
detect_system
install_dependencies
get_latest_version
install_nvm
verify_installation
finalize
}
main "$@"

View File

@@ -1,454 +1,141 @@
#!/bin/bash #!/bin/bash
set -euo pipefail set -euo pipefail
# 定义颜色常量,用于输出提示
RED='\033[0;31m' RED='\033[0;31m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
NC='\033[0m' # No Color BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
# 全局变量 - 自动识别系统信息 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OS_TYPE=""
ARCH_TYPE=""
CONDA_PATH="$HOME/mambaconda"
# 稳定版版本号(动态获取)
LATEST_CONDA_VERSION=""
LATEST_NVM_VERSION=""
# 打印信息函数
info() { info() {
echo -e "${GREEN}[INFO]${NC} $1" echo -e "${GREEN}[INFO]${NC} $1"
} }
# 打印警告函数
warn() { warn() {
echo -e "${YELLOW}[WARN]${NC} $1" echo -e "${YELLOW}[WARN]${NC} $1"
} }
# 打印错误函数 success() {
echo -e "${BLUE}[DONE]${NC} $1"
}
error() { error() {
echo -e "${RED}[ERROR]${NC} $1" echo -e "${RED}[ERROR]${NC} $1"
exit 1 exit 1
} }
# 检查系统类型和架构 section() {
detect_system() { echo
info "开始检测系统信息..." echo -e "${BOLD}${BLUE}== $1 ==${NC}"
# 检测操作系统类型
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
OS_TYPE="linux"
elif [[ "$OSTYPE" == "darwin"* ]]; then
OS_TYPE="macos"
else
error "不支持的操作系统:$OSTYPE,仅支持 Linux 和 macOS"
fi
# 检测系统架构
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" || "$ARCH" == "amd64" ]]; then
ARCH_TYPE="x86_64"
elif [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then
ARCH_TYPE="aarch64"
else
error "不支持的系统架构:$ARCH,仅支持 x86_64/amd64 和 aarch64/arm64"
fi
info "系统检测完成:$OS_TYPE $ARCH_TYPE"
} }
# 获取最新稳定版版本号 usage() {
get_stable_versions() { cat <<'EOF'
info "开始获取各工具最新稳定版版本号..." 用法:
bash install.sh # 交互式选择安装项
# 获取 Mambaconda 最新稳定版(跳过 pre-release bash install.sh all # 安装全部工具
info "获取 Mambaconda 最新稳定版..." bash install.sh docker # 仅安装 Docker
LATEST_CONDA_INFO=$(curl -s https://api.github.com/repos/conda-forge/miniforge/releases/latest) bash install.sh nvm # 仅安装 NVM
LATEST_CONDA_VERSION=$(echo "$LATEST_CONDA_INFO" | grep -Po '"tag_name": "\K.*?(?=")') bash install.sh mambaconda # 仅安装 Mambaconda
if [ -z "$LATEST_CONDA_VERSION" ]; then bash install.sh docker nvm # 安装多个指定工具
error "无法获取 Mambaconda 最新稳定版版本号,请检查网络" bash install.sh --help
fi
info "Mambaconda 最新稳定版:$LATEST_CONDA_VERSION"
# 获取 NVM 最新稳定版(跳过 pre-release
info "获取 NVM 最新稳定版..."
LATEST_NVM_INFO=$(curl -s https://api.github.com/repos/nvm-sh/nvm/releases/latest)
LATEST_NVM_VERSION=$(echo "$LATEST_NVM_INFO" | grep -Po '"tag_name": "\K.*?(?=")')
if [ -z "$LATEST_NVM_VERSION" ]; then
# 备用:使用已知稳定版
LATEST_NVM_VERSION="v0.39.7"
warn "无法获取 NVM 最新稳定版,使用备用稳定版:$LATEST_NVM_VERSION"
fi
info "NVM 最新稳定版:$LATEST_NVM_VERSION"
}
# 检查是否为 root 用户macOS 不建议 root
check_root() {
if [ "$(id -u)" -eq 0 ]; then
if [[ "$OS_TYPE" == "macos" ]]; then
error "macOS 系统禁止使用 root 用户运行此脚本,请使用普通用户"
else
warn "当前为 root 用户,将安装到 /root/mambaconda 目录"
fi
fi
}
# 安装系统依赖工具
install_dependencies() {
info "开始安装基础依赖工具..."
if [[ "$OS_TYPE" == "linux" ]]; then
if command -v apt &> /dev/null; then
apt update && apt install -y curl wget git ca-certificates --no-install-recommends
elif command -v yum &> /dev/null; then
yum install -y curl wget git ca-certificates
elif command -v dnf &> /dev/null; then
dnf install -y curl wget git ca-certificates
else
error "Linux 系统不支持的包管理器,请手动安装 curl wget git"
fi
elif [[ "$OS_TYPE" == "macos" ]]; then
# 检查是否安装 brew
if ! command -v brew &> /dev/null; then
warn "未检测到 Homebrew正在自动安装..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
brew install curl wget git
fi
info "基础依赖工具安装完成"
}
# 安装 mambaconda 并配置清华源(仅稳定版)
install_mambaconda() {
info "开始安装 Mambaconda稳定版 $LATEST_CONDA_VERSION..."
# 检查是否已安装 conda
if command -v conda &> /dev/null; then
warn "检测到已安装 conda跳过安装步骤"
configure_conda_env
return
fi
# Miniforge3-26.1.0-0-Linux-x86_64.sh
# 构建安装包名称
if [[ "$OS_TYPE" == "linux" ]]; then
MAMBAFORGE_PACKAGE="Miniforge3-${LATEST_CONDA_VERSION}-Linux-${ARCH_TYPE}.sh"
elif [[ "$OS_TYPE" == "macos" ]]; then
if [[ "$ARCH_TYPE" == "x86_64" ]]; then
MAMBAFORGE_PACKAGE="Miniforge3-${LATEST_CONDA_VERSION}-MacOSX-x86_64.sh"
else
MAMBAFORGE_PACKAGE="Miniforge3-${LATEST_CONDA_VERSION}-MacOSX-arm64.sh"
fi
fi
# https://github.com/conda-forge/miniforge/releases/download/26.1.0-0/Miniforge3-26.1.0-0-Linux-x86_64.sh
# 构建下载 URL仅稳定版
GITHUB_URL="https://github.com/conda-forge/miniforge/releases/download/${LATEST_CONDA_VERSION}/${MAMBAFORGE_PACKAGE}"
USTC_URL="https://mirrors.ustc.edu.cn/github-release/conda-forge/miniforge/${LATEST_CONDA_VERSION}/${MAMBAFORGE_PACKAGE}"
BACKUP_URL="https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniforge3-Linux-${ARCH_TYPE}.sh"
# 下载安装包(使用中科大镜像源)
info "下载 Mambaconda 安装包(中科大源)..."
if ! wget -q "$USTC_URL" -O "/tmp/$MAMBAFORGE_PACKAGE"; then
info "中科大源下载失败,尝试 GitHub 官方源..."
if ! wget -q "$GITHUB_URL" -O "/tmp/$MAMBAFORGE_PACKAGE"; then
info "GitHub 源下载失败,尝试备用源..."
if ! wget -q "$BACKUP_URL" -O "/tmp/$MAMBAFORGE_PACKAGE"; then
error "所有源下载 mambaconda 安装包均失败,请手动下载稳定版安装包到 /tmp 目录后重新运行"
fi
fi
fi
# 静默安装(不修改 shell 配置文件)
bash "/tmp/$MAMBAFORGE_PACKAGE" -b -p "$CONDA_PATH" || error "mambaconda 安装失败"
# 删除安装包
rm -f "/tmp/$MAMBAFORGE_PACKAGE"
# 配置 conda 环境变量
configure_conda_env
# 激活 conda
source "$CONDA_PATH/etc/profile.d/conda.sh"
source "$CONDA_PATH/etc/profile.d/mamba.sh"
# 配置清华源
info "配置 conda 清华源..."
cat > "$HOME/.condarc" << EOF
channels:
- defaults
show_channel_urls: true
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch-lts: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
EOF EOF
# 更新 conda 并安装 Python 3.10
info "安装 Python 3.10..."
conda install -y python=3.10 || error "Python 3.10 安装失败"
# 初始化 conda 到 shell
conda init bash
if command -v zsh &> /dev/null; then
conda init zsh
fi
if [[ "$OS_TYPE" == "macos" ]] && command -v fish &> /dev/null; then
conda init fish
fi
info "Mambaconda 稳定版安装并配置完成"
} }
# 配置 conda 环境变量 run_script() {
configure_conda_env() { local script_name="$1"
info "配置 conda 环境变量..." local script_path="$SCRIPT_DIR/$script_name"
# 检查 .bashrc 中是否已有 conda 配置
if ! grep -q "conda initialize" "$HOME/.bashrc"; then
cat >> "$HOME/.bashrc" << EOF
# >>> conda initialize >>> if [[ ! -f "$script_path" ]]; then
__conda_setup="\$('$CONDA_PATH/bin/conda' 'shell.bash' 'hook' 2> /dev/null)" error "未找到脚本: $script_path"
if [ \$? -eq 0 ]; then
eval "\$__conda_setup"
else
if [ -f "$CONDA_PATH/etc/profile.d/conda.sh" ]; then
. "$CONDA_PATH/etc/profile.d/conda.sh"
else
export PATH="$CONDA_PATH/bin:\$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<<
EOF
fi fi
# 配置 zsh如果存在 section "执行 $script_name"
if command -v zsh &> /dev/null && ! grep -q "conda initialize" "$HOME/.zshrc"; then bash "$script_path"
cat >> "$HOME/.zshrc" << EOF }
# >>> conda initialize >>> install_docker() {
__conda_setup="\$('$CONDA_PATH/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)" run_script "install-docker.sh"
if [ \$? -eq 0 ]; then
eval "\$__conda_setup"
else
if [ -f "$CONDA_PATH/etc/profile.d/conda.sh" ]; then
. "$CONDA_PATH/etc/profile.d/conda.sh"
else
export PATH="$CONDA_PATH/bin:\$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<<
EOF
fi
# 立即生效环境变量
export PATH="$CONDA_PATH/bin:$PATH"
info "conda 环境变量配置完成"
} }
# 安装 nvm 并配置淘宝源(仅稳定版)
install_nvm() { install_nvm() {
info "开始安装 NVM稳定版 $LATEST_NVM_VERSION..." run_script "install-nvm.sh"
# 检查是否已安装 nvm }
if [ -d "$HOME/.nvm" ]; then
warn "检测到已安装 nvm跳过安装步骤" install_mambaconda() {
configure_nvm_env run_script "install-mambaconda.sh"
}
install_targets() {
local target
for target in "$@"; do
case "$target" in
docker) install_docker ;;
nvm) install_nvm ;;
mambaconda) install_mambaconda ;;
all)
install_docker
install_nvm
install_mambaconda
;;
*)
error "未知安装目标: $target"
;;
esac
done
}
interactive_install() {
local reply=""
local selected=()
section "交互式安装"
read -r -p "是否安装 Docker? [y/N]: " reply
if [[ "$reply" =~ ^[Yy]$ ]]; then
selected+=("docker")
fi
read -r -p "是否安装 NVM? [y/N]: " reply
if [[ "$reply" =~ ^[Yy]$ ]]; then
selected+=("nvm")
fi
read -r -p "是否安装 Mambaconda? [y/N]: " reply
if [[ "$reply" =~ ^[Yy]$ ]]; then
selected+=("mambaconda")
fi
if [[ ${#selected[@]} -eq 0 ]]; then
warn "未选择任何安装项。"
return return
fi fi
# 构建 nvm 安装脚本 URL仅稳定版 install_targets "${selected[@]}"
NVM_INSTALL_URL="https://raw.githubusercontent.com/nvm-sh/nvm/${LATEST_NVM_VERSION}/install.sh" success "所选安装项已执行完成。"
NVM_MIRROR_URL="https://cdn.jsdelivr.net/gh/nvm-sh/nvm@${LATEST_NVM_VERSION}/install.sh"
# 下载并安装 nvm使用国内镜像源
info "下载 NVM 安装脚本(稳定版)..."
if ! wget -q "$NVM_MIRROR_URL" -O "/tmp/install_nvm.sh"; then
info "镜像源下载失败,尝试 GitHub 官方源..."
if ! wget -q "$NVM_INSTALL_URL" -O "/tmp/install_nvm.sh"; then
error "下载 NVM 稳定版安装脚本失败,请检查网络"
fi
fi
bash "/tmp/install_nvm.sh" || error "nvm 安装失败"
# 删除安装包
rm -f "/tmp/install_nvm.sh"
# 配置 nvm 环境变量
configure_nvm_env
# 激活 nvm
export NVM_DIR="$HOME/.nvm"
if [ -s "$NVM_DIR/nvm.sh" ]; then
. "$NVM_DIR/nvm.sh"
fi
if [ -s "$NVM_DIR/bash_completion" ]; then
. "$NVM_DIR/bash_completion"
fi
# 配置 nvm 镜像源(淘宝源)
info "配置 nvm 淘宝镜像源..."
echo 'export NVM_NODEJS_ORG_MIRROR="https://npmmirror.com/mirrors/node"' >> "$HOME/.bashrc"
if command -v zsh &> /dev/null; then
echo 'export NVM_NODEJS_ORG_MIRROR="https://npmmirror.com/mirrors/node"' >> "$HOME/.zshrc"
fi
export NVM_NODEJS_ORG_MIRROR="https://npmmirror.com/mirrors/node"
# 安装 Node LTS 稳定版
info "安装 Node LTS 稳定版..."
# 直接安装 LTS 稳定版,无需手动解析版本号
nvm install --lts || error "Node LTS 版本安装失败"
# 设置默认版本为 LTS
nvm alias default lts/* || error "设置 Node 默认版本失败"
# 配置 npm 淘宝源
info "配置 npm 淘宝源..."
npm config set registry https://registry.npmmirror.com/ || error "配置 npm 源失败"
# 持久化 npm 配置(全局生效)
npm config set registry https://registry.npmmirror.com/ --global
info "NVM 稳定版安装并配置完成"
# # 安装 Node LTS 稳定版(跳过 pre-release
# info "安装 Node LTS 稳定版..."
# # 获取 Node LTS 稳定版版本号(跳过 pre
# NODE_LTS_VERSION=$(nvm ls-remote --lts | grep -v "-rc" | grep -v "-beta" | tail -1 | awk '{print $1}')
# if [ -z "$NODE_LTS_VERSION" ]; then
# # 备用:直接安装 lts
# nvm install --lts || error "Node LTS 版本安装失败"
# else
# nvm install "$NODE_LTS_VERSION" || error "Node LTS 版本安装失败"
# fi
# nvm alias default lts/* || error "设置 Node 默认版本失败"
# # 配置 npm 淘宝源
# info "配置 npm 淘宝源..."
# npm config set registry https://registry.npmmirror.com/ || error "配置 npm 源失败"
# # 持久化 npm 配置
# npm config set registry https://registry.npmmirror.com/ --global
# info "NVM 稳定版安装并配置完成"
} }
# 配置 nvm 环境变量
configure_nvm_env() {
info "配置 nvm 环境变量..."
# 检查 .bashrc 中是否已有 nvm 配置
if ! grep -q "NVM_DIR" "$HOME/.bashrc"; then
cat >> "$HOME/.bashrc" << EOF
# >>> nvm initialize >>>
export NVM_DIR="$HOME/.nvm"
[ -s "\$NVM_DIR/nvm.sh" ] && \. "\$NVM_DIR/nvm.sh"
[ -s "\$NVM_DIR/bash_completion" ] && \. "\$NVM_DIR/bash_completion"
# <<< nvm initialize <<<
EOF
fi
# 配置 zsh如果存在
if command -v zsh &> /dev/null && ! grep -q "NVM_DIR" "$HOME/.zshrc"; then
cat >> "$HOME/.zshrc" << EOF
# >>> nvm initialize >>>
export NVM_DIR="$HOME/.nvm"
[ -s "\$NVM_DIR/nvm.sh" ] && \. "\$NVM_DIR/nvm.sh"
[ -s "\$NVM_DIR/bash_completion" ] && \. "\$NVM_DIR/bash_completion"
# <<< nvm initialize <<<
EOF
fi
# 立即生效环境变量
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
info "nvm 环境变量配置完成"
}
# 验证安装结果
verify_installation() {
info "开始验证安装结果..."
# 临时关闭未定义变量检查,避免 PS1 报错
set +u
# 重新加载环境变量
source "$HOME/.bashrc"
# 恢复严格模式
set -u
source "$CONDA_PATH/etc/profile.d/conda.sh"
# 验证 conda
if command -v conda &> /dev/null; then
info "✅ Mambaconda 安装成功:$(conda --version)"
info "✅ Python 版本:$(python --version)"
else
warn "❌ Mambaconda 验证失败,请手动执行 source $CONDA_PATH/etc/profile.d/conda.sh"
fi
# 验证 nvm/node
if command -v nvm &> /dev/null; then
info "✅ NVM 安装成功:$(nvm --version)"
info "✅ Node 版本:$(node --version)"
info "✅ NPM 源:$(npm config get registry)"
else
warn "❌ NVM 验证失败,请手动执行 source $HOME/.nvm/nvm.sh"
fi
}
# 清理和提示
finalize() {
info "========== 安装配置全部完成 =========="
info "已安装的稳定版:"
info " - Mambaconda: $LATEST_CONDA_VERSION (Python 3.10)"
info " - NVM: $LATEST_NVM_VERSION (Node LTS 稳定版)"
info "请执行以下命令使配置立即生效:"
if [[ "$OS_TYPE" == "linux" ]]; then
echo "source $HOME/.bashrc"
elif [[ "$OS_TYPE" == "macos" ]]; then
echo "source $HOME/.zshrc"
fi
info "验证安装的命令:"
echo "conda --version && python --version"
echo "nvm --version && node --version && npm --version"
echo "npm config get registry && conda config --show-sources"
}
# 主执行流程
main() { main() {
info "========== 开始自动安装稳定版 mambaconda 和 nvm ==========" section "环境安装入口"
# 1. 检测系统信息 if [[ $# -eq 0 ]]; then
detect_system interactive_install
return
fi
# 2. 检查用户权限 case "${1:-}" in
check_root -h|--help)
usage
return
;;
esac
# 3. 安装基础依赖 install_targets "$@"
install_dependencies success "安装流程执行完成。"
# 4. 获取最新稳定版版本号(跳过 pre-release
get_stable_versions
# 5. 安装 mambaconda 稳定版
install_mambaconda
# 6. 安装 nvm 稳定版
install_nvm
# 7. 验证安装结果
verify_installation
# 8. 最终提示
finalize
} }
# 执行主函数 main "$@"
main

114
uninstall-docker.sh Normal file
View File

@@ -0,0 +1,114 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
OS_TYPE=""
REMOVE_DOCKER_DATA="${REMOVE_DOCKER_DATA:-0}"
info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
success() {
echo -e "${BLUE}[DONE]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
section() {
echo
echo -e "${BOLD}${BLUE}== $1 ==${NC}"
}
detect_system() {
case "${OSTYPE:-}" in
linux-gnu*) OS_TYPE="linux" ;;
darwin*) OS_TYPE="macos" ;;
*) error "不支持的操作系统: ${OSTYPE:-unknown},仅支持 Linux 和 macOS。" ;;
esac
info "检测到系统: $OS_TYPE"
}
run_privileged() {
if [[ "$(id -u)" -eq 0 ]]; then
"$@"
elif command -v sudo >/dev/null 2>&1; then
sudo "$@"
else
error "该步骤需要 root 权限,请安装 sudo 或以 root 身份运行。"
fi
}
uninstall_linux() {
section "卸载 Docker"
info "移除 Docker 相关软件包..."
if command -v apt-get >/dev/null 2>&1; then
run_privileged apt-get remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras docker-compose || true
run_privileged rm -f /etc/apt/sources.list.d/docker.list
run_privileged rm -f /etc/apt/keyrings/docker.asc
elif command -v dnf >/dev/null 2>&1; then
run_privileged dnf remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras docker-compose || true
run_privileged rm -f /etc/yum.repos.d/docker-ce.repo
elif command -v yum >/dev/null 2>&1; then
run_privileged yum remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras docker-compose || true
run_privileged rm -f /etc/yum.repos.d/docker-ce.repo
else
warn "当前 Linux 包管理器不受支持,请手动卸载 Docker。"
fi
if [[ "$REMOVE_DOCKER_DATA" == "1" ]]; then
warn "删除 Docker 数据目录..."
run_privileged rm -rf /var/lib/docker /var/lib/containerd
else
warn "默认保留 Docker 数据。如需删除 /var/lib/docker 和 /var/lib/containerd请设置 REMOVE_DOCKER_DATA=1。"
fi
}
uninstall_macos() {
section "卸载 Docker"
if command -v brew >/dev/null 2>&1 && brew list --cask docker >/dev/null 2>&1; then
info "移除 Docker Desktop..."
brew uninstall --cask docker || true
else
warn "未检测到 Docker Desktop cask。"
fi
if [[ "$REMOVE_DOCKER_DATA" == "1" ]]; then
warn "删除 Docker Desktop 数据..."
rm -rf "$HOME/Library/Containers/com.docker.docker"
rm -rf "$HOME/Library/Application Support/Docker Desktop"
rm -rf "$HOME/.docker"
else
warn "默认保留 Docker Desktop 数据。如需删除用户数据,请设置 REMOVE_DOCKER_DATA=1。"
fi
}
main() {
section "Docker 卸载脚本"
detect_system
if [[ "$OS_TYPE" == "linux" ]]; then
uninstall_linux
else
uninstall_macos
fi
success "Docker 卸载流程结束。"
}
main "$@"

68
uninstall-mambaconda.sh Normal file
View File

@@ -0,0 +1,68 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
CONDA_PATH="${CONDA_PATH:-$HOME/mambaconda}"
info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
success() {
echo -e "${BLUE}[DONE]${NC} $1"
}
section() {
echo
echo -e "${BOLD}${BLUE}== $1 ==${NC}"
}
remove_block() {
local file="$1"
local begin="$2"
local end="$3"
local tmp_file=""
[[ -f "$file" ]] || return 0
tmp_file="$(mktemp)"
awk -v begin="$begin" -v end="$end" '
index($0, begin) { skip=1; next }
index($0, end) { skip=0; next }
!skip { print }
' "$file" > "$tmp_file"
mv "$tmp_file" "$file"
}
main() {
section "Mambaconda 卸载脚本"
if [[ -d "$CONDA_PATH" ]]; then
info "删除 $CONDA_PATH ..."
rm -rf "$CONDA_PATH"
else
warn "目录不存在: $CONDA_PATH"
fi
if [[ -f "$HOME/.condarc" ]]; then
info "删除 $HOME/.condarc ..."
rm -f "$HOME/.condarc"
fi
remove_block "$HOME/.bashrc" "# >>> mambaconda initialize >>>" "# <<< mambaconda initialize <<<"
remove_block "$HOME/.zshrc" "# >>> mambaconda initialize >>>" "# <<< mambaconda initialize <<<"
success "Mambaconda 卸载流程结束。"
}
main "$@"

78
uninstall-nvm.sh Normal file
View File

@@ -0,0 +1,78 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
success() {
echo -e "${BLUE}[DONE]${NC} $1"
}
section() {
echo
echo -e "${BOLD}${BLUE}== $1 ==${NC}"
}
remove_block() {
local file="$1"
local begin="$2"
local end="$3"
local tmp_file=""
[[ -f "$file" ]] || return 0
tmp_file="$(mktemp)"
awk -v begin="$begin" -v end="$end" '
index($0, begin) { skip=1; next }
index($0, end) { skip=0; next }
!skip { print }
' "$file" > "$tmp_file"
mv "$tmp_file" "$file"
}
remove_line() {
local file="$1"
local line="$2"
local tmp_file=""
[[ -f "$file" ]] || return 0
tmp_file="$(mktemp)"
awk -v line="$line" '$0 != line { print }' "$file" > "$tmp_file"
mv "$tmp_file" "$file"
}
main() {
section "NVM 卸载脚本"
if [[ -d "$HOME/.nvm" ]]; then
info "删除 $HOME/.nvm ..."
rm -rf "$HOME/.nvm"
else
warn "目录不存在: $HOME/.nvm"
fi
remove_block "$HOME/.bashrc" "# >>> nvm initialize >>>" "# <<< nvm initialize <<<"
remove_block "$HOME/.zshrc" "# >>> nvm initialize >>>" "# <<< nvm initialize <<<"
remove_line "$HOME/.profile" 'export NVM_DIR="$HOME/.nvm"'
if command -v npm >/dev/null 2>&1; then
npm config delete registry >/dev/null 2>&1 || true
fi
success "NVM 卸载流程结束。"
}
main "$@"

141
uninstall.sh Normal file
View File

@@ -0,0 +1,141 @@
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
BOLD='\033[1m'
NC='\033[0m'
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
success() {
echo -e "${BLUE}[DONE]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
section() {
echo
echo -e "${BOLD}${BLUE}== $1 ==${NC}"
}
usage() {
cat <<'EOF'
用法:
bash uninstall.sh # 交互式选择卸载项
bash uninstall.sh all # 卸载全部工具
bash uninstall.sh docker # 仅卸载 Docker
bash uninstall.sh nvm # 仅卸载 NVM
bash uninstall.sh mambaconda # 仅卸载 Mambaconda
bash uninstall.sh docker nvm # 卸载多个指定工具
bash uninstall.sh --help
EOF
}
run_script() {
local script_name="$1"
local script_path="$SCRIPT_DIR/$script_name"
if [[ ! -f "$script_path" ]]; then
error "未找到脚本: $script_path"
fi
section "执行 $script_name"
bash "$script_path"
}
uninstall_docker() {
run_script "uninstall-docker.sh"
}
uninstall_nvm() {
run_script "uninstall-nvm.sh"
}
uninstall_mambaconda() {
run_script "uninstall-mambaconda.sh"
}
uninstall_targets() {
local target
for target in "$@"; do
case "$target" in
docker) uninstall_docker ;;
nvm) uninstall_nvm ;;
mambaconda) uninstall_mambaconda ;;
all)
uninstall_docker
uninstall_nvm
uninstall_mambaconda
;;
*)
error "未知卸载目标: $target"
;;
esac
done
}
interactive_uninstall() {
local reply=""
local selected=()
section "交互式卸载"
read -r -p "是否卸载 Docker? [y/N]: " reply
if [[ "$reply" =~ ^[Yy]$ ]]; then
selected+=("docker")
fi
read -r -p "是否卸载 NVM? [y/N]: " reply
if [[ "$reply" =~ ^[Yy]$ ]]; then
selected+=("nvm")
fi
read -r -p "是否卸载 Mambaconda? [y/N]: " reply
if [[ "$reply" =~ ^[Yy]$ ]]; then
selected+=("mambaconda")
fi
if [[ ${#selected[@]} -eq 0 ]]; then
warn "未选择任何卸载项。"
return
fi
uninstall_targets "${selected[@]}"
success "所选卸载项已执行完成。"
}
main() {
section "环境卸载入口"
if [[ $# -eq 0 ]]; then
interactive_uninstall
return
fi
case "${1:-}" in
-h|--help)
usage
return
;;
esac
uninstall_targets "$@"
success "卸载流程执行完成。"
}
main "$@"