【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
相关推荐
wabs6664 小时前
关于贪心算法的思考
算法·贪心算法
YXXY3134 小时前
线程的介绍(四)
linux
李白你好5 小时前
AI Agent 架构的自动化渗透测试工具
运维·人工智能·自动化
社交怪人5 小时前
【判断大小】信息学奥赛一本通C语言解法(题号1043)
算法
Snasph5 小时前
GNU Make 用户手册(中文版)
服务器·算法·gnu
江澎涌5 小时前
拆解与 AI 的一次对话
人工智能·算法·程序员
一勺菠萝丶6 小时前
Docker Desktop 启动后容器自动启动怎么办?如何关闭容器自启动
运维·docker·容器
sheeta19986 小时前
LeetCode 每日一题笔记 日期:2026.06.02 题目:3635. 最早完成陆地和水上游乐设施的时间 II
笔记·算法·leetcode
Lsk_Smion6 小时前
力扣实训 _ [102].层序遍历--前序--后续_递归与非递归的实现
数据结构·算法·leetcode
ylscode6 小时前
Comodo防火墙曝致命零日漏洞:单个IPv6数据包即可触发Windows蓝屏死机
运维·网络·windows·安全·安全威胁分析