本机环境
windows 11 本地 git 已经与 github 配置了对应的 SSH 密钥
需求
笔者每天的学习都会有许多的笔记内容,笔者现在实验室配有电脑,自己还有一台笔记本电脑,每次写的笔记都是写在不同的电脑上。笔者希望可以在多个设备间很好的同步笔记内容,但是笔者一来不希望对笔记软件如语雀充钱,二来出于数据安全的考虑,笔者更希望笔记内容既有存储在本地电脑上,可以通过本地文件查看,同时也在云端有所备份。
解决方案
处于上述需求
从笔记本地化考虑
那么笔记就不能用现在语雀,飞书,有道,notion 等软件进行记录
所以本地的笔记一直都用的 obsidian 和 Typora 进行配合编写使用(obsidian 管理笔记分类分库,Typora 进行具体的笔记书写)
从云端备份考虑
无论是阿里云还是百度云,一来不易于云端的在线阅读,二来这两个软件占用较高,不希望让其占用在后台,三来希望空间不受限制
出于可以在线阅读,并且空间不受限制的考虑,这里选定了使用 github 进行同步,将所有的笔记放在一个文件夹下,让这个文件夹与在 github 创建的仓库建立好连接。
现在笔者每天写完笔记后,都可以使用 git 的命令将对应的更新内容推送到远程仓库,换电脑后也只需要从云端拉取后即可。但是这里有一个问题,笔者是一个巨懒的人,不想每天写完后都输入推送命令,而且大概率会写完笔记后忘记推送这件事情。
因此笔者希望可以在电脑上设置一个或者多个定时任务,每天定时检查,然后拉取远程仓库内容,定时推送本地内容。这里选用的是 PowerShell+Windows 任务计划程序+git 的方案
由于笔者的电脑都是 windows 环境,因此写的脚本都是 powershell 的脚本 首先是每天定时检查,推送本地内容的脚本
$repoPath
表示的本地存储所有笔记内容的文件夹$logPath
表示的本地存储每次推送日志的位置
sync_to_github.ps1
(注意其中的路径换成自己电脑上面的)
# 设置脚本执行路径
$repoPath = "F:\zsbao\Obsidian\WareHouse"
$logPath = "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
$logDir = Split-Path $logPath
# 创建日志目录(如果不存在)
try {
if (!(Test-Path $logDir)) {
New-Item -ItemType Directory -Force -Path $logDir | Out-Null
"Created log directory: $logDir" | Out-File -Append $logPath
}
} catch {
Write-Error "Failed to create log directory: $_"
exit 1
}
# 设置日期时间格式
$datetime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"===== Start sync to github everyday 12:00 or 18:00 or 21:30 at $datetime =====" | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
"Starting synchronization at: $datetime" | Out-File -Append $logPath
try {
# 切换到仓库目录
Set-Location -Path $repoPath -ErrorAction Stop
"Changed directory to: $repoPath" | Out-File -Append $logPath
} catch {
"Error changing directory: $_" | Out-File -Append $logPath
exit 1
}
try {
# 添加所有更改
git add .
"Executed: git add ." | Out-File -Append $logPath
} catch {
"Error adding files: $_" | Out-File -Append $logPath
exit 1
}
# 准备提交消息(使用Here-String避免引号问题)
$commitMsg = @"
Auto sync on $datetime everyday auto commit
"@
try {
# 提交更改(捕获标准错误)
$commitOutput = git commit -m $commitMsg 2>&1
if ($LASTEXITCODE -ne 0) {
# 如果没有更改,提交会失败,这不一定是错误
if ($commitOutput -match "nothing to commit") {
"No changes to commit" | Out-File -Append $logPath
} else {
"Commit failed: $commitOutput" | Out-File -Append $logPath
exit $LASTEXITCODE
}
} else {
"Committed changes: $commitOutput" | Out-File -Append $logPath
}
} catch {
"Error during commit: $_" | Out-File -Append $logPath
exit 1
}
try {
# 推送到远程仓库
$pushOutput = git push origin main 2>&1
if ($LASTEXITCODE -ne 0) {
"Push failed: $pushOutput" | Out-File -Append $logPath
exit $LASTEXITCODE
} else {
"Pushed to origin/main: $pushOutput" | Out-File -Append $logPath
}
} catch {
"Error during push: $_" | Out-File -Append $logPath
exit 1
}
# 记录成功同步
"Successfully synced at: $datetime" | Out-File -Append $logPath
"===== End sync to github everyday 12:00 or 18:00 or 21:30 at $datetime =====" | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
然后是每天定时检查,然后拉取仓库内容的脚本 pull_or_push_sync.ps1
# 智能同步脚本:本地有变更就上传,否则拉取远程
cd "F:\zsbao\Obsidian\WareHouse"
$datetime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"===== Start Smart Sync(every day push or pull at 9AM) at $datetime =====" | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
# 获取工作区状态
$status = git status --porcelain
if ($status) {
# 有本地修改或新增,执行提交并上传
git add .
git commit -m "Auto commit from local at $datetime morning has changed, push" 2>$null
git push origin main
"Local changes detected. Committed and pushed at $datetime." | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
} else {
# 无本地修改,尝试从远程拉取
git pull origin main | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
"No local changes. Pulled from remote at $datetime." | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
}
"===== Edd Smart Sync(every day push or pull at 9AM) at $datetime =====" | Out-File -Append "F:\zsbao\Obsidian\ScheduledSynchronizationShell\logs\obsidian_sync_log.txt"
现在脚本已经设置完毕,接下来我们利用 windows 操作系统的内置的任务计划程序 (Task Scheduler),即定时任务工具,来设置定时任务
首先按 Win + R 打开“运行”,输入
taskschd.msc
进入任务计划程序,点击右侧创建基本任务
填写任务名称,描述
填写触发器相关内容(这里笔者是希望每天都进行) 注意是每隔 1 天发生一次,开始时间电脑会自动填写你创建的当前时间 然后填写定时任务的操作,由于我们是运行脚本,因此选择启动程序
点击下一页后进入具体执行内容的填写完界面
其中填写内容为
程序:powershell
添加参数:-ExecutionPolicy Bypass -File "电脑中同步脚本的目录位置\sync_to_github.ps1"
,例如 -ExecutionPolicy Bypass -File "F:\zsbao\Obsidian\ScheduledSynchronizationShell\sync_to_github.ps1"
点击完成
笔者希望每天的 12:00,18:00,21:30电脑自动推送内容到远程仓库,每天的 9:30自动从远端拉取,因此笔者创建了 4 个定时任务
bug
在运行一段时间后,笔者突然发现,有一段时间并没有正确推送 查看日志记录文件发现有报错
Push failed: fatal: unable to access 'https://github.com/xxxx/ObsidianNote.git/': Recv failure: Connection was reset
这是一个典型的 HTTPS 连接被中途重置 问题(网络/代理/证书/HTTP2 兼容性等都会触发)
这种错误一般都是我们在推送是,推送的地址使用的是仓库的 HTTPS 所造成的问题
这里我们在配置好本地与 github 的 ssh 密钥后 进入本地仓库对应的文件夹,一般里面有个. git 目录
我们把远程地址换成 SSH 的对应地址 PowerShell 里执行执行以下命令
# 1) 进到仓库目录
cd F:\zsbao\Obsidian\WareHouse
# 2) 看看现在的远端
git remote -v
# 3) 改成 SSH 形式(关键一步)
git remote set-url origin [email protected]:xxxx/ObsidianNote.git
# 4) 再确认
git remote -v
修改后,问题解决。