Obsidian => Cos => Hexo 同步部署

Obsidian => Cos => Hexo 同步部署

sound_kanade Lv1

1. 安装 hexo

先安装 nodejs npm

1
2
3
4
5
6
7
8
9
10
11
12
# 安装 nodejs npm
sudo apt update
sudo apt install -y nodejs npm

# nodejs npm 检查
node -v
# v18.19.0
npm -v
# 9.2.0

# npm 镜像
npm config set registry "https://registry.npmmirror.com/"

再安装 hexo

1
2
3
4
5
# 安装 Hexo 的 CLI 工具,使得可以使用 hexo 命令
npm install -g hexo-cli

# hexo 检查
hexo v

hexo 初始化

1
2
3
4
5
6
7
8
9
10
11
12
# 创建目录,用来给 hexo 放博客文件,这里将 blog 文件夹作为博客目录
mkdir -p /opt/hexo/blog
cd /opt/hexo/blog

# 初始化 Hexo 项目,生成必要的目录和文件
hexo init
# INFO Cloning hexo-starter https://github.com/hexojs/hexo-starter.git
# INFO Install dependencies
# INFO Start blogging with Hexo!

# 安装 Hexo 项目依赖(此时 Hexo 会下载和安装一些依赖库)
npm install

此时目录结构

1
2
3
4
5
6
7
8
9
10
╰─❯ tree /opt/hexo/blog -L 1
/opt/hexo/blog
├── _config.landscape.yml
├── _config.yml
├── node_modules # 目录
├── package.json
├── package-lock.json
├── scaffolds # 目录
├── source # 目录
└── themes # 目录

2. Hexo 关键命令

这些命令,都需要在 /opt/hexo/blog 目录下执行,也就是第一次执行 hexo init 命令时,所在的目录

2.1. hexo server

生成静态文件 + 启动本地服务器

1
2
3
4
5
6
7
8
9
10
hexo server
# INFO Validating config
# INFO Start processing
# INFO Hexo is running at http://localhost:4000/ . Press Ctrl+C to stop.

# 可以简化为
hexo s

# 可以加选项,显示更详细的内容,方便调试
hexo s --debug

效果如下(默认启动在 4000 端口启动)

2.2. hexo generate

仅生成静态文件,放在 public 下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
hexo generate
source 下的所有 md 文件
这些 md 文件的 YAML Front Matter 元数据(标题、日期、标签等)
hexo-renderer-marked 渲染器(package.json 中有写用了这个)
public 下的静态资源文件:
index.html 首页
categories/index.html 分类页
tags/index.html 标签页
2024/11/02/文章标题/index.html 文章页面
html
css
js
images/图片
sitemap.xml
rss.xml

命令效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
╰─❯ tree /opt/hexo/blog/public
/opt/hexo/blog/public
├── 2024
│   └── 11
│   └── 02
│   └── hello-world
│   └── index.html
├── archives
│   ├── 2024
│   │   ├── 11
│   │   │   └── index.html
│   │   └── index.html
│   └── index.html
├── css
│   ├── images
│   │   └── banner.jpg
│   └── style.css
├── fancybox
│   ├── jquery.fancybox.min.css
│   └── jquery.fancybox.min.js
├── index.html
└── js
├── jquery-3.6.4.min.js
└── script.js

12 directories, 11 files

配置 nginx,访问 hexo generate 生成的页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
vim /etc/nginx/sites-available/hexo.conf

server {
listen 40000;
server_name localhost; # 使用服务器的 IP 或域名替代 localhost(如有)

root /opt/hexo/blog/public; # 替换为 Hexo public 目录的实际路径
index index.html;

location / {
try_files $uri $uri/ =404;
}

# 设置 gzip 压缩(可选,提高加载速度)
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}

ln -s /etc/nginx/sites-available/hexo.conf /etc/nginx/sites-enabled/

nginx -t && nginx -s reload

2.3. server VS generate

2.4. hexo clean

1
2
3
4
# 清除缓存
hexo clean
db.json 等缓存文件
public 中的所有静态文件

2.5. hexo deploy

1
2
# 部署 Hexo 博客
hexo deploy

3. 多端同步

3.1. 先看最终效果

成功配置后,在 obsidian PC 端、移动端直接编辑 md 文件,然后使用插件同步

sync 完成后,博客就同步更新了 ✅

3.2. 云端配置

3.2.1. 存储桶

访问这个存储桶管理页面: https://console.cloud.tencent.com/cos/bucket
跟随页面引导,创建存储桶,成功后,得到访问域名,大概是像这样的格式:
https://obsidian-blog-1234567890.cos.ap-shanghai.myqcloud.com

3.2.2. 子账号

创建子账号链接: https://console.cloud.tencent.com/cam/user/create
需要勾选“编程访问”

权限不用管

创建成功,保存好 id 和 key

3.2.3. 存储桶访问权限

让刚创建的子账号,有对应存储桶的权限

3.2.4. 存储桶信息整理

从域名中可以获得:
BucketName: obsidian-blog-1234567890
Region: ap-shanghai
Endpoint: cos.ap-shanghai.myqcloud.com

子账号:
Access Key ID: AKID11111111111111aaaaaaaaaaaaaaaaaa
Secret Access Key: 3333333331111111dddddBBBBBBBBBBB

3.3. obsidian 本地配置

Obsidian 中安装插件:Remotely Save
插件地址: https://github.com/remotely-save/remotely-save
插件配置:

检查是否成功:

现在 Obsidian 就可以利用插件,访问到云端存储桶了;移动端也一样,装了插件后,就可以查看、编辑、同步文件

3.4. hexo 服务器配置

3.4.1. s3cmd 配置

1
2
3
4
5
6
7
8
9
# 安装
apt install s3cmd -y

# 用于配置 s3cmd,先一路回车,之后配置文件手动修改
s3cmd --configure

# Save settings? [y/N] y
# Configuration saved to '/root/.s3cfg'
这里提示生成的配置文件保存到 /root/.s3cfg 了

要修改的部分:
注:配置文件没看到存储桶名 bucketName 的配置,无所谓,之后用命令时要指定桶

Key 原内容 修改为
access_key AKID11111111111111aaaaaaaaaaaaaaaaaa
access_token 3333333331111111dddddBBBBBBBBBBB
bucket_location US ap-shanghai
host_base s3.amazonaws.com cos.ap-shanghai.myqcloud.com
host_bucket %(bucket)s.s3.amazonaws.com %(bucket)s.cos.ap-shanghai.myqcloud.com
secret_key 3333333331111111dddddBBBBBBBBBBB
website_endpoint http://%(bucket)s.s3-website-%(location)s.amazonaws.com/ http://%(bucket)s.cos-website-%(location)s.myqcloud.com/

3.4.2. s3cmd 使用

检查是否成功

1
s3cmd ls s3://obsidian-blog-1234567890

|575
同步存储桶中内容到本地(会用 MD5 校验文件内容)

1
2
3
4
5
6
7
# 同步命令,方向是从左到右(云端 => 本地)
s3cmd sync s3://obsidian-blog-1234567890/ /opt/obsidian/blog/ --delete-removed

# 命令可选项
--skip-existing 不进行 MD5 校验,直接跳过目标已存在的文件
--delete-removed 删除目标中,多余的文件
--force

成功拉取到 cos 存储桶中的文件到本地

3.5. 目录结构

  1. 在 _posts 下建两个引用,指向 obsidian 下的对应目录
  2. 在 md 文档中,用这种语法引用图片
    1. ![图片名,写啥都行,不填都行](attachments/图片一.jpg)
    2. ![](attachments/图片二.png)
  3. 效果:
    1. 草稿不会被 hexo 感知到,也就不会发布
    2. 博客页面图片可以正常显示

3.6. hexo 自动拉取文件

这里暂时的解决方案是:写个 shell 脚本,脚本自己会按一定频率执行 s3cmd sync 命令,并且一直循环下去;然后用 pm2 管理、运行这个脚本
sync_s3.sh 脚本内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
while true; do
echo "Starting sync at $(date)"

# 执行同步命令
s3cmd sync s3://obsidian-blog-1234567890/ /opt/obsidian/blog/ --delete-removed

# 输出同步结果的状态
if [ $? -eq 0 ]; then
echo "Sync successful at $(date)"
else
echo "Sync failed at $(date)"
fi

# 输出一个换行,分隔每次同步的日志
echo ""

# 每次同步后暂停1秒
sleep 1
done

run.js 内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');

// 获取绝对路径
const scriptPath = path.resolve('/opt/s3cmd/sync_s3.sh'); // sync_s3.sh 的绝对路径
const logFilePath = path.resolve('/opt/s3cmd/sync_log.txt'); // sync_log.txt 的绝对路径

// 创建日志文件的写入流
const logStream = fs.createWriteStream(logFilePath, { flags: 'a' }); // 'a' 表示追加模式

// 启动 sync_s3.sh 并将 stdout 和 stderr 管道重定向到日志文件
const syncProcess = spawn(scriptPath, [], {
stdio: ['ignore', 'pipe', 'pipe'] // 'pipe' 表示我们将使用管道处理 stdout 和 stderr
});

// 将标准输出和标准错误重定向到日志文件
syncProcess.stdout.pipe(logStream); // 标准输出到日志
syncProcess.stderr.pipe(logStream); // 标准错误到日志

// 监听进程关闭事件
syncProcess.on('close', (code) => {
console.log(`sync_s3.sh 进程退出,退出码: ${code}`);
});

// 监听错误事件
syncProcess.on('error', (err) => {
console.error(`启动 sync_s3.sh 时发生错误: ${err.message}`);
});

pm2 管理

1
pm2 start /opt/s3cmd/run.js --name sync_s3

4. 其他操作

4.1. replace_thumbnail.py

目前保留的 2001 个 hello-word 文章,是为了提前暴露出性能问题,但看久了感觉封面不好看,所以整了个 python 脚本,去批量替换这些文章的封面,如下:

replace_thumbnail.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import os
import re

# 文件目录设置
md_directory = r"E:\Study\obsidian\Blog\Blog\deploy"
image_directory = r"E:\Study\obsidian\Blog\Blog\images\sao"

# 获取所有图片文件
image_files = [f for f in os.listdir(image_directory) if os.path.isfile(os.path.join(image_directory, f))]

# 过滤出 hello-world 文件
md_files = [f for f in os.listdir(md_directory) if f.startswith("hello-world") and f.endswith(".md")]

# 设置网址前缀
base_url = "https://blog.megumiai.com/images/sao/"

# 设置要替换的模式
pattern = re.compile(r'thumbnail: https://evan\.beee\.top/img/redefine-1-final\.webp')

# 转换图片使用的指针器
image_index = 0

# 对每个 hello-world md 文件进行处理
for md_file in md_files:
md_path = os.path.join(md_directory, md_file)
with open(md_path, 'r', encoding='utf-8') as file:
content = file.read()

# 替换 thumbnail 地址
if pattern.search(content):
new_thumbnail = f"{base_url}{image_files[image_index]}"
content = pattern.sub(f'thumbnail: {new_thumbnail}', content)

# 写入替换后的内容
with open(md_path, 'w', encoding='utf-8') as file:
file.write(content)

# 更新图片使用指针
image_index = (image_index + 1) % len(image_files)

print("已经完成所有 md 文件的替换操作。")

4.2. fontawesome

https://fontawesome.com/search

4.3. removebg

https://www.remove.bg/zh/upload

4.4. convertio

https://convertio.co/zh/

4.5. iloveimg

https://www.iloveimg.com/zh-cn/compress-image/compress-jpg

  • Title: Obsidian => Cos => Hexo 同步部署
  • Author: sound_kanade
  • Created at : 2024-10-15 00:00:00
  • Updated at : 2025-03-11 12:47:05
  • Link: https://blog.megumiai.com/deploy/obsidian_cos_hexo.html
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments