源图客头像
Apache Spark4.1.3 一键部署与卸载脚本封面图

Apache Spark4.1.3 一键部署与卸载脚本

前置条件

1. 三台主机名已配置为 node11/node12/node13,且能互相 ping 通;
2. root 用户节点间 ssh/scp 免密可用(部署 Hadoop 时已配置);
3. JDK 17、Hadoop 3.5.0 已部署完成;
4. scala-2.13.16.tgz 与 spark-4.1.3-bin-hadoop3.tgz 已上传到 /usr/local/soft

一键部署脚本

cd /usr/local/soft
touch spark_deploy.sh
touch spark_uninstall.sh
chmod +x spark_deploy.sh
chmod +x spark_uninstall.sh

spark_deploy.sh内容如下

#!/bin/bash
# =============================================================================
# deploy_spark.sh —— Spark 4.1.3 集群一键部署脚本
#
# 在 node11(主节点)上以 root 执行:
#   步骤1 前置检查              步骤2 node11 安装 Scala 2.13.16
#   步骤3 node11 部署 Spark     步骤4 分发 Scala/Spark/环境变量到工作节点
#   步骤5 启动 Hadoop、Spark    步骤6 jps 验证集群进程
#
# 前置条件:
#   1. 三台主机名已配置为 node11/node12/node13,且能互相 ping 通;
#   2. root 用户节点间 ssh/scp 免密可用(部署 Hadoop 时已配置);
#   3. JDK 17、Hadoop 3.5.0 已部署完成;
#   4. scala-2.13.16.tgz 与 spark-4.1.3-bin-hadoop3.tgz 已上传到 /usr/local/soft。
#
# 用法:bash deploy_spark.sh
#   脚本可重复执行:已完成的步骤自动跳过,配置块带标记、不会重复追加。
# =============================================================================
set -eo pipefail
# 注意:不启用 -u(nounset)。/etc/profile 等外部环境文件中可能存在未定义变量,
# set -u 会让 source 它们时以 "unbound variable" 致命错误无提示退出整个脚本

# ------------------------------ 可按需修改的参数 -----------------------------
SOFT_DIR="/usr/local/soft"                        # 软件统一安装目录
SCALA_PKG="scala-2.13.16.tgz"
SCALA_DIR="scala-2.13.16"
SPARK_PKG="spark-4.1.3-bin-hadoop3.tgz"
SPARK_DIR="spark-4.1.3-bin-hadoop3"

JAVA_HOME_DIR="$SOFT_DIR/jdk-17.0.1"              # 已部署的 JDK(讲义表3-2)
HADOOP_HOME_DIR="$SOFT_DIR/hadoop-3.5.0"          # 已部署的 Hadoop
HADOOP_CONF_DIR="$HADOOP_HOME_DIR/etc/hadoop"

MASTER="node11"                                   # 主节点(讲义表3-1)
WORKERS=(node12 node13)                           # 工作节点
SPARK_WORKER_MEMORY="1024m"                       # Worker 可分配内存(讲义表3-3)
AUTO_START="yes"                                  # 部署后是否自动启动集群 yes/no

PROFILE="/etc/profile"
MARKER_BEGIN="# >>> spark-auto-deploy >>>"        # 配置块标记,保证可重复执行
MARKER_END="# <<< spark-auto-deploy <<<"

log()  { echo -e "\033[32m[INFO]\033[0m $*"; }
warn() { echo -e "\033[33m[WARN]\033[0m $*"; }
die()  { echo -e "\033[31m[FAIL]\033[0m $*" >&2; exit 1; }
trap 'die "部署在第 $LINENO 行出错,可用 bash -x $0 复查;处理后可重新执行本脚本"' ERR

# 向文件追加带标记的配置块;若已有旧块先整体删除,重复执行不会叠加
append_block() {   # $1=目标文件,配置块内容从标准输入读入
    local file="$1" tmp
    touch "$file"
    tmp=$(mktemp)
    awk -v b="$MARKER_BEGIN" -v e="$MARKER_END" \
        '$0 == b {skip=1} !skip {print} $0 == e {skip=0}' "$file" > "$tmp"
    cat "$tmp" > "$file" && rm -f "$tmp"
    cat >> "$file"
}

# ------------------------------ 步骤 1:前置检查 -----------------------------
log "步骤 1/6:前置检查"

[ "$(id -u)" -eq 0 ] || die "请使用 root 用户执行本脚本"
[ "$(hostname -s)" = "$MASTER" ] || die "请在 $MASTER(主节点)上执行本脚本,当前主机:$(hostname -s)"

[ -f "$SOFT_DIR/$SCALA_PKG" ] || die "缺少 $SOFT_DIR/$SCALA_PKG,请先上传"
[ -f "$SOFT_DIR/$SPARK_PKG" ] || die "缺少 $SOFT_DIR/$SPARK_PKG,请先上传"
[ -d "$JAVA_HOME_DIR" ]       || die "未找到 JDK 目录 $JAVA_HOME_DIR,请先安装 JDK 17"
[ -d "$HADOOP_CONF_DIR" ]     || die "未找到 Hadoop 配置目录 $HADOOP_CONF_DIR,请先部署 Hadoop"

for node in "${WORKERS[@]}"; do
    ping -c 1 -W 2 "$node" >/dev/null 2>&1 || die "无法 ping 通 $node,请检查网络与 /etc/hosts"
done

# 首次 ssh 连接不进入交互确认,避免 start-all.sh 远程启动进程时卡住
export SPARK_SSH_OPTS="-o StrictHostKeyChecking=no"
export HADOOP_SSH_OPTS="-o StrictHostKeyChecking=no"

JPS="$JAVA_HOME_DIR/bin/jps"
[ -x "$JPS" ] || JPS=jps

log "前置检查通过"

# ------------------------- 步骤 2:node11 安装 Scala -------------------------
log "步骤 2/6:安装 Scala 2.13.16(node11,讲义 3.3)"

if [ ! -d "$SOFT_DIR/$SCALA_DIR" ]; then
    tar -zxvf "$SOFT_DIR/$SCALA_PKG" -C "$SOFT_DIR"
    log "已解压 $SCALA_PKG 到 $SOFT_DIR/$SCALA_DIR"
else
    log "$SOFT_DIR/$SCALA_DIR 已存在,跳过解压"
fi

# 写入 /etc/profile:SCALA_HOME 与 SPARK_HOME 一次性配好(对应讲义两次 vi /etc/profile)
log "写入 SCALA_HOME / SPARK_HOME 环境变量到 $PROFILE"
append_block "$PROFILE" <<EOF

$MARKER_BEGIN
export SCALA_HOME=$SOFT_DIR/$SCALA_DIR
export SPARK_HOME=$SOFT_DIR/$SPARK_DIR
export PATH=\$PATH:\$SCALA_HOME/bin:\$SPARK_HOME/bin
$MARKER_END
EOF

# 不在脚本内 source /etc/profile:脚本全部使用绝对路径,无需立即生效;
# 且 source 外部环境文件可能引入不可控的报错导致脚本中断
"$SOFT_DIR/$SCALA_DIR/bin/scala" -version
log "Scala 安装完成"

# ------------------------- 步骤 3:node11 部署 Spark -------------------------
log "步骤 3/6:部署 Spark 4.1.3(node11,讲义 3.4)"

if [ ! -d "$SOFT_DIR/$SPARK_DIR" ]; then
    tar -zxvf "$SOFT_DIR/$SPARK_PKG" -C "$SOFT_DIR"
    log "已解压 $SPARK_PKG 到 $SOFT_DIR/$SPARK_DIR"
else
    log "$SOFT_DIR/$SPARK_DIR 已存在,跳过解压"
fi

SPARK_CONF_DIR="$SOFT_DIR/$SPARK_DIR/conf"
[ -d "$SPARK_CONF_DIR" ] || die "未找到 Spark 配置目录 $SPARK_CONF_DIR,解压可能不完整"

# 3.1 spark-env.sh:由模板复制后追加配置(讲义表3-3)
if [ ! -f "$SPARK_CONF_DIR/spark-env.sh" ] && [ -f "$SPARK_CONF_DIR/spark-env.sh.template" ]; then
    cp "$SPARK_CONF_DIR/spark-env.sh.template" "$SPARK_CONF_DIR/spark-env.sh"
fi
log "写入 spark-env.sh 配置"
append_block "$SPARK_CONF_DIR/spark-env.sh" <<EOF

$MARKER_BEGIN
# JDK目录:所有 Spark 进程都以它启动 JVM
export JAVA_HOME=$JAVA_HOME_DIR
# Scala目录
export SCALA_HOME=$SOFT_DIR/$SCALA_DIR
# Master 所在节点(集群入口地址);SPARK_MASTER_HOST 是 Spark 3+ 的官方变量名
export SPARK_MASTER_IP=$MASTER
export SPARK_MASTER_HOST=$MASTER
# 每个 Worker 进程可分配给 Executor 的总内存
export SPARK_WORKER_MEMORY=$SPARK_WORKER_MEMORY
# Hadoop 配置目录:Spark 通过它找到 HDFS 并接入 YARN
export HADOOP_CONF_DIR=$HADOOP_CONF_DIR
$MARKER_END
EOF

# 3.2 workers 文件:只写工作节点,绝不能保留 localhost(讲义 3.4 注意)
log "写入 workers 文件"
printf '%s\n' "${WORKERS[@]}" > "$SPARK_CONF_DIR/workers"
log "spark-env.sh 与 workers 配置完成(workers:${WORKERS[*]})"

# ---------------- 步骤 4:分发到 node12 / node13(讲义 3.3/3.4) --------------
log "步骤 4/6:分发 Scala、Spark 与环境变量到工作节点"

for node in "${WORKERS[@]}"; do
    log "向 $node 分发中(如未配置免密,请按提示输入 root 密码)..."
    # 先删除目标节点旧目录,避免 scp -r 把目录拷进同名旧目录里形成嵌套
    ssh "root@$node" "rm -rf '$SOFT_DIR/$SCALA_DIR' '$SOFT_DIR/$SPARK_DIR'"
    scp -q -r "$SOFT_DIR/$SCALA_DIR" "root@$node:$SOFT_DIR/"
    scp -q -r "$SOFT_DIR/$SPARK_DIR" "root@$node:$SOFT_DIR/"
    scp -q "$PROFILE" "root@$node:$PROFILE"
    # 讲义约定:分发完成后在目标节点执行验证
    ssh "root@$node" ". /etc/profile >/dev/null 2>&1; '$SOFT_DIR/$SCALA_DIR/bin/scala' -version"
    log "$node 分发并验证完成"
done

# ------------------------- 步骤 5:启动集群(讲义 3.5) -----------------------
if [ "$AUTO_START" = "yes" ]; then
    log "步骤 5/6:启动集群(先检测 Hadoop 是否已启动,已启动的不再重复启动)"

    # HDFS:NameNode 已在运行则跳过
    if "$JPS" -l 2>/dev/null | grep -qw NameNode; then
        log "Hadoop 的 HDFS 已在运行(NameNode 正常),跳过启动"
    else
        [ -x "$HADOOP_HOME_DIR/sbin/start-dfs.sh" ] || die "未找到 $HADOOP_HOME_DIR/sbin/start-dfs.sh,请检查 Hadoop 安装目录"
        "$HADOOP_HOME_DIR/sbin/start-dfs.sh"
        log "HDFS 启动完成"
    fi

    # YARN:ResourceManager 已在运行则跳过
    if "$JPS" -l 2>/dev/null | grep -qw ResourceManager; then
        log "Hadoop 的 YARN 已在运行(ResourceManager 正常),跳过启动"
    else
        [ -x "$HADOOP_HOME_DIR/sbin/start-yarn.sh" ] || die "未找到 $HADOOP_HOME_DIR/sbin/start-yarn.sh,请检查 Hadoop 安装目录"
        "$HADOOP_HOME_DIR/sbin/start-yarn.sh"
        log "YARN 启动完成"
    fi

    if "$JPS" -l 2>/dev/null | grep -qw Master; then
        log "Spark Master 已在运行,跳过 Spark start-all.sh"
    else
        # 讲义 3.5 注意:Hadoop 与 Spark 都有 start-all.sh,必须用完整路径
        "$SOFT_DIR/$SPARK_DIR/sbin/start-all.sh"
        log "Spark 集群启动完成"
    fi
    sleep 5
else
    log "步骤 5/6:跳过启动与验证(AUTO_START=$AUTO_START)"
fi

# ------------------------- 步骤 6:验证集群(讲义表3-4) ----------------------
if [ "$AUTO_START" = "yes" ]; then
    log "步骤 6/6:验证集群进程(讲义表3-4)"

    check_proc() {   # $1=节点  $2=应存在的进程
        local node="$1" proc="$2"
        if ssh "root@$node" ". /etc/profile >/dev/null 2>&1; jps" 2>/dev/null | grep -qw "$proc"; then
            log "  $node  $proc 进程正常"
        else
            warn "  $node  未发现 $proc,请登录该节点执行 jps 排查"
        fi
    }

    check_proc "$MASTER" NameNode
    check_proc "$MASTER" Master
    for node in "${WORKERS[@]}"; do
        check_proc "$node" DataNode
        check_proc "$node" Worker
    done
fi

echo
log "=============================================================="
log " Spark 集群部署完成!"
log "   版本   : Spark 4.1.3 / Scala 2.13.16 / Java 17"
log "   Master : $MASTER(spark-shell / spark-submit 在此节点运行)"
log "   Worker : ${WORKERS[*]}"
log "   Web UI : http://$MASTER:8080(Master),Worker UI 端口 8081"
log ""
log " 当前会话请先执行 source /etc/profile,再使用 spark-shell 等命令"
log " 停止集群:$SOFT_DIR/$SPARK_DIR/sbin/stop-all.sh"
log "          $HADOOP_HOME_DIR/sbin/stop-all.sh"
log "=============================================================="

一键卸载脚本

spark_uninstall.sh内容如下

#!/bin/bash
# =============================================================================
# spark_uninstall.sh —— 一键卸载 Spark 4.1.3 与 Scala 2.13.16(保留 JDK/Hadoop)
#
# 与 spark_deploy.sh 配套,按部署的逆序在 node11(主节点)上以 root 执行:
#   步骤1 前置检查                步骤2 停止 Spark 集群(不动 Hadoop)
#   步骤3 清除 /etc/profile 配置块 步骤4 删除 scala、spark 安装目录
#   步骤5 验证:spark/scala 已清除,java/hadoop 完好
#
# 说明:
#   1. 只删除 spark_deploy.sh 装的 scala-2.13.16 与 spark-4.1.3-bin-hadoop3
#      两个目录;
#   2. /etc/profile 中与 Scala/Spark 相关的环境变量全部清除,包括两类:
#      a) spark_deploy.sh 写入的标记配置块;
#      b) 手动 vi 添加的 SCALA_HOME、SPARK_HOME 及其 PATH 行;
#   3. JDK、Hadoop 及其在 /etc/profile 中的配置一概不动;
#   4. /usr/local/soft 下的两个 .tgz 安装包保留,需要时请自行删除;
#   5. 脚本可重复执行:已卸载的部分自动跳过。
#
# 用法:bash spark_uninstall.sh          (直接卸载,无需用户确认)
# =============================================================================
set -u

# ------------------------------ 可按需修改的参数 -----------------------------
# 与 spark_deploy.sh 保持一致
SOFT_DIR="/usr/local/soft"                        # 软件统一安装目录
SCALA_DIR="scala-2.13.16"
SPARK_DIR="spark-4.1.3-bin-hadoop3"

JAVA_HOME_DIR="$SOFT_DIR/jdk-17.0.1"              # 保留:已部署的 JDK
HADOOP_HOME_DIR="$SOFT_DIR/hadoop-3.5.0"          # 保留:已部署的 Hadoop
HADOOP_CONF_DIR="$HADOOP_HOME_DIR/etc/hadoop"

MASTER="node11"
WORKERS=(node12 node13)

PROFILE="/etc/profile"
MARKER_BEGIN="# >>> spark-auto-deploy >>>"        # 与 spark_deploy.sh 相同的标记
MARKER_END="# <<< spark-auto-deploy <<<"

log()  { echo -e "\033[32m[INFO]\033[0m $*"; }
warn() { echo -e "\033[33m[WARN]\033[0m $*"; }
die()  { echo -e "\033[31m[FAIL]\033[0m $*" >&2; exit 1; }

JPS="$JAVA_HOME_DIR/bin/jps"
[ -x "$JPS" ] || JPS=jps

# 清除文件中的 Scala/Spark 环境变量:标记配置块 + 手动添加的相关行
remove_block() {   # $1=目标文件
    local file="$1" tmp leftover
    [ -f "$file" ] || return 0

    if ! grep -qF "$MARKER_BEGIN" "$file" \
       && ! grep -q 'SCALA_HOME=' "$file" \
       && ! grep -q 'SPARK_HOME=' "$file"; then
        log "$file 中未发现 Scala/Spark 环境变量,跳过"
        return 0
    fi

    # 逐行过滤,删除两类内容:
    #   1) spark_deploy.sh 写入的标记配置块(含标记行本身);
    #   2) 按讲义手动 vi 添加的四行:
    #        export SCALA_HOME=/usr/local/soft/scala-2.13.16
    #        export PATH=$PATH:$SCALA_HOME/bin
    #        export SPARK_HOME=/usr/local/soft/spark-4.1.3-bin-hadoop3
    #        export PATH=$PATH:$SPARK_HOME/bin
    tmp=$(mktemp)
    awk -v b="$MARKER_BEGIN" -v e="$MARKER_END" '
        $0 == b {inb=1; next}
        $0 == e {inb=0; next}
        inb {next}
        index($0, "SCALA_HOME=") && index($0, "/usr/local/soft/scala") {next}
        index($0, "SPARK_HOME=") && index($0, "/usr/local/soft/spark") {next}
        index($0, "$SCALA_HOME/bin") {next}
        index($0, "$SPARK_HOME/bin") {next}
        {print}
    ' "$file" > "$tmp"
    cat "$tmp" > "$file" && rm -f "$tmp"
    log "$file:标记配置块与手动添加的 Scala/Spark 环境变量已全部删除"

    # 极少数情况:仍存在指向其他目录的 SCALA_HOME/SPARK_HOME,不误删,仅提示
    leftover=$(grep -nE 'SCALA_HOME=|SPARK_HOME=' "$file" 2>/dev/null || true)
    if [ -n "$leftover" ]; then
        warn "$file 中仍存在其他 Scala/Spark 环境变量(未动),请自行确认:"
        echo "$leftover" | sed 's/^/        /'
    fi
}

# ------------------------------ 步骤 1:前置检查 -----------------------------
log "步骤 1/5:前置检查"

[ "$(id -u)" -eq 0 ] || die "请使用 root 用户执行本脚本"
[ "$(hostname -s)" = "$MASTER" ] || die "请在 $MASTER(主节点)上执行本脚本,当前主机:$(hostname -s)"

for node in "${WORKERS[@]}"; do
    ping -c 1 -W 2 "$node" >/dev/null 2>&1 || die "无法 ping 通 $node,请检查网络与 /etc/hosts"
done

export SPARK_SSH_OPTS="-o StrictHostKeyChecking=no"

if [ ! -d "$SOFT_DIR/$SCALA_DIR" ] && [ ! -d "$SOFT_DIR/$SPARK_DIR" ] \
   && ! grep -qE 'SCALA_HOME=|SPARK_HOME=' "$PROFILE" 2>/dev/null; then
    log "本机未发现 Scala/Spark 安装目录和环境变量,无需卸载"
    exit 0
fi
log "前置检查通过"

# 不询问确认,直接卸载(仅提示卸载范围)
log "将在 $MASTER、${WORKERS[*]} 上卸载 Scala 与 Spark,并清除 /etc/profile 环境变量"
log "JDK($JAVA_HOME_DIR)与 Hadoop($HADOOP_HOME_DIR)不受影响"

# ------------------- 步骤 2:停止 Spark 集群(不动 Hadoop) -------------------
log "步骤 2/5:停止 Spark 集群"

if [ -x "$SOFT_DIR/$SPARK_DIR/sbin/stop-all.sh" ]; then
    "$SOFT_DIR/$SPARK_DIR/sbin/stop-all.sh" || warn "stop-all.sh 返回非零,继续执行"
    sleep 5
else
    log "未找到 $SPARK_DIR/sbin/stop-all.sh,跳过(安装目录可能已删除)"
fi

if "$JPS" 2>/dev/null | grep -qw Master; then
    warn "node11 上 Master 进程仍在运行,请手动处理:$JPS 查看 PID 后 kill"
else
    log "node11 上 Master 进程已停止"
fi
for node in "${WORKERS[@]}"; do
    if ssh "root@$node" ". /etc/profile >/dev/null 2>&1; jps" 2>/dev/null | grep -qw Worker; then
        warn "$node 上 Worker 进程仍在运行,请登录该节点手动 kill"
    else
        log "$node 上 Worker 进程已停止"
    fi
done

# ---------------- 步骤 3:清除 /etc/profile 环境变量(三个节点) ----------------
log "步骤 3/5:清除 /etc/profile 中的 Scala/Spark 环境变量"

remove_block "$PROFILE"
for node in "${WORKERS[@]}"; do
    scp -q "$PROFILE" "root@$node:$PROFILE"
    ssh "root@$node" "grep -qE 'SCALA_HOME=|SPARK_HOME=' '$PROFILE' && echo '$node: 环境变量清除异常' || echo '$node: 环境变量已清除'"
done

# ---------------- 步骤 4:删除 scala、spark 安装目录(三个节点) ---------------
log "步骤 4/5:删除 Scala 与 Spark 安装目录"

rm -rf "$SOFT_DIR/$SCALA_DIR" "$SOFT_DIR/$SPARK_DIR"
log "$MASTER:安装目录已删除"

for node in "${WORKERS[@]}"; do
    ssh "root@$node" "rm -rf '$SOFT_DIR/$SCALA_DIR' '$SOFT_DIR/$SPARK_DIR'"
    log "$node:安装目录已删除"
done

# --------------- 步骤 5:验证——spark/scala 已清除,java/hadoop 完好 ------------
log "步骤 5/5:验证卸载结果"

# 5.1 安装目录与环境变量应已清除,JDK/Hadoop 目录应完好
check_node() {   # $1=节点
    local node="$1"
    if ssh "root@$node" \
        "[ ! -d '$SOFT_DIR/$SCALA_DIR' ] && [ ! -d '$SOFT_DIR/$SPARK_DIR' ] \
         && ! grep -qE 'SCALA_HOME=|SPARK_HOME=' '$PROFILE' \
         && [ -d '$JAVA_HOME_DIR' ] && [ -d '$HADOOP_CONF_DIR' ]"; then
        log "  $node  scala/spark 已删除,环境变量已清除,JDK/Hadoop 完好"
    else
        warn "  $node  卸载不彻底或 JDK/Hadoop 目录异常,请登录该节点检查 $SOFT_DIR 与 $PROFILE"
    fi
    return 0
}
check_node "$MASTER"
for node in "${WORKERS[@]}"; do check_node "$node"; done

# 5.2 JDK 与 Hadoop 功能应不受影响(仅检查主节点)
if "$JAVA_HOME_DIR/bin/java" -version >/dev/null 2>&1; then
    log "JDK 正常:$("$JAVA_HOME_DIR/bin/java" -version 2>&1 | head -n 1)"
else
    warn "JDK 验证失败,请检查 $JAVA_HOME_DIR"
fi
[ -d "$HADOOP_CONF_DIR" ] && log "Hadoop 配置目录正常:$HADOOP_CONF_DIR"
if "$JPS" 2>/dev/null | grep -qw NameNode; then
    log "Hadoop NameNode 仍在运行(未受影响)"
else
    warn "NameNode 未运行。若卸载前 Hadoop 在运行,可用 $HADOOP_HOME_DIR/sbin/start-all.sh 重新启动"
fi

echo
log "=============================================================="
log " Spark 与 Scala 卸载完成!"
log "   已删除:$SOFT_DIR/$SCALA_DIR"
log "           $SOFT_DIR/$SPARK_DIR"
log "   已清除:/etc/profile 中的 SCALA_HOME、SPARK_HOME 及其 PATH 行"
log "   未动  :JDK($JAVA_HOME_DIR)、Hadoop($HADOOP_HOME_DIR)"
log "   保留  :/usr/local/soft 下的两个 .tgz 安装包"
log ""
log " 当前终端 PATH 可能仍残留 scala/spark 路径,执行 source /etc/profile"
log " 或重新登录后即恢复干净环境(hash -r 可清空命令缓存)"
log "=============================================================="

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/taogumo/article/details/169848449

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--