Merge branch 'master' of github.com:Colin-XKL/Colinx-Blog

This commit is contained in:
2022-05-27 10:39:08 +08:00
37 changed files with 1649 additions and 200 deletions

View File

@@ -14,13 +14,15 @@ jobs:
- uses: actions/checkout@v2
- name: Find and Replace Release
uses: jacobtomlinson/gha-find-replace@0.1.1
uses: jacobtomlinson/gha-find-replace@2.0.0
with:
find: "blog-1301127393.cos.ap-shanghai.myqcloud.com"
replace: "blog-1301127393.file.myqcloud.com"
include: "**/*.md"
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "Change img CDN URL"

View File

@@ -0,0 +1,47 @@
name: Azure Static Web Apps CI/CD
on:
push:
branches:
- master
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- master
jobs:
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_GLACIER_095B09E00 }}
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/" # App source code path
api_location: "" # Api source code path - optional
output_location: "public" # Built app content directory - optional
###### End of Repository/Build Configurations ######
env:
HUGO_VERSION: 0.91.2
close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
name: Close Pull Request Job
steps:
- name: Close Pull Request
id: closepullrequest
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_GLACIER_095B09E00 }}
action: "close"

View File

@@ -1,8 +1,6 @@
name: SEO check
name: MD SEO check
on:
push:
branches: [ master ]
on: [pull_request]
jobs:
seocheck:
@@ -13,7 +11,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Markdown SEO Check
uses: zentered/markdown-seo-check@v1.1.0
uses: zentered/markdown-seo-check@v1.1.5
with:
max_title_length: 70
max_description_length: 150

View File

@@ -1,2 +1,17 @@
# Colinx-Blog
[![Netlify Status](https://api.netlify.com/api/v1/badges/44687adc-b001-4295-b919-2ff15b914f37/deploy-status)](https://app.netlify.com/sites/colins-blog/deploys)
![Vercel Build Status](https://img.shields.io/github/deployments/Colin-XKL/Colinx-Blog/production?label=vercel&logo=vercel&logoColor=white)
Colin's Personal Blog http://blog.colinx.one
## Mirrors
This site has been deployed to multiple static web hosting providers, for load balacing and performance testing.
* Netlify
[colins-blog.netlify.app](https://colins-blog.netlify.app)
* Vercel
[colinx-blog.vercel.app](https://colinx-blog.vercel.app)
* CloudFlare Pages
[colinx-blog.pages.dev](https://colinx-blog.pages.dev)
* Azure Static Web
[nice-glacier-095b09e00.1.azurestaticapps.net](https://nice-glacier-095b09e00.1.azurestaticapps.net)

View File

@@ -2,6 +2,7 @@ baseurl = "/"
languageCode = "en-us"
defaultContentLanguage = "zh-cn"
defaultContentLanguageInSubdir = false
hasCJKLanguage = true
theme = "hello-friend"
paginate = 10
enableRobotsTXT = true
@@ -21,6 +22,9 @@ showReadingTime = false
# leave empty to disable, enter display text to enable
lastModDisplay = "最后修改"
rssFullText = true
# custom params
# The values nested under params: will populate the .Site.Params variable for use in templates
canonicalRelLinkBase = 'https://blog.colinx.one/'
[languages]
[languages.en]
@@ -37,12 +41,10 @@ rssFullText = true
minuteReadingTime = "min read"
dateFormatSingle = "2006-01-02"
dateFormatList = "2006-01-02"
[languages.en.params.logo]
logoText = "Colinx Blog"
logoHomeLink = "/"
# or
#
# path = "/img/your-example-logo.svg"
# alt = "Your example logo alt text"
@@ -67,7 +69,7 @@ rssFullText = true
[languages.zh-cn]
title = "Colinx Blog"
subtitle = "Colin的个人博客"
keywords = "Colin,个人博客"
keywords = "Colin,个人博客,技术,后端,Linux,前端"
copyright = ""
menuMore = "显示更多"
writtenBy = "作者"

9
content/_index.md Normal file
View File

@@ -0,0 +1,9 @@
+++
framed = true
+++
# Hi there!
Welcome to my blog👋 Check these
[💻 技术文章](/categories/%E6%8A%80%E6%9C%AF/) | [📖 My Readings](https://reading.colinx.one) | [💡 My Github](https://github.com/Colin-XKL/)

View File

@@ -4,7 +4,7 @@ date: 2019-04-08
lastmod: 2020-04-29
description: 经过两三天的折腾,从 Linux 结构及指令,到 LNMP 框架搭建,再到数据库的配置,最后端口转发 + 内网穿透,博客终于成功上线!在此将部署过程及踩过的坑记录下来,一方面是纪念,另一方面希望能够后来人提供一点帮助。
categories:
- 踩坑记
- 技术
tags:
- Blog
- 网站

View File

@@ -4,7 +4,7 @@ date: 2021-02-25
lastmod: 2021-03-30
description: 小玩具及他们的demo
categories:
- 杂记
- 技术
tags:
- 技术
- Python
@@ -22,7 +22,7 @@ tags:
> 自动分割给定的英文文本,提取词元后在数据库中搜索,根据给定的词汇量和难度等级进行筛选,只能提取阅读障碍词汇并高亮当前备考项目(如四级)的重点单词
![360截图20210206210445677](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20210330233722.jpg)
![360截图20210206210445677](https://blog-1301127393.file.myqcloud.com/BlogImgs/20210330233722.jpg)
## 知乎爬虫及JS逆向
@@ -40,7 +40,7 @@ tags:
> 1核2G学生机从2人联机频频崩溃到8人挖矿毫无压力学习了JVM GC种种对服务端程序的一些参数也渐渐熟悉。优化效果喜人总有还能压榨的性能就像资本家看手下的骡子一样hhh
![屏幕截图(12)](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205949.png)
![屏幕截图(12)](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205949.png)
@@ -48,7 +48,7 @@ tags:
> 一款跨平台的灵感素材收集与简易管理App基于Flutter构建跨平台颜值在线。
![截屏2021-03-30 23.21.32](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20210330233350.png)
![截屏2021-03-30 23.21.32](https://blog-1301127393.file.myqcloud.com/BlogImgs/20210330233350.png)
> 持续开发中附roadmap
>

View File

@@ -4,7 +4,7 @@ date: 2021-03-30
lastmod: 2021-03-30
description: Flutter 拖动排序列表与跨平台优化实践
categories:
- 教程
- 技术
tags:
- 技术
- Flutter
@@ -46,7 +46,7 @@ Flutter中实现拖动排序的列表非常简单使用官方的`ReorderableL
![截屏2021-03-30 23.04.59](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20210330234001.png)
![截屏2021-03-30 23.04.59](https://blog-1301127393.file.myqcloud.com/BlogImgs/20210330234001.png)
虽然可以实现拖动了,但是右边有一个按钮很碍眼。不过这个是用来控制拖动的,鼠标移上去才能触发拖动。
@@ -65,7 +65,7 @@ Flutter中实现拖动排序的列表非常简单使用官方的`ReorderableL
不过相应的ListTile的`onLongPress`就不能再有响应了。刚好今天完成了滑动删除的实现,现在列表也的删除、排序已经高度可用且多平台统一了。
![截屏2021-03-30 23.21.32](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20210330233350.png)
![截屏2021-03-30 23.21.32](https://blog-1301127393.file.myqcloud.com/BlogImgs/20210330233350.png)
附相关代码实现:

View File

@@ -0,0 +1,310 @@
---
title: Huginn指南为任意网站制作RSS
date: 2022-05-08
lastmod: 2022-05-08
description: 又一篇介绍使用Huginn制作RSS的教程🕶
categories:
- 技术
- 指南
tags:
- Huginn
- RSS
- 爬虫
- CSS
- 技术
---
<!-- # Huginn指南为任意网站制作RSS -->
Huginn使用多个不同功能的Agent组合搭配来实现一系列功能一个Agent可以执行特定的操作并产生一个Event你可以指定他产生的Event由哪个Agent接收处理。
比如我们需要使用WebSite Agent来爬取某个网站上的列表内容爬取后列表的每一项会生成一个Event我们可以指定一个Output Agent来接收这些Event并将其转换为RSS的格式进行输出复制Output Agent返回给你的URL就可以进行订阅啦Huginn爬取网站生成RSS的基本原理就是这样。
## Huginn爬取普通网页制作RSS
右键网页打开开发者工具屏幕会分出一部分空间显示开发者工具窗口点击左上角的按钮再把鼠标移动到页面上可以选择页面的某一个元素比如这里我们要爬取推荐文章列表推荐文章列表的每一项都有同样的样式我们可以使用CSS选择器来指定爬取该项
![image-20220508160659378](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207138.png)
该元素可以用CSS选择器`.meiwen`选择到。
**Tips:** class=xxx则使用`.xxx`,如果为id=xxx则使用`#xxx`
该标签是a标签我们可以继续限定一下条件使用`a.meiwen`
如果要限制必须是h2 标签下的带有meiwen的class属性的a标签可以使用`h2 a.meiwen`
如果要再加一个限制是列表元素li下面的h2标签里带有meiwen的class属性的a标签可以使用`li h2 a.meiwen`
添加其他附加限定条件以此类推
你也可以在右侧Style面板里点击加号添加一个自定义样式输入CSS选择器浏览器会自动高亮符合条件的网页元素你可以使用这个功能来检验你写的CSS选择器是否正确以及是不是提取的你想要的内容
![image-20220508163359806](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207716.png)
接下来在Huginn里创建一个Scenario然后点击新建一个Agent类型选择WebSite Agent填写一个名称并在最下面的配置处指定你要爬取的网页元素
> ###### **Website Agent**
>
> The Website Agent scrapes a website, XML document, or JSON feed and creates Events based on the results.
```json
url: {
css: li h2 a.meiwen
value: @href
}
```
以爬取url为例css表示使用css选择器选择网页元素value表示从哪里获取对应的值对于刚才我们选取的一个元素来说
```html
<a class="meiwen" href="/article/58030.html" title="缘起则聚,缘灭则散">缘起则聚,缘灭则散</a>
```
href属性里面的内容是他的链接title属性里面的内容则是他的标题。接下来在value中填写`@href`指定从href属性提取内容就可以取到链接地址了
> **Pro Tips:**
>
> 如果是纯文本节点或是想提取标签内嵌的文本value里可以填写`string(.)`
>
> 如果想删除多余的空格,可以使用`normalize-space(.)`
> **Pro Tips 2:**
>
> 字符串处理函数和标签属性值变量可以一起使用,如`normalize-space(@title)`可以获取该标签的title属性值并删除多余的空白字符
![image-20220508163714342](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207717.png)
接下来点击Dry Run按钮进行测试不出意外我们会得到一个json的输出里面包括我们爬取到的每一项他的url和title。
如果没有成功你可能需要删掉上面没有使用到的hovertext节点因为该项指定的内容在我们刚才的网页中并不存在。
![image-20220508164259295](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207718.png)
点击Save保存我们开始下一步输出RSS。在刚才的Scenario中再新建一个Agent选择Data Output Agent并设置他的名字和Source Agent
> ###### Data output Agent
>
> The Data Output Agent outputs received events as either RSS or JSON. Use it to output a public or private stream of Huginn data.
![image-20220508164941647](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207719.png)
**Propagate immediately**是指即时处理来自Source Agent的Event启用他方便我们调试但会略微增加服务器负载你可以自行决定是否使用。
![image-20220508165345792](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207720.png)
在secret字段中为你的这个RSS标注一个英文的名字修改title字段标注你的RSS的名字。item字段是每条文章会有的属性一般来说主要就title和link分别设置为上文我们提取的值的变量名。这里添加一个guid字段这是一篇文章的唯一标识符避免RSS阅读器读到的文章标题不同但是内容相同常见于某篇文章的标题被修改这会导致RSS阅读器内出现多篇重复文章。
此外建议增加一个link字段值设置为与爬取的网站的主域名一致避免网站内使用相对链接开头的资源无法正常加载。
![image-20220508170038722](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207721.png)
![image-20220508170115192](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207722.png)
点击Save保存回到Scenario界面第一次需要手动点击运行一下刚才的Website Agent。稍等片刻后台会进行爬取右上角会显示产生了多少个Event。再点开刚才设置的Data Output Agent查看详情vola右侧就会显示生成的RSS链接了复制以xml结尾的链接到RSS阅读器中就可以订阅啦🎉
![image-20220508170212112](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207723.png)
如果你的配置正确但是WebSite Agent又没有输出任何内容的话那么你要爬取的站点的内容应该是通过JavaScript在你带开浏览器时动态生成的。
> **Pro Tips:**
>
> 你可以右键网页在开发人员菜单中点击显示源代码然后用Ctrl+F搜索你在页面上见到的想爬取的某一条内容如果有说明该网站的页面时静态的否则说明你要爬取的内容并不是静态的。
要爬取这样的站点我们需要模拟浏览器操作执行页面上的JavaScript脚本待数据生成完毕后再使用上面的方法去爬取内容。要模拟浏览器操作这里介绍两个方案一个是利用browserless的无头浏览器另一个是使用在线PhatomJS服务。
## 使用Huginn+Browserless为动态网页生成RSS
部署了[RSS Man X](https://github.com/Colin-XKL/RSSmanX)的完整版的话默认已经包含huginn和browserless服务无需重复安装。且huginn可以通过`service.browserless:3000`访问到browserless服务。
总体步骤与上文一样不过因为被抓取的内容是通过JavaScript动态生成的所以直接使用WebSite Agent是抓取不到东西的我们需要先使用Post Agent向browserless服务发送指令让他帮我们模拟浏览器操作再将最终完整的网页返回给我们再使用WebSite Agent进行后续处理。
> ###### **Post Agent**
>
> A Post Agent receives events from other agents (or runs periodically), merges those events with the Liquid-interpolated contents of payload, and sends the results as POST (or GET) requests to a specified url. To skip merging in the incoming event, but still send the interpolated payload, set no_merge to true.
接下来以[这个网站](https://pccz.court.gov.cn/pcajxxw/pcgg/ggdh?lx=0)为例介绍一下这个列表页的内容是由JavaScript动态生成的
![image-20220508205159783](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207724.png)
按照以下内容设置你的Post Agent
```json
{
"post_url": "http://service.browserless:3000/content",
"expected_receive_period_in_days": "1",
"content_type": "json",
"method": "post",
"payload": {
"url": "https://pccz.court.gov.cn/pcajxxw/pcgg/ggdh?lx=0"
},
"headers": {
"Cache-Control": "no-cache",
"Content-Type": "application/json"
},
"emit_events": "true",
"no_merge": "false",
"output_mode": "clean"
}
```
其中`post_url`为你的browserless实例地址如果你使用了RSS MAN X里的Huginn可以直接向上面一样填写。`payload`中的`url`字段填写你需要的网页地址。注意emit_events要设置为`true`这样才方便我们后续使用WebSite Agent操作。
点击Dry Run如果能返回一个带有`body`字段且里面有文本内容说明调用成功
![image-20220508195731732](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207725.png)
接下来点击Save保存再新建一个Website AgentSource设置为刚才的Post Agent。
```json
{
"expected_update_period_in_days": "2",
"data_from_event": "{{ body }}",
"type": "html",
"mode": "on_change",
"extract": {
"url": {
"css": "ul#wslb li a",
"value": "normalize-space(@href)"
},
"title": {
"css": "ul#wslb li a",
"value": "@title"
},
"author": {
"css": "ul#wslb li div.center",
"value": "normalize-space(.)"
}
}
}
```
注意修改`data_from_event`的值其他地方与爬取普通网站一样。再新建并配置一下Output AgentRSS的链接就出来了
![image-20220508205856407](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207726.png)
## 使用PhantomJS为动态页面生成RSS
首先需要到[Phantom Js Cloud的官网](https://phantomjscloud.com)注册一个账户每个账户官方提供了一定的免费额度每天大概可以爬取500个页面对于做RSS来说妥妥的够用了。注册之后可以得到一个API KEY这个待会会使用到。
接下来新建一个Phantom JS Cloud Agent填写基本的名称、API KEY和目标URLrender type选择html。底下User Agent建议改用真实的浏览器UA减少触发反爬虫的可能性。如果不知道自己的UA可以到这个网站查看当前浏览器的UA复制字符串即可。如果懒得查也可以用这个
```
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.81 Safari/537.36
```
> ###### Phantom JS Cloud Agent
>
> This Agent generates PhantomJs Cloud URLs that can be used to render JavaScript-heavy webpages for content extraction.
>
> URLs generated by this Agent are formulated in accordance with the PhantomJs Cloud API. The generated URLs can then be supplied to a Website Agent to fetch and parse the content. Sign up to get an api key, and add it in Huginn credentials.
点击Dry Run后会返回一条url返回格式类似这样
```json
[
{
"url": "https://phantomjscloud.com/api/browser/xxxxxxx"
}
]
```
之后创建一个WebSite AgentSource Agent设置为上面的Phantom JS Cloud Agent然后稍微改一下url的部分
```json
{
"expected_update_period_in_days": "2",
"url_from_event": "{{url}}",
"type": "html",
"mode": "on_change",
"extract": {...}
}
```
注意将原来的`url:??`的部分更改为`"url_from_event": "{{url}}"`,这样就指定使用Phantom JS Cloud为我们获取的完整网页接下来的操作就大同小异了。配置好要爬取的字段和规则后点击Dry Run就可以看到结果
![image-20220508215636780](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207727.png)
这里是刚才的Agent产生的一个Event。这里除了url和title我还提取了date字段。在Output Agent中可以配置为每一条文章输出发布时间的信息。对于这种规整的日期字母串可以使用`{{ date | date: %F }}`进行解析并格式化输出为rss规范的时间格式如果没有配置的话每篇文章的发布时间显示的都是一样的为Huginn爬虫更新的时间。
```json
"item": {
"title": "{{title}}",
"link": "{{url}}",
"pubDate": "{{ date | date: %F }}"
},
```
> **Pro Tips:**
>
> Huginn解析日期
>
> 注意`{{ date | date: %F }}`里面,第一个`date`是上面的Website Agent产生的Event里面的变量名第二个`date`是Huginn使用的Liquid模版引擎语法里内置的一个filter可以理解为有特定功能的函数
![image-20220508220438696](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/202205082207637.png)
## FAQ
* **为什么启动docker容器后访问Huginn显示网络错误**
Huignn冷启动较慢需要等待三五分钟。如果还是不行检查端口映射和防火墙设置
* **为什么抓取到的包含相对路径的结果网页上可以点击访问但是生成的RSS不能正常使用**
检查link的设置有些网站只是域名有些网站有子目录具体查看该网页源码中head节点里base url的设置
* 如何对爬取到的某一项的字符串做更高级更复杂的处理?
可以参考[Hugnn官方对Liquid语法的文档](https://github.com/huginn/huginn/wiki/Formatting-Events-using-Liquid)以及[Shopify官方关于Liquid模板的语法文档](https://shopify.dev/api/liquid)
* **为什么部署了Huginn等了很长时间都无法访问后台页面**
若部署后某个应用一直无法通过浏览器访问请检查是否绑定到了6000/6666等特殊端口浏览器会拦截对这些端口的访问参见[这里](https://blog.colinx.one/posts/docker-compose%E7%9A%84%E9%94%99%E8%AF%AF%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/)
## 扩展阅读
* [Huginn官方文档](https://github.com/huginn/huginn/wiki/)
* [Liquid模板引擎语法官方文档](https://shopify.dev/api/liquid/filters/)
* [RSS Man X部署指南](https://blog.colinx.one/posts/rssmanx%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97/)
* [docker compose 的错误使用姿势](https://blog.colinx.one/posts/docker-compose%E7%9A%84%E9%94%99%E8%AF%AF%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/)

View File

@@ -4,7 +4,7 @@ date: 2021-01-09
lastmod: 2021-01-10
description: 折腾了自己的专属RSS信息流每天都能从那些高质量的信息源中获得不少干货知识一般就会顺手收藏一下。有一天突然想起自己收藏的那些文章本身不就是经过二次筛选的高质量文章吗于是便在构想能不能通过某种方式将这个信息源也公开出来一方面是记录另一方面也是间接地展示自己。恰逢遇见JAMStack最近在国外非常火国内的阿里和腾讯也在跟进搞静态托管那一套。经多方物色最终确定基于Pocket API+Gatsby来构建这样一个自己的「网络日志」。
categories:
- 教程
- 技术
tags:
- 技术
- JAMStack

View File

@@ -4,7 +4,7 @@ date: 2020-12-18
lastmod: 2020-12-19
description: Mac 平台配置C/Python/Java学习环境
categories:
- 教程
- 技术
- 指南
tags:
- C
@@ -36,7 +36,7 @@ tags:
C语言的编译需要编译器一般可以选择gcc或是clang。Mac系统默认安装了clang同时兼容了gcc的指令。在终端中进行查看
![screenshot](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015258.png)
![screenshot](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015258.png)
输入`gcc -v`指令测试gcc命令是否可用并查看其版本由上图输出可以看到该命令可用版本信息显示的则是clang的信息。一般来说刚学习C语言无需关注两者的异同。
@@ -48,35 +48,35 @@ C语言的编译需要编译器一般可以选择gcc或是clang。Mac系统
如果下载速度太慢,可以参考[这篇文章](https://zhuanlan.zhihu.com/p/112215618)。
![截屏2020-12-18 22.20.00](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015416.png)
![截屏2020-12-18 22.20.00](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015416.png)
安装完毕后,打开会看到如下图所示的界面。默认界面为英文,下面对其进行汉化并安装一些必要的插件。
![截屏2020-12-18 22.21.59](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015546.png)
![截屏2020-12-18 22.21.59](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015546.png)
单击方形图标,打开扩展面板。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015621.png" alt="image-20201218223234296" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015621.png" alt="image-20201218223234296" style="zoom:50%;" />
搜索`chinese`安装汉化插件。
![image-20201218222747511](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015622.png)
![image-20201218222747511](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015622.png)
搜索`code runner`安装Code Runner插件。并按指示重启应用Reload字样
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015620.png" alt="image-20201218222511011" style="zoom:50%;" />截图中因为本地已安装故只显示了Uninstall卸载按钮。未安装的情况下会显示Install按钮可点击安装
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015620.png" alt="image-20201218222511011" style="zoom:50%;" />截图中因为本地已安装故只显示了Uninstall卸载按钮。未安装的情况下会显示Install按钮可点击安装
其他插件可根据需要安装。此处推荐安装C/C++插件以实现C代码的高亮和补全等功能。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015624.png" alt="image-20201218223432859" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015624.png" alt="image-20201218223432859" style="zoom:50%;" />
重启后进入应用,界面自动切换到中文。再点击扩展图标,展开扩展列表,在已安装扩展中找到**Code Runner**,点击齿轮图标展开菜单,点击进入扩展设置。<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015627.png" alt="image-20201218224215676" style="zoom:50%;" />
重启后进入应用,界面自动切换到中文。再点击扩展图标,展开扩展列表,在已安装扩展中找到**Code Runner**,点击齿轮图标展开菜单,点击进入扩展设置。<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015627.png" alt="image-20201218224215676" style="zoom:50%;" />
在输入栏中,在当前选项卡为**用户**的情况下,输入`run`并按回车进行搜索。修改`Run in Terminal``Save File Before Run`的设置项。<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015626.png" alt="image-20201218224059150" style="zoom:50%;" />
在输入栏中,在当前选项卡为**用户**的情况下,输入`run`并按回车进行搜索。修改`Run in Terminal``Save File Before Run`的设置项。<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015626.png" alt="image-20201218224059150" style="zoom:50%;" />
@@ -86,19 +86,19 @@ C语言的编译需要编译器一般可以选择gcc或是clang。Mac系统
点击左侧第一个按钮,来到文件管理面板。点击打开文件夹按钮,打开一个空白的文件夹(任意文件夹都可以,只是保存你代码的地方,一般一个干净整洁的新文件夹为宜)
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015623.png" alt="image-20201218230901008" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015623.png" alt="image-20201218230901008" style="zoom:50%;" />
打开文件夹后,在空白处单击右键,新建一个文件,文件名输入为`hello.c`
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015629.png" alt="image-20201218224536077" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015629.png" alt="image-20201218224536077" style="zoom:50%;" />
键入代码。
![image-20201218224343393](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015628.png)
![image-20201218224343393](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015628.png)
点击右上角的三角形按钮即可自动编译运行你的C语言代码。在窗口下方的终端即可看到输出的`Hello,C!`字样。
![image-20201219021624927](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219021631.png)
![image-20201219021624927](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219021631.png)
### 完成✅
@@ -116,13 +116,13 @@ C语言的编译需要编译器一般可以选择gcc或是clang。Mac系统
Mac系统会自带有Python环境。在终端中输入python并回车。
![截屏2020-12-18 22.54.54](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015630.png)
![截屏2020-12-18 22.54.54](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015630.png)
可以看到系统已经安装有Python但是显示版本为2.7。现在的主流版本是Python3Python2与Python3的语法并不兼容。
`>>>`后面键入`exit()`退出python2的交互程序。再次在终端输入`python3`
![image-20201218231954777](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015634.png)
![image-20201218231954777](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015634.png)
@@ -132,7 +132,7 @@ Mac系统会自带有Python环境。在终端中输入python并回车。
在交互式命令行界面我们可以直接输入python语句并执行。
![截屏2020-12-18 23.00.54](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219021016.png)
![截屏2020-12-18 23.00.54](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219021016.png)
一句一句地输入代码再执行显然太低效了。我们需要一个趁手的代码编辑器。
@@ -146,25 +146,25 @@ Mac系统会自带有Python环境。在终端中输入python并回车。
![image-20201218230442930](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015633.png)
![image-20201218230442930](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015633.png)
点击左侧第一个按钮,来到文件管理面板。点击打开文件夹按钮,打开一个空白的文件夹(任意文件夹都可以,只是保存你代码的地方,一般一个干净整洁的新文件夹为宜)
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015623.png" alt="image-20201218230901008" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015623.png" alt="image-20201218230901008" style="zoom:50%;" />
打开文件夹后,在空白处单击右键,新建一个文件,文件名输入为`hello.py`
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015629.png" alt="image-20201218224536077" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015629.png" alt="image-20201218224536077" style="zoom:50%;" />
键入代码。
![截屏2020-12-18 22.58.44](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015631.png)
![截屏2020-12-18 22.58.44](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015631.png)
点击右上角的三角形按钮开始运行我们编写的代码
![截屏2020-12-18 23.00.54](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015632.png)
![截屏2020-12-18 23.00.54](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015632.png)
@@ -201,13 +201,13 @@ Mac OS并没有内置Java语言的支持需要我们另外安装。
下载完成后点击打开,出现如下的安装界面。根据指引完成安装。
![image-20201218232011039](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015635.png)
![image-20201218232011039](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015635.png)
安装完成后,在终端中输入`java -version`并回车确认。看到如下输出说明已经正确安装且Java的版本为`11.0.9.1`即Java 11.
![image-20201218235233365](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015640.png)
![image-20201218235233365](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015640.png)
下面来为Java的学习配置一个趁手的代码编辑器以VSCode为例。
@@ -221,23 +221,23 @@ Mac OS并没有内置Java语言的支持需要我们另外安装。
在左侧扩展面板的搜索栏中搜索`java`,选择`Language Support for Java`并安装。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015641.png" alt="image-20201218235514041" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015641.png" alt="image-20201218235514041" style="zoom:50%;" />
点击左侧第一个按钮,来到文件管理面板。点击打开文件夹按钮,打开一个空白的文件夹(任意文件夹都可以,只是保存你代码的地方,一般一个干净整洁的新文件夹为宜)
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015623.png" alt="image-20201218230901008" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015623.png" alt="image-20201218230901008" style="zoom:50%;" />
打开文件夹后,在空白处单击右键,新建一个文件,文件名输入为`hello.java`
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015629.png" alt="image-20201218224536077" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015629.png" alt="image-20201218224536077" style="zoom:50%;" />
键入代码。
![image-20201218235213233](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015639.png)
![image-20201218235213233](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015639.png)
可以看到,在窗口下方的终端面板中,已经成功出现了**Hello, Java!**字样,代码运行成功。
![截屏2020-12-19 00.05.33](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015637.png)
![截屏2020-12-19 00.05.33](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015637.png)
### 完成✅
@@ -253,7 +253,7 @@ Mac OS并没有内置Java语言的支持需要我们另外安装。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201219015638.png" alt="image-20201218234917588" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201219015638.png" alt="image-20201218234917588" style="zoom:50%;" />
这是因为插件内置的一些功能需要Java来运行而这些功能又依赖于一些较新的特性这些特性最早出现在Java 11中。为了更好地学习和使用Java这里推荐安装Java 11 或Java 12。网站教程或学校授课常常以Java 8为例但对于初学者来说几者无太大区别Java 8的代码都可以被很好地支持。

View File

@@ -4,7 +4,7 @@ date: 2021-02-07
lastmod: 2021-02-07
description: Minecraft上云笔记 - MC服务器快速搭建&MOD推荐&性能优化。MC快速上云学生机轻松带动三五好友畅快联机
categories:
- 教程
- 技术
- 指南
tags:
- Java
@@ -89,7 +89,7 @@ services:
ONLINE_MODE: "FALSE" #正版校验开关
ALLOW_FLIGHT: "FALSE"
USE_AIKAR_FLAGS: "false" # 一些优化
RESOURCE_PACK: "https://blog-1301127393.cos.ap-shanghai.myqcloud.com/MC/Distribution/VNR-1.0.1.zip" # 我自己会用的资源包这里填url
RESOURCE_PACK: "https://blog-1301127393.file.myqcloud.com/MC/Distribution/VNR-1.0.1.zip" # 我自己会用的资源包这里填url
NETWORK_COMPRESSION_THRESHOLD: 512 # 网络优化
restart: unless-stopped
rcon:
@@ -146,7 +146,7 @@ volumes:
上一张HMCL的主页的图
![image-20210129172401421](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205913.png)
![image-20210129172401421](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205913.png)
其他没有使用过的启动器暂时不予评价。
@@ -344,7 +344,7 @@ MC服务器的优化主要聚焦在两个地方
* 联机游戏间或卡顿,但很快恢复
* 查看日志发现空载时时竟然仍会`can't keep up`
![服务器在空载](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205922.png)
![服务器在空载](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205922.png)
@@ -364,8 +364,7 @@ JVM优化的大头是GC。网上吹的漫天飞的G1GC的确有他的可取之
* **G1GC天生是为了现代互联网应用环境而设计的**,需要开很多个线程协同来完成垃圾回收工作。他适用于多核处理器+大内存机器上的高负荷运算。而我的服务器是单核,内存也并不富裕。
* **多线程的GC模式跑在单核机器上**时出现的问题就是:单核机器无法并行处理多个任务,其本质上只是在多个任务之间快速切换,来实现各个任务基本“实时”“并行”运行。但是线程之间的切换是有代价的,**性能损耗积少成多**。
* **G1GC追求在延迟可控的情况下达到更高的吞吐量**。但他的**代价是[更多的内存占用](jvm G1 垃圾收集器有什么缺点? - SegmentFault 思否
https://segmentfault.com/q/1010000021658061)。**小内存机器并不适合使用G1GC。
* **G1GC追求在延迟可控的情况下达到更高的吞吐量**。但他的**代价是[更多的内存占用](https://segmentfault.com/q/1010000021658061)。**小内存机器并不适合使用G1GC。
物色了一番我最终选择换用Serial GC代替原本的G1GC。
@@ -382,19 +381,19 @@ JVM优化的大头是GC。网上吹的漫天飞的G1GC的确有他的可取之
1. 优化前MC服务器的资源占用情况
![360截图20210129163301881](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205932.jpg)
![360截图20210129163301881](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205932.jpg)
2. SERIAL GC (1 ONLINE)
![image-20210202194034351](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205936.png)
![image-20210202194034351](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205936.png)
3. 进一步对mod优化后2 online
![image-20210202221554906](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205939.png)
![image-20210202221554906](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205939.png)
@@ -412,11 +411,11 @@ JVM优化的大头是GC。网上吹的漫天飞的G1GC的确有他的可取之
我家:
![屏幕截图(13)](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205942.png)
![屏幕截图(13)](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205942.png)
![屏幕截图(16)](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205946.png)
![屏幕截图(16)](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205946.png)
@@ -424,13 +423,13 @@ JVM优化的大头是GC。网上吹的漫天飞的G1GC的确有他的可取之
我安装的光影 Sildurs Vibrant Shaders v1.281 High 效果图
![屏幕截图(12)](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205949.png)
![屏幕截图(12)](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205949.png)
Better HUD + 旅行地图效果图
![屏幕截图(17)](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210207205953.png)
![屏幕截图(17)](https://blog-1301127393.file.myqcloud.com/BlogImgs20210207205953.png)

View File

@@ -4,7 +4,7 @@ date: 2021-02-22
lastmod: 2021-02-22
description: Minecraft上云笔记 - MC自定义皮肤并支持联机
categories:
- 教程
- 技术
- 指南
tags:
- Java
@@ -15,8 +15,6 @@ tags:
- 游戏
- 服务器
---
<!-- # Minecraft上云笔记 - MC自定义皮肤并支持联机 -->

View File

@@ -4,7 +4,7 @@ date: 2021-05-08
lastmod: 2021-05-08
description: 网站没有源海外站的源看不了这也许是第一个自带海外加速的RSS解决方案
categories:
- 教程
- 技术
- 指南
tags:
- RSS
@@ -12,14 +12,10 @@ tags:
- Github
- 代理
---
![logo](https://cdn.jsdelivr.net/gh/Colin-XKL/RSSmanX/.github/logo.png)
![author](https://img.shields.io/badge/author-Colin-blue)
![license](https://img.shields.io/github/license/Colin-XKL/RSSmanX)
![release](https://img.shields.io/github/v/release/Colin-XKL/RSSmanX)
![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FColin-XKL%2FRSSmanX.svg?type=shield)
![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)
![license](https://img.shields.io/github/license/Colin-XKL/RSSmanX)
![release](https://img.shields.io/github/v/release/Colin-XKL/RSSmanX)
[中文说明](https://github.com/Colin-XKL/RSSmanX/blob/master/README-zh_cn.md) [English](https://github.com/Colin-XKL/RSSmanX/)
@@ -29,7 +25,7 @@ tags:
**Feature 简单一键部署,常用组件支持,自动更新支持,服务健康自检支持,海外站点 RSS 解锁**
## 快速开始
### 快速开始
(若已安装 `docker``docker-compose`)
@@ -37,7 +33,7 @@ tags:
mkdir RSSmanX && cd $_ && wget https://cdn.jsdelivr.net/gh/Colin-XKL/RSSmanX/docker-compose.yml && sudo docker-compose up -d
```
# 说明
## 说明
本项目旨在为 RSS 的同好提供一个方便地搭建自己的 RSS 服务的捷径。毕竟不是所有 RSS 爱好者都懂代码 😂。如果你想快速地搭建自己的 RSS 服务,能够有 RSS 订阅管理、RSS 在线阅读界面,进阶功能包括服务健康自检、海外站点 RSS 解锁等。希望订阅国内外的各大网站的 RSS 信息源又不想跟着网上漫天飞的教程瞎折腾的话,那么你可以使用本仓库的脚本快速完成安装部署。
@@ -71,15 +67,15 @@ mkdir RSSmanX && cd $_ && wget https://cdn.jsdelivr.net/gh/Colin-XKL/RSSmanX/doc
选择对应版本下载到本地后都 compose 文件需要重命名为标准的`docker-compose.yml`才可使用
# 安装说明
## 安装说明
## 需求
### 需求
- 一台 Linux 系统的服务器
> 本文以腾讯云 Ubuntu 18.04 系统的服务器为例,其他云服务商的没差,系统为 CentOS 的会有点差异
## 依赖项
### 依赖项
- docker
- docker-compose
@@ -111,7 +107,7 @@ sudo apt install docker-compose
- https://docs.docker.com/engine/install/
- https://docs.docker.com/compose/install/
## 如何安装
### 如何安装
安装好了 `docker``docker-compose` 后可以执行文章开头的快速开始的指令。或者可以按照下面的步骤手动操作:
@@ -133,7 +129,7 @@ sudo apt install docker-compose
- TTRSS 相关文档 [https://ttrss.henry.wang/](https://ttrss.henry.wang/)
- RSSHub 相关文档 [https://docs.rsshub.app/](https://docs.rsshub.app/)
## 功能模块介绍
### 功能模块介绍
**Tiny Tiny RSS**
RSS 订阅管理与在线阅读工具
@@ -165,7 +161,7 @@ RSS 订阅管理与在线阅读工具
**Clash**
智能路由与正向代理工具,用于解锁海外站点及提供海外 RSS 源的加速
# Acknowledgement
## Acknowledgement
- [Tiny tiny RSS](https://tt-rss.org/)
- [OpenCC](https://github.com/BYVoid/OpenCC)
@@ -174,11 +170,11 @@ RSS 订阅管理与在线阅读工具
- [RSShub](https://github.com/DIYgod/RSSHub)
- [Awesome TTRSS](https://github.com/HenryQW/Awesome-TTRSS)
# License
## License
GPL-3.0
# Changelogs
## Changelogs
- 2020-07-07 v1.0 First release
- 2020-07-14 v1.1 Update quick start shell script

View File

@@ -0,0 +1,265 @@
---
title: RSSManX安装部署指南
date: 2022-05-07
description: RSS Man X是我两年前入坑RSS后为了方便更多人更方便地使用RSS所发起的一个项目主要是用docker-compose整合了一些常用的服务如TTRSS、RSSHub、Huginn、OpenCC等并进行了一些优化调整如自动更新反反爬虫等。这篇文章会尽可能详尽地讲解安装部署的步骤以及安装过程中可能会遇到的一些问题。
categories:
- 技术
- 指南
tags:
- RSS
- Linux
- 教程
- Docker
---
<!-- # RSSManX安装部署指南 -->
RSS Man X是我两年前入坑RSS后为了方便更多人更方便地使用RSS所发起的一个项目主要是用docker-compose整合了一些常用的服务如TTRSS、RSSHub、Huginn、OpenCC等并进行了一些优化调整如自动更新反反爬虫等。这篇文章会尽可能详尽地讲解安装部署的步骤以及安装过程中可能会遇到的一些问题。
RSS Man X会利用到docker和docker-compose首先需要确保你的服务器正确安装了这些软件
## 1. Docker环境准备
检查服务器中是否已经安装了docker和docker-compose并检查他们的版本是否太老。比如输入`docker --version`来检查docker的版本
docker的版本建议不要低于19docker-compose的版本建议不要低于1.20
```shell
~ » docker --version
Docker version 20.10.12, build 20.10.12-0ubuntu2~20.04.1
```
```shell
~ » docker-compose --version
docker-compose version 1.25.0, build unknown
```
如果上面命令执行后提示`command not found`那么说明并没有安装对应的软件包或是安装的路径并不在当前用户的PATH变量中尝试切换到root操作详细的原因和解决方法见后文
### 1.1 Ubuntu/Debian安装Docker
ubuntu和debian主要是用apt安装和管理软件包可以使用以下命令来安装根据实际情况选择是否要加sudo。下面以Ubuntu为例。Debian下的安装略有不同可以参见[Docker官方文档](https://docs.docker.com/engine/install/debian/),以及[清华镜像源](https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/)。其中`download.docker.com`连接不同的可以尝试讲域名部分更换为[中科大提供的镜像](https://mirrors.ustc.edu.cn/help/docker-ce.html)地址`mirrors.ustc.edu.cn/docker-ce`
```shell
# 首先移除老旧的软件包
sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update
# 安装一些必要的依赖
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
```
如果你的服务器在墙外可以直接使用docker官方的软件源
```shell
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
如果你的服务器在墙内,可以使用由中科大提供的镜像
```shell
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
导入docker软件源后即可开始安装docker安装完成后可以输入`docker --version`来检查docker的版本
```shell
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```
### 1.2 CentOS/Fedora安装Docker
CentOS和Fedora使用yum安装和管理软件包新版本则是使用dnf不过两者功能一致且高度兼容。下面以CentOS为例Fedora可参见[官方文档](https://docs.docker.com/engine/install/fedora/)或[清华镜像源](https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/)
```shell
# 1. 首先移除老旧的软件包
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 2.
sudo yum install -y yum-utils
# 3.A 之后使用官方docker软件库
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 3.B 墙内方案
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
# 4. 即可开始安装
sudo yum update
sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```
### 1.3 安装或更新docker-compose
docker-compose目前有两个主要版本V1和V2都是可用的。V1使用Python编写使用时类似`sudo docker-compose up -d`V2则是Golang编写与前者高度兼容但是是作为docker的插件安装的使用时类似`sudo docker compose up -d`,中间的短杠不需要了。
如果是按照上文的步骤安装的docker那么默认已经安装了docker compose v2可以通过`docker compose version`查看版本
```shell
~ » docker compose version
Docker Compose version v2.3.3
```
如果需要是安装的比较老的v1版本的docker-compose想要单纯更新docker-compose而又不想动其他东西的话可以更新安装v1版本的docker-compose。
首先删除老旧版本(如果有的话)
```shell
rm $DOCKER_CONFIG/cli-plugins/docker-compose
sudo rm /usr/local/lib/docker/cli-plugins/docker-compose
pip uninstall docker-compose
```
然后使用pip来安装
```shell
pip3 install docker-compose
```
墙内也可以临时使用镜像源下载
```shell
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple
```
如果提示pip命令不存在需要先安装一下
```shell
# Ubuntu/Debian
sudo apt install python3-pip
# CentOS/Fedora
sudo yum install python3-pip
```
如果pip报错试着升级一下pip的版本
```shell
python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip
```
### 1.4 为Docker配置镜像源
如果Docker下载镜像非常慢你可能需要单独配置一下Docker的镜像源。==**注意Docker安装软件源的镜像和Docker镜像或者说映像的国内源并不是同一个英文表述可能更准确一些**==
* 上文安装docker时配置的是docker的reporepo里含有docker的软件包[国内的镜像](https://mirrors.ustc.edu.cn/help/docker-ce.html)为Docker CE安装软件包的镜像
* 现在我们要配置的是Docker Hub的MirrorDocker里拉取Image默认会访问[Docker Hub](https://hub.docker.com)国内有多个Docker Hub镜像或是Docker镜像加速器如[中科大的源](https://mirrors.ustc.edu.cn/help/dockerhub.html)
`/etc/docker/daemon.json`文件中写入以下内容如不存在可先行创建注意json中列表的最后一项末尾是没有逗号的
```json
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://docker.mirrors.ustc.edu.cn"
]
}
```
配置完成后`sudo systemctl restart docker`重启docker服务然后输入`sudo docker info`,在输出结果的末尾可以看到`Registry Mirrors`里会出现我们刚刚配置的Docker Hub镜像
群辉等NAS的系统并不是标准版Linux安装的也是魔改版docker上面的配置文件地址并不适用建议自行搜索对应的文档或教程。
## 2. 安装RSS Man X
[RSS MAN X项目](https://github.com/Colin-XKL/RSSmanX)旨在为 RSS 的同好提供一个方便地搭建自己的 RSS 服务的捷径,毕竟不是所有 RSS 爱好者都懂代码 😂。RSS Man X能够有 RSS 订阅管理、RSS 在线阅读界面,进阶功能包括服务健康自检、海外站点 RSS 解锁等,提供不同的版本供选择,三个版本的 `docker-compose` 文件对应不同的需求,包含的组件和服务有差异。
| 组件 / 服务 / 功能名称 | 标准版 | Lite 版 | Ultimate 版 ✨ |
| ---------------------- | ------ | ------- | ------------- |
| TTRSS | ✅ | ✅ | ✅ |
| RSSHub | ✅ | ✅ | ✅ |
| Huginn | | | ✅ |
| Mercury | ✅ | | ✅ |
| OpenCC | | | ✅ |
| Redis | ✅ | | ✅ |
| Browserless | | | ✅ |
| 数据持久化保存 | ✅ | ✅ | ✅ |
| 容器自动更新 | ✅ | | ✅ |
| 容器健康检查 | ✅ | | ✅ |
| 海外站点加速 | | | ✅ |
| 智能路由 | | | ✅ |
| 反反爬虫 | | | ✅ |
### 2.1 安装流程
安装好了 `docker``docker-compose` 后,可以使用`git clone https://github.com/Colin-XKL/RSSmanX --depth=1`快速克隆本仓库,也可以通过[这个镜像地址](https://archive.fastgit.org/Colin-XKL/RSSmanX/archive/refs/heads/master.zip)下载仓库zip文件[Gitee上也有镜像](https://gitee.com/colin-xkl/RSSmanX)不过不经常更新。
1. cd 进入文件夹,修改`.env`中的值如密码和TTRSS入口URL等
2. 运行 `sudo docker-compose up -d`
3. 等待程序跑完
4. 安装完成 ✅
### 2.2 相关事宜
1. 访问你设置的 `SELF_URL` 即可看到 Tiny Tiny RSS 的登陆页面,使用默认账户 `admin`,密码 `password` 登陆即可开始使用
2. 如开启海外站点解锁支持,第一次冷启动需要等待 3-5 分钟才能完全启动所有组件。
3. 数据保存位置`/data/docker/`
4. 在 TTRSS 中将原来订阅的 `https://rsshub.app/*` 更改为 `http://rsshub/*` 即可使用 RSS Man X内的自建 RSSHub 实例,并激活反反爬虫和海外源加速等功能
5. 如无法访问rsshub的官方文档站点可以使用我维护的反代站点[https://rsshub-doc.azure.colinx.one/](https://rsshub-doc.azure.colinx.one/)
6. 关于 ARM 平台的支持可查阅[置顶的 issue](https://github.com/Colin-XKL/RSSmanX/issues/5)
7. 默认情况下只有TTRSS和Huginn可以从外部访问其他组件互相可以访问但不能直接从内部访问以提高安全性
8. RSS Man X的除 lite 以外的版本默认包含了自托管的 mercury 实例,你只需要在插件配置页面设置 mercury 实例地址为 `service.mercury:3000` 即可同理OpenCC实例地址为`service.opencc:3000`
9. 如果部分RSS源不能订阅检查是否使用了非常规端口。在`.env`文件中设置`RSS_ALLOEW_PORTS`
10. 若部署后某个应用一直无法通过浏览器访问,请检查是否绑定到了`6000`/`6666`等特殊端口,浏览器会拦截对这些端口的访问参见[这里](https://blog.colinx.one/posts/docker-compose%E7%9A%84%E9%94%99%E8%AF%AF%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/)
11. `ls`没有显示`.env`文件是因为以点开头的文件在Linux中都是默认隐藏的可以使用`ls -a`查看到
12. vi/vim编辑文本太麻烦可以尝试使用nano
**获取帮助**
* **For Tiny tiny RSS problems:**
[https://tt-rss.org/wiki.php](https://tt-rss.org/wiki.php)
[http://ttrss.henry.wang/](http://ttrss.henry.wang/)
* **For RSShub problems:**
[https://docs.rsshub.app/faq.html](https://docs.rsshub.app/faq.html)
* **For Huginn problems:**
[https://github.com/huginn/huginn#readme](https://github.com/huginn/huginn#readme)
### 2.3 链接
* [我的 RSS 方案与心得](https://blog.colinx.one/posts/%E6%88%91%E7%9A%84rss%E6%96%B9%E6%A1%88%E4%B8%8E%E5%BF%83%E5%BE%97/)
* [RSS Man X GitHub repo](https://github.com/Colin-XKL/RSSmanX)
* [Huginn 指南:为任意网站制作 RSS](https://blog.colinx.one/posts/huginn%E6%8C%87%E5%8D%97%E4%B8%BA%E4%BB%BB%E6%84%8F%E7%BD%91%E7%AB%99%E5%88%B6%E4%BD%9Crss/)
* [docker compose 的错误使用姿势](https://blog.colinx.one/posts/docker-compose%E7%9A%84%E9%94%99%E8%AF%AF%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/)

View File

@@ -4,7 +4,7 @@ date: 2020-12-27
lastmod: 2020-12-27
description: VC6.0太古老Dev C++没补全不友好MinGW安装太烦恼你用着最新的电脑最新的系统却在用着上个世纪的软件开始你人生第一门编程课你需要这篇指南在现代化的硬件和平台上使用现代化工具学习C语言
categories:
- 教程
- 技术
- 指南
tags:
- C
@@ -65,7 +65,7 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164821.png" alt="image-20201224235413884" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164821.png" alt="image-20201224235413884" style="zoom:50%;" />
@@ -73,7 +73,7 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164829.png" alt="image-20201224235436360" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164829.png" alt="image-20201224235436360" style="zoom:50%;" />
@@ -83,13 +83,13 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
网络条件不好的情况下,半分钟以内就会报错说网络连接失败。不过不用担心,接下来可以自己填写国内镜像地址。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164833.png" alt="image-20201224235644342" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164833.png" alt="image-20201224235644342" style="zoom:50%;" />
在User URL的输入框输入`https://mirrors.tuna.tsinghua.edu.cn/cygwin/`并点击Add添加。之后点击下一步继续。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164836.png" alt="image-20201224235719679" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164836.png" alt="image-20201224235719679" style="zoom:50%;" />
@@ -97,13 +97,13 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
之后会进入一个选择界面。这里选择要安装的组件。我们只需要C语言的编译器这里在搜索框内输入`gcc`,然后在下方找到`gcc-core``gcc-g++`点击右侧的三角形打开下拉菜单选择9开头的版本。如下图所示。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164839.png" alt="image-20201225000518139" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164839.png" alt="image-20201225000518139" style="zoom:50%;" />
选择完成后,一路点击下一步安装。如果出现如下的警告信息,直接用默认的设置,点下一步继续就可以了。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164842.png" alt="image-20201225000604625" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164842.png" alt="image-20201225000604625" style="zoom:50%;" />
@@ -115,51 +115,51 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
在开始菜单中找到`Windows系统` - 控制面板。如果这里没有的话,按`Windows徽标键`+`S`可以呼出搜索面板,可以在此搜索控制面板菜单项。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164856.png" alt="image-20201227152139118" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164856.png" alt="image-20201227152139118" style="zoom:50%;" />
在控制面板主页找到系统与安全。
![image-20201227152347064](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164859.png)
![image-20201227152347064](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164859.png)
或者如果你的控制面板打开不是上面的布局而是下面这种布局的话,找到系统菜单。
![image-20201227152420458](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164903.png)
![image-20201227152420458](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164903.png)
进入如下的页面,点击高级系统设置。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164910.png" alt="image-20201225001127874" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164910.png" alt="image-20201225001127874" style="zoom:50%;" />
切换到高级选项卡,点击下方的环境变量菜单
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164913.png" alt="image-20201225000925342" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164913.png" alt="image-20201225000925342" style="zoom:50%;" />
在用户变量中,点击`Path`,点击下方编辑按钮进行编辑
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164916.png" alt="image-20201225000949291" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164916.png" alt="image-20201225000949291" style="zoom:50%;" />
输入Cygwin安装路径下的bin目录。如果你之前没有自定义安装路径直接设置如图即可。否则设置为你自定义的路径。
**注意:这一步只要添加这一个就好**,不要看我截图里面的很干净,就把其他的都删了
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164919.png" alt="image-20201225001045854" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164919.png" alt="image-20201225001045854" style="zoom:50%;" />
一路点击确定。修改完之后重启下电脑确保改动生效。
在PowerShell中或者命令提示符中输入gcc并回车。如果显示no input files则表示安装成功。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164921.png" alt="image-20201225001234917" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164921.png" alt="image-20201225001234917" style="zoom:50%;" />
### 配置编辑器
安装完了编译器可以先来Hello world了
![image-20201225001723920](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164924.png)
![image-20201225001723920](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164924.png)
按住Shift键右键点击文件夹空白处会出现在此处打开Powershell窗口的选项。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164932.png" alt="image-20201225001744160" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164932.png" alt="image-20201225001744160" style="zoom:50%;" />
@@ -167,7 +167,7 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
输入`./hello.exe`即可执行该exe文件。
![image-20201225002338213](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227164937.png)
![image-20201225002338213](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227164937.png)
@@ -201,41 +201,41 @@ https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165016.png" alt="image-20201227155805507" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165016.png" alt="image-20201227155805507" style="zoom:50%;" />
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165019.png" alt="image-20201227155937465" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165019.png" alt="image-20201227155937465" style="zoom:50%;" />
![image-20201227160036085](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165022.png)
![image-20201227160036085](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165022.png)
![image-20201227160129001](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165026.png)
![image-20201227160129001](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165026.png)
![image-20201227160209263](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165029.png)
![image-20201227160209263](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165029.png)
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165032.png" alt="image-20201227160939375" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165032.png" alt="image-20201227160939375" style="zoom:50%;" />
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165035.png" alt="image-20201227161003478" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165035.png" alt="image-20201227161003478" style="zoom:50%;" />
在输入栏中,在当前选项卡为**用户**的情况下,输入`run`并按回车进行搜索。修改`Run in Terminal``Save File Before Run`的设置项。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165038.png" alt="image-20201227161205762" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165038.png" alt="image-20201227161205762" style="zoom:50%;" />
@@ -245,20 +245,20 @@ https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user
点击左侧第一个按钮,来到文件管理面板。点击打开文件夹按钮,打开一个空白的文件夹(任意文件夹都可以,只是保存你代码的地方,一般一个干净整洁的新文件夹为宜)
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165059.png" alt="image-20201227163528187" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165059.png" alt="image-20201227163528187" style="zoom:50%;" />
打开文件夹后,在空白处单击右键,新建一个文件,文件名输入为`hello.c`
![image-20201227164010460](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165107.png)
![image-20201227164010460](https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165107.png)
点击右上角的三角形按钮即可自动编译运行你的C语言代码。在窗口下方的终端即可看到输出的`Hello,C!`字样。
<img src="https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20201227165112.png" alt="image-20201227164041803" style="zoom:50%;" />
<img src="https://blog-1301127393.file.myqcloud.com/BlogImgs/20201227165112.png" alt="image-20201227164041803" style="zoom:50%;" />

View File

@@ -0,0 +1,162 @@
---
title: docker compose的错误使用姿势
date: 2022-05-11
description: 这篇文章记录几个docker compose使用过程中几个难以察觉的错误使用姿势。1. 变量值使用`@`符号开头 2. 使用6000或6666端口
categories:
- 技术
- 指南
tags:
- YAML
- Linux
- Docker
- docker-compose
---
<!-- # docker compose 的错误使用姿势 -->
这篇文章记录几个docker compose使用过程中几个难以察觉的错误使用姿势
## 1. 变量值使用`@`符号开头
我在RSS MAN X的docker-compose配置文件中huignn的环境变量出来时是这样写的
```yaml
environment:
- DATABASE_ADAPTER=postgresql
- DATABASE_HOST=database.huginn
- DATABASE_USERNAME=postgres
- DATABASE_PASSWORD=@pass_for_DB
- DATABASE_PORT=5432
```
自己使用的时候没发现什么问题,别人从零创建容器的时候报错了。刚开始排查了很久,后面发现我默认密码这样写其实是有问题的。
上面的使用列表来描述环境变量在docker-compose解析的时候没有任何报错信息。但是使用下面这种key-value的map的形式时`docker-compose up`命令报错了说YAML解析时出现问题
```yaml
environment:
DATABASE_ADAPTER: postgresql
DATABASE_HOST: database.huginn
DATABASE_USERNAME: postgres
DATABASE_PASSWORD: @pass_for_DB
DATABASE_PORT: 5432
```
```
yaml: line 17: found character that cannot start any token
```
删除前导`@`符号则一切正常了。
```yaml
DATABASE_PASSWORD: pass_for_DB
```
后续测试了几次到底是什么原因导致的
```yaml
# error
DATABASE_PASSWORD: @pass_for_DB
# correct
DATABASE_PASSWORD: pass_for_DB
# correct
DATABASE_PASSWORD: ${DB_Password:-'pass_for_DB'}
## in .env
DB_Password=www_123
# correct
DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
## in .env
DB_Password=www_123
# error
DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
## no .env
# error
DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
## in .env
DB_Password=@www_123
# correct
DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
## in .env
DB_Password=A@www_123
```
最终发现无论是否使用docker-compose变量替换只要最终设定值的时候包含前导@符号最终一定会失败。Huginn的这边的报错为解析容器内的一个YAML文件时失败
```
huginn1 | foreman stderr |
huginn1 | Caused by:
huginn1 | foreman stderr | Psych::SyntaxError: (<unknown>): found character that cannot start any token while scanning for the next token at line 8 column 13
huginn1 | foreman stderr | /app/vendor/bundle/ruby/2.6.0/gems/railties-6.0.4.4/lib/rails/application/configuration.rb:232:in `database_configuration'
```
后面我又进入容器查看了下容器内部读取到的环境变量到底是不是预期的值,发现了问题所在
能正常使用的情况
```shell
~ » sudo docker exec -it huginn1 /bin/bash
default@3b652a8413fb:~$ echo $DATABASE_HOST
database.huginn
default@3b652a8413fb:~$ echo $DATABASE_PASSWORD
A@www_123
```
出错的情况
```shell
~ » sudo docker exec -it huginn1 /bin/bash
default@42e19e692b24:~$ echo $DATABASE_HOST
database.huginn
default@42e19e692b24:~$ echo $DATABASE_PASSWORD
'@pass_for_DB'
```
可以看到,如果以`@`符号开头最终的环境变量会加上引号这对于某些应用来说会产生预期之外的结果如此处测试的Huginn。
## 2. 使用6000或6666端口
这也是一定挺特殊的场景虽然与docker compose关系不大但是难免会遇到。在映射端口的时候有一个很坑的地方如果你要部署一个web服务然后映射的时候填写的是`6000`端口或者是`6666`端口你会发现无论怎么重启容器、更改容器设置、更换Edge/Chrome浏览器就是访问不了页面。
实在折腾地快疯了点开Chrome的错误详情才发现这么一句
***ERR_UNSAFE_PORT***
一查才发现Chrome等浏览器会限制部分特殊端口的网页访问这些端口一般都已经有特殊的作用。
https://www.jianshu.com/p/40f79f584eae
这里列出1000以上的部分会有相关问题的端口别的不说感觉`6000``6666`还是很容易一不小心就会设置的端口。。。。
```c
2049, // nfs
3659, // apple-sasl / PasswordServer
4045, // lockd
6000, // X11
6665, // Alternate IRC
6666, // Alternate IRC
6667, // Standard IRC
6668, // Alternate IRC
6669, // Alternate IRC
```
Chrome、FireFox等都会有类似的行为换多少浏览器、换多少版本可能也都不行。。。
根据网友描述,部分特殊情况下,其他可能会被拦截的端口也包括`8080``8443``10080`
总之,日常映射端口还是选取`10000`以上的高位端口吧,避免不必要的麻烦:)

View File

@@ -4,7 +4,7 @@ date: 2019-10-10
lastmod: 2020-04-29
description: 在内网的树莓派上部署了 AdGuardHome做 DNS 服务器的同时也可以为内网所有设备过滤广告。本来嘛拦截了广告理应网络加载会更快然而实际体验却很糟糕。网页加载要比之前慢得多。AdGuardHome 的面板显示的平均反应时间一度达到了 1000ms。1s 的延时还是会非常影响网络体验的。用 dig 命令看了下 DNS 查询的情况。不看不知道一看吓一跳,随便查询一个域名竟然废了四秒多!这怎么能忍受!
categories:
- 踩坑记
- 技术
tags:
- 服务器
- 树莓派
@@ -13,7 +13,8 @@ tags:
在内网的树莓派上部署了 AdGuardHome做 DNS 服务器的同时也可以为内网所有设备过滤广告。本来嘛拦截了广告理应网络加载会更快然而实际体验却很糟糕。网页加载要比之前慢得多。AdGuardHome 的面板显示的平均反应时间一度达到了 1000ms。1s 的延时还是会非常影响网络体验的。用 dig 命令看了下 DNS 查询的情况。不看不知道一看吓一跳,随便查询一个域名竟然废了四秒多!这怎么能忍受!
![](http://192.168.1.200/wp-content/uploads/2019/12/image-1-1280x784.png)
\[图片已丢失\]
<!-- ![](http://192.168.1.200/wp-content/uploads/2019/12/image-1-1280x784.png) -->
看网上其他人的评价,并没有我这种龟速的情况。况且我的上游 DNS 已经更换为了国内几个大厂的 DNS 比如阿里的腾讯的,测试查询一般反应时间也才 50ms。本地这个结果肯定是不能接受的。最开始还想过要根据常用域名手动制作 hosts 直接重定向。但是 dnspython 这个库不好直接指定 dns 查询adguardhome 的 query 日志又经过特殊加密,这条路困难重重。决定将其作为备用方案。接下来进入漫长的排雷环节。
@@ -23,10 +24,14 @@ tags:
后来发现了这货:
![](http://192.168.1.200/wp-content/uploads/2019/12/image-1280x191.png)
\[图片已丢失\]
<!-- ![](http://192.168.1.200/wp-content/uploads/2019/12/image-1280x191.png) -->
原来,他会把每次查询的域名先交给他服务器做安全性检查,这在国内的互联网环境中完全是鸡肋,而且因为每次都要连接境外服务器,其延迟可想而知。果然禁用了这一项,速度嗖嗖的就起来了:
![](http://192.168.1.200/wp-content/uploads/2019/12/image-2-1280x708.png)
<!-- ![](http://192.168.1.200/wp-content/uploads/2019/12/image-2-1280x708.png) -->
\[图片已丢失\]
即便是冷门的实验室官网的域名,也在 100ms 内解决了,对于常见的热门网站由于多设备频繁访问,会直接查询本地缓存。虽然基本只有可怜的差不多 60s 的缓存时间,但是一旦命中,就可以在 < 10ms 的时间响应如果是过滤器中的域名更是可以达到 < 5ms终于这个 AdGuard Home DNS 可以正式投入使用了

View File

@@ -4,7 +4,7 @@ date: 2020-03-15
lastmod: 2020-04-29
description: 各大厂商持续发力云计算,上云的门槛也越来越低。获取云服务器的门槛越来越低,但是真正使用好云服务器的难度一直都很高。本文旨在为新上云的小白提供方向性的指引并引导入坑
categories:
- 教程
- 技术
- 指南
tags:
- 服务器

View File

@@ -4,7 +4,7 @@ date: 2020-02-08
lastmod: 2020-04-29
description: 经过两三天的折腾,从 Linux 结构及指令,到 LNMP 框架搭建,再到数据库的配置,最后端口转发 + 内网穿透,博客终于成功上线!在此将部署过程及踩过的坑记录下来,一方面是纪念,另一方面希望能够后来人提供一点帮助。
categories:
- 踩坑记
- 技术
tags:
- 防火墙
- 服务器
@@ -28,7 +28,7 @@ tags:
由于要分配的公网 IPv6 地址是要由路由器从公网获取一个前缀然后再为局域网的每个支持 IPv6 的设备分配地址,这一项任务不能由内网的树莓派代劳,所以当时就没有改动,没想到现在竟然成了救命稻草。
通过 IPv6 的方式,成功连接上了树莓派。查看了 AdGuardHome 的 DNS 服务以及 DHCP 服务,并没有发现任何异常。
例行 SSH 连上查看日志。`sudo systemctl status AdGuardHome.service`,果然,发现了端倪。
![](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20200121221431.png)
![](https://blog-1301127393.file.myqcloud.com/BlogImgs/20200121221431.png)
原来DHCP 服务!是要单独监听 67 端口的!
而一个小时之前,为了防止暴露在公网上的树莓派遭到攻击,我特地启用了防火墙,并设置规则为,除了放行的 DNS 53 等端口,其他默认屏蔽。想来应该是误伤了 DHCP 的 67 端口。而之前 DHCP 设置每个 IP 地址的租约为一个小时,即,每间隔一个小时才会重新进行一次 DHCP 请求。于是`sudo ufw allow 67/tcp`端口放行 DHCP 服务信息。win10 断网重连以令其重新获取 IP 地址。
没想到还是不成功。AdGuardHome 的 DHCP 租约面板,依然显示没有任何设备连接。依据以往的经验,乖乖去查了 DHCP 所使用的端口信息,发现 DHCP 需要`67/udp``68/udp`两个端口,且还是使用 udp 连接。
@@ -43,7 +43,7 @@ tags:
-----
防火墙抵挡了来自外部的威胁,也会对现有的服务造成影响。除了网页访问的 80 和 443 端口,其他有固定端口的特定服务要手动在防火墙中添加规则。对于像 BT 下载这种没有固定端口的,需要根据实际设定来更新防火墙规则。
![](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20200122140951.png)
![](https://blog-1301127393.file.myqcloud.com/BlogImgs/20200122140951.png)
图中为 Aria2 的默认监听端口,为了保证正常的 BT 下载,需要保证这个范围的端口也添加进防火墙允许通过的规则。
最简单有效的办法是,将所有出站的请求默认允许,对于外部传入的请求,除了必要的几个服务,其他一概默认禁止。

View File

@@ -0,0 +1,154 @@
---
title: 前端静态资源加载的一些优化
date: 2022-05-06
description: 最近在折腾优化博客由于全站都是部署在Netlify、Vercel的CDN上都是海外节点国内访问延迟高在想办法优化下访问速度和体验。这篇文章来探讨下前端CSS和JS资源的加载。优化目标主要就两个1. 尽可能快,但是不希望我引入的辅助性第三方库影响到页面体验,不要阻塞主要内容渲染. 2. 为了快第三方静态资源肯定是上CDN但是要有容灾CDN挂了要能fallback到其他url
categories:
- 技术
tags:
- 技术
- 前端
- CDN
- JavaScript
---
<!-- # 前端静态资源加载的一些优化 -->
最近在折腾优化博客由于全站都是部署在Netlify、Vercel的CDN上都是海外节点国内访问延迟高在想办法优化下访问速度和体验。线路部分的优化可以看另一篇文章[国外静态网站托管服务商国内速度对比及线路优化](https://blog.colinx.one/posts/%E5%9B%BD%E5%A4%96%E9%9D%99%E6%80%81%E7%BD%91%E7%AB%99%E6%89%98%E7%AE%A1%E5%9C%A8%E5%9B%BD%E5%86%85%E9%80%9F%E5%BA%A6%E5%AF%B9%E6%AF%94%E5%8F%8A%E7%BA%BF%E8%B7%AF%E4%BC%98%E5%8C%96/)。这篇文章来探讨下前端CSS和JS资源的加载。
优化目标主要就两个:
* 尽可能快,但是不希望我引入的辅助性第三方库影响到页面体验,不要阻塞主要内容渲染
* 为了快第三方静态资源肯定是上CDN但是要有容灾CDN挂了要能fallback到其他url
## 静态资源异步加载
`prefetch``preload`这些预加载技术暂且不谈,博客站点没那么多资源。这里主要是用`async``defer`来控制脚本异步加载以避免阻塞DOM解析和页面渲染。
使用`async`异步加载,对于[pangu](https://github.com/vinta/pangu.js/)这种会影响到内容呈现的使用`async`,对于统计类第三方库使用`defer`延迟加载到DOM加载完再执行
有些第三方库需要手动init这样就不能使用`defer``async`关键字加载资源了,**`defer``async`关键字只适用于远程资源**,本以为把远程资源的`<script>`和内嵌在HTML里用来init的`<script>`都加上`defer`就可以利用它顺序加载的特性解决这个问题结果发现不是这样的。。。。异步打乱脚本执行顺序init脚本不等待资源下载完毕会先执行。利用好`onload`事件可以解决这个问题。
before
```html
<script src="https://cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
<script>
pangu.spacingElementByClassName('post');
pangu.spacingElementByTagName('p');
document.addEventListener('DOMContentLoaded', () => {
pangu.autoSpacingPage();
});
</script>
```
after
```html
<script>
function panguSpaing() {
pangu.spacingElementByClassName('post');
pangu.spacingElementByTagName('p');
document.addEventListener('DOMContentLoaded', () => {
// listen to any DOM change and automatically perform spacing via MutationObserver()
pangu.autoSpacingPage();
});
}
</script>
<script async onload="panguSpaing()" src="https://cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
```
除了`onload`还有`onerror`,还可以利用`onerror`事件在资源加载失败时fallback到其他CDN详见下文
这里跑了个测试看下优化前后的差距
**优化前**
![image-20220506193639029](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205062117479.png)
![image-20220506193800266](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205062117127.png)
First Contentful Pain Time在1.5s整个页面到1.5s才能可见DOM加载总时间达到了2.5s
本来我都已经把首页不需要加载的三方库都拿走了但是还剩下一个这个用于前端性能监控的js阻塞了渲染挂的是腾讯云的CDN国内快到飞起国外就卡到不行作为对比上图里从jsdelivr加载的js也是快到飞起墙内就慢得一批
**优化后**
![image-20220506193652188](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205062117498.png)
优化后页面没有再阻塞0.8s页面就可用了总DOM加载时间只有1.5s,相较之前简直直接起飞。
![cn](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205071426038.png)
国内某检测平台的结果也显示优化效果明显
## 静态资源Fallback加载
国内好用的静态资源CDN还真没有新浪那种只提供那么几个热门的库完全不符合需求BootCDN炸了不是一次两次字节CDN的资源URL有够uglyURL里面还带节点信息多半后面会出问题。360奇舞CDN之前也换过域名、备案出问题感觉每一个能省心用。七牛的目前看上去还行也不知道后面会不会出什么幺蛾子。。。为了稳妥起见+照顾全球的访客还是优先使用的cloudflare和jsdelivr的CDN
网站主要三方库都是通过jsdelivr和cloudflare引入的但是毕竟是海外的节点不知道哪一天就被墙了所以还要为墙内的访客准备一个fallback方案。这里利用到`script`标签的`onerror`事件
现代浏览器都支持`script``link`标签上的`onload``onerror`事件,详细支持情况可以查看这里
[https://pie.gd/test/script-link-events/](https://pie.gd/test/script-link-events/)
关于`onerror`,中文互联网上有好几篇文章说他会捕获`script`标签里的代码的执行错误。。。简直离谱。稍微查下MDN之类的文档就可以发现这玩意本来就是只捕获资源加载错误的
> The onerror event is triggered if an error occurs while loading an external file (e.g. a document or an image).
>
> https://www.w3schools.com/jsref/event_onerror.asp
利用好这个特性就可以实现在资源加载失败时fallback从另一个url加载资源。
```html
<script>
function fallbackJSloader(url, loadedEvent) {
console.log('Error loading asset, using fallback url');
console.log('load asset from', url);
let script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
script.async = true;
if (loadedEvent)
script.setAttribute('onload', `${loadedEvent}()`)
document.body.appendChild(script);
}
</script>
<script defer onload="init_gitalk()"
onerror="fallbackJSloader('https://cdn.staticfile.org/gitalk/1.7.2/gitalk.min.js','init_gitalk')"
src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js">
```
CSS的fallback加载同理此处不再赘述
优化后如图在开发者工具中手动block资源网站可以自动fallback从另一个url加载资源这下网站的可用性又提升了一点点🤏哈哈哈
![66230832-3581-42DF-9F2F-B817E88DAF4D](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205062133393.png)
## 扩展阅读
* [消除阻塞页面渲染的资源](https://www.w3cplus.com/performance/remove-block-rendering.html)
* [defer 和 async 的区别](https://segmentfault.com/q/1010000000640869)
* [动态加载 css](http://lengyun.github.io/js/3-2-2dynamicAddCSS.html#%E4%B8%8E%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BDjs%E7%9A%84%E5%8C%BA%E5%88%AB)
**网站profile**工具
* [https://www.webpagetest.org](https://www.webpagetest.org)

View File

@@ -0,0 +1,146 @@
---
title: 国外静态网站托管服务商国内速度对比及线路优化
date: 2022-05-05
description: 主要探讨Netlify、Vercel、Cloudflare Pages、Azure Web Hosting在国内的速度对比及线路优化
categories:
- 技术
tags:
- 技术
- Netlify
- Vercel
- 优化
---
<!-- # 国外静态网站托管服务商国内速度对比及线路优化 -->
本文主要探讨 Netlify、Vercel、Cloudflare Pages、Azure Web Hosting 在国内的速度对比及线路优化
以我的博客站点 blog.colinx.one 为例,使用 hugo 构建,选用的模板也很轻量没有太多奇奇怪怪的第三方组件,使用这些静态服务托管主要图个方便,不用备案而且基本流量不限。
分别挂了四个服务商的 CI, 每次更新 Git 仓库都会自动触发构建。分别对四个默认分配的域名进行检测。
## 四家服务商默认设置国内速度测试对比
**Netlify**
[colins-blog.netlify.app](https://colins-blog.netlify.app)
![Netlify在国内的速度检测](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505191719.png)
**Vercel**
[colinx-blog.vercel.app](https://colinx-blog.vercel.app)
![Vercel在国内的速度检测](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505191728.png)
**Azure**
[nice-glacier-095b09e00.1.azurestaticapps.net](https://nice-glacier-095b09e00.1.azurestaticapps.net)
![Azure在国内的速度检测](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505191733.png)
**CloudFlare Pages**
[colinx-blog.pages.dev](https://colinx-blog.pages.dev)
![Cloudflare Pages在国内的速度检测](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505191738.png)
emmm Cloudflare 这在国内的速度可太拉胯了,虽说可以通过自选节点的方式曲线救国,但想了想还是算了。利用好其他三家的节点应该足够国内大部分用户访问。
筛选后可用的节点
```
Netlify
18.140.226.100 amazon SG
54.255.56.197 amazon SG
206.189.46.168 digital ocean SG
Vercel
显示caronet据说为AWS节点 (76.76.21.21 Anycast)
76.76.21.241
76.76.21.98
76.76.21.93
76.76.21.142
76.76.21.22
76.76.21.61
76.76.21.164
Azure
52.175.64.109 US MS
13.70.37.114 HK MS
51.124.12.35 UK
```
## 优化前
优化前使用了 dnspod 的解析服务做 4 个 A 记录的负载均衡,免费版套餐单记录单线路只能设置最多两个负载均衡记录,我这个是之前开通专业版套餐设置的,套餐到期了原有记录依旧保留,所以能设置四条同线路 A 记录负载均衡。
```
before
206.189.46.168 digital ocean %netlify
76.223.126.88 %vercel
18.140.226.100 amazon %netlify
18.139.201.98 amazon %netlify
```
检测一波,红了好几个省份
![image-20220504222718997](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505191745.png)
慢点可以接受,线路不通可不能忍。之前粗略筛的几个节点,如今过了快两年了,线路估计也发生了变化,简单跑了一下这几条,发现这个线路现在的状况实在不咋地
![trace](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505191749.png)
这圈子兜的也太大了些。。。哦原来是 Digital Ocean 的节点啊,那没事了。
亚马逊的节点稍微好些,没有绕道日本这么离谱的行为
![trace](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505191834.png)
再来看看 vercel 节点的表现
![trace2](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505191933.png)
这里是自选的节点,直连东京节点,好评
![trace3](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505192022.png)
但是默认的 AnyCast 节点这个路由就稍微绕路了,看来大中华区还是得自己动手调整下线路
## 优化后
after
![image-20220505190011635](https://blog-1301127393.file.myqcloud.com/BlogImgs/20220505192417.png)
检测优化过程就不赘述了,都是拿几个基本的工具`ping``tcping``httping``traceroute`还有上文的全国网速检测网站对那几个节点挨个检测,直接上结论:
1. Vercel 的 Anycast 基本上都是路由到日本,但是同一个地方可能会被路由到不同的路线,比如有些 IP 从上海出口转日本东京,有些是从广东出口转日本
2. Netlify 的节点主要是在新加坡,提供商有 AWS 和 Digital Ocean实测后者的节点经常性抽风国内流量过去会绕个大圈子还是 AWS 的靠谱些
3. Azure 的静态网页托管服务现在是免费的,带宽和流量啥的妥妥够用,不过开账户有门槛,我是用 Github Education Pack 在 Azure 开了个 Azure for Students 订阅,每年 100 刀额度,到期可续
4. Azure 能用的就香港节点,其他都是去往北美和欧洲的,直接 pass。对电信友好**移动和联通很不友好,饶了一大圈**
5. **AWS 的节点对移动和联通挺友好**,对电信支持略差
6. **Vercel 节点也是对移动和联通友好些**
其他附加信息
1. Netlify 可自定义证书Vercel 不可以。所以要保证 vercel 的服务器可以把域名解析到自家服务器,不然没法续签 SSL 证书
2. Cloudflare 的 CI 啥的做的挺垃圾,起步晚,很多东西不完善
3. Netlify 可以安装插件,推送 sitemap 和网站安全性检测这些我感觉挺好使
最终线路设置
- 电信和其他走 Azure 与 Vercel
- 移动联通走 Netlify 的 AWS 节点,以及 Vercel 在 JP 的节点
- 海外走 Vercel 的 Anycast IP
## 常用线路检测与优化工具链接
Best Trace
https://apps.apple.com/us/app/best-trace/id1037779758?l=zh
IP 批量查询
http://www.jsons.cn/ipbatch/

View File

@@ -4,7 +4,7 @@ date: 2019-09-12
lastmod: 2020-04-29
description: 在一次编译 VSCode 的项目中,跨越千山万水,解决重重依赖后,终于来到了编译环节。然而才开始没多久,就出现了一个匪夷所思的报错。
categories:
- 踩坑记
- 技术
tags:
- 服务器
---

View File

@@ -12,7 +12,7 @@ tags:
- 代理
categories:
- 杂记
- 指南
- 技术
---
<!-- # 我的 RSS 方案与心得 -->
@@ -85,7 +85,7 @@ google 了一番,没人写过我这个问题。。。人家都是爬虫绕过
>
> **Feature 简单一键部署,常用组件整合,自动更新支持,服务健康自检支持,海外站点 RSS 解锁**
![image-20210512190732383](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs20210512190819.png)
![image-20210512190732383](https://blog-1301127393.file.myqcloud.com/BlogImgs20210512190819.png)
感兴趣的朋友可以关注一下 🍺

View File

@@ -4,7 +4,7 @@ date: 2020-02-18
lastmod: 2020-04-29
description: 继机械化、电气化、自动化的三次工业革命后,人类正迎来以互联网为载体的智能化时代。互联网与我们的生活结合得越来越紧密。除了装修房子,购置服装,优化家庭互联网体验也是提升生活质量的一个良好途径。本篇中我们将聚焦网页浏览来优化我们的互联网体验。
categories:
- 教程
- 技术
tags:
- 去广告
- 黑科技
@@ -36,9 +36,9 @@ tags:
![](https://i.loli.net/2020/01/20/JgRAjFCdDpwreBU.png)
![](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20200120213009.png)
![](https://blog-1301127393.file.myqcloud.com/BlogImgs/20200120213009.png)
![](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20200121223647.png)
![](https://blog-1301127393.file.myqcloud.com/BlogImgs/20200121223647.png)
这样的广告呢,虽然他的侵略性或许比以往更小了,不过还是有点碍眼。而且在某种程度上,依然可能会误导家里的老人或是小孩。为了统一家庭的互联网体验,减少不必要的麻烦,这个广告也是我们的 target。由于这个广告是嵌入搜索结果中的如果你用之前的小伎俩打算单独屏蔽这个广告对应的元素的话你就要失望了。因为他会连带着屏蔽所有的搜索结果。这显然是不可取的。下面我们要介绍另外两个工具。
@@ -52,16 +52,16 @@ tags:
![](https://i.loli.net/2020/01/21/ZYhCx2Xzd9yABcI.png)
安装好油猴插件后,你可以在 [Greasyfork.org](https://greasyfork.org/zh-CN/) 上下载各种黑科技般的脚本。安装成功后,油猴会在你进入符合条件的网页时自动启用对应的脚本。比如,你安装了 AC 的这个脚本,而这个网页是适配了某度的,那么当你进入某度的网页时,油猴就会自动启用这个脚本。快来领取属于你的纯净版度度吧。
![](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20200121231059.png)
![](https://blog-1301127393.file.myqcloud.com/BlogImgs/20200121231059.png)
前面介绍的几个,都只是借助第三方工具来屏蔽网页上特定的碍眼的元素。如果我们要阅读来自不同网站的新闻,为了获得机制纯净的阅读体验,难道要用 AdBlock 一个一个选中页面中除文章主体文字以外其他所有元素? 对于这种页面结构非常固定的一类网站,我们是否可以通过某种方式,来只提取页面主体的文字,以优化我们的阅读体验呢?
### 使用浏览器自带的阅读工具
苹果很早就想到了这一点Safari 浏览器可以识别当前的的页面是否是一个结构简单文字为主题的页面。在符合条件的网页上Safari 会提示你使用阅读工具来优化页面,以获得更好的阅读体验。当然,你也可以手动启用他。
![](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20200121233256.png)
![](https://blog-1301127393.file.myqcloud.com/BlogImgs/20200121233256.png)
微软也不甘示弱,在随 Win10 推出的 Microsoft Edge 上,也内置了阅读工具。你可以在地址栏的右边找到他。
![](https://blog-1301127393.cos.ap-shanghai.myqcloud.com/BlogImgs/20200121233739.png)
![](https://blog-1301127393.file.myqcloud.com/BlogImgs/20200121233739.png)
_[注:区别与 2020 年新的基于 Chromium 内核的新 Edge 浏览器,此处指的是老版 Edge HTML 内核的 Microsoft Edge 浏览器]_
### 使用第三方阅读工具 - [简阅 SimpRead](http://ksria.com/simpread/)

View File

@@ -4,7 +4,7 @@ date: 2020-03-10
lastmod: 2020-04-29
description: 随着树莓派上部署的项目越来越多,每次使用 IP + 端口 访问也越来越不方便。考虑使用 Apache 来特定子域名跳转到不同端口对应的不同应用。
categories:
- 踩坑记
- 技术
tags:
- 服务器
- 树莓派

View File

@@ -0,0 +1,141 @@
---
title: 论如何下载任意网站视频
date: 2022-05-09
description: 视频已然成为当今互联网上信息传播的一个重要载体有时会需要下载一些网上某个站点的视频插入PPT或者用做视频素材无论是自己用抑或单纯是给朋友帮个忙掌握一些使用的下载视频的小技巧总是不会错的这里分享一些自用的小技巧包括热门站点下载工具以及应对冷门网站视频下载的技巧应该可以覆盖99.9%的视频下载场景
categories:
- 技术
- 指南
tags:
- 视频
- Linux
- 前端
- FFMPEG
---
<!-- # 论如何下载任意网站视频 -->
视频已然成为当今互联网上信息传播的一个重要载体有时会需要下载一些网上某个站点的视频插入PPT或者用做视频素材无论是自己用抑或单纯是给朋友帮个忙掌握一些使用的下载视频的小技巧总是不会错的这里分享一些自用的小技巧包括热门站点下载工具以及应对冷门网站视频下载的技巧应该可以覆盖99.9%的视频下载场景
## 热门网站电影/电视剧下载
这种其实建议直接找对应资源而不是从源站点下载百度云阿里云盘等找资源的方式我就不再赘述了网上教程多的是。如果是电影资源或者是欧美、日韩的剧可以搜索BT资源自行下载。
这里安利一个油猴脚本:[豆瓣资源下载大师](https://greasyfork.org/zh-CN/scripts/329484-%E8%B1%86%E7%93%A3%E8%B5%84%E6%BA%90%E4%B8%8B%E8%BD%BD%E5%A4%A7%E5%B8%88-1%E7%A7%92%E6%90%9E%E5%AE%9A%E8%B1%86%E7%93%A3%E7%94%B5%E5%BD%B1-%E9%9F%B3%E4%B9%90-%E5%9B%BE%E4%B9%A6%E4%B8%8B%E8%BD%BD),可以在豆瓣的影视详情页右侧显示有资源的站点,非常方便
![image-20220509144533549](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205091548956.png)
分享下个人常用的下载站点:
* 欧美资源下载:[1337X](https://www.1337x.to/)
* 欧美资源下载:[海盗湾](https://piratebay.live/)
* 动漫资源下载:[ACG RIP](https://acg.rip/?term=JOJO%E7%9A%84%E5%A5%87%E5%A6%99%E5%86%92%E9%99%A9)
* 中文字幕下载:[字幕库](http://zimuku.org)
个人推荐的下载工具:
* [qBittorrent](https://www.qbittorrent.org)强推老牌专业BT工具有图形化界面[支持Docker部署](https://hub.docker.com/r/linuxserver/qbittorrent)且带Web界面
* [aria2](http://aria2.github.io):强大的命令行下载工具,灵活但上手成本略高,可[自行部署Web GUI界面](https://ariang.mayswind.net/zh_Hans/),也可使用[公开版本demo](http://ariang.mayswind.net/latest)
* [Motrix](https://motrix.app)高颜值跨平台的下载工具有漂亮的GUI界面底层基于aria2
Tracker列表
* 一个独立的收集trackerlist的页面[https://trackerslist.com/#/zh](https://trackerslist.com/#/zh)
* 通用tracker list[ngosang/trackerslist](ngosang/trackerslist)
* 动漫资源tracker list[animeTrackerList](https://github.com/DeSireFire/animeTrackerList) (๑•̀ㅂ•́)و✧
## 热门站点普通视频资源下载
如果是UGC内容比如B站用户上传的视频那么BT通常是没有资源的需要单独从源网站下载。不过既然是热门站点都有很多人造过轮子了这里推荐几个
[**YouTube-DL**](https://github.com/ytdl-org/youtube-dl)
一款强大的命令行视频下载工具别看人家名字只写了youtube但其实国内爱优腾都是支持的。命令行调用也非常简洁[知乎也有教程](https://github.com/ytdl-org/youtube-dl)需要的话可以瞅瞅。
[**YT-DLPYouTube DownLoader Plus**](https://github.com/yt-dlp/yt-dlp)
YouTube-DL的一个分支包括一些bug修复和增强的特性
[**Lux原名Annie**](https://github.com/iawia002/lux)
Golang编写的一个视频下载工具同样支持国内站点
**[硕鼠](https://www.flvcd.com/index.htm)**
很早之前就出的一款免费视频下载合并工具主要针对国内视频网站但是像腾讯视频这种之前发过律师函人家就迫不得已取消了支持。Windows版有界面对于不是那么热门但是稍微又有点名气的网站支持较好
## 冷门站点普通视频资源下载
冷门站点的资源得我们自己动手了,不过利用浏览器的开发人员工具还是很容易获取的资源的。右键找到开发人员选项打开开发人员工具,可以点击左上角的按钮选择网页元素,找到`<video>`标签,里面一般会有一个链接地址,复制地址打开即可。
这种简单的视频嵌入很容易下载,浏览器工具也很容易嗅探到。比如可以使用`专业视频下载工具`插件,你可以[访问360插件中心下载](https://ext.chrome.360.cn/webstore/detail/noaehhegaeigebicejggjdecdkfphced)。这种工具很多,这里不再赘述
链接后缀为`mp4`的一般来说都是说明该网页上面的视频只是从那一个文件加载的,没有经过分片和其他处理。如果没有后缀名,或者是`flv``ts`或者链接含有`m3u8`字样的,说明该网页的资源是经过分片的,需要我们动点手段。
## 冷门站点m3u8动态分片视频资源下载
以中国庭审网的庭审录像视频为例打开开发者工具定位到视频的部分发现video标签里面的url很奇怪访问该链接也并不能访问到有效的视频。这种网页一般都是通过m3u8来下发分片文件的信息
![image-20220509151813071](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205091548957.png)
打开开发者工具的网络选项卡监听网络活动点击播放视频会多出来很多条目分别代表每一个网络请求。在搜索框输入m3u8来进行过滤。定位到该请求后可以在新标签页打开保存这个m3u8文件。
![image-20220509144410278](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205091548958.png)
之后我们可以利用ffmpeg载入这个m3u8文件并进行合并如有需要可一并进行转码操作
```shell
ffmpeg -i xxxx.m3u8 -c xxxx.mp4
```
如果报错提示不支持的protocol那么需要再加个参数让ffmpeg使用http下载
```shell
ffmpeg -protocol_whitelist concat,file,http,https,tcp,tls,crypto -i xxxx.m3u8 -c copy xxxx.mp4
```
接下来等待命令跑完,我们就可以得到需要的视频文件了。
其他常用处理命令
使用`-i`参数读取文件,查看详细参数
```shell
ffmpeg -i xxxx.mp4
```
使用ffmepg提取视频中的音频部分方便后续处理。比如要生成字幕或是转写为文本省的上传几百兆的视频文件。[网易见外工作台](https://jianwai.youdao.com/)做这些很方便,而且免费额度也很足,安利一波
```shell
ffmpeg -i xxxx.mp4 -vn -codec copy xxxx.aac
```
![image-20220509153021601](https://blog-1301127393.file.myqcloud.com/BlogImgs/202205091548959.png)
解析并下载m3u8视频的其他方案
* 使用硕鼠解析https://www.flvcd.com/index.htm
* 使用Chrome插件[CoCoCut](https://chrome.google.com/webstore/detail/video-downloader-cococut/gddbgllpilhpnjpkdbopahnpealaklle)
* 使用油猴脚本:[m3u8-downloader](https://greasyfork.org/zh-CN/scripts/440577-m3u8-%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD-vip%E8%A7%A3%E6%9E%90%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD-%E7%BD%91%E7%AB%99%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD),配套工具[地址](https://github.com/Momo707577045/m3u8-downloader)
* 使用软件:[NeatDownloadManager](http://www.neatdownloadmanager.com/index.php/en/)
----
以上

View File

@@ -4,10 +4,10 @@ date: 2019-03-12
lastmod: 2020-04-29
description: 从两年前第一次听说黑苹果,到暑假第一次装黑苹果,再到几个月前成功装上黑苹果,一路走来,收获颇丰。在这里将 Dell G3 大致安装过程记录下来。
categories:
- 教程
- 笔记
- 技术
tags:
- 黑苹果
- Apple
---

View File

@@ -1,21 +1,52 @@
<div id="gitalk-container" style="
margin: 20px auto;
max-width: 800px;
padding: 20px;
width: 100%;
text-align: left;
"></div>
<script src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>
<div id="gitalk-container"></div>
<div class='js-toc'></div>
<script>
const gitalk = new Gitalk({
clientID: '94eae56b89dcc480bf4d',
clientSecret: '1e4218c0293a998a9483ab09ba9ace46cabc76b3',
repo: 'Colinx-Blog', // The repository of store comments,
owner: 'Colin-XKL',
admin: ['Colin-XKL'],
id: decodeURI(location.pathname), // Ensure uniqueness and length less than 50
distractionFreeMode: false // Facebook-like distraction free mode
});
gitalk.render('gitalk-container');
let meta = document.querySelectorAll('.post:not(.on-list) .post-meta')[0];
const visitors = `<span id="busuanzi_container_page_pv" style='display:none'> 浏览:<span id="busuanzi_value_page_pv"></span>次</span>`
if (meta) meta.innerHTML = meta.innerHTML + visitors
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.css">
<script>
function tocbot_init() {
tocbot.init({
// Where to render the table of contents.
tocSelector: '.js-toc',
// Where to grab the headings to build the table of contents.
contentSelector: '.post-content',
// Which headings to grab inside of the contentSelector element.
headingSelector: 'h1, h2, h3',
// For headings inside relative or absolute positioned containers within content.
hasInnerContainers: true,
});
}
function init_gitalk() {
const gitalk = new Gitalk({
clientID: '94eae56b89dcc480bf4d',
clientSecret: '1e4218c0293a998a9483ab09ba9ace46cabc76b3',
repo: 'Colinx-Blog', // The repository of store comments,
owner: 'Colin-XKL',
admin: ['Colin-XKL'],
id: decodeURI(location.pathname), // Ensure uniqueness and length less than 50
distractionFreeMode: false // Facebook-like distraction free mode
});
gitalk.render('gitalk-container');
}
</script>
<script defer
onerror="fallbackJSloader('https://cdn.staticaly.com/gh/panr/hugo-theme-hello-friend/master/static/assets/prism.js')"
src="{{ "assets/prism.js" | absURL }}"></script>
<script defer onload="tocbot_init()"
onerror="fallbackJSloader('https://cdn.staticfile.org/tocbot/4.9.1/tocbot.min.js','tocbot_init')"
src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.11.1/tocbot.min.js"></script>
<link rel="stylesheet"
onerror="fallbackCSSloader('https://cdn.staticfile.org/tocbot/4.9.1/tocbot.css')"
href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.11.1/tocbot.css">
<script defer onload="init_gitalk()"
onerror="fallbackJSloader('https://cdn.staticfile.org/gitalk/1.7.2/gitalk.min.js','init_gitalk')"
src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>
<link rel="stylesheet"
onerror="fallbackCSSloader('https://cdn.staticfile.org/gitalk/1.7.2/gitalk.css')"
href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.css">
<!-- no min css version fallback for gitalk css -->

View File

@@ -0,0 +1,18 @@
<script>
function panguSpaing() {
pangu.spacingElementByClassName('post');
pangu.spacingElementByTagName('p');
// listen to any DOM change and automatically perform spacing via MutationObserver()
document.addEventListener('DOMContentLoaded', () => {
pangu.autoSpacingPage();
});
}
</script>
<script async
onerror="fallbackJSloader('https://cdn.staticaly.com/gh/panr/hugo-theme-hello-friend/master/static/assets/main.js')"
src="{{ "assets/main.js" | absURL }}"></script>
<script async onload="panguSpaing()"
onerror="fallbackJSloader('https://cdn.staticfile.org/pangu/4.0.7/pangu.min.js','panguSpaing')"
src="https://cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>

View File

@@ -1,7 +1,47 @@
<script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<style type="text/css">body {font-weight: unset !important;font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif!important;}</style>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22>
<text y=%22.9em%22 font-size=%2290%22>👋</text></svg>">
<script>
function loadAgies() {
const aegis = new Aegis({
id: 'gQ7V9SgjxZdOm1gy35', // 上报 id
// uin: 'xxx', // 用户唯一 ID可选
reportApiSpeed: true, // 接口测速
reportAssetSpeed: true, // 静态资源测速
spa: true // spa 应用页面跳转的时候开启 pv 计算
});
}
function fallbackJSloader(url, loadedEvent) {
console.log('Error loading asset, using fallback url');
console.log('load asset from', url);
let script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
script.async = true;
if (loadedEvent)
script.setAttribute('onload', `${loadedEvent}()`)
document.body.appendChild(script);
}
function fallbackCSSloader(url) {
console.log('Error loading asset, using fallback url');
console.log('load asset from', url);
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = url;
let head = document.getElementsByTagName("head")[0];
head.appendChild(link);
}
</script>
<script async onload="loadAgies()" src="https://cdn-go.cn/aegis/aegis-sdk/latest/aegis.min.js"></script>
<script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<link rel="preconnect" href="https://cdnjs.cloudflare.com">
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<meta http-equiv="x-dns-prefetch-control" content="on">
<link rel="dns-prefetch" href="//api.github.com" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22>
<text y=%22.9em%22 font-size=%2290%22>👋</text></svg>">
<link rel="dns-prefetch" href="//avatars.githubusercontent.com" />
<style type="text/css">body {font-weight: unset !important;font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Microsoft YaHei,Source Han Sans SC,Noto Sans CJK SC,WenQuanYi Micro Hei,sans-serif!important;}
.framed{width: 100%;} .framed .h-anchor{display: none;}</style>

View File

@@ -1,23 +1,3 @@
<!-- 超链接样式 -->
<style>
.post-tags a,
.post-content a {
text-decoration: none;
border-bottom: 1px dashed #d71a1b;
-webkit-transition: all .2s;
transition: all .2s;
}
.post-tags a:hover,
.post-content a:hover,
nav a:hover {
text-decoration: none;
border-bottom: 1px solid #d71a1b;
-webkit-transition: all .2s ease-out;
transition: all .2s ease-out;
}
</style>
<footer class="footer">
<span id="busuanzi_container_site_pv" style='display:none'>
嗨,第<span id="busuanzi_value_site_pv"></span>位小伙伴 : )
@@ -38,29 +18,4 @@
</div>
</footer>
<script src="{{ "assets/main.js" | absURL }}"></script>
<script async src="{{ "assets/prism.js" | absURL }}"></script>
<script>
meta = document.querySelectorAll('.post:not(.on-list) .post-meta')[0];
var visitors = `<span id="busuanzi_container_page_pv" style='display:none'> 浏览:<span id="busuanzi_value_page_pv"></span>次</span>`
if (meta) meta.innerHTML = meta.innerHTML + visitors
</script>
<!-- Sentry -->
<script src="https://browser.sentry-cdn.com/6.15.0/bundle.tracing.min.js"
integrity="sha384-1k7XKRQgqjUbNyG2sI+qsY8HTHMOeLdycMx6hoGuNSANZ3WrMa3LXkr+M4t+SIpF"
crossorigin="anonymous"></script>
<script>
Sentry.init({
dsn: "https://446fb53b106744b1b70e1074e68a5e71@o850059.ingest.sentry.io/6077493",
integrations: [new Sentry.Integrations.BrowserTracing()],
// Set tracesSampleRate to 1.0 to capture 100%
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 1.0,
});
</script>
{{- partial "extended_footer.html" . }}

View File

@@ -0,0 +1,38 @@
<!-- this file was ported and edited from theme, check if there's any update in the original repo -->
<!-- do not use code formatting -->
<!-- do not edit this file unless neccessary -->
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="{{ if .IsHome }}{{ $.Site.Params.Subtitle }}{{ else }}{{ .Summary | plainify }}{{ end }}"
/>
<meta
name="keywords"
content="{{ with .Params.Keywords }}{{ delimit . ", " }}{{ else }}{{ $.Site.Params.Keywords }}{{ end }}"
/>
<meta name="robots" content="noodp" />
<link rel="canonical" href="{{ path.Join $.Site.Params.canonicalRelLinkBase .Permalink }}" />
<!-- head custom -->
{{- partial "prepended_head.html" . }}
<!-- Custom CSS to override theme properties (/static/style.css) -->
<link rel="stylesheet" href="{{ "style.css" | absURL }}" />
<!-- Theme CSS -->
<link rel="stylesheet" href="{{ "assets/style.css" | absURL }}" />
<!-- Icons,deleted for using emoji favicon-->
<!-- Fonts, disabled-->
<!-- OG data -->
{{ template "_internal/opengraph.html" . }}
<!-- RSS | JSON -->
{{ range .AlternativeOutputFormats -}}
{{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .RelPermalink $.Site.Title | safeHTML }}
{{ end -}}
<!-- head custom -->
{{- partial "extended_head.html" . }}

118
static/style.css Normal file
View File

@@ -0,0 +1,118 @@
/* gittalk comment style */
#gitalk-container {
margin: 20px auto;
max-width: 800px;
padding: 20px;
width: 100%;
text-align: left;
}
/* toc style */
@media (min-width: 1500px) {
.js-toc {
display: block !important;
}
}
.js-toc {
display: none;
/* IE and Edge */
-ms-overflow-style: none;
/* Firefox */
scrollbar-width: none;
}
.js-toc::-webkit-scrollbar {
/* Chrome, Safari and Opera */
display: none;
}
.js-toc {
position: fixed;
width: 20%;
max-width: 400px;
right: 3rem;
top: 10em;
text-align: left;
overflow-y: scroll;
overflow-x: hidden;
padding: 1rem 0rem;
}
ol.toc-list > li > a:hover {
text-underline-position: under;
font-weight: bolder;
}
.toc-list li {
list-style: none;
}
.toc-list a {
text-decoration: none;
text-overflow: ellipsis;
display: inline-block;
white-space: nowrap;
font-size: 1rem;
}
.is-active-link::before {
background-color: #d71a1b !important;
}
.logo__cursor {
background: #d71a1b;
}
/* 超链接样式 */
.post-tags a,
.post-content a {
text-decoration: none;
border-bottom: 1px dashed #d71a1b;
-webkit-transition: all 0.2s;
transition: all 0.2s;
}
.post-tags a:hover,
.post-content a:hover,
nav a:hover {
text-decoration: none;
border-bottom: 2px solid #d71a1b;
-webkit-transition: all 0.1s ease;
transition: all 0.1s ease;
}
/* custom ::selection */
::selection {
background: #b5b5b5;
color: #fff;
}
::-moz-selection {
background: #b5b5b5;
color: #fff;
}
::-webkit-selection {
background: #b5b5b5;
color: #fff;
}
/* abandoned link style */
/* .post-content a {
transition: background-size 0.1s ease;
background: linear-gradient(to bottom, transparent 62%, #fff56644 0) center center/0% 75% no-repeat;
color: #52c41a;
cursor: pointer;
}
.post-content a:hover {
background-size: 100% 100%;
color: #389e0d;
}
.post-content a:active {
background-size: 80% 100%;
} */