前言
经常使用Linux终端的都会碰到文件上传和下载的问题,无论是上传/下载到本地,还是主机跟主机之间的上传/下载传输都是不可避免的,虽然我们有Xshell这个强大的SSH远程终端软件这些都不是问题,那么如果条件不允许情况下没有Xshell怎么办呢?其实在【Windows 平台下XShell如何给Linux主机上传下载文件 】一文里分享的rz/sz命令就可以解决,但强大的Linux还有不少办法来直接还终端上传/下载文件的。今天就来个汇总分享一下:
脚本语言
很多脚本语言都可以临时启动一个http server。于是我们便可以通过浏览器来下载一些文件
Python
Python可以临时启动一个http server来提供文件访问
Python 2
python -m SimpleHTTPServer 8000
Python 3
python3 -m http.server 8000
通过浏览器我们就可以看到目录可以进行下载。前提是需要你的Python装有 SimpleHTTPServer 模块,站长的Python没有这个模块,所以也就不截图了。
PHP
启动php内置的服务器之后,虽然我们没有办法通过浏览器来浏览目录,但可以直接通过浏览器下载文件
php -S 0.0.0.0:8000
显示如下:
[Mon Feb 20 15:04:35 2023] PHP 7.4.27 Development Server (http://0.0.0.0:8000) started
这个方法最简单了,只需要在iptables里开启8000端口即可,跟上述的Python类似,站长感觉最简单,毕竟站长所有的服务器几乎都是有PHP的,安全上更是可以借助iptables/ipset来解决,近乎完美。
鲜为人知的 nc
nc是netcat的简写,有着网络界的瑞士军刀美誉。因为它 短小精悍、功能实用 ,被设计为一个简单、可靠的网络工具
很多人只知道nc可以用来探测端口是否打开,功能和 telnet类似
nc -v 192.168.199.226 1001
nc: connectx to 192.168.199.226 port 1001 (tcp) failed: Connection refused
nc -v 192.168.199.226 1000
Connection to 192.168.199.226 port 1000 [tcp/cadlock2] succeeded!
但不知道nc也可以进行端口监听!利用nc端口监听的功能我们就可以实现文件传输
监听端口
在目标机器上监听端口,并使用管道输出到某文件。注意:下面的-l是小写的L,不是数字1
nc -l 1000 > dst/main.go
发送数据
在本地机器上执行
nc -v 192.168.199.226 1000 < source/main.go
Connection to 192.168.199.226 port 1000 [tcp/cadlock2] succeeded!
source/main.go 就被传输到了 192.168.199.226 的机器上,并且文件名为 dst/main.go
说明
nc进行文件传输,功能非常简陋,能做的事情不多,但不失为没有其他命令时的应急方案
上面两种方式只能上传或者下载文件,下面来介绍些既可以上传又可以下载的玩法
虚拟终端软件中的rz 和 sz
当我们使用虚拟终端软件,如Xshell、SecureCRT或PuTTY来连接远程服务器后,可以使用rz或sz来上传下载文件。
可参考:
Windows 平台下XShell如何给Linux主机上传下载文件
说明
rz命令 与 sz命令 常用在虚拟终端软件中,如果是在两台linux直接传输文件,往往是不可行的。
传统的sftp和ftp
sftp与ftp有着几乎一样的语法和功能,sftp是一个独立的SSH封装协议包,通过安全连接以相似的方式工作。这意味着只要目标端启动了sshd服务器就可以使用sftp,而且是一种安全传输文件的方式,因此我更推荐你使用sftp
要连接到远程 sftp 服务器,如下建立一个安全 SSH 连接并创建 SFTP 会话:
sftp [email protected]
登录到远程主机后,你可以如下运行交互式的 sFTP 命令:
sftp> ls -al # 展示远程主机文件列表
drwxr-xr-x 6 wentao wheel 192 Feb 19 18:35 .
drwxrwxrwt 13 root wheel 416 Feb 19 18:26 ..
-rw-r--r-- 1 wentao wheel 73 Feb 19 18:35 main.go
drwxr-xr-x 6 wentao wheel 192 Feb 19 18:35 sub
sftp> pwd # 远程主机当前路径
Remote working directory: /private/tmp/dst
sftp> lls -al # 展示本地主机文件列表
total 8
drwxr-xr-x 6 wentao wheel 192 Feb 19 16:54 .
drwxrwxrwt 9 root wheel 288 Feb 19 18:29 ..
-rw-r--r-- 1 wentao wheel 0 Feb 19 18:30 a
-rw-r--r-- 1 wentao wheel 73 Feb 19 18:30 main.go
drwxr-xr-x 6 wentao wheel 192 Feb 19 18:25 sub
sftp> lpwd # 本地主机当前路径
Local working directory: /private/tmp/source
上传文件
把本地当前路径下的main.go上传到远程主机当前路径
sftp> put main.go
Uploading main.go to /private/tmp/dst/main.go
把本地当前路径下的main.go上传到远程主机当前路径,并命名成a.go
sftp> put main.go a.go
Uploading main.go to /private/tmp/dst/a.go
下载文件
把远程主机当前路径下的main.go下载到本地当前路径
sftp> get main.go
Fetching /private/tmp/dst/main.go to main.go
依旧可以自定义名字
sftp> get main.go a.go
Fetching /private/tmp/dst/main.go to a.go
退出
退出sftp shell可以输入 !
sftp> !
说明
还有许多图形界面甚至是语言SDK支持 sftp ,它的目标不仅仅是传输文件,是历史非常悠久的文件管理协议。
功能专一的 scp
scp 消耗资源少,功能专一,并且加密传输,可以说是最常用的跨主机复制命令。
和 cp 的命令相似, scp 的使用非常简单
scp [参数] [原路径] [目标路径]
- 第一个路径是原路径
- 第二个是目标路
- 两者都可以是远程机器
- 路径:和ssh命令一样,使用@符分割用户名和ip,同时使用:连接目标目录
把本地文件复制到远程
scp source/main.go [email protected]:/tmp/dst/
把远程机器上的文件复制到本地
scp [email protected]:/tmp/dst/main.go source/
上传目录使用 -r
scp -r source/* [email protected]:/tmp/dst/
说明
scp 在小文件场景下确实得心应手,但面对大文件或者网络不好需要续传的场景, scp 的效率就会受到较大的影响了。此时就是另一个命令的大显身手的时候了。
增量同步的神: rsync
rsync 是一种快速且非常通用的文件复制工具。它使用增量传输算法,该算法仅发送源文件和目标文件之间的差异以减少网络发送的数据量。所以它广泛用于备份和镜像,或作为日常使用的拷贝命令
不带任何选项
我们可以使用rsync进行本地复制
rsync main.go [email protected]:/tmp/dst
或者把本地文件复制到远程。和ssh命令一样,使用@符分割用户名和ip,同时使用:连接目标目录
rsync main.go [email protected]:/tmp/dst
或者把远程机器上的文件复制到本地
rsync [email protected]:/tmp/source/main.go /tmp/dst
只要目的端的文件内容和源端不一样,并且对源文件的读权限,对目标路径有写权限,就会触发数据同步,rsync就能确保目的端文件同步到和源端一致。(⚠️ 注意是同步文件)
✨ 【quick check】 rsync 很聪明,它对两边时间戳和文件大小一致的文件将不会采取更新动作。但聪明有时也反被聪明误,如果目的端文件的时间戳、大小和源端完全一致,但是内容恰巧不一致时, rsync 是发现不了的
✨ 【modify time】 rsync 不会同步文件的modify time,凡是有数据同步的文件,目的端的文件的modify time总是会被修改为最新时刻的时间
✨ 【rwx权限】 rsync 不会关注目的端文件的rwx权限,如果目的端没有此文件,那么权限会保持与源端一致;如果目的端有此文件,则权限不会随着源端变更
✨ 【用户和组】rsync 只能以登陆目的端的账号来创建文件,它没有能力保持目的端文件的用户和用户组和源端一致。(除非你使用root权限,才有资格要求用户一致、用户组一致)
✨ 【删除策略】rsync 只确保源目录(使用-r,下文会讲)的所有内容都复制到目标目录,并且不会删除目标目录的文件
同步文件类型
-r , --recursive :同步文件夹
当我们不加选项的同步一个文件夹时,rsync会跳过其中的文件夹,仅同步文件
跳过了source中的sub文件夹
rsync -v source/* [email protected]:/tmp/dst
skipping directory source/sub
连source都跳过了
rsync -v source [email protected]:/tmp/dst
skipping directory source
加上 -r 选项,指示需要递归所有文件夹一起同步
rsync -vr source [email protected]:/tmp/dst
building file list ... done
source/a
source/main.go
source/sub/
source/sub/c
-l, --links :同步软链接文件
如果我们要同步一个软链接文件,你猜rsync会提示什么?
ll source/
total 0
lrwxr-xr-x 1 wentao wheel 9B Feb 18 21:19 d -> outsync/d
-rw-r--r-- 1 wentao wheel 0B Feb 18 20:08 main.go
rsync source/d [email protected]:/tmp/dst
skipping non-regular file "d"
你猜对了,rsync又无情了拒绝了我们。它一旦发现某个文件是 软链接 ,就会无视它,除非我们增加 -l 选项。
rsync -l source/d [email protected]:/tmp/dst
使用了-l选项后,rsync会完全保持软链接文件类型,原原本本的将软链接文件复制到目的端,而不会“follow link”到指向的实体文件。
示例中,虽然软链接文件被同步过去了,但因为软连接指向的文件并没有,所以自然会提示 No such file or directory
dst ll
total 0
-rw-r--r-- 1 wentao wheel 0B Feb 18 20:35 a
-rw-r--r-- 1 wentao wheel 0B Feb 18 20:24 b
lrwxr-xr-x 1 wentao wheel 9B Feb 18 21:20 d -> outsync/d
dst cat d
cat: d: No such file or directory
如果我偏偏就想让rsync采取"follow link"的方式,那就用 -L 选项就可以了
rsync -vv -L source/d [email protected]:/tmp/dst
此时目标端已经不再时软连接文件了,而是实体文件
dst ll
total 0
-rw-r--r-- 1 wentao wheel 0B Feb 18 20:35 a
-rw-r--r-- 1 wentao wheel 0B Feb 18 20:24 b
-rw-r--r-- 1 wentao wheel 0B Feb 18 21:34 d
--devices :同步块设备文件
块设备也能被同步,但前提是目标端使用 super-user 用户传输
--specials :同步特殊文件
特殊文件主要包含着命名 sockets 和 fifos
同步文件属性
-p, --perms :同步权限
还记得无选项时提到的rwx权限么?
如果目的端没有此文件,那么在同步后会将目的端文件的权限保持与源端一致
如果目的端已存在此文件,那么只会同步文件内容,权限保持原有不变
如果你使用了-p选项,则无论如何,rsync都会让目的端保持与源端的权限一致的
-t, --times :同步修改时间
还记得无选项时提到的modify time么? rsync 不会同步文件的modify time,凡是有数据同步的文件,目的端的文件的modify time总是会被修改为最新时刻的时间
如果你使用了-t选项,则无论如何,rsync都会让目的端保持与源端的修改时间一致的
-g, --group :同步文件用户组
-o, --owner :同步文件用户
还记得无选项时提到的用户和组么? rsync 只能以登陆目的端的账号来创建文件,它没有能力保持目的端文件的用户和用户组和源端一致
这两个选项是一对,用来保持文件的属组(group)和属主(owner),作用应该很清晰明了。不过要注意的一点是,改变属主和属组,往往只有管理员权限才可以
复合命令
-a, --archive : -rlptgoD
-a 选项,就相当于使用了-rlptgoD这一坨选项,以一敌七。(在看了前文之后,你应该可以很轻松的理解这七个选项的作用了)
-r , --recursive :同步文件夹
-l, --links :同步软链接文件
-p, --perms :同步权限
-t, --times :同步修改时间
-g, --group :同步文件用户组
-o, --owner :同步文件用户
-D : 等同于 --devices --specials
--devices :同步块设备文件
--specials :同步特殊文件
用户体验
-v, --verbose :展示日志信息
这个选项简单易懂,就是让 rsync 输出更多的信息,我们可以举一个例子:
rsync -v main.go [email protected]:/tmp/dst
sent 84 bytes received 42 bytes 252.00 bytes/sec
total size is 0 speedup is 0.00
增加越多的v,就可以获得越多的日志信息。
rsync -vvvv main.go [email protected]:/tmp/dst
cmd= machine=192.168.199.151 user=wentao path=/tmp/dst
cmd[0]=ssh cmd[1]=-l cmd[2]=wentao cmd[3]=192.168.199.151 cmd[4]=rsync cmd[5]=--server cmd[6]=-vvvv cmd[7]=. cmd[8]=/tmp/dst
opening connection using ssh -l wentao 192.168.199.151 rsync --server -vvvv . /tmp/dst
(Server) Protocol versions: remote=29, negotiated=29
(Client) Protocol versions: remote=29, negotiated=29
[sender] make_file(main.go,*,2)
server_recv(2) starting pid=3420
[sender] i=0 <NULL> main.go mode=0100644 len=0 flags=0
send_file_list done
...
-n, --dry-run :不实际执行
如果担心执行删除等危险操作时误操作,可以使用 -n 进行测试
加上 -n 之后并不会真正执行同步,与 -v 搭配则会展示rsync要如何操作每一个文件
rsync -n -v --delete -r source/ [email protected]:/tmp/dst
building file list ... done
deleting b
a
main.go
控制同步策略
-I, --ignore-times :不使用quick check
还记得无选项时提到的quick check么? rsync 会忽略两边时间戳和文件大小一致的文件,以提高传输速度,但有时却会产生问题
rsync -I source/main.go [email protected]:/tmp/dst
✨ -I 选项会让rsync变得很乖很老实,它会挨个文件去发起数据同步
✨ -I 选项可以确保数据的一致性,代价便是速度上会变慢,因为我们放弃了“quick check”策略
--delete :删除目标的文件
还记得无选项时提到的删除策略么?如果在源端删除了某文件,目的端是不会被删除的
当使用了 --delete 之后,如果源端没有此文件,那么发送方也别想拥有,删除之。(如果你使用这个选项,就必须搭配-r选项一起)
-z, --compress :压缩传输
这是个压缩选项,只要使用了这个选项, rsync 就会把发向对端的数据先进行压缩再传输,从而减小数据量
对于网络环境较差的情况下建议使用
总结
通过介绍的内容占比大家也可以看出来,我最爱的命令是 rsync ,但我并不是所有场景都使用它,我最常用的其实是scp。首先它非常简单,消耗资源少,而且大部分linux发行版都自带这个命令。但当要传输非常大或者非常多的文件,或者网络环境不太好的时候,我更喜欢 rsync 。它使用增量同步的方案,支持压缩,因此传输非常快,而且断线之后还可以续传。当主机上没有这两个命令时,我才会尝试使用 sfpt、nc 、或者 脚本语言 等方式。
本文共 2993 个字数,平均阅读时长 ≈ 8分钟
评论 (0)