Add modular install and uninstall scripts
This commit is contained in:
114
README.md
Normal file
114
README.md
Normal 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
171
install-docker.sh
Normal 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
274
install-mambaconda.sh
Normal 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
215
install-nvm.sh
Normal 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 "$@"
|
||||||
511
install.sh
511
install.sh
@@ -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. 检测系统信息
|
|
||||||
detect_system
|
|
||||||
|
|
||||||
# 2. 检查用户权限
|
|
||||||
check_root
|
|
||||||
|
|
||||||
# 3. 安装基础依赖
|
|
||||||
install_dependencies
|
|
||||||
|
|
||||||
# 4. 获取最新稳定版版本号(跳过 pre-release)
|
|
||||||
get_stable_versions
|
|
||||||
|
|
||||||
# 5. 安装 mambaconda 稳定版
|
|
||||||
install_mambaconda
|
|
||||||
|
|
||||||
# 6. 安装 nvm 稳定版
|
|
||||||
install_nvm
|
|
||||||
|
|
||||||
# 7. 验证安装结果
|
if [[ $# -eq 0 ]]; then
|
||||||
verify_installation
|
interactive_install
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
# 8. 最终提示
|
case "${1:-}" in
|
||||||
finalize
|
-h|--help)
|
||||||
|
usage
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
install_targets "$@"
|
||||||
|
success "安装流程执行完成。"
|
||||||
}
|
}
|
||||||
|
|
||||||
# 执行主函数
|
main "$@"
|
||||||
main
|
|
||||||
|
|||||||
114
uninstall-docker.sh
Normal file
114
uninstall-docker.sh
Normal 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
68
uninstall-mambaconda.sh
Normal 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
78
uninstall-nvm.sh
Normal 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
141
uninstall.sh
Normal 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 "$@"
|
||||||
Reference in New Issue
Block a user