xsync集群分发脚本的改良[通俗易懂]

xsync集群分发脚本的改良[通俗易懂]集群分发脚本xsync带多参数1.0增强了一下带参个数xsync1.0#!/bin/bash#校验参数pcount=$#if(($pcount==0))then exitfi#获取用户名user=`whoami`#获取文件名,路径for((i=1;i<=$#;i++))#对多个传参进行分析dob=${!i} #这里用到了“间接变量”语法fname=`basename$b`dname=`dirname$b`dir=`cd$dname;pwd`

大家好,又见面了,我是你们的朋友全栈君。

集群分发脚本xsync带多参数1.0到2.0

不好用的分发脚本,缺点:不能同时传多个文件,集群规模需要手动调整,某些变量不是完全解耦

#!/bin/bash
#1 获取输入参数个数,如果没有参数,直接退出
pcount=$#
if((pcount==0)); then
echo no args;
exit;
fi

#2 获取文件名称
p1=$1
fname=`basename $p1`
echo fname=$fname

#3 获取上级目录到绝对路径
pdir=`cd -P $(dirname $p1); pwd`
echo pdir=$pdir

#4 获取当前用户名称
user=`whoami`

#5 循环
for((host=103; host<105; host++)); do
        echo ------------------- hadoop$host --------------
        rsync -av $pdir/$fname $user@hadoop$host:$pdir
done

xsync1.0

增强了一下带参个数

起因 拟了一个test脚本尝试实现 循环遍历后面跟的多个文件的basename,获取文件名称

#!/bin/bash
#循环遍历,获取文件名称
#for((i=1;i<=$#;i++))
for i in `seq $#`
do
   echo `basename $i`
done

测试结果:

[root@flinkbeginning ~]# ./test 3.txt 5.txt 
1
2

无法获取正确的文件名称 3.txt 5.txt;
我需要把 $i 作为一个整体,继续对其进行 $ 取值,但是 $$i 在shell脚本中直接用是不成立的

#!/bin/bash
#for((i=1;i<=$#;i++))
for i in `seq $#`
do
    echo $$i
    #echo `basename $i`
done

测试结果

[root@flinkbeginning ~]# ./test.sh 3.txt 5.txt 
125435i
125435i

此处↓

知识点:间接变量

#!/bin/bash
#2 获取文件名,路径
#for((i=1;i<=$#;i++))
for i in `seq $#`   #对多个传参进行分析 例如:~/xsync /opt/module /etc/profile
do
file=${ 
   !i}		#这里用到了 “间接变量”语法 或者 eval file=\$$i
#eval file=\$$i
fname=`basename $file`
dname=`dirname $file`
dir=`cd $dname;pwd`
#echo $dir
done

解释一下,用到一个知识点:间接变量

1.使用间接变量你这个使用间接变量就可以解决了,这是我之前的笔记:
什么是间接变量:假设一个变量的值是第二个变量的名字,举个例子:x=a, a=123, 就是通过x这个变量,来引用123这个值,bash4.0-中文文档里的介绍:在很多其它语言中,可以用

$$A

来表示以 $A 为名称的间接变量,而 bash shell中不可以,即使

$$A

这样的也不可以;bash shell只识别感叹号形式的间接变量。不过,这个功能在其它的shell 中可能没有。所以,为了增强可移植性,可以这样写:

eval echo \$$B
或者
echo b=${!b}

下面是三个简单的例子:

#!/bin/bash
b=a
a=1
echo b="$$b"

执行结果为: b=1385b

#!/bin/bash
b=a
a=1
echo b=${ 
   !b}

执行结果为:b=1

#!/bin/bash
a=1
b=a
eval echo b=\$$b

执行结果为:b=1

前一种方法不行,后面两种方法都可以!注:eval的作用是再次执行命令行处理,也就是说,对一个命令行,执行两次命令行处理(记住是执行两次命令行处理,不是执行两次命令)。
我刚在centos7上的测试结果:
源码:

#!/bin/bash
for i in `seq $#`
do
    eval b=\$$i
    echo 'b='$b

    c=${ 
   !i}
    echo 'c='$c
done 

执行结果:

# sh test.sh 123

b=123
c=123

2.使用数组
楼上有提到使用数组了,使用数组确实简单一点 ,这是例子:

# cat test.sh

#!/bin/bash

#把参数转化为数组
a=( "$@" )     

#遍历数组
for i in ${a[*]};do
    echo $i
done 

执行结果:

# sh test.sh 123 456

123
456

希望对你能有所帮助。

xsync 2.0

#!/bin/bash
#校验参数
pcount=$#
if (($pcount==0))
then
	exit
fi

#获取用户名
user=`whoami`

#获取文件名,路径 例如: 
#for((i=1;i<=$#;i++))
for i in `seq $#`
do
	file=${ 
   !i}
	fname=`basename $file`
	dname=`dirname $file`
	dir=`cd $dname;pwd`

#循环发
    #需要优先配置/etc/hosts下的hostname列对应集群信息
    #或者awk配合正则使用,我这里只是学习环境所以我只需要匹配我的主机名含有flink就可以了
    #192.168.66.110 flinkbeginning
    #192.168.66.111 flinkslave1
    #192.168.66.112 flinkslave2
    #140.82.113.4 github
    #140.82.114.4 github
    
	# for host in `awk -F " " '{if(NR>2){print $2}}' /etc/hosts`
	#这里使用 正则
	for host in `awk '/flink/{print $2}' /etc/hosts`
	do
		echo -------------$fname-TO-$host--------------
        rsync -ral $dname/$fname $user@$host:$dir
		if (($?==0))
		then
			echo "传输成功!"
		else
			echo "传输失败!"
		fi
	done
done

用到了awk工具,NR是awk内置参数 代表 “行号”

[root@flinkbeginning ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.66.110 flinkbeginning
192.168.66.111 flinkslave1
192.168.66.112 flinkslave2
140.82.113.4 github
140.82.114.4 github

[root@flinkbeginning ~]# awk -F " " '{if(NR>2){print $2}}' /etc/hosts
flinkbeginning
flinkslave1
flinkslave2
github
github

此处awk的if是不严谨的,按需要应该采用awk配合正则。

awk '/flink/{print $2}' /etc/hosts
此处的"flink"可以灵活替换
“$”理论基础 —— { 
   print $0}是可以输出整行的信息

然后我把 xsync的脚本文件、module 承载软件的文件夹 和 /etc/profile 环境文件 同时分发尝试:

[root@flinkbeginning ~]# xsync ~/xsync /opt/module /etc/profile
-------------xsync-TO-flinkbeginning--------------
传输成功!
-------------xsync-TO-flinkslave1--------------
传输成功!
-------------xsync-TO-flinkslave2--------------
传输成功!
-------------module-TO-flinkbeginning--------------
传输成功!
-------------module-TO-flinkslave1--------------
传输成功!
-------------module-TO-flinkslave2--------------
传输成功!
-------------profile-TO-flinkbeginning--------------
传输成功!
-------------profile-TO-flinkslave1--------------
传输成功!
-------------profile-TO-flinkslave2--------------
传输成功!

去从机器上创建软连接
[root@flinkslave1 ~]# ln -s ~/xsync /usr/bin/xsync
[root@flinkslave2 ~]# ln -s ~/xsync /usr/bin/xsync
或者直接在主机器上写个脚本
对于脚本的方式:
  有些远程执行的命令内容较多,单一命令无法完成,考虑脚本方式实现:

#!/bin/bash
#获取用户名
user=`whoami`

for host in `awk '/flink/{print $2}' /etc/hosts`
do
    ssh $user@$host > /dev/null 2>&1 << eeooff ln -s ~/xsync /usr/bin/xsync exit eeooff
echo "$host xsync is ok!"
done

远程执行的内容在“<< eeooff ” 至“ eeooff ”之间,在远程机器上的操作就位于其中,注意的点:

<< eeooff,ssh后直到遇到eeooff这样的内容结束,eeooff可以随便修改成其他形式。
重定向目的在于不显示远程的输出了
在结束前,加exit退出远程节点

[root@flinkbeginning ~]# ./ssh-xsync 
flinkslave1 xsync is ok!
flinkslave2 xsync is ok!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/137526.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号