(原) Hugo静态博客增量更新

原创文章,请后转载,并注明出处。

随着博客内容的越来越多,特别是图片的增多,需要考虑博客的增量更新,而不是象现在的全面更新。否则,十年以后将更(新)不动。

现在考虑增量更新方案。

  1. 生成新文章或运行本地服务器时,监控目录,记录修改的文件,记入文本文件中。

  2. 增量更新blog.sh up时,生成文字压缩包,将记录文本中的文件添加到压缩包中。


2019.8.17 更新方案

每一次上传之前,扫描生成的静态文件,静态文件生成MD5,与上一次的文件MD5作比较。发现有增量文件,则加入更新。发现文件MD5变化,则更新。

基本已实现,比较结果后,待tar进行压缩后上传。

package main

import (
	"crypto/md5"
	"database/sql"
	"fmt"
	"io/ioutil"
	"os"

	_ "github.com/mattn/go-sqlite3"
	"github.com/soease/tools"
)

const DBFILE = "./up.db"

var (
	db *sql.DB
)

func Md5SumFile(file string) (value string, err error) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return
	}
	value = fmt.Sprintf("%x", md5.Sum(data))

	return
}

//是否存在数据库
func ExistsDB() {
	if tools.FileExist(DBFILE) {
		return
	}

	db.Exec("CREATE TABLE 't1' ( 'filename' TEXT NOT NULL, 'md5' TEXT NOT NULL )")
}

func main() {
	CheckFile := "''"
	if len(os.Args) < 2 {
		fmt.Printf("Usage: %s path\n", os.Args[0])
		return
	}

	db, _ = sql.Open("sqlite3", DBFILE)
	ExistsDB()
	defer db.Close()

	files, err := tools.WalkDir(os.Args[1], "") //遍历所有文件
	if err != nil {
		return
	}
	for _, n := range files {
		md5Value, _ := Md5SumFile(n) //生成文件Md5
		rows, err := db.Query(fmt.Sprintf("SELECT md5  FROM t1 WHERE filename='%s'", n))
		defer rows.Close()
		var RecNum int
		if err != nil {
			return
		}

		var md5 string
		for rows.Next() { //查询表中文件的md5
			RecNum = RecNum + 1
			rows.Scan(&md5)
		}
		if md5 == md5Value { //表中存在此文件,且md5相同
		} else {
			if RecNum == 0 {
				fmt.Println("新增文件", n)
				stmt, _ := db.Prepare("INSERT INTO t1 (filename,md5) values (?,?)") //不存在文件,插入表中
				stmt.Exec(n, md5Value)
			} else {
				fmt.Println("更新文件", n) //表中存在此文件,但md5不相同
				stmt, _ := db.Prepare("UPDATE t1 SET md5 = ? WHERE filename=?")
				stmt.Exec(md5Value, n)
			}
		}
		CheckFile = fmt.Sprintf("%s,'%s'", CheckFile, n)
	}

	//查询可能存在的删除文件
	rows, _ := db.Query("SELECT filename  FROM t1 WHERE filename not in (" + CheckFile + ")")
	defer rows.Close()
	var filename string
	for rows.Next() {
		rows.Scan(&filename)
		fmt.Println("删除文件", filename)
	}
	db.Exec("DELETE FROM t1 WHERE filename not in (" + CheckFile + ")")
}

余下的就是读取信息,打包的事了。或许应该把更新脚本一并附上。

#!/bin/bash

#上传并更新
function UpLoad() {
   echo "$(date '+%Y-%m-%d %H:%M:%S') 文件上传"
   scp -q /dev/shm/blog.tar.gz ease@dgong.net:/data
   echo "$(date '+%Y-%m-%d %H:%M:%S') 更新..."
   ssh ease@dgong.net "cd /data ; tar zxvf blog.tar.gz --overwrite > /dev/null ;  "
   echo "$(date '+%Y-%m-%d %H:%M:%S') 更新完成"
   notify-send "更新" "博客i.scwy.net更新完毕!" -t 3000   
}

#增量更新,速度最快
function AddUp() {
   echo "$(date '+%Y-%m-%d %H:%M:%S') 增量更新博客,准备生成静态文件"
   ( cd /home/ease/Documents/hugo/EaseBlog ; hugo -d /dev/shm/blog )   
   ( touch -m /dev/shm/blog/css /dev/shm/blog/js /dev/shm/blog/img /dev/shm/blog )   
   echo "$(date '+%Y-%m-%d %H:%M:%S') 文件比较"
   cp /home/ease/Documents/hugo/up.db /dev/shm
   if [ -f "/dev/shm/tmp.txt"  ];   
   then
        rm /dev/shm/tmp.txt
   fi   
   ( cd /dev/shm;  file_md5 blog) | while read line
   do
         op=$(echo $line | awk '{print $1}');
         file=$(echo $line | awk '{print $2}'); 
         echo $op,$file >> /dev/shm/tmp.txt
         if [ "$op" == "update"  ]; then
               echo "更新",$file
               ( cd /dev/shm; tar -rvf blog.tar $file  > /dev/null )
         elif [ "$op" == "add"  ]; then
               echo "添加",$file
               ( cd /dev/shm; tar -rvf blog.tar $file  > /dev/null )
         elif [ "$op" == "delete"  ]; then               
               echo "删除",$file
         fi
   done   
   cp /dev/shm/up.db /home/ease/Documents/hugo

   if [ -f "/dev/shm/tmp.txt"  ];   
   then
      echo "$(date '+%Y-%m-%d %H:%M:%S') 比较完成,开始压缩"
      ( cd /dev/shm; gzip -c blog.tar > blog.tar.gz )

      UpLoad
   else 
      echo "$(date '+%Y-%m-%d %H:%M:%S') 比较完成,没有更新"               
   fi
}

#完整更新,速度很慢
function AllUp() {
   echo "$(date '+%Y-%m-%d %H:%M:%S') 完整更新博客,准备生成静态文件"
   ( cd /home/ease/Documents/hugo/EaseBlog ; hugo -d /dev/shm/blog )
   ( touch -m /dev/shm/blog/css /dev/shm/blog/js /dev/shm/blog/img /dev/shm/blog)
   
   echo "$(date '+%Y-%m-%d %H:%M:%S') 压缩"
   (cd /dev/shm ; tar czvf /dev/shm/blog.tar.gz blog > /dev/null)

   UpLoad
}

#文档部份更新,速度中等
function PortionUp() {
   echo "$(date '+%Y-%m-%d %H:%M:%S') 部份更新博客,准备生成静态文件"
   ( cd /home/ease/Documents/hugo/EaseBlog ; hugo -d /dev/shm/blog )
   ( touch -m /dev/shm/blog/css /dev/shm/blog/js /dev/shm/blog/img /dev/shm/blog)
   echo "$(date '+%Y-%m-%d %H:%M:%S') 压缩"
   (cd /dev/shm ; tar czvf /dev/shm/blog.tar.gz --exclude=*.jpg --exclude=*.png --exclude=*.mp4 --exclude=*.mp3 blog > /dev/null)
   UpLoad   
}

#------------------------------------------------------------------------------------------

if [ "$1" = "new" ]; then 
   #新建一个文档
   ( cd  /home/ease/Documents/hugo/EaseBlog ; ~/tools/hugo $* )
elif  [ "$1" = "run" ]; then
  #运行hugo服务   
   cd ~/Documents/hugo/EaseBlog ; ~/tools/hugo server -D &
elif  [ "$1" = "up" ]; then
   #部份更新
   PortionUp
elif [ "$1" = "all" ];  then
   #完整更新
   AllUp
else 
  #增量上传
   AddUp
fi 

虽然脚本还可以优化,不过功能基本可行。脚本暂时没有处理删除功能,留后处理吧。

相关文章