前言

前两天在 v2ex 看到 此帖。一直以来我用的都是官方的主题,然后我也心动了。于是乎我也换上了这个主题,慢慢踩坑直到现在让自己满意……

正片

我修改的博客地址: https://blog.hellodk.com/blog/dk11。该博客运行在我家里的 Phicomm N1 这台 armbian 设备上,是 docker 安装的leanote。使用的镜像是: https://hub.docker.com/r/lstcml/n1_leanote

n1 驾驭这些应用是小菜一碟,丝毫没有性能压力。但是由于 n1 是 arm 架构的,docker image 中使用的 leanote binary 程序亦需要是 arm based 的。这个 image 是基于 arm 的 Ubuntu 18.04,在更换国内镜像源以及安装软件包的过程中尽是坎坷。安装 python3pip3 遇到各种困难,主要是依赖非常麻烦。最终我放弃了在 n1 上运行,改在 x64 cpu 的软路由上运行。

原帖作者做了一些工作的,简要概括就是

  • 移植了 Chirpy 主题,创建 repo ctaoist/leanote-theme-chirpy
  • 改写 mongodb 数据库,让每篇文章具有一个 '是否是博客' 的属性。原本 leanote 2.6.1 需要将整个 notebook public as blog 才可以看到这个 category。作者改写了服务端程序让该 notebook 具有 public 的 blog 就自动生成 category
  • 归档页面排序 bug 修复

感谢作者的工作,我现在也用上了这个主题。


记录一些日志

  1. 原先 arm ubuntu 18.04 容器遇到问题 The certificate chain uses expired certificate. Could not handshake: Error in the certificate
    解决办法:软件包增加 [trusted=yes] 声明

    deb [trusted=yes] http://mirrors.ustc.edu.cn/ubuntu-ports/ bionic universe
    deb [trusted=yes] http://mirrors.ustc.edu.cn/ubuntu-ports/ bionic-updates universe
    deb [trusted=yes] http://mirrors.ustc.edu.cn/ubuntu-ports/ bionic multiverse
    deb [trusted=yes] http://mirrors.ustc.edu.cn/ubuntu-ports/ bionic-updates multiverse
    deb [trusted=yes] http://mirrors.ustc.edu.cn/ubuntu-ports/ bionic-backports main restricted universe multiverse
    deb [trusted=yes] http://mirrors.ustc.edu.cn/ubuntu-ports/ bionic-security main restricted
    deb [trusted=yes] http://mirrors.ustc.edu.cn/ubuntu-ports/ bionic-security universe
    deb [trusted=yes] http://mirrors.ustc.edu.cn/ubuntu-ports/ bionic-security multiverse
  2. 换了 amd64 架构的硬件,leanote 的服务端程序选了这个镜像 https://hub.docker.com/r/hjh142857/leanote
    容器是 x86_64 的 Ubuntu 18.04

    需要安装 python3 以及 pip3 然后通过 pip3 安装 pymongo


将以下代码命名成文件 leanote_2.6.1_to_2.7.0.py

#!/usr/bin/python3

import pymongo
from bson.objectid import ObjectId
import sys

if len(sys.argv) < 5:
    host = input('Mongodb Host: ')
    dbname = input('DB Name: ')
    user = input('DB Username: ')
    passwd = input("DB Password: ")
else:
    host, dbname, user, passwd = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]

dbClient = pymongo.MongoClient(f"mongodb://{user}:{passwd}@{host}:27017/?authSource={dbname}")
leanotedb = dbClient[dbname]

def updateNotebooks():
    for notebook in leanotedb.notebooks.find({"IsDeleted": False}):
        notebookId, userId, parentId = notebook["_id"], notebook["UserId"], notebook.get("ParentNotebookId")
        if parentId is not None:
            parentNotebook =  leanotedb.notebooks.find_one({"_id": parentId, "UserId": userId})
            if parentNotebook is not None:
                childs = parentNotebook.get("ChildNotebookIds", [])
                childs.append(notebookId)
                childs = set([str(c) for c in childs]) # 消除重复
                leanotedb.notebooks.update_one({"_id": parentId, "UserId": userId}, {"$set": {"ChildNotebookIds": [ObjectId(c) for c in childs]}})

def updateNotes():
    for note in leanotedb.notes.find({"IsDeleted": False}):
        cates = []
        noteId = note["_id"] # ObjectId
        i = 0
        notebookId, userId = note["NotebookId"], note["UserId"]
        while i < 10: # 最多10层目录
            i = i + 1
            notebook = leanotedb.notebooks.find_one({"_id": notebookId, "UserId": userId})
            if notebook is not None:
                # print(notebook["Title"])
                cates.append({"Title": notebook["Title"], "UrlTitle": notebook["UrlTitle"], "NotebookId": str(notebookId)})
                notebookId = notebook.get("ParentNotebookId", "")
                if len(str(notebookId)) > 0:
                    continue
                else:
                    break
        cates.reverse()
        # print(cates)
        leanotedb.notes.update_one({"_id": noteId, "UserId": userId}, {"$set": {"Cates": cates}})

if __name__ == '__main__':
    try:
        updateNotebooks()
        updateNotes()
        dbClient.close()
    except Exception as e:
        print(e)
        dbClient.close()

由于我的 leanote 数据库配置没有用户名和密码,在我更新数据库执行上面的 python script 时遇到了数据库认证错误。我更改为了以下版本

#!/usr/bin/python3

import pymongo
from bson.objectid import ObjectId
import sys

if len(sys.argv) < 5:
    host = input('Mongodb Host: ')
    dbname = input('DB Name: ')
    user = input('DB Username: ')
    passwd = input("DB Password: ")
else:
    host, dbname, user, passwd = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]

#dbClient = pymongo.MongoClient(f"mongodb://{user}:{passwd}@{host}:27017/?authSource={dbname}")
dbClient = pymongo.MongoClient(f"mongodb://127.0.0.1:27017/")
leanotedb = dbClient['leanote']

def updateNotebooks():
    for notebook in leanotedb.notebooks.find({"IsDeleted": False}):
        notebookId, userId, parentId = notebook["_id"], notebook["UserId"], notebook.get("ParentNotebookId")
        if parentId is not None:
            parentNotebook =  leanotedb.notebooks.find_one({"_id": parentId, "UserId": userId})
            if parentNotebook is not None:
                childs = parentNotebook.get("ChildNotebookIds", [])
                childs.append(notebookId)
                childs = set([str(c) for c in childs]) # 消除重复
                leanotedb.notebooks.update_one({"_id": parentId, "UserId": userId}, {"$set": {"ChildNotebookIds": [ObjectId(c) for c in childs]}})

def updateNotes():
    for note in leanotedb.notes.find({"IsDeleted": False}):
        cates = []
        noteId = note["_id"] # ObjectId
        i = 0
        notebookId, userId = note["NotebookId"], note["UserId"]
        while i < 10: # 最多10层目录
            i = i + 1
            notebook = leanotedb.notebooks.find_one({"_id": notebookId, "UserId": userId})
            if notebook is not None:
                # print(notebook["Title"])
                cates.append({"Title": notebook["Title"], "UrlTitle": notebook["UrlTitle"], "NotebookId": str(notebookId)})
                notebookId = notebook.get("ParentNotebookId", "")
                if len(str(notebookId)) > 0:
                    continue
                else:
                    break
        cates.reverse()
        # print(cates)
        leanotedb.notes.update_one({"_id": noteId, "UserId": userId}, {"$set": {"Cates": cates}})

if __name__ == '__main__':
    try:
        updateNotebooks()
        updateNotes()
        dbClient.close()
    except Exception as e:
        print(e)
        dbClient.close()

做了两点修改

  1. 数据库认证: dbClient = pymongo.MongoClient(f"mongodb://127.0.0.1:27017/")
  2. 获取数据库实例: leanotedb = dbClient['leanote']

归纳了说,本次更新主题所做的事情的主要步骤

  1. n1 上的 leanote mongodb 数据库备份
  2. 在 x86_64 的机器(我的软路由)上运行 leanote 服务程序
  3. 在软路由上恢复数据库,这样之前写的文章就回来了

    下面的操作都是在软路由上进行的了

  4. 进入容器,通过 apt install 安装 python3pip3,再通过 pip3 安装 pymongo library
  5. 执行修改过的 python 脚本,python3 leanote_2.6.1_to_2.7.0.py 终端让你输入 dhhost dbname username password 可以随便填写了,因为变量值已经在脚本中写死了
  6. 下载帖子作者编译好的 leanote-linux-amd64-2.7.0.zip
  7. 解压缩上面的 zip 文件,取出其中的 leanote-linux-amd64run.sh 替换掉容器中的对应文件,取出其中的 routes 路由声明文件替换掉容器中的对应文件。注意: 操作前请一定记得备份
  8. 重启容器
  9. 导入主题,可以看到分类页面正常工作了,归档页面也能按照文章创建时间排序了(原本只能是发布时间)
  10. 自己修改样式,做一些自定义

上面第9点我想吐嘈一下,我有三个 notebook,每个 notebook 都有若干篇文章公开为了博客,加起来一共几十篇,我对整个notebook设置了公开为博客,后面又给取消了,然后所有文章都不见了!!!也被取消公开博客了…… 一时间气死。好在我还记得哪些文章我有公开为博客,一篇一篇的改了回来,然后就发现了 leanote 2.6.1 归档页面只能根据发布时间排序的bug


后记

本次更换主题的折腾过程还是蛮酸爽的,作者只编译了 linux-amd 程序,没写过 go 的我,速成学习了一下 go 语言,学习了一下项目交叉编译,构建成功了 Linux arm 的可执行程序,但是 arm ubuntu 的安装软件体验实在是不好,依赖问题极其麻烦…… 后面放弃换了 x86_64 真就方便了很多,遇到极少数问题也能很快解决,网上的资料都更多。所以说,生态真是非一日之寒,一旦形成了生态,那么这个平台用户就不会少,平台的未来也就更加光明。

最后欢迎你光临我家里的博客 Allen Hua's another blog