遠程文件傳輸命令千千萬,我卻獨愛它一個!
前言
若干年前,我曾對面試者問出過一個類似的問題:有哪些遠程傳輸文件的命令?
他的回答令我非常意外:
-
答:使用
rz或sz -
我:如果沒有
xshell之類的軟件呢? -
答:那就下載一個
-
我:emmmm.......,還有其他命令麼?
-
答:不會了
-
我:emmmm.......
雖然標題裏的千千萬有些誇張,但跨主機傳輸文件的命令可是真不少的。下面就來介紹些我曾經用過的那些文件傳輸命令吧!
腳本語言也可以
很多腳本語言都可以臨時啓動一個http server。於是我們便可以通過瀏覽器來下載一些文件
Python
Python可以臨時啓動一個http server來提供文件訪問
Python 2
$ python -m SimpleHTTPServer 8000
Python 3
$ python3 -m http.server 8000
通過瀏覽器我們就可以看到目錄可以進行下載
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
鮮爲人知的 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來上傳下載文件
rz 命令
使用rz命令可以上傳本地文件到遠程服務器。運行該命令會彈出一個文件選擇窗口,從本地選擇文件上傳到 Linux 服務器
sz 命令
將選定的文件發送到本地機器。運行該命令會彈出一個文件選擇窗口,從 Linux 服務器發送到本地(保存的目錄是可以配置)
說明
rz命令與sz命令常用在虛擬終端軟件中,如果是在兩臺linux直接傳輸文件,往往是不可行的
傳統的sftp和ftp
sftp與ftp有着幾乎一樣的語法和功能,sftp是一個獨立的SSH封裝協議包,通過安全連接以相似的方式工作。這意味着只要目標端啓動了sshd服務器就可以使用sftp,而且是一種安全傳輸文件的方式,因此我更推薦你使用sftp
要連接到遠程 sftp 服務器,如下建立一個安全 SSH 連接並創建 SFTP 會話:
$ sftp wentao@192.168.199.151
登錄到遠程主機後,你可以如下運行交互式的 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
把本地當前路徑下的main.go上傳到遠程主機當前路徑,並命名成a.go
sftp> put main.go a.go
Uploading main.go to /private/tmp/dst/a.go
main.go
下載文件
把遠程主機當前路徑下的main.go下載到本地當前路徑
sftp> get main.go
Fetching /private/tmp/dst/main.go to main.go
main.go
依舊可以自定義名字
sftp> get main.go a.go
Fetching /private/tmp/dst/main.go to a.go
main.go
退出
退出sftp shell 可以輸入 !
sftp> !
說明
還有許多圖形界面甚至是語言 SDK 支持sftp,它的目標不僅僅是傳輸文件,是歷史非常悠久的文件管理協議
功能專一的scp
scp消耗資源少,功能專一,並且加密傳輸,可以說是最常用的跨主機複製命令。
和cp的命令相似,scp的使用非常簡單
scp [參數] [原路徑] [目標路徑]
-
第一個路徑是原路徑,第二個是目標路,兩者都可以是遠程機器
-
路徑:
ssh命令一樣,使用@符分割用戶名和 ip,同時使用:連接目標目錄
把本地文件複製到遠程
$ scp source/main.go wentao@192.168.199.151:/tmp/dst/
把遠程機器上的文件複製到本地
$ scp wentao@192.168.199.151:/tmp/dst/main.go source/
上傳目錄使用-r
$ scp -r source/* wentao@192.168.199.151:/tmp/dst/
說明
scp在小文件場景下確實得心應手,但面對大文件或者網絡不好需要續傳的場景,scp的效率就會受到較大的影響了。此時就是另一個命令的大顯身手的時候了。
增量同步的神:rsync
rsync是一種快速且非常通用的文件複製工具。它使用增量傳輸算法,該算法僅發送源文件和目標文件之間的差異以減少網絡發送的數據量。所以它廣泛用於備份和鏡像,或作爲日常使用的拷貝命令
不帶任何選項
我們可以使用rsync把本地文件複製到遠程。和ssh命令一樣,使用@符分割用戶名和 ip,同時使用:連接目標目錄
rsync main.go wentao@192.168.199.151:/tmp/dst
或者把遠程機器上的文件複製到本地
rsync wentao@192.168.199.151:/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/* wentao@192.168.199.151:/tmp/dst
skipping directory source/sub
a
main.go
# 連source都跳過了
$ rsync -v source wentao@192.168.199.151:/tmp/dst
skipping directory source
加上-r選項,指示需要遞歸所有文件夾一起同步
$ rsync -vr source wentao@192.168.199.151:/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 wentao@192.168.199.151:/tmp/dst
skipping non-regular file "d"
你猜對了,rsync又無情了拒絕了我們。它一旦發現某個文件是軟鏈接,就會無視它,除非我們增加-l選項。
$ rsync -l source/d wentao@192.168.199.151:/tmp/dst
使用了-l選項後,rsync會完全保持軟鏈接文件類型,原原本本的將軟鏈接文件複製到目的端,而不會 “follow link” 到指向的實體文件。
示例中,雖然軟鏈接文件被同步過去了,但因爲軟連接指向的文件並沒有,所以自然會提示No such file or directory
# wentao@192.168.199.151
➜ 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 wentao@192.168.199.151:/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 wentao@192.168.199.151:/tmp/dst
main.go
sent 84 bytes received 42 bytes 252.00 bytes/sec
total size is 0 speedup is 0.00
增加越多的v,就可以獲得越多的日誌信息。
$ rsync -vvvv main.go wentao@192.168.199.151:/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/ wentao@192.168.199.151:/tmp/dst
building file list ... done
deleting b
a
main.go
控制同步策略
🌲 -I, --ignore-times:不使用 quick check
還記得無選項時提到的 quick check 麼?rsync會忽略兩邊時間戳和文件大小一致的文件,以提高傳輸速度,但有時卻會產生問題
$ rsync -I source/main.go wentao@192.168.199.151:/tmp/dst
✨ -I選項會讓rsync變得很乖很老實,它會挨個文件去發起數據同步
✨ -I選項可以確保數據的一致性,代價便是速度上會變慢,因爲我們放棄了 “quick check” 策略
🌲 --delete:刪除目標的文件
還記得無選項時提到的刪除策略麼?如果在源端刪除了某文件,目的端是不會被刪除的
當使用了 --delete之後,如果源端沒有此文件,那麼發送方也別想擁有,刪除之。(如果你使用這個選項,就必須搭配-r選項一起)
🌲 -z, --compress:壓縮傳輸
這是個壓縮選項,只要使用了這個選項,rsync就會把發向對端的數據先進行壓縮再傳輸,從而減小數據量
對於網絡環境較差的情況下建議使用
總結
通過介紹的內容佔比大家也可以看出來,我最愛的命令是rsync,但我並不是所有場景都使用它
我最常用的其實是scp。首先它非常簡單,消耗資源少,而且大部分 linux 發行版都自帶這個命令
但當要傳輸非常大或者非常多的文件,或者網絡環境不太好的時候,我更喜歡rsync。它使用增量同步的方案,支持壓縮,因此傳輸非常快,而且斷線之後還可以續傳
當主機上沒有這兩個命令時,我纔會嘗試使用 sfpt、nc、或者腳本語言等方式
參考資料
[1]
《rsync 同步的藝術》–linux 命令五分鐘系列之四十二: http://roclinux.cn/?p=2643
[2]
rsync(1) - Linux man page: https://linux.die.net/man/1/rsync
[3]
sftp(1) - Linux man page: https://linux.die.net/man/1/sftp
[4]
nc(1) - Linux man page: https://linux.die.net/man/1/nc
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/HblMuCLZ2pikXvjcrCGHlQ