ssh花样传文件

每日一个linux命令——ssh

回顾我们的老朋友 scp

说到ssh,大家一定不陌生,毕竟老板叫你进去去服务器看看日志有啥报错总归得敲下面的命令:

ssh user@ip

今天遇到了一个比较烦人的情况,我的pc是可以连上服务器A和服务器B。

但是服务器A和B之间网络并不通。如下图:

image.png

前端老哥走 CI/CD 自动 build 好的 目标文件 在 S1服务器 上面,我需要把这些目标文件部署在S2上面,并且让nginx去host这些文件。很显然,从上面的图看出,我并不能直接做以下的操作。

ssh root@s1
scp /usr/share/auto/fontend/dist/* root@s2:/usr/share/nginx/host/

其实也很简单,我在我的pc上面,用两次scp,先把S1中的需要传的文件先传到PC本地,然后再传去S2。

scp root@s1:/usr/share/auto/fontend/dist/* .
scp ./* root@s2:/usr/share/nginx/host/
rm -rf *

嗯哼,问题似乎已经解决了。但是我需要去rm 掉我PC中的中转站文件呢!这似乎有点不够优雅。作为一个新时代的弄潮儿,我们需要更加cool的操作去完成这个事情!

ssh可以远程输入命令

ssh不光可以远程到别的服务器上,他也可以直接输入命令!

ssh root@s1 'pwd'

上面这个命令就是远程到s1服务器,并且输入pwd命令,并且把程序的输出接入到本地的stdout中

也就是说,其实我根本不需要用scp命令!我从远程的服务器上下载一个文件到本地只需要借助重定向就行!

ssh root@s1 'cat file1' > file1

那么上传一个文件呢?我们需要借助管道符!

使用飘逸的管道符传单个文件

我们可以借助管道符,把命令的stdout接入下一个命令的stdin,ssh命令是可以支持接入stdin的。

cat file1 | ssh root@s1 'cat - > file1'

这里的流程是 pc: stdout -> pc: ssh: stdin -> s1: stdin -> s1: stdout -> pc:ssh: stdout

这样一来不需要scp,文件就从本地到服务器了。

更进一步,传多文件?

我们又需要另外借助一个好兄弟 tar ,我们先把本地/远程的多个文件先打成tar包,然后再在远程/本地再进行解压,这不就完成了多文件传输了吗。

下面这个例子会将s1服务器中/root/files中的所有文件传输到本地的当前目录下,并且我们可以看到tar中有-z,这代表他打包的同时会压缩,-C代表会切换到/root/files目录下再进行打包,如果没有加-C后果不堪设想哈(不建议随意尝试)

玩过英雄联盟亚索的人应该知道,很多时候你花里胡哨E几次,你就超鬼了

ssh root@s1 'tar -czf - -C /root/files .' | tar -xzv

逆向思维一下,本地传去远程呢?那就在本地去打包,远程的去解压

tar -cz . | ssh root@s1 'tar -xz -C /root/files'

来一套Combo

回到我们一开始提出的问题,如果S1服务器和S2网络不通,那如何优雅的从S1传文件多个文件到S2呢?

不如让我们把两个ssh命令用管道符连接起来吧!

ssh root@s1 'tar -czf - -C /usr/share/auto/fontend/dist .' | ssh root@s1 'tar -xz -C /usr/share/nginx/host'

这样一来,我们就把s1中前端老哥编译好的文件全部复制到s2中了!