分发大法:scp,rsync,xsync-plus
「这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战」
前提
创建三台虚拟机
可以参考我之前的文章: 环境篇:Virtualbox+Vagrant安装Centos7 - 掘金 (juejin.cn)
修改主机名
vim /etc/hostname
每台虚拟机为 k8s1,k8s2,k8s3:
配置hosts文件
- 查看默认网卡
ip route show
- 查询k8s1默认网卡ip(其他虚拟机也要查看)
- 三台虚拟机互ping这个ip
vim /etc/hosts
- 能ping通了,为每台虚拟机的hosts文件添加如下内容:
10.0.2.9 k8s1
10.0.2.8 k8s2
10.0.2.15 k8s3
k8s1测试连接k8s2
[root@k8s1 test]# ssh k8s2
输入密码是可以ssh连接的,则说明hosts配置成功。
SSH免密登录
由于服务器没有配置免密登录,下面的脚本运行时还要输入账号密码,所有要配置免密登录。由于篇幅问题。请参考我的另一篇文章:
linux小技巧:SSH免密登录和配置环境变量 - 掘金 (juejin.cn)
scp-安全拷贝
定义
scp(secure copy)安全拷贝意思,scp可以实现服务器与服务器之间的数据拷贝(服务器不一定是自己)。
基本语法
scp -r $pdir/$fname $user@$host:$pdir/$fname
- scp :命令
- -r :递归
- $pdir/$fname :要拷贝的文件路径/名称(
可以是目录或文件) - $user@$host:$pdir/$fname :目的地用户@主机:目的地路径/名称
案例实战
- 前提:在 k8s1、k8s2、k8s3 都已经创建好的文件夹,并且拥有权限
sudo chown 拥有者:组名 -R /app/test
1. 我主动复制给他
在 k8s1 上,将 k8s1 中/app/test 目录拷贝到 k8s2的/test目录下:即是/app/test/test。
[root@k8s1 .ssh]# mkdir /app/test
[root@k8s1 .ssh]# cd /app/test
[root@k8s1 test]# touch scp-test.txt
[root@k8s1 test]$ scp -r /app/test root@k8s2:/app/test
2. 我要他复制给我
在 k8s1 上,将 k8s2 中/app/test/pull.txt 目录拷贝到 k8s1 上。
k8s2:新建文件pull.txt
[root@k8s2 test]# touch pull.txt
[root@k8s2 test]# ll
total 0
-rw-r--r--. 1 root root 0 Nov 25 13:27 pull.txt
drwxr-xr-x. 2 root root 26 Nov 25 13:23 test
k8s1:拉取k8s2文件到本地
[root@k8s1 test]# scp -r root@k8s2:/app/test/pull.txt /app/test/
root@k8s2's password:
pull.txt 100% 0 0.0KB/s 00:00
[root@k8s1 test]# ll
total 0
-rw-r--r--. 1 root root 0 Nov 25 13:30 pull.txt
-rw-r--r--. 1 root root 0 Nov 25 13:06 scp-test.txt
3. 我要他复制给另一个他
在 k8s1 上操作,将 k8s2 中/app/test 目录下所有目录拷贝到 k8s3 上。
[root@k8s1 test]# scp -r root@k8s2:/app/test/pull.txt /app/test/
root@k8s2's password:
pull.txt 100% 0 0.0KB/s 00:00
[root@k8s1 test]# ll
total 0
-rw-r--r--. 1 root root 0 Nov 25 13:30 pull.txt
-rw-r--r--. 1 root root 0 Nov 25 13:06 scp-test.txt
[root@k8s1 test]# scp -r root@k8s2:/app/test/* root@k8s3:/app/test
root@k8s2's password:
The authenticity of host 'k8s3 (192.168.56.103)' can't be established.
ECDSA key fingerprint is SHA256:yk/B9iEdgbi8h2XVM4klHaKjmobewr1/hFGZq6CqNSA.
ECDSA key fingerprint is MD5:b3:15:fc:c6:79:4f:10:df:e9:87:01:ab:5b:ab:ba:9c.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'k8s3,192.168.56.103' (ECDSA) to the list of known hosts.
root@k8s3's password:
pull.txt 100% 0 0.0KB/s 00:00
scp-test.txt 100% 0 0.0KB/s 00:00
Connection to k8s2 closed.
rsync-同步
rsync 主要用于备份和镜像。具有速度快、避免复制相同内容和支持符号链接的优点。 该命令系统自带的,没有就安装yum install -y rsync
rsync 和 scp 区别:
- 用 rsync 做文件的复制要比 scp 的速度快,rsync 只对
差异文件做更新。 - scp 是把所有文件都复制过去。
基本语法
rsync -av $pdir/$fname $user@$host:$pdir/$fname
- rsync:命令
- -av:选项参数
- -a :归档拷贝
- -v :显示复制过
- $pdir/$fname:要拷贝的文件路径/名称
- $user@$host:$pdir/$fname:目的地用户@主机:目的地路径/名称
案例实战
同步 k8s1 中的/app/test/目录下数据 到 k8s2的/app/test/目录下
[root@k8s1 test]# rsync -av /app/test/ root@k8s2:/app/test/
root@k8s2's password:
sending incremental file list
./
pull.txt
scp-test.txt
sent 178 bytes received 57 bytes 94.00 bytes/sec
total size is 0 speedup is 0.00
xsync-plus-分发
需求
- 默认分发多目录或多文件给所有机器
- 命令设计:
xsync-plus file1 file2 ... - 命令设计:
xsync-plus -d file1 file2 ...
- 命令设计:
- 分发一个目录或文件给主机名k8sy递增的机器 y=[n,m] m>n,n为整数
- 命令设计:
xsync-plus -f file server_pref start end - server_pref:主机名前缀
- start :开始序号
- end :结束序号
- 命令设计:
- 分发一个目录或文件给枚举的机器
- 命令设计:
xsync-plus -e file server1 server2 ...
- 命令设计:
脚本实现
查看命令的全局路径:echo $PATH
选择一个目录下编写一个脚本: vi /usr/local/bin/xsync-plus
#!/bin/bash
#########################################################方法区结束###########################################################
#######################默认操作######################
## ljw
##默认分发多文件给所有机器
###命令设计:xsync-plus file1 file2 ...
###命令设计:xsync-plus -d file1 file2 ...
#######################默认操作######################
function defaultSend() {
for host in ${cluster[@]}
do
#3. 遍历所有目录,挨个发送
for file in $@
do
#4. 判断文件是否存在
if [ $file != "-d" ] && [ -e $file ]
then
#5. 获取父目录: $(dirname $file)是获取文件(相对路径还是绝对路径)的父目录,-P就是软连接的真实父目录,cd就是进去里面,;另一个命令。进去后pwd获取父目录
pdir=$(cd -P $(dirname $file); pwd)
#6. 获取当前文件的名称 -p路径存不存在都不报错,保证有该路径
fname=$(basename $file)
ssh $host "mkdir -p $pdir"
echo run ---------- rsync -av $pdir/$fname $host:$pdir --------------------
rsync -av $pdir/$fname $host:$pdir
else
if [ $file != "-d" ]
then
echo $file 文件或文件夹不存在!
exit;
fi
fi
done
done
}
#######################-e操作######################
## ljw
##分发一个文件给枚举的机器
###命令设计: xsync-plus -e file server1 server2 ...
#######################-e操作######################
function eSend() {
#2.判断第二个参数
if [ $action == "-e" ]
then
##3个参数
if [ $paramcount -lt 3 ]
then
echo 参数个数不足!
echo $0 -e file_name server1 server2 ...
exit;
else
# 获取文件名称
file=$2
#4. 判断文件是否存在
if [ -e $file ]
then
#获取父目录
pdir=$(cd -P $(dirname $file); pwd)
#获取当前文件的名称
fname=$(basename $file)
#开始号码
start=3
#结束号码
end=$paramcount
# 循环
for((num=$start; num<=$end; num++)); do
##要先赋值中间变量,这地方太坑了
ser=$num
## 获取入参的$n n个参数,深坑啊。。。
server=`eval echo '$'"$ser"`
ssh $server "mkdir -p $pdir"
echo run ---------- rsync -av $pdir/$fname $server:$pdir ----------
rsync -av $pdir/$fname $server:$pdir
done
else
echo $file 文件或文件夹不存在!
fi
fi
fi
}
#######################-f操作######################
## ljw
##分发一个文件给主机名k8sy递增的机器 y=[n,m] m>n,n为整数
###命令设计:xsync-plus -f file server_pref start end
###server_pref:主机名前缀
###start :开始序号
###end :结束序号
#######################-f操作######################
function fSend() {
if [ $action == "-f" ]
then
##没有5个参数
if [ $paramcount -ne 5 ]
then
echo 参数个数不足!
echo $0 -f file server_pref start end
exit;
else
# 获取文件名称
file=$2
#4. 判断文件是否存在
if [ -e $file ]
then
#获取父目录
pdir=$(cd -P $(dirname $file); pwd)
#获取当前文件的名称
fname=$(basename $file)
# 获取hostname及起止号
server_pref=$3
#开始号码
start=$4
#结束号码
end=$5
# 循环
for((host=$start; host<=$end; host++)); do
ssh $server_pref$host "mkdir -p $pdir"
echo run ---------- rsync -av $pdir/$fname $server_pref$host:$pdir ----------
rsync -av $pdir/$fname $server_pref$host:$pdir
done
else
echo $file 文件或文件夹不存在!
fi
fi
fi
}
#########################################################方法区结束###########################################################
#######################全局参数######################
#1. 判断命令后的参数个数
paramcount=$#
params=$@
if [ $paramcount -lt 1 ]
then
echo 参数个数不足!
exit;
fi
##参数动作
action=$1
## 我的机器
cluster=('k8s1' 'k8s2' 'k8s3')
#######################-默认操作######################
#2.判断第二个参数
if [ $action == "-d" ]
then
echo $0 -d file1 file2 ...
defaultSend $@;
elif [ $action == "-f" ]
then
echo $0 -f file server_pref start end
fSend $@;
elif [ $action == "-e" ]
then
echo $0 -e file server1 server2 ...
eSend $@ $params;
else
echo default:$0 file1 file2 ...
defaultSend $@;
fi
echo 传输完成!!!
测试
- 默认分发/app/test/文件夹数据到
全部服务器xsync-plus /app/test/或xsync-plus -d /app/test/
- 分发/app/test/文件夹数据到主机名
递增服务器:k8s2 k8s3
xsync-plus -f /app/test/ k8s 2 3
- 分发/app/test/文件夹数据到
枚举主机名
xsync-plus -e /app/test/ k8s2 k8s3
问题
脚本从win复制到linux格式问题
查看脚本文件是dos格式还是unix格式,dos格式的文件行尾为^M$ ,unix格式的文件行尾为美元符号
cat -A filename
如果没有dos2unix命令,请安装
sudo yum install dos2unix
把dos格式的文件转换为unix格式的文件
dos2unix filename
注:如果大段代码复制到linux,代码中某行的开头有i字母,上面文字会被截断,系统会认为是i输入模式。
拾遗-用户组相关命令
groups:查看当前登录用户的组内成员groups test:查看test用户所在的组,以及组内成员whoami:查看当前登录用户名cat /etc/group:查看所有组信息cat /etc/group|grep 组名:用于查找某个用户组cat /etc/passwd:查看所有的用户信息cat /etc/passwd|grep 用户名:用于查找某个用户