天天看點

使用rsync部署Hexo部落格

使用rsync部署Hexo部落格 | Tony's toy blog

Hexo擁有強大的插件系統,在部落格建構的各個環節都有各種各樣的插件來滿足不同的需求,對于部署部落格這個過程來說也不例外。本部落格由于使用了雲伺服器和獨立的域名,不依賴于github,最後使用nginx直接通路生成的html内容,綜合考慮後選擇采用rsync進行部署。

什麼是rsync

rsync是linux系統下的資料鏡像備份工具,可通過LAN/WAN快速同步多台主機間的檔案。rsync使用所謂的“rsync算法”來使本地和遠端兩個主機之間的檔案達到同步,這個算法隻傳送兩個檔案的不同部分,而不是每次都整份傳送,是以速度相當快。

CentOS系統預設安裝了rsync,使用指令rsync --version來檢視版本。此外windows也有相應的移植比如cwRsync和 Cygwin。

rsync的幾種傳輸方式

為了更好地表達指令的格式,一些替代符号的意義如下:

  • [options] :附加的指令選項
  • [user]:用于操作的使用者名
  • [host]:遠端主機位址或主機名
  • [src]:源檔案的路徑
  • [dest]:目标檔案的路徑

主機本地傳輸

Rsync不僅可以遠端同步資料,還可以本地同步資料(類似于cp),但不同于cp或scp的一點是,rsync不像cp/scp一樣會覆寫以前的資料(如果資料已經存在),它會先判斷已經存在的資料和新資料有什麼不同,隻有不同時才會把不同的部分覆寫掉。

使用的指令格式如下

rsync [options] [src] [dest]           

使用rsync認證協定進行傳輸

網上大多數的rsync使用教程都是在描述使用rsync認證協定進行傳輸。在傳輸沒有建立之前,這種形式有server和client的概念,server端需要啟動一個rsync守護程序(daemon/service),等待接受client發起的連接配接。一旦連接配接建立,Client(用戶端)/Server(伺服器)的這兩個角色的差别,就被Sender(發送者)/Receiver(接收者)所取代。

對于移植到windows的rsync軟體來說,你可能會發現有server版本和client版本,但是server和client都是可以主動進行”推送“的。這個概念對于初次接觸rsync的人員來說比較容易混淆。

使用的指令格式如下

rsync [options] [user]@[host]::[src] [dest] # 拉取遠端檔案
rsync [options] [src] [user]@[host]::[dest] # 推送本地檔案           

使用遠端shell進行操作

rsync也支援本地主機借助ssh和rcp等工具使用遠端shell和遠端主機進行通信。使用這種形式進行傳輸則不需要任何一方開啟守護程序,另外要注意rsync本身的配置檔案rsync.conf并不會在這種形式下起作用。

使用的指令格式如下

# 注意差別在于兩個':'還是一個:"
rsync [options] [user]@[host]:[src] [dest] # 拉取遠端檔案
rsync [options] [src] [user]@[host]:[dest] # 推送本地檔案           

使用遠端shell臨時啟動rsync daemon

通過遠端shell也能臨時啟動一個rsync daemon,這不同于使用rsync協定,它不要求遠端主機上事先啟動rsync服務,而是臨時派生出rsync daemon,它是單用途的一次性daemon,僅用于臨時讀取daemon的配置檔案,當此次rsync同步完成,遠端shell啟動的rsync daemon程序也會自動消逝。使用時要求options部分必須明确指定”–rsh”選項或其短選項”-e”。

rsync常用參數

rsync的參數非常多,詳細請參考相關文檔以及本身的help指令。這裡僅列出一下比較常用的選項:

-v, --verbose 詳細模式輸出
-q, --quiet 精簡輸出模式
-c, --checksum 打開校驗開關,強制對檔案傳輸進行校驗
-a, --archive 歸檔模式,表示以遞歸方式傳輸檔案,并保持所有檔案屬性
-r, --recursive:遞歸到目錄中
-z, --compress 對備份的檔案在傳輸時進行壓縮處理
--delete 删除DST中SRC沒有的檔案
--ignore-errors 忽略IO錯誤
--rsync-path=PATH 指定遠端伺服器上的rsync指令所在路徑資訊
--remove-source-files:要求删除源端已經成功傳輸的檔案
-o, --owner:保持owner屬性
-g, --group:保持group屬性
--chmod=Dg+s,ug+w,Fo-w,+X 指定傳輸後的檔案權限
                 文法為[D|F][ugo][+-][rwxs],表示為目錄(D)和檔案(F)增加(+)減少(-)權限           

最常用的選項組合是”avz”,即壓縮和顯示部分資訊,并以歸檔模式傳輸。另外從windows傳輸到linux系統時,控制檔案權限的--chmod也是非常有用的。

插件hexo-deployer-rsync

這個插件的位址為https://github.com/hexojs/hexo-deployer-rsync,安裝還是非常便捷容易的,但是和其他很多Hexo插件一樣,使用說明少之又少。對于不熟悉rsync的使用者來說,初次使用很容易找不到頭緒,到底是使用rsync的什麼形式進行傳輸?如果是rsync協定那麼本機作為server還是遠端伺服器作為server?…這還是在基于了解rsync的傳輸方式之後才能想到的問題,如果不了解rsync的基礎更是一頭霧水,總之很惡心。

由于多種使用方式的存在,以及當時網上能查到的相關内容非常之爛,翻遍了各個文章,還嘗試在本機啟動了一個rsync server,弄得一團糟。

源碼

很煩,最後沒法了直接看這個插件的源碼,沒想到源碼短到隻有50行。這裡就直接貼一下。

'use strict';

var chalk = require('chalk');
var spawn = require('hexo-util/lib/spawn');
var pathFn = require('path');

module.exports = function(args) {
  if (!args.host || !args.user || !args.root) {
    var help = '';

    help += 'You should configure deployment settings in _config.yml first!\n\n';
    help += 'Example:\n';
    help += '  deploy:\n';
    help += '    type: rsync\n';
    help += '    host: <host>\n';
    help += '    user: <user>\n';
    help += '    root: <root>\n';
    help += '    port: [port] # Default is 22\n';
    help += '    delete: [true|false] # Default is true\n';
    help += '    args: <rsync args>\n';
    help += '    verbose: [true|false] # Default is true\n';
    help += '    ignore_errors: [true|false] # Default is false\n\n';
    help += 'For more help, you can check the docs: ' + chalk.underline('http://hexo.io/docs/deployment.html');

    console.log(help);
    return;
  }

  if (!args.hasOwnProperty('delete')) args.delete = true;
  if (!args.hasOwnProperty('verbose')) args.verbose = true;
  if (!args.hasOwnProperty('ignore_errors')) args.ignore_errors = false;

  var params = [
    '-az',
    process.platform === 'win32' ? pathFn.basename(this.public_dir) + '/' : this.public_dir,
    args.user + '@' + args.host + ':' + args.root
  ];

  if (args.port && args.port > 0 && args.port < 65536) {
    params.splice(params.length - 2, 0, '-e');
    params.splice(params.length - 2, 0, 'ssh -p ' + args.port);
  }

  if (args.verbose) params.unshift('-v');
  if (args.ignore_errors) params.unshift('--ignore-errors');
  if (args.delete) params.unshift('--delete');
  if (args.args) params.unshift(args.args);

  return spawn('rsync', params, {verbose: true});
};           

可以看到最終這個插件就隻是調用了一下rsync指令,剩下的都是指令内容的拼接。

為了更加清晰得說明問題,把這個插件的配置參數也貼出來

host: Address of remote host
user: Username
root: Root directory of remote host
port: Port
delete: Delete old files on remote host
args: Rsync arguments
verbose: Display verbose messages
ignore_errors: Ignore errors           

源碼簡析

按照代碼順序解釋如下:

  1. host、user、root這三個參數必填,否則将會列印You should configure deployment settings in _config.yml first! ...提示你輸入必填參數。
  2. delete預設為true,verbose預設為true,ignore_errors預設為false
  3. 建立參數集合,固定使用-az這兩個參數;根據平台擷取部落格public目錄的路徑;拼裝遠端目錄路徑
  4. 參數集合判斷加入端口、ssh
  5. 判斷增加verbose、ignore_errors、delete選項對應參數
  6. 使用組裝好的參數調用rsync指令

很明顯就是要去使用ssh遠端shell進行操作,是以隻要本機和伺服器都裝上rsync即可,不需要啟動daemon程序。

使用注意

對于windows系統來說有幾個需要注意的點。

推薦使用cwRsync,貌似是要收費,但是你懂的。注意要安裝client版本,使用server版本可能會出現報錯,原因與ssh指令有關,可以發現client版本bin目錄下自帶了一個ssh.exe。因為插件直接執行rsync指令,是以安裝完成後還需要把安裝目錄添加到系統環境變量中,這樣才能直接使用。

此外由于軟體本身是linux移植過來的,在填寫路徑的時候無法識别類似 d:\\dir\\public 的win風格路徑格式,cwRsync使用 /cygdrive/d/dir/public 的格式來讀取win路徑下的内容。

繼續閱讀