Linux安装go最新版脚本

AI摘要
该内容提供了一个用于在Linux系统上自动安装Go语言环境的Bash脚本。脚本功能包括检测系统架构、下载最新版Go、配置系统及用户环境变量、创建Go工作目录,并提供安装后的验证与使用指引。这是一个典型的【知识分享】型技术教程,旨在帮助用户快速部署Go开发环境。

找到了获取go版本的办法,讲一下内容保存为一个sh文件,bash .sh执行,脚本执行完成之后,手动执行 source ~/.bashrc命令,在当前用户下重新加载.basrc文件包含的环境变量。

#!/bin/bash
# Go 语言一键安装脚本(最新版)
# 自动适配 bash/zsh,完美支持颜色输出
# 使用方法: sudo bash install-go.sh

set -e

# 颜色定义(修复转义问题)
if [ -t 1 ]; then
    RED=$(printf '\033[0;31m')
    GREEN=$(printf '\033[0;32m')
    YELLOW=$(printf '\033[1;33m')
    BLUE=$(printf '\033[0;34m')
    NC=$(printf '\033[0m')
else
    RED='' GREEN='' YELLOW='' BLUE='' NC=''
fi

# 日志函数
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[✓]${NC} $1"; }
warning() { echo -e "${YELLOW}[!]${NC} $1"; }
error() { echo -e "${RED}[✗]${NC} $1"; exit 1; }

# 检查 root 权限
[ "$(id -u)" -ne 0 ] && error "请使用 sudo 运行此脚本"

# 获取实际用户信息
ACTUAL_USER="${SUDO_USER:-$(logname 2>/dev/null || who am i | awk '{print $1}' || echo $USER)}"
USER_HOME=$(eval echo ~$ACTUAL_USER)

# 检测用户使用的 Shell
USER_SHELL=$(grep "^$ACTUAL_USER:" /etc/passwd | cut -d: -f7)
USER_SHELL_NAME=$(basename "$USER_SHELL")

info "开始安装 Go 语言环境..."
info "检测到用户: $ACTUAL_USER (Shell: $USER_SHELL_NAME)"

# 1. 检测系统架构
info "检测系统架构..."
ARCH=$(uname -m)
case $ARCH in
    x86_64) GO_ARCH="amd64" ;;
    aarch64|arm64) GO_ARCH="arm64" ;;
    armv7l) GO_ARCH="armv6l" ;;
    i386|i686) GO_ARCH="386" ;;
    *) error "不支持的架构: $ARCH" ;;
esac
success "系统架构: $GO_ARCH"

# 2. 安装必要依赖
info "检查依赖工具..."
MISSING_DEPS=()
for cmd in curl wget tar; do
    if ! command -v $cmd &>/dev/null; then
        MISSING_DEPS+=($cmd)
    fi
done

if [ ${#MISSING_DEPS[@]} -gt 0 ]; then
    info "安装依赖: ${MISSING_DEPS[*]}..."
    if command -v apt &>/dev/null; then
        apt update -qq && apt install -y ${MISSING_DEPS[@]}
    elif command -v yum &>/dev/null; then
        yum install -y ${MISSING_DEPS[@]}
    fi
fi

# 3. 获取最新版本
info "获取 Go 最新版本信息..."
GO_VERSION=$(curl -sL https://golang.org/VERSION?m=text 2>/dev/null | head -1)
if [ -z "$GO_VERSION" ]; then
    warning "无法获取最新版本,尝试备用方法..."
    GO_VERSION=$(curl -sL https://go.dev/VERSION?m=text 2>/dev/null | head -1)
fi
[ -z "$GO_VERSION" ] && GO_VERSION="go1.23.4"

GO_VERSION=${GO_VERSION#go}
success "目标版本: $GO_VERSION"

# 4. 备份旧版本
if [ -d "/usr/local/go" ]; then
    BACKUP_DIR="/usr/local/go.backup.$(date +%Y%m%d_%H%M%S)"
    warning "发现已安装版本,备份至: $BACKUP_DIR"
    mv /usr/local/go "$BACKUP_DIR"
fi

# 5. 下载 Go
FILENAME="go${GO_VERSION}.linux-${GO_ARCH}.tar.gz"
info "下载 Go $GO_VERSION ($FILENAME)..."

# 多镜像源尝试
MIRRORS=(
    "https://go.dev/dl"
    "https://golang.google.cn/dl"
    "https://mirrors.aliyun.com/golang"
    "https://dl.google.com/go"
)

DOWNLOADED=false
for MIRROR in "${MIRRORS[@]}"; do
    DOWNLOAD_URL="${MIRROR}/${FILENAME}"
    info "尝试: $MIRROR"

    if wget -q --show-progress --timeout=30 -O "$FILENAME" "$DOWNLOAD_URL" 2>/dev/null || \
       curl -L --progress-bar --max-time 30 -o "$FILENAME" "$DOWNLOAD_URL" 2>/dev/null; then
        DOWNLOADED=true
        success "下载完成"
        break
    else
        warning "失败,尝试下一个..."
    fi
done

[ "$DOWNLOADED" = false ] && error "所有镜像下载失败,请检查网络"

# 6. 安装 Go
info "解压安装..."
tar -C /usr/local -xzf "$FILENAME" || error "解压失败"
success "安装完成: /usr/local/go"

# 7. 配置环境变量
info "配置环境变量..."

# 系统级配置
cat > /etc/profile.d/go.sh << 'EOF'
#!/bin/sh
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin:$GOBIN
export GOPROXY=https://goproxy.cn,direct
export GO111MODULE=on
EOF
chmod 644 /etc/profile.d/go.sh
success "系统配置: /etc/profile.d/go.sh"

# 用户级配置 - 智能检测并配置所有 Shell 配置文件
info "检测并配置用户 Shell 环境..."

# 定义要检查的配置文件(按优先级)
SHELL_CONFIGS=(
    "$USER_HOME/.zshrc"          # zsh 主配置
    "$USER_HOME/.bashrc"         # bash 主配置  
    "$USER_HOME/.bash_profile"   # bash 登录配置
    "$USER_HOME/.profile"        # 通用登录配置
)

GO_ENV_CONFIG='
# ============ Go Environment ============
# Auto-generated by Go installer
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin:$GOBIN
export GOPROXY=https://goproxy.cn,direct
export GO111MODULE=on
# ========================================
'

CONFIGURED_COUNT=0
for CONFIG in "${SHELL_CONFIGS[@]}"; do
    if [ -f "$CONFIG" ]; then
        CONFIG_NAME=$(basename "$CONFIG")

        # 检查是否已有 Go 配置
        if grep -q "GOROOT=/usr/local/go" "$CONFIG" 2>/dev/null; then
            info "$CONFIG_NAME 已有 Go 配置,正在更新..."
        else
            info "$CONFIG_NAME 未配置,正在添加..."
        fi

        # 创建备份
        cp "$CONFIG" "$CONFIG.bak.$(date +%Y%m%d_%H%M%S)" 2>/dev/null || true

        # 删除所有旧的 Go 相关配置(支持多种格式)
        sed -i '/# ============ Go Environment/,/# ========================================/d' "$CONFIG" 2>/dev/null || true
        sed -i '/# Go environment/,/^$/d' "$CONFIG" 2>/dev/null || true
        sed -i '/export GOROOT=\/usr\/local\/go/d' "$CONFIG" 2>/dev/null || true
        sed -i '/export GOPATH=.*\/go/d' "$CONFIG" 2>/dev/null || true
        sed -i '/export GOBIN=/d' "$CONFIG" 2>/dev/null || true
        sed -i '/export GOPROXY=/d' "$CONFIG" 2>/dev/null || true
        sed -i '/export GO111MODULE=/d' "$CONFIG" 2>/dev/null || true
        sed -i '/.*GOROOT.*bin.*PATH/d' "$CONFIG" 2>/dev/null || true

        # 添加新配置
        echo "$GO_ENV_CONFIG" >> "$CONFIG"
        chown $ACTUAL_USER:$ACTUAL_USER "$CONFIG"

        success "✓ 已配置 $CONFIG_NAME"
        CONFIGURED_COUNT=$((CONFIGURED_COUNT + 1))
    fi
done

if [ $CONFIGURED_COUNT -eq 0 ]; then
    warning "未找到任何 Shell 配置文件,创建 .bashrc..."
    echo "$GO_ENV_CONFIG" > "$USER_HOME/.bashrc"
    chown $ACTUAL_USER:$ACTUAL_USER "$USER_HOME/.bashrc"
    success "✓ 已创建并配置 .bashrc"
else
    success "共配置了 $CONFIGURED_COUNT 个 Shell 配置文件"
fi

# 创建工作目录
mkdir -p "$USER_HOME/go"/{src,bin,pkg}
chown -R $ACTUAL_USER:$ACTUAL_USER "$USER_HOME/go"
success "工作目录: $USER_HOME/go"

# 8. 验证安装
info "验证安装..."
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin

if $GOROOT/bin/go version &>/dev/null; then
    INSTALLED_VERSION=$($GOROOT/bin/go version)
    success "$INSTALLED_VERSION"
else
    error "验证失败"
fi

# 9. 清理
rm -f "$FILENAME"
success "清理完成"

# 10. 显示安装信息(纯文本,无转义问题)
cat << EOF

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
         Go 安装成功!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📦 安装信息:
  版本:      Go $GO_VERSION
  架构:      $GO_ARCH  
  路径:      /usr/local/go
  工作目录:  $USER_HOME/go
  用户Shell: $USER_SHELL_NAME

📁 已配置的文件:
EOF

# 显示配置了哪些文件
for CONFIG in "${SHELL_CONFIGS[@]}"; do
    if [ -f "$CONFIG" ]; then
        echo "  ✓ $(basename $CONFIG)"
    fi
done

cat << 'EOF'

🔧 环境变量:
  GOROOT=/usr/local/go
  GOPATH=$USER_HOME/go
  GOPROXY=https://goproxy.cn,direct

⚡ 立即使用(自动加载):
EOF

# 显示加载状态
if [ "$AUTO_LOADED" = true ]; then
    echo "  ✅ 环境已自动加载,可以直接使用!"
    echo "  ✅ 新终端会话会自动生效"
elif [ -f "$RELOAD_SCRIPT" ]; then
    echo "  执行自动加载脚本:"
    echo "  bash $RELOAD_SCRIPT"
    echo ""
    echo "  或手动加载配置:"
    if [[ "$USER_SHELL_NAME" == "zsh" ]]; then
        echo "  source ~/.zshrc"
    elif [[ "$USER_SHELL_NAME" == "bash" ]]; then
        echo "  source ~/.bashrc"
    else
        echo "  source ~/.profile"
    fi
else
    if [[ "$USER_SHELL_NAME" == "zsh" ]]; then
        echo "  source ~/.zshrc"
    elif [[ "$USER_SHELL_NAME" == "bash" ]]; then
        echo "  source ~/.bashrc"
    else
        echo "  source /etc/profile"
    fi
fi

cat << 'EOF'

📝 快速开始:
  1. 验证安装
     go version

  2. 查看环境
     go env

  3. 创建第一个程序
     mkdir -p ~/go/src/hello && cd ~/go/src/hello
     go mod init hello
     cat > main.go << 'GOCODE'
package main
import "fmt"
func main() {
    fmt.Println("Hello, Go!")
}
GOCODE
     go run main.go

💡 常用命令:
  go version      查看版本
  go env          查看环境
  go mod init     初始化模块
  go get          安装依赖
  go build        编译程序
  go run          运行程序
  go test         测试程序

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EOF

# 11. 自动加载环境(关键!)
info "正在为当前会话加载环境变量..."

# 导出到系统环境(当前 root 会话)
export GOROOT=/usr/local/go
export GOPATH=$USER_HOME/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin:$GOBIN
export GOPROXY=https://goproxy.cn,direct
export GO111MODULE=on

# 加载系统级配置
source /etc/profile.d/go.sh 2>/dev/null || true

# 创建自动加载脚本
RELOAD_SCRIPT="/tmp/reload-go-env-$ACTUAL_USER.sh"
cat > "$RELOAD_SCRIPT" << 'RELOAD_EOF'
#!/bin/bash
# Go 环境自动加载脚本

# 颜色定义
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m'

echo -e "${BLUE}[自动加载] 正在加载 Go 环境...${NC}"

# 检测当前 Shell
if [ -n "$ZSH_VERSION" ]; then
    SHELL_TYPE="zsh"
    CONFIG_FILE="$HOME/.zshrc"
elif [ -n "$BASH_VERSION" ]; then
    SHELL_TYPE="bash"
    CONFIG_FILE="$HOME/.bashrc"
else
    SHELL_TYPE="unknown"
    CONFIG_FILE="$HOME/.profile"
fi

# 加载配置
if [ -f "$CONFIG_FILE" ]; then
    source "$CONFIG_FILE"
    echo -e "${GREEN}[✓]${NC} 已加载 $CONFIG_FILE"
fi

# 加载系统配置
if [ -f "/etc/profile.d/go.sh" ]; then
    source /etc/profile.d/go.sh
    echo -e "${GREEN}[✓]${NC} 已加载系统配置"
fi

# 直接设置环境变量(确保生效)
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin:$GOBIN
export GOPROXY=https://goproxy.cn,direct
export GO111MODULE=on

# 验证
if command -v go &>/dev/null; then
    echo -e "${GREEN}[✓]${NC} Go 环境已成功加载!"
    echo ""
    go version
    echo ""
    echo -e "${BLUE}提示:${NC} 当前 Shell 会话的环境已生效"
    echo -e "${BLUE}提示:${NC} 新终端会话会自动加载配置"
else
    echo -e "${YELLOW}[!]${NC} 环境加载失败,请手动执行:"
    echo "  export PATH=\$PATH:/usr/local/go/bin"
    echo "  go version"
fi
RELOAD_EOF

chmod +x "$RELOAD_SCRIPT"
chown $ACTUAL_USER:$ACTUAL_USER "$RELOAD_SCRIPT"

# 尝试为用户 Shell 自动加载(如果是通过 sudo 运行)
AUTO_LOADED=false
if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
    info "尝试为用户 $SUDO_USER 自动加载环境..."

    # 方法1: 通过 su 执行加载脚本
    if su - $SUDO_USER -c "bash $RELOAD_SCRIPT" 2>/dev/null; then
        AUTO_LOADED=true
        success "✓ 已自动加载到用户环境"
    fi

    # 方法2: 创建提示信息
    if [ "$AUTO_LOADED" = false ]; then
        warning "无法自动加载到用户 Shell,需要手动执行"
    fi
fi

# 在当前 root 会话测试
if command -v go &>/dev/null; then
    echo ""
    success "✓ 当前会话环境已生效"
    go version
    echo ""
fi

# 创建简化的加载命令
if [ "$AUTO_LOADED" = false ]; then
    echo ""
    warning "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    warning "  请执行以下命令使环境立即生效:"
    warning "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""

    # 根据 Shell 类型给出精确命令
    if [[ "$USER_SHELL_NAME" == "zsh" ]]; then
        echo "  source ~/.zshrc && go version"
    elif [[ "$USER_SHELL_NAME" == "bash" ]]; then
        echo "  source ~/.bashrc && go version"
    else
        echo "  source ~/.profile && go version"
    fi

    echo ""
    echo "或者直接运行加载脚本:"
    echo "  bash $RELOAD_SCRIPT"
    echo ""
    warning "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
fi

success "安装完成!"
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 7

GO本身有工具支持安装多版本: go.dev/doc/manage-install

3年前 评论
yanling (楼主) 3年前

请问 这个脚本没用设置GOROOT和单独设置GOPATH吗 可以加上设置完后 自动 GO111MODULE=on 和goproxy.cn/ 也一起设置就好了 这样就可以偷懒了

3年前 评论
yanling (楼主) 3年前
yanling (楼主) 3年前
yanling (楼主) 3年前

#!/bin/bash

# 检查系统权限
if [ "$(whoami)" != "root" ]; then
  echo "请使用 root 权限运行此脚本!"
  exit 1
fi

# 检查 curl 命令是否存在
if ! command -v curl &> /dev/null
then
    echo "错误:curl 命令未找到,请先安装 curl。"
    exit 1
fi

# 获取最新版本信息
golang_version_info=$(curl -s https://go.dev/VERSION?m=text)
if [ $? -ne 0 ]; then
  echo "错误:无法从 go.dev 获取版本信息。"
  exit 1
fi
golang_version=$(echo "${golang_version_info}" | grep -oP 'go\d+\.\d+(?:\.\d+)?') # 提取版本号
if [ -z "${golang_version}" ]; then
  echo "错误:无法解析版本号。"
  exit 1
fi

# 下载 Golang 安装包
golang_url="https://dl.google.com/go/go${golang_version}.linux-amd64.tar.gz"
echo "正在下载 Golang ${golang_version} 安装包..."
wget -qO golang.tar.gz "${golang_url}"
if [ $? -ne 0 ]; then
  echo "错误:下载 Golang 安装包失败。"
  exit 1
fi

# 解压安装包
echo "正在解压安装包..."
tar -xzf golang.tar.gz -C /usr/local
if [ $? -ne 0 ]; then
  echo "错误:解压安装包失败。"
  exit 1
fi

# 设置环境变量 (添加到 /etc/profile)
echo "正在设置环境变量..."
if ! grep -q "export GOROOT=/usr/local/go" /etc/profile; then # 检查是否已存在,避免重复添加
  cat << EOF >> /etc/profile
export GOROOT=/usr/local/go
export GOPATH=\$HOME/go # 注意转义 $ 符号
export PATH=\$PATH:/usr/local/go/bin
EOF
fi

# 更新环境变量
source /etc/profile

# 删除临时文件
rm -f golang.tar.gz # -f 即可,golang.tar.gz 不太可能是目录

# 打印安装成功信息
echo "Golang ${golang_version} 安装成功!"
echo "请重启您的终端以使环境变量生效。"

exit 0 # 脚本成功退出
11个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!