【Shell实战】Linux多节点分发文件

多节点分发文件

通过shell脚本将跳板机或者软件中转机上的文件,分发至一组目标机器中。

使用前提:

  • 跳板机或者软件中转机与目标集群均配置免密。
  • 目标机器的接收目录拥有足够的大小。

脚本使用说明:

sh distributing_packages.sh /data/gd/distributing /data/software 22

  • 第一个参数为分发文件所在目录所在的绝对路径:/data/gd/distributing
  • 第二个参数为目标机器接收目录所在的绝对路径:/data/software
  • 第三个参数为(可选参数) ssh端口号 要求整个分发机器们统一.22

使用日志输出样例

shell 复制代码
2023-11-15 17:46:39,273 [INFO ] 参数提示:
	第一个参数为分发目录所在的绝对路径,
	第二个参数为目标接收目录所在的绝对路径,
	第三个参数为(可选参数) ssh端口号 要求整个分发机器们统一.
例如: sh distributing_packages.sh /data/gd/distributing /data/software 22
2023-11-15 17:46:39,275 [INFO ] =================== 安装前检查开始 ===================
2023-11-15 17:46:39,280 [INFO ] =================== 安装前检查完毕 ===================
2023-11-15 17:46:39,665 [INFO ] =================== 分发文件开始 ===================
2023-11-15 17:46:39,672 [INFO ] 正在向[192.168.1.1]发送文件[apache-doris-2.0.2-bin-x64-noavx2.tar.gz]...
2023-11-15 17:47:04,260 [INFO ] 正在向[192.168.1.1]发送文件[apache-doris-2.0.2-bin-x64.tar.gz]...
2023-11-15 17:47:28,916 [INFO ] 正在向[192.168.1.1]发送文件[distributing_config.properties]...
2023-11-15 17:47:29,055 [INFO ] 正在向[192.168.1.1]发送文件[distributing_packages.sh]...
2023-11-15 17:47:29,195 [INFO ] 正在向[192.168.1.1]发送文件[jdk1.8.0_161.tgz]...
2023-11-15 17:47:30,969 [INFO ] 向[192.168.1.1]发送文件完毕
2023-11-15 17:47:30,977 [INFO ] 正在向[192.168.1.2]发送文件[apache-doris-2.0.2-bin-x64-noavx2.tar.gz]...
2023-11-15 17:47:55,485 [INFO ] 正在向[192.168.1.2]发送文件[apache-doris-2.0.2-bin-x64.tar.gz]...
2023-11-15 17:48:19,987 [INFO ] 正在向[192.168.1.2]发送文件[distributing_config.properties]...
2023-11-15 17:48:20,132 [INFO ] 正在向[192.168.1.2]发送文件[distributing_packages.sh]...
2023-11-15 17:48:20,272 [INFO ] 正在向[192.168.1.2]发送文件[jdk1.8.0_161.tgz]...
2023-11-15 17:48:22,036 [INFO ] 向[192.168.1.2]发送文件完毕
2023-11-15 17:48:22,044 [INFO ] 正在向[192.168.1.3]发送文件[apache-doris-2.0.2-bin-x64-noavx2.tar.gz]...
2023-11-15 17:48:46,588 [INFO ] 正在向[192.168.1.3]发送文件[apache-doris-2.0.2-bin-x64.tar.gz]...
2023-11-15 17:49:11,176 [INFO ] 正在向[192.168.1.3]发送文件[distributing_config.properties]...
2023-11-15 17:49:11,323 [INFO ] 正在向[192.168.1.3]发送文件[distributing_packages.sh]...
2023-11-15 17:49:11,470 [INFO ] 正在向[192.168.1.3]发送文件[jdk1.8.0_161.tgz]...
2023-11-15 17:49:13,266 [INFO ] 向[192.168.1.3]发送文件完毕
2023-11-15 17:49:13,269 [INFO ] =================== 分发文件成功 ===================

目标机器的IP存放在配置文件distributing_config.properties中,脚本通过解析配置文件获取它们。

脚本源码:

distributing_packages.sh

shell 复制代码
#!/bin/bash
# Author                : Donny
# Date                  : 2023/11/15
# Func                  : 软件包分发脚本
#                         例如:sh distributing_packages.sh /data/gd/distributing /data/software 22
##########################################################################

# ############################## Prameter area ##############################
# 采用绝对地址表示软件包分发的目录,容量至少50G。
distributingPackagePath=$1
# 分发配置文件名
distributingConfigFile="distributing_config.properties"
# 获取本地IP
localIP=$(ifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}')
# ssh端口 为可选参数
sshPort=22

# 分发目标节点IP
targetIps=""

# 分发目标节点的接收目录,容量至少50G。
targetPath=$2

if [[ -n "${3}" ]]; then
    sshPort=${3}
fi

# ############################## Buildin function area ##############################
# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 日志模块 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# 初始化日志模块
function initLogModule() {
    # 初始化日志输出
    logPath=$(pwd)
    # 脚本日志目录
    LogFile="$logPath/logs/distributing_package_$(date +%F).log"
    mkdir -p "${distributingPackagePath}/logs"

    # 创建日志文件
    if ! [ -f "${LogFile}" ]; then
        touch "$LogFile"
    fi

    echo "日志文件为: ${LogFile}"
}

# 输出红色高亮字体并标记ERROR
function echo_error() {
    echo -e "\033[1;31m$1\033[0m"
    [ -n "${LogFile}" ] && echo "$(date +%F\ %T,%N | cut -c1-23) [ERROR] $1" >>"${LogFile}"
}

# 输出默认字体并标记INFO
function echo_info() {
    echo -e "$1"
    [ -n "${LogFile}" ] && echo "$(date +%F\ %T,%N | cut -c1-23) [INFO ] $1" >>"${LogFile}"
}

# 输出绿色字体并标记INFO
function echo_green() {
    echo -e "\033[32m$1\033[0m"
    [ -n "${LogFile}" ] && echo "$(date +%F\ %T,%N | cut -c1-23) [INFO ] $1" >>"${LogFile}"
}
# <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 日志模块 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

# 获取配置文件内容
function getPropertiesValue() {

    # check文件是否存在
    if ! [ -f "${distributingPackagePath}/${distributingConfigFile}" ]; then
        echo_error "缺少配置文件[${distributingPackagePath}/${distributingConfigFile}]"
        exit 1
    fi

    # check 文件中是否配置了distributingTargeIps
    file=$(grep 'distributingTargeIps' "${distributingPackagePath}"/"${distributingConfigFile}")

    if [[ -z "${file}" ]]; then
        echo_error "缺少配置项distributingTargeIps"
        exit 1
    fi

    # check distributingTargeIps的合法性
    targetIps=$(echo "$file" | awk -F "=" '{print $2}' | awk -F "," '{for(i=1;i<=NF;i++) a[i,NR]=$i}END{for(i=1;i<=NF;i++) {for(j=1;j<=NR;j++) printf a[i,j] " ";print ""}}')

    length1=$(echo "$targetIps" | wc -l)
    length2=$(echo "$targetIps" | sort -u | wc -l)

    if [[ "$length1" != "$length2" ]]; then
        echo_error "distributingTargeIps中存在IP重复或存在多余分隔符"
        exit 1
    fi

    errorIp=""
    for ip in ${targetIps}; do
        if [[ "${ip}" != "${localIP}" ]]; then
            ssh -p${sshPort} "${ip}" 'mkdir -p '${targetPath}'' &>/dev/null
            [ "$?" != "0" ] && errorIp="$errorIp"$ip, && continue
        fi
    done

    if [[ -n "${errorIp}" ]]; then
        errorIp=${errorIp::-1}
        echo_error "${errorIp}无法ssh"
        exit 1
    fi

}

# ############################## Execute body area ##############################
# 初始化日志
initLogModule
echo_info "参数提示:
	第一个参数为分发目录所在的绝对路径,
    第二个参数为目标接收目录所在的绝对路径,
	第三个参数为(可选参数) ssh端口号 要求整个分发机器们统一.
例如: sh $0 /data/gd/distributing /data/software 22"

echo_info "=================== 安装前检查开始 ==================="
current=$(whoami)
# 0.用户检查
if [[ "root" != "$current" ]]; then
    echo_error "请使用root用户执行脚本!"
    exit 1
fi
# 1.检查参数是否齐全
if [[ -z "${distributingPackagePath}" || -z "${targetPath}" ]]; then
    echo_error "请输入正确参数:
	第一个参数为分发目录所在的绝对路径,
    第二个参数为目标接收目录所在的绝对路径
	第三个参数为(可选参数) ssh端口号 要求整个集群统一.
例如: sh $0 /data/gd/distributing /data/software 22"
    exit 1
# 2.检查路径是否非法
elif ! [ -d "${distributingPackagePath}" ]; then
    echo_error "目录${distributingPackagePath}不存在"
    exit 1
fi
echo_green "=================== 安装前检查完毕 ==================="

getPropertiesValue

errorflag=0
echo_info "=================== 分发文件开始 ==================="
# 向集群结点分发
for ip in ${targetIps}; do
    errorDistribution=""
    if [[ "${ip}" != "${localIP}" ]]; then
        # 发送配置文件
        packageFiles=$(ls ${distributingPackagePath})
        for file in ${packageFiles}; do
            sudo scp -P${sshPort} ${distributingPackagePath}/${file} root@${ip}:${targetPath}/${file} &>/dev/null
            [ "$?" != "0" ] && errorDistribution="$errorDistribution""向[$ip]发送[$file]失败, "
        done

        if [[ -n "${errorDistribution}" ]]; then
            errorflag=1
            errorDistribution=${errorDistribution}"。"
            echo_error "${errorDistribution}"
        else
            echo_info "向[${ip}]发送文件完毕"
        fi
    fi

done

if ((${errorflag} == 1)); then
    echo_error "=================== 分发文件失败 ==================="
    exit 1
else
    echo_green "=================== 分发文件成功 ==================="
fi

# ############################## Return value area ##############################
exit 0

distributing_config.properties

shell 复制代码
# distributingTargeIps代表软件包需要分发到的IP地址,格式ip1,ip2,ip3
distributingTargeIps=192.168.1.1,192.168.1.2,192.168.1.3
相关推荐
海绵宝宝转agent6 分钟前
2026-10-16 4算法+1面经
算法
秋名山小白8 分钟前
UI自动化-Airtest框架落地实战
运维·ui·自动化
刘胡子大叔9 分钟前
Docker 容器名 ping 不通
运维·docker·容器
a59865227 分钟前
Docker多开云手机,六边云独立端口隔离访问实战
android·运维·docker·容器·智能手机·云手机
小poop30 分钟前
基础排序算法详解——插入、选择与交换排序
算法·排序算法
戴西软件33 分钟前
企业如何搭建自己的AI智能体?戴西智能体管理与戴西SKILL管理实战解析
运维·jvm·人工智能·自动化·rpa
青蓝智慧马老师34 分钟前
想学数据分析但零基础,正确顺序不是先学 Python
大数据·人工智能·算法
wei0913043 分钟前
2026 企业 AI 办公工具选型指南:搭建 AI 与现有办公流程融合体系
大数据·运维·人工智能
ggaofeng44 分钟前
如何配置snat(让内网访问外网)和dnat(将外网请求转发到内网服务器)
运维·服务器·snat·dnat·局域网访问外网·外网访问局域网
jeo陽1 小时前
05-数组与冒泡排序:第一个数据结构与经典算法
c语言·数据结构·算法