【博客】使用GithubAction自動同步obisidian和hexo倉庫

使用Github Action自動同步obisidian和hexo倉庫,避免手動操作。

本文首發于?慕雪的寒舍

1. 煩惱

先來說說慕雪現在的筆記和博客是怎么管理的吧,我正在使用兩套筆記軟件

  • 思源筆記:私密性高一些,不是博客的筆記都在這里面。由于思源筆記不是markdown編輯器,不能直接和hexo對接;
  • obisdian:專門管理hexo的博客;

然后我的hexo博客和obsidian又有分離,hexo配置倉庫是一個單獨的git倉庫(后文簡稱為hexo倉庫),obsidian博客庫也是一個單獨的git倉庫(后文簡稱為obisidian倉庫)。

我采用的操作特別繁瑣,步驟如下:

  1. 在obsidian里面寫好博客之后,手動使用FreeFileSync軟件,將obisidian/blog目錄同步到hexo/source/_posts目錄中(這兩個目錄完全一樣);
  2. 然后再到hexo本地倉庫中執行hexo三板斧命令,給新的博客生成abbrlink,push到hexo的github倉庫;
  3. 再用FreeFileSync反向將hexo/source/_posts目錄同步回obisidian/blog目錄,因為新的博客會多出abbrlink;

是不是聽起來都頭大了?

2. 曾經的想法

先前我一直在想怎么讓這套流程簡化,考慮過幾個方案都不太滿意。我想過直接把obsidian vaults丟到hexo/source/_posts目錄里面,但是考慮到我的obsidian中還有博客模板這種不需要上傳到博客里面的內容,此項并不方便(雖然hexo其實可以跳過渲染某些md文件)

現在就想出了自動化的方案,也就是用github action來同步obsidian和hexo的倉庫,當obisidian/blog目錄有變動的時候,觸發action,自動將這個目錄的內容拷貝到hexo/source/_posts倉庫目錄中,并push到hexo倉庫。

這里就有一個問題,abbrlink是基于hexo插件生成的,如果用這種方式那就沒辦法給新的博客md文件生成一個固定abbrlink了。不管是怎么讓github action執行hexo g命令,最后都會出現遠程倉庫md文件中有abbrlink,但本地需要pull才能更新的問題,這會對我后續的博客編寫和git操作帶來不便(畢竟之前都是無腦push上去的)

之前每次想折騰github action的時候就會發現這個問題(由于沒記筆記導致折騰的時候忘記了之前為啥沒搞定……),然后又不了了之。

今天突然想起來,既然問題是在abbrlink插件上,那我不用hexo來生成abbrlink不就行了?反正abbrlink本質上和隨機數沒啥關系,我只要給新的博客手動加上一個和其他博客不沖突的abbrlink不就ok了?

注:hexo的abbrlink插件是通過crc16/crc32算法計算得到文件的abbrlink的,并非隨機數生成。但對于abbrlink的作用來看,只要博客上每個文章都有一個獨立的abbrlink其實就夠了,所以abbrlink說它是隨機數也沒啥問題。

解決方法明了:用別的方法給新博客生成abbrlink,然后再用github action自動化同步obsidian倉庫和hexo倉庫。

3. 解決步驟

3.1. 生成abbrlink的python腳本

其實obsidian中是有一個abbrlink插件的,首先感謝插件作者能提供一個hexo-abbrlink插件的替代品。但是,這個插件不太符合本人的需求,因為它直接針對于obsidian全局,會把我的其他文件以及博客模板文件都加上abbrlink。

折騰了一會后,感覺不如返璞歸真,直接寫個python腳本,把所有博客文件的abbrlink遍歷出來,然后生成30個不沖突的abbrlink寫入到一個文件里面,每次寫新博客的時候從這個文件里面取一個abbrlink出來用就完事啦!

說干就干,GPT,啟動!

# 生成不沖突的abbrlink
import yaml
import re
import os
import randomMD_FILE_PATH = '../../Notes/CODE'
"""博客md文件路徑"""
NEW_ABBRLINK_SIZE = 20
"""生成幾個abbrlink"""
NEW_ABBRLINK_MD_FILE = '../../Notes/ABBRLINK歸檔.md'
"""生成的abbrlink寫入這個md文件里面"""def extract_front_matter(file_path):"""提取 Markdown 文件中的 front-matter 內容。假設 front-matter 是以 '---' 包圍的 YAML 格式內容。"""with open(file_path, 'r', encoding='utf-8') as file:content = file.read()# 使用正則表達式匹配 front-mattermatch = re.match(r'---\n(.*?)\n---\n', content, re.DOTALL)if match:front_matter = match.group(1)return yaml.safe_load(front_matter)  # 使用 yaml 解析 front-matterelse:return Nonedef remove_front_matter(file_path):"""移除 Markdown 文件中的 front-matter 部分,返回去除 front-matter 后的內容。"""with open(file_path, 'r', encoding='utf-8') as file:content = file.read()# 使用正則表達式去除 front-mattercleaned_content = re.sub(r'---\n(.*?)\n---\n', '', content, flags=re.DOTALL)return cleaned_contentdef update_front_matter(file_path, new_front_matter):"""更新 Markdown 文件中的 front-matter 內容。"""with open(file_path, 'r+', encoding='utf-8') as file:content = file.read()# 使用正則表達式替換 front-matternew_front_matter_str = yaml.dump(new_front_matter, default_flow_style=False)content = re.sub(r'---\n(.*?)\n---\n', f'---\n{new_front_matter_str}\n---\n', content, flags=re.DOTALL)# 寫回文件with open(file_path, 'w', encoding='utf-8') as file:file.write(content)def extract_front_matter_from_dir(directory_path):"""遍歷指定目錄及其子目錄下的所有 .md 文件,提取它們的 front-matter 內容,并將所有內容添加到列表中。"""front_matter_list = []# 遍歷目錄中的所有文件和子目錄for root, dirs, files in os.walk(directory_path):for filename in files:file_path = os.path.join(root, filename)# 只處理 .md 文件if filename.endswith('.md'):front_matter = extract_front_matter(file_path)if front_matter:front_matter_list.append(front_matter)return front_matter_listdef generate_unique_10digit_numbers(existing_numbers, n):"""生成 n 個不在 existing_numbers 列表中的 10 位數字。:param existing_numbers: 已存在的整數列表:param n: 需要生成的數字數量:return: 不重復的 10 位數字列表"""unique_numbers = set(existing_numbers)  # 將現有的數字轉換為集合,加速查找generated_numbers = []# 如果現有數字數量已經非常大,可能無法生成足夠的唯一數字if len(unique_numbers) > 9999999999 - 1000000000:return Nonewhile len(generated_numbers) < n:num = random.randint(1000000000, 9999999999)  # 隨機生成一個10位數字if num not in unique_numbers:generated_numbers.append(num)unique_numbers.add(num)  # 將新生成的數字添加到現有數字集合中return generated_numbersdef write_int_list_to_md(file_path, int_list):"""將整數列表的成員按行寫入一個Markdown文件。:param file_path: Markdown文件的路徑:param int_list: 要寫入文件的整數列表"""with open(file_path, 'w', encoding='utf-8') as file:for number in int_list:file.write(f"{number}\n")  # 每個數字寫一行# 示例使用
if __name__ == "__main__":# 假設 markdown 文件目錄路徑為 "../../Notes/CODE"file_path = MD_FILE_PATH# 提取所有 .md 文件的 front-matterfront_matter_list = extract_front_matter_from_dir(file_path)# 打印所有文件的 front-matterif not front_matter_list:print("沒有找到 front-matter 或目錄為空。")os.abort()abbrlink_list = []for fm in front_matter_list:# print(f"文件的 front-matter 內容:", fm)if 'abbrlink' not in fm:print(f"ERR! abbrlink not in {fm}")continuelink = int(fm['abbrlink'])if link in abbrlink_list:print(f"ERR! {link} in abbrlink list!")continueabbrlink_list.append(link)# 獲取新的abbrlinknew_abbrlink = generate_unique_10digit_numbers(abbrlink_list, NEW_ABBRLINK_SIZE)for link in new_abbrlink:print(link)print("Gen abbrlink success")write_int_list_to_md(NEW_ABBRLINK_MD_FILE, new_abbrlink)print("Write abbrlink to", NEW_ABBRLINK_MD_FILE)

腳本運行效果如下,會生成新的abbrlink鏈接數字,然后寫入到指定的md文件中。這樣在obsidian里面就能看到這個md文件,取用里面的abbrlink了。用完了之后再手動執行一下腳本更新abbrlink就完事啦。

? python3 gen_abbrlink.py
8608489065
7885829874
8484489314
4284761477
1589125738
9151131777
4800824161
7141292217
2714461943
5131440419
2816690027
9574459795
6572894529
2920325088
2724835080
7631222809
1802821635
3120273636
2860205445
3100823185
Gen abbrlink success
Write abbrlink to ../../Notes/ABBRLINK歸檔.md

3.2. Github Action配置

接下來就是配置Github Action來同步兩個倉庫了。讓GPT寫了個大概,發現GPT在瞎說,它給出https的倉庫clone鏈接,并表示用自帶的GITHUB_TOKEN就能克隆私有倉庫了,但實際上完全沒用。最后還是得用老辦法ssh密鑰對來實現。

首先使用如下命令生成一個ssh密鑰,彈出的提示中填寫一個文件名字(不然會覆蓋默認目錄的ssh密鑰對)

ssh-keygen -t rsa -C "github action" 

然后,搞清楚同步的方向,我的需要是將obsidian倉庫中的內容同步到hexo倉庫,所以公鑰放在hexo倉庫,私鑰放在obsidian倉庫中。

在hexo倉庫(被推送的倉庫)中,倉庫設置Settings->Deploy keys->Add deploy key添加公鑰,命名為HEXO_PUB_KEY注意需要勾選允許write寫入倉庫,不然默認權限只允許pull和clone倉庫。

在obsidian倉庫中,倉庫設置Settings->Secrets and variables->Secrets添加私鑰,命名為HEXO_PRI_KEY

最后的Github Action Workflow文件如下,將該文件寫入obsidian倉庫的.github/workflows/sync-code-to-posts.yml即可,每個步驟都寫了注釋。

name: Sync CODE to _postson:push:paths:- 'Notes/CODE/**' # 監聽 CODE 文件夾內的文件變化,沒有變化不會觸發actionjobs:sync:runs-on: ubuntu-lateststeps:      # 檢出 obsidian 倉庫的代碼- name: Checkout muob repositoryuses: actions/checkout@v3# 設置 Git 配置- name: Set up Gitenv:ACTIONS_KEY: ${{ secrets.HEXO_PRI_KEY }}run: |mkdir -p ~/.ssh/echo "$ACTIONS_KEY" > ~/.ssh/id_rsachmod 700 ~/.sshchmod 600 ~/.ssh/id_rsassh-keyscan github.com >> ~/.ssh/known_hostsgit config --global user.name "musnows"git config --global user.email "ezplayingd@126.com"git config --global core.quotepath falsegit config --global i18n.commitEncoding utf-8 git config --global i18n.logOutputEncoding utf-8 # 克隆 HexoBlog 倉庫(私有倉庫),使用 ssh 來進行認證- name: Checkout HexoBlog repositoryrun: |git clone git@github.com:musnows/Hexo-Blog.git HexoBlog# 同步文件:將 obsidain 倉庫中的 CODE 文件夾內容復制到 HexoBlog 倉庫的 _posts 文件夾- name: Sync files from CODE to _postsrun: |rsync -av --delete Notes/CODE/ HexoBlog/source/_posts/# 提交更改并推送到 HexoBlog 倉庫- name: Commit and push changes to HexoBlog repositoryrun: |cd HexoBloggit add .git commit -m "Sync CODE to _posts at $(TZ='Asia/Shanghai' date '+%Y-%m-%d %H:%M:%S')"git push origin hexo

第二步的Git操作中,我們將倉庫配置的secrets.HEXO_PRI_KEY映射成環境變量ACTIONS_KEY,然后寫入執行action的ubuntu環境的~/.ssh/id_rsa私鑰文件中,這樣就能操作另外一個倉庫了。

第四步的Sync操作使用了rsync命令

rsync -av --delete 源文件夾 目標文件夾

解釋一下這里的幾個命令參數,-a用于保持文件的原有屬性,-v代表verbose,會輸出詳細的日志,--delete用于在目標目錄中刪除源目錄中不存在的文件(同步刪除操作)。

4. 測試效果

我在目錄中創建了一個測試文件,push到了遠端倉庫中,觸發了action

image.png

hexo配置倉庫成功被push了,有更新的文件也是在obsidain倉庫中被修改的文件,符合預期。

image.png

這樣就搞定啦!以后我只需要push博客到obsidian倉庫中,就能自動同步到hexo倉庫內了。不需要手動做那部分繁瑣的操作

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76160.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76160.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76160.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

scala簡介和基礎語法

Scala簡介 Scala 是一門多范式&#xff08;multi-paradigm&#xff09;的編程語言&#xff0c;設計初衷是要集成面向對象編程和函數式編程的各種特性。 Scala 運行在 Java 虛擬機上&#xff0c;并兼容現有的 Java 程序。Scala 源代碼被編譯成 Java 字節碼&#xff0c;所以它可…

7.4考研408數據結構B樹與B+樹專題深度解析

考研408數據結構B樹與B+樹專題深度解析 一、B樹(B-Tree) 1.1 定義與性質 定義: B樹是一種平衡多路查找樹,滿足以下條件: 階數:每個結點最多有 m m m個子樹( m ≥

WEB安全--RCE--RCE的危險函數

一、命令執行 1.1、命令執行原理 <?php $cmd $_GET[cmd]; // 直接獲取用戶輸入 system($cmd); // 不安全 ?>#payload: http://example.com/vuln.php?cmdwhoami#結果: www-data 1.2、危險函數 1.2.1、system() 介紹&#xff1a; 執行外部命令&#xff0c;將命令…

Linux C++ 利用 io_uring 技術批量讀取 tun 文件描述符的數據。

以下是參考的實現代碼&#xff0c;IO_URING 操作必須要進行按頁大小對齊&#xff08;僅在O_DIRECT直接I/O下&#xff09;&#xff0c;不能是非對稱的&#xff0c;一般大多數操作系統頁大小為&#xff1a;4KB。 批量讀取、writev 批量簡寫。 static constexpr int MTU ITap::M…

時序數據庫:InfluxDB命令行操作

學習 InfluxDB 的命令行操作至關重要&#xff0c;它不僅是與數據庫直接交互的工具&#xff0c;也是理解 InfluxDB 核心概念的關鍵途徑。通過命令行&#xff0c;用戶可以高效地執行數據庫管理、數據查詢和插入等任務&#xff0c;深入掌握 InfluxQL 的語法及功能。這對于調試、快…

Bootstrap 表格:高效布局與動態交互的實踐指南

Bootstrap 表格:高效布局與動態交互的實踐指南 引言 Bootstrap 是一個流行的前端框架,它為開發者提供了豐富的組件和工具,使得構建響應式、美觀且功能豐富的網頁變得更加簡單。表格是網頁中常見的元素,用于展示數據。Bootstrap 提供了強大的表格組件,可以幫助開發者輕松…

⑥ ACG-系統管理

上網管理行為是指對員工在工作時間內使用公司網絡的行為進行管理和監督。在企業中&#xff0c;系統管理是實施上網管理行為的重要方式之一。系統管理包括以下幾個方面&#xff1a; 1. 訪問控制&#xff1a;通過設置網絡訪問權限&#xff0c;對員工訪問特定網站或使用特定應用程…

【Docker】Dockerfile 優化工具 hadolint

本文內容均來自個人筆記并重新梳理&#xff0c;如有錯誤歡迎指正&#xff01; 如果對您有幫助&#xff0c;煩請點贊、關注、轉發、訂閱專欄&#xff01; 專欄訂閱入口 | 精選文章 | Kubernetes | Docker | Linux | 羊毛資源 | 工具推薦 | 往期精彩文章 【Docker】&#xff08;全…

接口自動化——初識pytest

縮寫單詞含義.passed通過Ffailed失敗&#xff08;用例執行時報錯&#xff09;Eerror出錯&#xff08;fixture執行報錯&#xff09;sskipped跳過Xxpassed預期外的通過&#xff08;不符合預期&#xff09;xxfailed預期內的失敗&#xff08;符合預期&#xff09; 1.pytest 配置 1…

leetcode日記(100)填充每個節點的下一個右側節點指針

和層序遍歷差不多的思路&#xff0c;將節點儲存在隊列里&#xff0c;一邊取出節點一邊放入取出節點的左右節點&#xff0c;直到隊列空。 /* // Definition for a Node. class Node { public:int val;Node* left;Node* right;Node* next;Node() : val(0), left(NULL), right(NU…

MySQL配置文件my.cnf詳解

目前使用的服務器系統是CentOS8.5 ,針對MySql8.4的配置示例&#xff0c;自己根據實際情況修改。 安裝MySql8.4時&#xff0c;MySql8.4沒有默認的my.cnf,需要用戶根據需要自行配置my.cnf文件&#xff0c;大概可看到下面這樣的參數列表&#xff0c;可能不同版本的mysql參數多少會…

【解決】XCode不支持舊版本的iOS設備

辦法&#xff1a; 手動添加設備支持文件&#xff08;暫時解決方式&#xff09; 如果您無法立即升級 Xcode&#xff0c;也可以通過下載設備支持文件來暫時解決問題。 檢查當前設備的 iOS 版本&#xff1a; 連接設備到 Mac&#xff0c;打開 Xcode 查看提示的 iOS 版本。例如&…

每日c/c++題 備戰藍橋杯(全排列問題)

題目描述 按照字典序輸出自然數 1 到 n 所有不重復的排列&#xff0c;即 n 的全排列&#xff0c;要求所產生的任一數字序列中不允許出現重復的數字。 輸入格式 一個整數 n。 輸出格式 由 1~n 組成的所有不重復的數字序列&#xff0c;每行一個序列。 每個數字保留 5 個場…

注意力蒸餾技術

文章目錄 摘要abstract論文摘要簡介方法預備知識注意力蒸餾損失注意力引導采樣 實驗結論總結參考文獻 摘要 本周閱讀了一篇25年二月份發表于CVPR 的論文《Attention Distillation: A Unified Approach to Visual Characteristics Transfer》,論文開發了Attention Distillation…

flutter android端抓包工具

flutter做的android app&#xff0c;使用fiddler抓不了包&#xff0c;現介紹一款能支持flutter的抓包工具Reqable&#xff0c;使用方法如下&#xff1a; 1、下載電腦端安裝包 下載地址為【https://reqable.com/zh-CN/download/】 2、還是在上述地址下載 android 端apk&#xf…

PyTorch單機多卡訓練(DataParallel)

PyTorch單機多卡訓練 nn.DataParallel 是 PyTorch 中用于多GPU并行訓練的一個模塊&#xff0c;它的主要作用是將一個模型自動拆分到多個GPU上&#xff0c;并行處理輸入數據&#xff0c;從而加速訓練過程。以下是它的核心功能和工作原理&#xff1a; 1、主要作用 數據并行&am…

PyTorch中的Tensor

PyTorch中的Tensor? 是核心數據結構&#xff0c;類似于 NumPy 的多維數組&#xff0c;但具備 GPU 加速和自動求導等深度學習特性。 一、基本概念 ?核心數據結構? Tensor 是存儲和操作數據的基礎單元&#xff0c;支持標量&#xff08;0D&#xff09;、向量&#xff08;1D&am…

基于Python的圖書館信息管理系統研發

標題:基于Python的圖書館信息管理系統研發 內容:1.摘要 在數字化信息快速發展的背景下&#xff0c;傳統圖書館管理方式效率低下&#xff0c;難以滿足日益增長的信息管理需求。本研究旨在研發一款基于Python的圖書館信息管理系統&#xff0c;以提高圖書館信息管理的效率和準確性…

RCE復現

1.過濾flag <?php error_reporting(0); if(isset($_GET[c])){$c $_GET[c];if(!preg_match("/flag/i", $c)){eval($c);}}else{highlight_file(__FILE__);代碼審計過濾了"flag"關鍵詞&#xff0c;但限制較弱&#xff0c;容易繞過 ?csystem("ls&…

FPGA_YOLO(四) 部署yolo HLS和Verilog 分別干什么

首先,YOLO作為深度學習模型,主要包括卷積層、池化層、全連接層等。其中,卷積層占據了大部分計算量,尤其適合在FPGA上進行并行加速。而像激活函數(如ReLU)和池化層相對簡單,可能更容易用HLS實現。FPGA的優勢在于并行處理和定制化硬件加速,因此在處理這些計算密集型任務時…