added 文章一篇
This commit is contained in:
1 parent
558020036f
commit
f1865dca6c
9 files changed
+478
-151
No files matched your search
@@ -0,0 +1,141 @@
|
||||
---
|
||||
title: "博客友链实时健康监测方案"
|
||||
date: 2026-02-01T10:00:00+08:00
|
||||
draft: false
|
||||
categories: ["技术"]
|
||||
tags: ["GitHub Actions", "Node.js", "博客优化", "自动化"]
|
||||
---
|
||||
|
||||
最近给博客加上了一个实用的功能:**友链实时健康监测**。
|
||||
|
||||
起因是备案审查越来越严格。对于个人博客来说,如果友链中的某个域名过期被抢注,摇身一变成为博彩或色情网站,而我的博客还挂着它的链接,那么我的域名很有可能因为“导流违规内容”而被注销备案,甚至面临关站风险。
|
||||
|
||||
为了避免这种“人在家中坐,锅从天上来”的情况,手动每天一个个点开检查显然是不现实的。于是,利用 GitHub Actions 和简单的 Node.js 脚本实现自动化监测,就成了最佳解决方案。
|
||||
|
||||
## 实现思路
|
||||
|
||||
整体流程非常简单,分为三个环节:
|
||||
|
||||
1. **数据源**:读取博客现有的友链配置文件(YAML 格式)。
|
||||
2. **监测脚本**:编写 Node.js 脚本,批量请求友链地址,检测 HTTP 状态码。
|
||||
3. **自动化运行**:通过 GitHub Actions 定时执行脚本,生成状态报告(JSON),并在前端展示。
|
||||
|
||||
## 1. 编写监测脚本
|
||||
|
||||
首先,在博客根目录的 `scripts` 文件夹下创建一个 `check_links.js`。我们需要用到 `axios` 来发送请求,`js-yaml` 来读取友链数据。
|
||||
|
||||
这个脚本的核心逻辑是:
|
||||
- 读取 `themes/Ying/data/links.yaml`。
|
||||
- 对每个链接发起 `HEAD` 请求(如果失败则重试 `GET`)。
|
||||
- 如果状态码在 200-400 之间,判定为存活(True),否则为挂了(False)。
|
||||
- 将结果保存为 `static/link_status.json`。
|
||||
|
||||
```javascript
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
const axios = require('axios');
|
||||
const path = require('path');
|
||||
|
||||
// 配置文件路径
|
||||
const linksPath = path.join(__dirname, '../themes/Ying/data/links.yaml');
|
||||
// 输出结果路径(直接输出到 static 目录,Hugo 构建时会直接复制到根目录)
|
||||
const outputPath = path.join(__dirname, '../static/link_status.json');
|
||||
|
||||
async function checkLinks() {
|
||||
try {
|
||||
const fileContents = fs.readFileSync(linksPath, 'utf8');
|
||||
const data = yaml.load(fileContents);
|
||||
const results = {};
|
||||
|
||||
// 遍历所有友链
|
||||
const blogs = data.blogs;
|
||||
for (const blog of blogs) {
|
||||
try {
|
||||
// 优先使用 HEAD 请求节省流量
|
||||
await axios.head(blog.url, { timeout: 10000 });
|
||||
results[blog.url] = true;
|
||||
console.log(`[OK] ${blog.name}`);
|
||||
} catch (error) {
|
||||
// HEAD 失败尝试 GET
|
||||
try {
|
||||
await axios.get(blog.url, { timeout: 10000 });
|
||||
results[blog.url] = true;
|
||||
console.log(`[OK] ${blog.name} (GET)`);
|
||||
} catch (err2) {
|
||||
results[blog.url] = false;
|
||||
console.log(`[FAIL] ${blog.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(outputPath, JSON.stringify(results, null, 2));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
checkLinks();
|
||||
```
|
||||
|
||||
## 2. 配置 GitHub Actions
|
||||
|
||||
脚本写好了,需要让它动起来。修改 `.github/workflows/upy.yml`(或者你的部署流程文件),在 Hugo 构建之前加入监测步骤。
|
||||
|
||||
这样每次博客更新,或者定时触发时,都会生成最新的 `link_status.json`。
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
deploy:
|
||||
steps:
|
||||
# ... 前置环境配置 ...
|
||||
|
||||
- name: Check Link Status
|
||||
run: node scripts/check_links.js
|
||||
|
||||
- name: Build
|
||||
run: hugo --minify
|
||||
```
|
||||
|
||||
为了保证数据的实时性,建议配置 `schedule` 定时触发:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */12 * * *' # 每12小时自动检查一次
|
||||
```
|
||||
|
||||
## 3. 前端展示状态
|
||||
|
||||
最后一步,在前端 JS 中读取这个 JSON 文件,并根据状态给友链添加样式。
|
||||
|
||||
我在 `main.js` 中加入了如下逻辑:
|
||||
1. `fetch('/link_status.json')` 获取状态。
|
||||
2. 遍历页面上的友链元素。
|
||||
3. 如果状态为 `true`,添加绿色圆点;如果为 `false`,添加红色圆点。
|
||||
|
||||
```javascript
|
||||
// 伪代码示例
|
||||
fetch('/link_status.json')
|
||||
.then(response => response.json())
|
||||
.then(statusMap => {
|
||||
document.querySelectorAll('.friend-link-item').forEach(item => {
|
||||
const url = item.getAttribute('href');
|
||||
if (statusMap[url] === false) {
|
||||
item.classList.add('dead-link'); // 样式控制显示红点
|
||||
} else {
|
||||
item.classList.add('active-link'); // 样式控制显示绿点
|
||||
}
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
配合 CSS,就能实现如下效果:
|
||||
- 🟢 **绿色**:网站可访问,安心。
|
||||
- 🔴 **红色**:网站无法访问,需要重点关注。
|
||||
|
||||
## 总结
|
||||
|
||||
这套方案最大的好处是**零成本、自动化**。不需要额外部署监控服务,完全利用 GitHub Actions 的计算资源。
|
||||
|
||||
对于注重 SEO 和网站安全的博主来说,这是一个性价比极高的“基建”工作。既对自己负责,也对访客负责。毕竟,谁也不想点击一个链接后发现是 404,或者跳转到奇怪的页面吧。
|
||||
Reference in new issue
Block a user