共计 4092 个字符,预计需要花费 11 分钟才能阅读完成。
SHell 的近程传递
0x00
家喻户晓,有个命令叫 rsync
。
不晓得?那你可能听过 scp
,都不晓得也没事,正好。
个别,你想往远处(10.60.111.124
)用指定用户(heihei
)的指定目录($HOME/yoyo
)里,传过来一个文件(oho.iex
),这个文件就在当前目录。
(对本机来说也就是上传本地文件到远端某目录)
那么个别的做法就是这样:
rsync -avz -- oho.iex heihei@10.60.111.124:yoyo
这样的话能做到以下几件事:
- 完全相同的文件如果曾经在目标目录存在,这个文件就不会被传输;文件名雷同文件内容不同则会笼罩。
- 选项
a
使得这个文件的元数据信息(创立工夫、批改工夫、文件归属等这些并不存在文件内容里的信息)失去保留;选项z
会开启压缩即上传前先压缩过了网络后再主动解压,这样就能省流;选项v
则是显示传输过程,有没有都不影响传输终局。
因为要上传的文件就在当前目录,所以 --
前面的 oho.iex
连相对路径的 ./
也不必写,更不须要写绝对路径。又因为文件夹正好在这个用户的 $HOME
目录下,所以冒号 :
前面也不必写绝对路径。事实上,如果只有冒号 :
前面空着,文件就会被上传到所应用用户 heihei
的家目录。(但如果你冒号都没写,这个工具就认为你只是把文件从本地传到本地,就会当前目录建设一个 heihei@10.60.111.124
文件夹而后把文件复制进去。。。)
从远端(10.60.111.128
)通过指定用户(haha
)把指定文件(/etc/profile.d/miaomiao.sh
)拉到本地指定目录(当前目录 .
),也是相似的。
(对本机来说也就是下载指定文件到本地指定目录)
你能够这样写:
rsync -avz -- haha@10.60.111.128:/etc/profile.d/miaomiao.sh .
这个应该不必解说了吧。。。
然而,还有个问题:这个软件须要对面也装了才行。而且还得不能出错。
0x01
如果只关怀文件内容的传递,只有你们两边都有 SSH,那么大能够像这样做:
拉取(对本机来说算下载)
ssh haha@10.60.111.128 -- 'cat /etc/profile.d/miaomiao.sh' > miaomiao.sh
推送(对本机来说算上传)
cat oho.iex | ssh heihei@10.60.111.124 -- 'cat > yoyo/oho.iex'
当然,还能够自行选定压缩工具(须要两边都安)。这里以 xz
举例:
拉取(对本机来说算下载)
ssh haha@10.60.111.128 -- 'cat /etc/profile.d/miaomiao.sh | xz -T0 --best' | xz -dc > miaomiao.sh
推送(对本机来说算上传)
(cat oho.iex | xz -T0 --best) | ssh heihei@10.60.111.124 -- 'cat | xz -dc > yoyo/oho.iex'
另外,当初不是有很多玩容器化的吗,docker
间接把 Go 这个语言带起来了。它的镜像反对导出 save
为文件和从文件和加载 load
。
个别的做法就是远端导出一个文件起个名字叫 啥啥.tar
(导出的确实是 Tar 格局不论你给它文件名啥扩展名)而后挪到另一台上再导入。
当初咱们能够让它中途压缩,并且全程管道,不必专门学生成文件,不留多余的货色。
(这也多亏 docker
命令反对从规范输出加载镜像或从规范输入写出文件)
(这里的劳模镜像就用 docker.io/trinodb/trino
了。这个工作次要是用能连互联网的机器往不通互联网的机器传送镜像。)
## 远端镜像来本机:ssh haha@10.60.111.128 -- 'docker save docker.io/trinodb/trino | xz -T0 --best' | xz -dc | docker load
## 本机镜像到远端:docker save docker.io/trinodb/trino | xz -T0 --best | ssh haha@10.60.111.128 -- 'xz -dc | docker load'
## 甚至能够从这个远端间接送到那个远端!啊对!一般文件当然也能够这么玩儿!ssh haha@10.60.111.128 -- 'docker save docker.io/trinodb/trino | xz -T0 --best' | ssh heihei@10.60.111.124 -- 'xz -dc | docker load'
0x02
不过,ssh
是要明码的(基于 SSH 协定的工具都要(如 rsync
就是一个))。而有的时候其实不便于输明码。怎么办呢?
能够用 sshpass
。
(查了一下,这应该是个用 C 写的开源工具,不过貌似也有 PY 版本。。。无所谓,命令就能安,这里也有各种零碎的包。)
用法很简略:把下面的 ssh
换成 sshpass -p $xx -- ssh
就好了,其中变量 xx
曾经存入了对应节点对应用户的明码。
几个示例:
## 镜像远到本
sshpass -p $hahapassword -- ssh haha@10.60.111.128 -- 'docker save docker.io/trinodb/trino | xz -T0 --best' | xz -dc | docker load
## 文件远到远
sshpass -p $hahapassword -- ssh haha@10.60.111.128 -- 'cat /etc/profile.d/miaomiao.sh | xz -T0 --best' | sshpass -p $heiheipassword -- ssh heihei@10.60.111.124 -- 'cat | xz -dc > /etc/profile.d/miaomiao.sh'
## rsync 也能用 sshpass
sshpass -p $heiheipassword -- rsync -avz -- oho.iex heihei@10.60.111.124:yoyo
0x03
然而 rsync
还能一下传一个文件夹呢!
的确,下面这种最原始的伎俩只是传单个文件而已。要传文件夹的话,大能够先打包成 Tar 格局的文件,而后再传单个文件就好:
(用 SSH 协定的时候如果删掉指定的远端登录用户名和 @
的话就等于用本机正在用的以后用户登录,这须要远端有雷同名称的用户并且你还晓得明码。)
## 远到本 当前目录
sshpass -p $xx -- ssh 10.20.202.233 -- 'tar cf - /etc/profile.d' | tar -x
## 远到本 指定目录中途有压缩
sshpass -p $xx -- ssh 10.20.202.233 -- 'tar cf - /etc/profile.d | xz -T0 --best' | xz -dc | tar -x -C $HOME/documents
## 本到远 齐全同上的口头
tar cf - /etc/profile.d | xz -T0 --best | sshpass -p $xx -- ssh 10.20.202.233 -- 'xz -dc | tar -x -C $HOME/documents'
## 远到远 齐全同上的口头
sshpass -p $xx -- ssh 10.20.202.233 -- 'tar cf - /etc/profile.d | xz -T0 --best' | sshpass -p $xxx -- ssh 10.20.203.244 -- 'xz -dc | tar -x -C $HOME/documents'
其实只有能变成 Tar 包,剩下的就跟镜像的本义齐全一样了。
0x04
还能够批量搞事件。
比方你在本地某个目录,你想把外面所有文件名 .docx
结尾的文件传输给指定远端目录的特定目录里。
首先要手动建设目录:
sshpass -p $xx -- ssh haha@10.20.103.237 -- mkdir -p to_kiki
而后这样就能传了:
ls *.docx |
xargs -i -P0 -- bash -c "cat {} | sshpass -p $xx -- ssh haha@10.20.103.237 --'cat > to_kiki/{}'"
当然,批量拉取也是能够的(起源文件夹必定曾经是有的所以不再建设了):
sshpass -p $xx -- ssh haha@10.20.103.237 -- ls kiki |
xargs -i -P0 -- bash -c "sshpass -p $xx -- ssh haha@10.20.103.237 --'cat kiki/{}'> {}"
思路就是拼接命令,交给 xargs
批量执行。
这些示例没开压缩,需要的话本人触类旁通。其实没必要,只有货色不太大。
另外,也能够不必 xz
这个命令来压缩,也能够用 zstd
,后者仿佛更适宜于这种场景。(原本用 .tar.xz
存安装包的 Arch 团队通过测试后改用这个压缩算法(级别是 18),速度大幅晋升同时压缩率则只是差了微不足道一点点。)
0x05
还能够这么着:
sshpass -p $xx -- ssh haha@10.20.103.237 -- 'wget https://ghproxy.com/https://github.com/rustdesk/rustdesk/releases/download/1.1.6/rustdesk-1.1.6.exe -O /dev/stdout' > rustdesk-1.1.6.exe
如果你本机不能连互联网,而某个服务器能够的话。
反过来也是能够的:
wget https://ghproxy.com/https://github.com/rustdesk/rustdesk/releases/download/1.1.6/rustdesk-1.1.6.exe -O /dev/stdout | sshpass -p $xx -- ssh haha@10.20.103.237 -- 'cat > rustdesk-1.1.6.exe'
备注
其实晓得命令该怎么切会更好了解。答案是,先依照空格(引号外的没本义的)切,再依照管道符 |
切。
双横线 --
只是对命令传入参数的一个,能够省略,反对不省略的时候倡议写上,帮你对一个命令进一步划分档次。
更多 SHell 常识能够看这个。
分享注明起源: https://segmentfault.com/a/1190000040324158