自动发布学习笔记
学习笔记有几十个, 平时更新频繁, 内容更新之后往往没有发布最新内容.
因此还是需要一个自动发布的机制, 定期检查各个学习笔记有没有更新, 如果有则触发发布流程, 将最新的内容发布到 nginx 下.
目录结构
学习笔记的父目录一般为 /home/sky/work/code/learning/ , 子目录为 “learning-” 开头的几十个文件夹, 每个子目录是一个独立的 git 仓库.
如:
$ pwd
/home/sky/work/code/learning
$ ls -l
total 196
drwxr-xr-x 9 sky sky 4096 Oct 9 20:15 learning-golang
drwxr-xr-x 9 sky sky 4096 Oct 21 10:33 learning-grpc
drwxr-xr-x 10 sky sky 4096 Oct 21 10:26 learning-hugo
drwxr-xr-x 9 sky sky 4096 Oct 21 10:29 learning-inoreader
drwxr-xr-x 9 sky sky 4096 Oct 21 10:26 learning-java-aot
drwxr-xr-x 9 sky sky 4096 Oct 21 10:29 learning-jdk
drwxr-xr-x 9 sky sky 4096 Oct 21 10:24 learning-kuasar
drwxr-xr-x 9 sky sky 4096 Oct 21 10:33 learning-linux-mint
......
脚本内容(串行版本)
串行版本是一个接一个的处理子目录, 因为子目录比较多,所以速度有点慢:
vi /home/sky/work/code/learning/auto_publish.sh
内容为:
#!/bin/bash
# 自动检查并发布 learning-* 子目录
# 运行环境: Debian 12/13
BASE_DIR="/home/sky/work/code/learning"
PUBLISH_SCRIPT="$BASE_DIR/publish.sh"
# 遍历所有以 learning- 开头的子目录
for repo in "$BASE_DIR"/learning-*; do
if [ -d "$repo/.git" ]; then
cd "$repo" || continue
echo ">>> 检查仓库: $(basename "$repo")"
# 获取远程更新
git fetch origin &>/dev/null
# 判断是否有更新
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse @{u} 2>/dev/null)
BASE=$(git merge-base @ @{u} 2>/dev/null)
if [ "$LOCAL" = "$REMOTE" ]; then
echo " 已是最新,无需更新"
elif [ "$LOCAL" = "$BASE" ]; then
echo " 检测到远程更新,执行 git pull..."
git pull --ff-only
echo " 调用发布脚本..."
"$PUBLISH_SCRIPT" "$(basename "$repo")"
elif [ "$REMOTE" = "$BASE" ]; then
echo " 本地有未推送的提交,跳过发布"
else
echo " 本地与远程有分歧,请手动处理"
fi
fi
done
增加执行属性:
chmod +x /home/sky/work/code/learning/auto_publish.sh
跑起来确实比较慢,因为子目录太多了(30上下). 不过可以清晰的看到哪个仓库有更新.
脚本内容(并行版本)
并行版本同时检查所有子目录的更新情况, 好处是执行起来特别快,尤其大部分情况下子目录都是没有内容更新的:
vi /home/sky/work/code/learning/auto_publish_parallel.sh
内容为:
#!/bin/bash
# 自动检查并发布 learning-* 子目录 (并发版本)
# 运行环境: Debian 12/13
BASE_DIR="/home/sky/work/code/learning"
PUBLISH_SCRIPT="$BASE_DIR/publish.sh"
check_and_publish() {
repo="$1"
cd "$repo" || exit 1
repo_name=$(basename "$repo")
echo ">>> 检查仓库: $repo_name"
# 获取远程更新
git fetch origin &>/dev/null
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse @{u} 2>/dev/null)
BASE=$(git merge-base @ @{u} 2>/dev/null)
if [ "$LOCAL" = "$REMOTE" ]; then
echo " [$repo_name] 已是最新"
elif [ "$LOCAL" = "$BASE" ]; then
echo " [$repo_name] 检测到远程更新,执行 git pull..."
git pull --ff-only
echo " [$repo_name] 调用发布脚本..."
"$PUBLISH_SCRIPT" "$repo_name"
elif [ "$REMOTE" = "$BASE" ]; then
echo " [$repo_name] 本地有未推送的提交,跳过发布"
else
echo " [$repo_name] 本地与远程有分歧,请手动处理"
fi
}
export -f check_and_publish
export BASE_DIR PUBLISH_SCRIPT
# 遍历所有 learning-* 子目录并发执行
for repo in "$BASE_DIR"/learning-*; do
if [ -d "$repo/.git" ]; then
check_and_publish "$repo" &
fi
done
# 等待所有后台任务完成
wait
echo ">>> 所有仓库检查完成"
增加执行属性:
chmod +x /home/sky/work/code/learning/auto_publish_parallel.sh
手工执行:
/home/sky/work/code/learning/auto_publish_parallel.sh
输出为:
$ ./auto_publish_parallel.sh
>>> 检查仓库: learning-ai-agent
>>> 检查仓库: learning-durabletask
>>> 检查仓库: learning-golang
>>> 检查仓库: learning-computer-hardware
>>> 检查仓库: learning-debian
>>> 检查仓库: learning-grpc
>>> 检查仓库: learning-cloudstate
>>> 检查仓库: learning-esxi
>>> 检查仓库: learning-distributed-state
>>> 检查仓库: learning-datamesh
>>> 检查仓库: learning-inoreader
>>> 检查仓库: learning-mockito
>>> 检查仓库: learning-macos
>>> 检查仓库: learning-git
>>> 检查仓库: learning-openwrt
>>> 检查仓库: learning-cloud-hypervisor
>>> 检查仓库: learning-kuasar
>>> 检查仓库: learning-distributed-transaction
>>> 检查仓库: learning-linux-mint
>>> 检查仓库: learning-hugo
>>> 检查仓库: learning-python
>>> 检查仓库: learning-jdk
>>> 检查仓库: learning-rust
>>> 检查仓库: learning-java-aot
>>> 检查仓库: learning-tokio
>>> 检查仓库: learning-spring-cloud
>>> 检查仓库: learning-ubuntu-server
>>> 检查仓库: learning-windows-server
>>> 检查仓库: learning-windows11
>>> 检查仓库: learning-photoshop
>>> 检查仓库: learning-pve
>>> 检查仓库: learning-serverless
>>> 检查仓库: learning-vscode
[learning-jdk] 已是最新
[learning-grpc] 已是最新
[learning-kuasar] 已是最新
[learning-windows-server] 已是最新
[learning-computer-hardware] 已是最新
[learning-vscode] 已是最新
[learning-cloudstate] 已是最新
[learning-hugo] 已是最新
[learning-windows11] 已是最新
[learning-mockito] 已是最新
[learning-java-aot] 已是最新
[learning-tokio] 已是最新
[learning-esxi] 已是最新
[learning-cloud-hypervisor] 已是最新
[learning-python] 已是最新
[learning-rust] 已是最新
[learning-durabletask] 已是最新
[learning-golang] 已是最新
[learning-pve] 已是最新
[learning-inoreader] 已是最新
[learning-macos] 已是最新
[learning-linux-mint] 已是最新
[learning-spring-cloud] 已是最新
[learning-openwrt] 已是最新
[learning-distributed-state] 已是最新
[learning-debian] 已是最新
[learning-git] 已是最新
[learning-ubuntu-server] 已是最新
[learning-distributed-transaction] 已是最新
[learning-datamesh] 已是最新
[learning-serverless] 已是最新
[learning-photoshop] 已是最新
[learning-ai-agent] 已是最新
>>> 所有仓库检查完成
没有内容更新的情况下, 大概15到20秒就检查完成,速度快多了.
如果多个仓库同时更新, 可能会有并发执行发布人物的性能问题,不过通常我不太会在10分钟内更新多个仓库的内容,所以就不额外处理了(比如设置最大并发数)
设置定时任务
设置定时任务, 每 10 分钟执行一次.
编辑 crontab:
crontab -e
添加一行:
*/10 * * * * /bin/bash /home/sky/work/code/learning/auto_publish_parallel.sh >> /home/sky/work/code/learning/auto_publish_parallel.log 2>&1
这样脚本会每 10 分钟运行一次,并把日志写到 auto_publish.log。
如果不想打印日志:
*/10 * * * * /bin/bash /home/sky/work/code/learning/auto_publish_parallel.sh >/dev/null 2>&1
注意: 用 sky 帐号执行 crontab -e,不要用 root 帐号或者 sudo 执行 crontab -e, 那样编辑的是 root 帐号的 cron,执行命令是用的是 root 用户来执行自动发布版本. 而我的 git 仓库一般都是用 sky 帐号 clone 的. 在新版本的 git 中会报错:
fatal: detected dubious ownership in repository at '/home/sky/work/code/learning/learning-windows-server'
To add an exception for this directory, call:
git config --global --add safe.directory /home/sky/work/code/learning/learning-windows-server
全部发布
有时自动发布脚本因故没能成功执行,而因为 git pull 已经执行,git 的更新已经拉到本地,导致不会激活内容的发布。
因此,新增一个全部发布的脚本,手动执行,强制发布所有内容。作为必要时的补充。
cd /home/sky/work/code/learning
vi all_publish.sh
内容为:
#!/bin/bash
# 自动拉取并发布 learning-* 子目录(带错误处理)
# 运行环境: Debian 12/13
BASE_DIR="/home/sky/work/code/learning"
PUBLISH_SCRIPT="$BASE_DIR/publish.sh"
# 遍历所有以 learning- 开头的子目录
for repo in "$BASE_DIR"/learning-*; do
if [ -d "$repo/.git" ]; then
cd "$repo" || continue
echo ">>> 仓库: $(basename "$repo")"
echo " 执行 git pull..."
if git pull --ff-only; then
echo " git pull 成功,调用发布脚本..."
if "$PUBLISH_SCRIPT" "$(basename "$repo")"; then
echo " 发布成功"
else
echo " 发布脚本执行失败,跳过"
fi
else
echo " git pull 失败,跳过发布"
fi
fi
done
增加执行属性:
chmod +x all_publish.sh
手工执行:
./all_publish.sh