<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>东东's Blog</title><link href="https://blog.yasking.org/" rel="alternate"></link><link href="https://blog.yasking.org/atom.xml" rel="self"></link><id>https://blog.yasking.org/</id><updated>2026-03-17T13:15:00+08:00</updated><entry><title>Memos: Ghostty 开箱即用配置</title><link href="https://blog.yasking.org/a/1773724092.html" rel="alternate"></link><published>2026-03-17T13:15:00+08:00</published><updated>2026-03-17T13:15:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-17:/a/1773724092.html</id><summary type="html">&lt;p&gt;之前使用 Ghostty 默认配置，在网上看到有人分享了一份开箱即用的配置，效果良好已经装配。&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/memos/1773724092/03.png" alt="Ghostty 01"&gt;
  &lt;img src="https://images.yasking.org/memos/1773724092/02.jpeg" alt="Ghostty 02"&gt;
  &lt;img src="https://images.yasking.org/memos/1773724092/01.png" alt="Ghostty 03"&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;配置和安装说明&lt;/summary&gt;

安装字体


&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install --cask …&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;</summary><content type="html">&lt;p&gt;之前使用 Ghostty 默认配置，在网上看到有人分享了一份开箱即用的配置，效果良好已经装配。&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/memos/1773724092/03.png" alt="Ghostty 01"&gt;
  &lt;img src="https://images.yasking.org/memos/1773724092/02.jpeg" alt="Ghostty 02"&gt;
  &lt;img src="https://images.yasking.org/memos/1773724092/01.png" alt="Ghostty 03"&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;配置和安装说明&lt;/summary&gt;

安装字体


&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install --cask font-maple-mono-nf-cn
&lt;/code&gt;&lt;/pre&gt;


将配置放置到 `~/.config/ghostty/config`


&lt;pre&gt;&lt;code class="language-bash"&gt;# ===========================
# Ghostty 完整配置
# ===========================

# --- 外观 ---
# 主题跟随系统深色模式自动切换
# theme = light:Catppuccin Latte,dark:Catppuccin Mocha
theme = Catppuccin Mocha

# 背景透明度（0.0 ~ 1.0）
background-opacity = 0.88

# 背景模糊（配合透明度使用，毛玻璃效果）
background-blur = 20

# 背景图片（可选，放一张喜欢的图，终端瞬间好看）
# background-image = ~/Pictures/wallpaper.png
# background-image-opacity = 0.3
# background-image-fit = cover

# 标题栏集成 Tab 栏（比 hidden 多了 Tab 支持）
macos-titlebar-style = tabs

# 非活跃分屏的透明度（让你一眼看出焦点在哪）
unfocused-split-opacity = 0.9

# --- 字体 ---
# 推荐 Maple Mono NF CN（brew install --cask font-maple-mono-nf-cn）
font-family = &amp;quot;Maple Mono NF CN&amp;quot;
font-size = 14
font-thicken = true

# 连字支持
font-feature = calt
font-feature = liga

# --- 窗口行为 ---
# 永远记住窗口状态（分屏、Tab、目录）
window-save-state = always

# 新分屏继承当前目录
window-inherit-working-directory = true

# 新窗口继承字体大小
window-inherit-font-size = true

# 内边距
window-padding-x = 4
window-padding-y = 4
window-padding-balance = true

# --- Quick Terminal（下拉终端） ---
keybind = global:ctrl+grave_accent=toggle_quick_terminal
quick-terminal-screen = main
quick-terminal-position = top
quick-terminal-size = 50%
quick-terminal-autohide = true
quick-terminal-animation-duration = 0.15

# --- Shell 集成 ---
# 自动注入 shell 集成（光标样式、sudo、标题、SSH terminfo）
shell-integration-features = cursor,sudo,title,ssh-terminfo,ssh-env

# --- 滚动 ---
# 滚动缓冲区大小，单位是字节（默认 10MB，这里设为 50MB）
scrollback-limit = 50000000

# --- 光标 ---
cursor-style = block
cursor-style-blink = false

# 鼠标隐藏（打字时自动隐藏鼠标）
mouse-hide-while-typing = true

# --- 剪贴板 ---
# 选中即复制到系统剪贴板（和 iTerm2 一样）
copy-on-select = clipboard

# 复制时自动去除行尾空格
clipboard-trim-trailing-spaces = true

# --- macOS 专属 ---
# 退出时不弹确认框（如果你习惯了 Cmd+Q）
confirm-close-surface = false

# Option 键作为 Alt 使用（对 vim/emacs 用户很重要）
macos-option-as-alt = true
&lt;/code&gt;&lt;/pre&gt;


原文章链接：[https://x.com/alin_zone/status/2033524177295274496](https://x.com/alin_zone/status/2033524177295274496)

&lt;/details&gt;</content><category term="Memos"></category><category term="Terminal"></category><category term="Software"></category></entry><entry><title>代码考古：用 gitcharts 挖掘 Git 仓库的演变轨迹</title><link href="https://blog.yasking.org/a/git-code-archaeology.html" rel="alternate"></link><published>2026-03-16T12:29:41+08:00</published><updated>2026-03-16T12:29:41+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-16:/a/git-code-archaeology.html</id><summary type="html">&lt;p&gt;运行了几个项目，效果如下&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/technology/1773638587/01.svg" alt="gitcharts 01"&gt;
  &lt;img src="https://images.yasking.org/technology/1773638587/02.svg" alt="gitcharts 02"&gt;
  &lt;img src="https://images.yasking.org/technology/1773638587/03.svg" alt="gitcharts 03"&gt;
  &lt;img src="https://images.yasking.org/technology/1773638587/04.svg" alt="gitcharts 04"&gt;
&lt;/div&gt;

&lt;p&gt;不同颜色代表不同时期的代码，可以看到项目是否频繁重构。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意本篇非严肃性技术文章，仓库 …&lt;/strong&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;运行了几个项目，效果如下&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/technology/1773638587/01.svg" alt="gitcharts 01"&gt;
  &lt;img src="https://images.yasking.org/technology/1773638587/02.svg" alt="gitcharts 02"&gt;
  &lt;img src="https://images.yasking.org/technology/1773638587/03.svg" alt="gitcharts 03"&gt;
  &lt;img src="https://images.yasking.org/technology/1773638587/04.svg" alt="gitcharts 04"&gt;
&lt;/div&gt;

&lt;p&gt;不同颜色代表不同时期的代码，可以看到项目是否频繁重构。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意本篇非严肃性技术文章，仓库作者的项目(&lt;a href="https://github.com/koaning/gitcharts"&gt;koaning/gitcharts&lt;/a&gt;)可能会随时有破坏性改动，当前的脚本也仅适用于在本地项目根目录中执行，如遇报错建议使用 AI 进行评估和校正。&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;安装 koaning/gitcharts&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ mkdir -p ~/Portable/gitcharts &amp;amp;&amp;amp; cd ~/Portable/gitcharts

$ git clone https://github.com/koaning/gitcharts.git gitcharts-viewer
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;创建一个便捷脚本并添加到 PATH&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ mkdir -p ~/Portable/bin

$ cat &amp;gt; ~/Portable/bin/git-archaeology &amp;lt;&amp;lt;'EOF'
#!/usr/bin/env bash
set -euo pipefail
uv run --python 3 &amp;quot;$HOME/Portable/gitcharts/gitcharts-viewer/git_archaeology.py&amp;quot; &amp;quot;$@&amp;quot;
EOF

$ chmod +x ~/Portable/bin/git-archaeology


# 加到 Path
$ echo 'export PATH=&amp;quot;$HOME/Portable/bin:$PATH&amp;quot;' &amp;gt;&amp;gt; ~/.zshrc

$ source ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之后就可以使用&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ git-archaeology --repo . --samples 80 --file-extensions .md,.js,.mjs,.py,.html,.css,.rst,.go --version-source none
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当然这仍然比较麻烦，运行后像查看数据、清理仓库中的临时文件和产出&lt;/p&gt;
&lt;p&gt;再创建一个脚本&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ cat &amp;gt; ~/Portable/bin/gitcharts-add &amp;lt;&amp;lt;'EOF'
#!/usr/bin/env bash
set -euo pipefail

repo_name=&amp;quot;${1:-$(basename &amp;quot;$PWD&amp;quot;)}&amp;quot;
viewer_dir=&amp;quot;$HOME/Portable/gitcharts/gitcharts-viewer&amp;quot;
viewer_charts=&amp;quot;$viewer_dir/charts&amp;quot;

git-archaeology \
  --repo . \
  --samples 80 \
  --file-extensions .md,.js,.mjs,.py,.html,.css,.rst,.go \
  --version-source none

mkdir -p &amp;quot;$viewer_charts&amp;quot;
cp charts/.-clean.json &amp;quot;$viewer_charts/${repo_name}-clean.json&amp;quot;

if [ -f charts/.-versioned.json ]; then
  cp charts/.-versioned.json &amp;quot;$viewer_charts/${repo_name}-versioned.json&amp;quot;
fi

cd &amp;quot;$viewer_dir&amp;quot;
uv run --python 3 --with jsonschema generate_repos_list.py

cd &amp;quot;$OLDPWD&amp;quot;
rm -rf .downloads charts git-research
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加为可执行文件&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;chmod +x ~/Portable/bin/gitcharts-add
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之后，在&lt;strong&gt;Git 项目根目录&lt;/strong&gt;下运行 &lt;code&gt;gitcharts-add&lt;/code&gt; 命令即可自动生成和清理&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 执行
$ gitcharts-add

# 或者可以执行
$ gitcharts-add my-repo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;每次运行，生成的数据 JSON 被同步到了以下目录&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;~/Portable/gitcharts/gitcharts-viewer/charts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看图表&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;cd ~/Portable/gitcharts/gitcharts-viewer

uv run --python 3 -m http.server 8100
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;浏览器访问：&lt;code&gt;http://127.0.0.1:8100&lt;/code&gt;&lt;/p&gt;</content><category term="Technology"></category><category term="Git"></category></entry><entry><title>烹饪日记：香煎罗非鱼</title><link href="https://blog.yasking.org/a/fry-tilapia.html" rel="alternate"></link><published>2026-03-15T22:00:00+08:00</published><updated>2026-03-15T22:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-15:/a/fry-tilapia.html</id><summary type="html">&lt;p&gt;食材是从淘宝网购的冷冻罗非鱼，去骨去刺 52.9/3斤，不知道性价比如何，化开后看着肉质比想象中的要好，生鱼闻着也有肉 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;食材是从淘宝网购的冷冻罗非鱼，去骨去刺 52.9/3斤，不知道性价比如何，化开后看着肉质比想象中的要好，生鱼闻着也有肉香味&lt;/p&gt;
&lt;p&gt;切块并清洗干净，使用厨房用纸沾干上面的水分&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/01.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;加盐和黑胡椒煨制，一斤鱼肉大概一啤酒盖盐，黑胡椒适量增味去腥&lt;/p&gt;
&lt;p&gt;煨制时间十分钟左右，最好不超过 15 分钟，太长时间鱼可能会被盐重新沙出水来&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/02.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;热锅凉油，我使用的铸铁锅，油不要太少，可以半煎半炸&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/03.jpg" alt="热锅凉油"&gt;
&lt;/div&gt;

&lt;p&gt;裹上面粉口感和香味都更好！面粉和红薯淀粉，配比大概2比1，比例我感觉随意一些即可&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/04.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;将鱼裹上面粉，抖掉多余的面粉，在过面粉之前鱼如果不太干爽，仍可用厨房用纸吸附下上面的水份&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/05.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;然后一个个的下到平底锅煎制，可以按照钟表顺时针方向摆放，便于知道哪块是新下的，翻面的时候也能知道最早下的&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/06.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;全程中小火，不要频繁翻动，让其充分定形，我感觉裹上面粉的罗非鱼不太粘锅，鱼肉也比较‘硬’，不是那种‘绵绵’的肉质，轻易不会粘锅，烹饪难度较低&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/07.jpg" alt="罗非鱼"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/08.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;罗非鱼比较好熟，并且已经切成了小块，颜色看着差不多了捞出控油就行，肯定是熟的&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/09.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;继续烹饪 🍳&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/10.jpg" alt="罗非鱼"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/11.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;撒上一些烧烤料，香气扑鼻，罗非鱼是很适合煎制的鱼，口感不错，营养价值一般，胜在没有刺鱼肉蛋白好吸收&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/13.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;

&lt;p&gt;进行分装，分两顿吃，最后就是厨房忘记关门，煎完鱼发现客厅油烟爆炸&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/kitchen/1773580729/12.jpg" alt="罗非鱼"&gt;
&lt;/div&gt;</content><category term="Kitchen"></category></entry><entry><title>Memos: 新时代程序员的顶级焦虑</title><link href="https://blog.yasking.org/a/1773397828.html" rel="alternate"></link><published>2026-03-13T19:30:00+08:00</published><updated>2026-03-13T19:30:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-13:/a/1773397828.html</id><content type="html">&lt;p&gt;Without AI, I wouldn't be able to code. 🤷‍♂️&lt;/p&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/memos/1773397828/07.png" alt="Cursor 额度用尽"&gt;
  &lt;img src="https://images.yasking.org/memos/1773397828/06.png" alt="Codex 续命但额度也用尽了"&gt;
&lt;/div&gt;

&lt;p&gt;P.S. 感谢黄鱼 6.99 RMB 月抛 &lt;em&gt;Open AI Business&lt;/em&gt; 车拯救了我。&lt;/p&gt;</content><category term="Memos"></category><category term="Cursor"></category><category term="Codex"></category></entry><entry><title>Memos: 博客新增图文布局和轮播图效果支持</title><link href="https://blog.yasking.org/a/1773193856.html" rel="alternate"></link><published>2026-03-12T19:30:00+08:00</published><updated>2026-03-12T19:30:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-12:/a/1773193856.html</id><summary type="html">&lt;p&gt;借助 AI Support，博客完善了图像显示，这篇 memo 用于记录可复用的图文布局。&lt;/p&gt;
&lt;h3&gt;并排 2 张图&lt;/h3&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/01.jpg" alt="布局示例图 01"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/03.jpg" alt="布局示例图 03"&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;查看代码&lt;/summary&gt;


&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;media-pair&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 01&amp;quot;&amp;gt;
  &amp;lt;img …&lt;/code&gt;&lt;/pre&gt;&lt;/details&gt;</summary><content type="html">&lt;p&gt;借助 AI Support，博客完善了图像显示，这篇 memo 用于记录可复用的图文布局。&lt;/p&gt;
&lt;h3&gt;并排 2 张图&lt;/h3&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/01.jpg" alt="布局示例图 01"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/03.jpg" alt="布局示例图 03"&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;查看代码&lt;/summary&gt;


&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;media-pair&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 01&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 02&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;/details&gt;

&lt;!--more--&gt;

&lt;h3&gt;并排 2 张图（超过 2 张自动切换）&lt;/h3&gt;
&lt;div class="media-pair"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/01.jpg" alt="布局示例图 01"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/03.jpg" alt="布局示例图 03"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/05.jpg" alt="布局示例图 05"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/06.jpg" alt="布局示例图 06"&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;查看代码&lt;/summary&gt;


&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;media-pair&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 01&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 02&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 03&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 04&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;/details&gt;

&lt;h3&gt;自适应多图网格&lt;/h3&gt;
&lt;div class="media-grid cols-3 masonry-js"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/01.jpg" alt="布局示例图 01"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/02.jpg" alt="布局示例图 02"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/03.jpg" alt="布局示例图 03"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/04.jpg" alt="布局示例图 04"&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;查看代码&lt;/summary&gt;


&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;media-grid cols-3 masonry-js&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 01&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 02&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 03&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;/details&gt;

&lt;h3&gt;图左文右&lt;/h3&gt;
&lt;div class="media-split"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/02.jpg" alt="布局示例图 02"&gt;
  &lt;div&gt;
    &lt;p&gt;这里是图文混排文案区域。你可以放一段简短说明、心得、步骤、引用等。&lt;/p&gt;
    &lt;p&gt;这种布局适合「一张重点图 + 一段解释」的场景，阅读节奏会更自然。&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;查看代码&lt;/summary&gt;


&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;media-split&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图片&amp;quot;&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;p&amp;gt;文案内容&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;/details&gt;

&lt;h3&gt;图右文左&lt;/h3&gt;
&lt;div class="media-split reverse"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/04.jpg" alt="布局示例图 04"&gt;
  &lt;div&gt;
    &lt;p&gt;给容器增加 &lt;code&gt;reverse&lt;/code&gt; 即可反转左右顺序，移动端会自动改为单列堆叠。&lt;/p&gt;
    &lt;p&gt;你后续只需要复制这一段结构，替换图片 URL 和文字内容就能复用。&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;查看代码&lt;/summary&gt;


&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;media-split reverse&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图片&amp;quot;&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;p&amp;gt;文案内容&amp;lt;/p&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;/details&gt;

&lt;h3&gt;图片轮播（含灯箱）&lt;/h3&gt;
&lt;div class="media-carousel"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/01.jpg" alt="布局示例图 01"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/03.jpg" alt="布局示例图 03"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/05.jpg" alt="布局示例图 05"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/06.jpg" alt="布局示例图 06"&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;查看代码&lt;/summary&gt;


&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;media-carousel&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 01&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 02&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 03&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;/details&gt;

&lt;hr&gt;
&lt;h3&gt;画廊灯箱（media-gallery）&lt;/h3&gt;
&lt;p&gt;主图大图居中展示，下方缩略图条显示所有图片并高亮当前项，点击 &amp;lt; &amp;gt; 或缩略图切换，点击主图进入全屏灯箱。&lt;/p&gt;
&lt;div class="media-gallery"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/01.jpg" alt="布局示例图 01"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/03.jpg" alt="布局示例图 03"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/05.jpg" alt="布局示例图 05"&gt;
  &lt;img src="https://images.yasking.org/memos/1773193856/06.jpg" alt="布局示例图 06"&gt;
&lt;/div&gt;

&lt;details&gt;
&lt;summary&gt;查看代码&lt;/summary&gt;


&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;div class=&amp;quot;media-gallery&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 01&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 02&amp;quot;&amp;gt;
  &amp;lt;img src=&amp;quot;图片链接&amp;quot; alt=&amp;quot;图 03&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;/details&gt;

&lt;p&gt;顺带，支持了代码折叠显示功能。&lt;/p&gt;</content><category term="Memos"></category><category term="博客配置"></category></entry><entry><title>Memos: 最适合空气炸锅烤着吃的红薯品类</title><link href="https://blog.yasking.org/a/1773138288.html" rel="alternate"></link><published>2026-03-10T19:58:00+08:00</published><updated>2026-03-10T19:58:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-10:/a/1773138288.html</id><summary type="html">&lt;p&gt;「当属小象超市的黄金榴莲蜜薯」。&lt;/p&gt;
&lt;p&gt;自从年前买过两次 “烟薯25号”，我一度不敢轻易购买 “蜜薯”。我固执的认为它们是泡在蜂蜜罐中 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;「当属小象超市的黄金榴莲蜜薯」。&lt;/p&gt;
&lt;p&gt;自从年前买过两次 “烟薯25号”，我一度不敢轻易购买 “蜜薯”。我固执的认为它们是泡在蜂蜜罐中长大的，烤制后流着糖浆，透露着饱含碳水的邪恶微笑，吃起来心里负担极大。&lt;/p&gt;
&lt;p&gt;直到购买了黄金榴莲蜜薯，其软糯适中、甜度又恰到好处（在我能接受的甜度上限之下），空气炸锅烤制 40+ 分钟，散发着焦糖的香味，重拾了我对红薯的热爱，我认为其是烤食红薯 T0 级的存在。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/memos/1773138288/01.jpg"&gt;&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/memos/1773138288/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;商品详情页面介绍显示其产地为：海南澄迈县。&lt;/em&gt;&lt;/p&gt;</content><category term="Memos"></category><category term="美食记录"></category><category term="红薯爱好者"></category></entry><entry><title>Memos: 记录「95分」好吃的‘小帅香菇面’</title><link href="https://blog.yasking.org/a/1772974579.html" rel="alternate"></link><published>2026-03-08T20:58:00+08:00</published><updated>2026-03-08T20:58:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-08:/a/1772974579.html</id><summary type="html">&lt;p&gt;好友小帅的香菇鸡蛋肉丁面，为了追求完美，食材均来自‘地标’原产地，一年前首次吃还能吃到某个食材味道‘更突出’，半年前 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;好友小帅的香菇鸡蛋肉丁面，为了追求完美，食材均来自‘地标’原产地，一年前首次吃还能吃到某个食材味道‘更突出’，半年前吃略感勾芡过重，今天的口感夯中夯，十多样食材味道完美融合，美食不可辜负，我吃了两碗！&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/memos/1772974579/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;与之并列的是老田的老北京炸酱面，炸酱卤+辣椒卤吃到停不下来，下次再吃我发上来！&lt;/p&gt;</content><category term="Memos"></category><category term="美食记录"></category></entry><entry><title>妻子爷爷的‘朝鲜军功奖章’</title><link href="https://blog.yasking.org/a/kangmeiyuanchao.html" rel="alternate"></link><published>2026-03-08T19:59:36+08:00</published><updated>2026-03-08T19:59:36+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-08:/a/kangmeiyuanchao.html</id><summary type="html">&lt;p&gt;过年回家躺在农村的热炕上，聊起妻子的爷爷，他参加过抗美援朝战争，在九死一生中平安归来，岳母拿出来一些当年的奖 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;过年回家躺在农村的热炕上，聊起妻子的爷爷，他参加过抗美援朝战争，在九死一生中平安归来，岳母拿出来一些当年的奖章，说还有好几枚，不知道遗失到了哪里，看着七十多年的物件，感慨系之，它承载着那段沉重的历史，也似在诉说着战争残酷，务要珍惜和平。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/moments/1772971176/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;⬆️ 朝鲜军功奖章是朝鲜政府为了表彰在战争中建立功勋的指战员而设立颁发的奖章，也是当时授予中国人民志愿军最普遍的奖章之一。&lt;/p&gt;
&lt;p&gt;这个是第二版的证书样式（&lt;a href="https://baike.baidu.com/item/%E6%9C%9D%E9%B2%9C%E5%86%9B%E5%8A%9F%E5%A5%96%E7%AB%A0/14808026"&gt;百度百科-朝鲜军功奖章&lt;/a&gt;）&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/moments/1772971176/02.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.webp" src="https://images.yasking.org/moments/1772971176/03.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.webp" src="https://images.yasking.org/moments/1772971176/04.webp"&gt;&lt;/p&gt;
&lt;p&gt;⬇️ 和平万岁纪念章是 1953 年 10 月中国人民第三届赴朝慰问团赠送给全体志愿军指战员的纪念章，它不仅是慰问品，更是对志愿军将士为和平作出巨大牺牲的崇高敬意和表彰。&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.webp" src="https://images.yasking.org/moments/1772971176/05.webp"&gt;&lt;/p&gt;
&lt;p&gt;这只和平鸽大有来头，其原型是西班牙著名画家毕加索为1952年世界和平大会绘制的宣传画。&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.webp" src="https://images.yasking.org/moments/1772971176/06.webp"&gt;&lt;/p&gt;
&lt;p&gt;⬇️ 这枚章是 1951 年 10 月，在中国人民志愿军出国作战一周年之际，由中国人民政治协商会议全国委员会颁发给所有参加抗美援朝人员。&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.webp" src="https://images.yasking.org/moments/1772971176/07.webp"&gt;&lt;/p&gt;
&lt;p&gt;它通常也被称为 “政协纪念章” 或 “毛主席像章”，它是抗美援朝战争期间，由国家颁发的第一枚全国性纪念章。&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.webp" src="https://images.yasking.org/moments/1772971176/08.webp"&gt;&lt;/p&gt;
&lt;p&gt;⬇️ 民国时期广州著名皮具老字号 “朱芳记” 最典型的商标标识上一只展翅的鹰。&lt;/p&gt;
&lt;p&gt;&lt;img alt="09.webp" src="https://images.yasking.org/moments/1772971176/09.webp"&gt;&lt;/p&gt;
&lt;p&gt;听说是抗美援朝回来国家给的奖励。&lt;/p&gt;
&lt;p&gt;&lt;img alt="10.webp" src="https://images.yasking.org/moments/1772971176/10.webp"&gt;&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>Memos: 博客切换为 Shiki 代码高亮方案</title><link href="https://blog.yasking.org/a/1772778070.html" rel="alternate"></link><published>2026-03-06T23:35:00+08:00</published><updated>2026-03-06T23:35:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-06:/a/1772778070.html</id><summary type="html">&lt;p&gt;最近将博客的 highlight.js + Pygments 的高亮方案替换为 &lt;code&gt;github.com/shikijs/shiki&lt;/code&gt;，这里记几个我觉得有意思、最实用的效果。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Diff 效果&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在行尾写注释 &lt;code&gt;// [!code --]&lt;/code&gt; 和 &lt;code&gt;// [!code …&lt;/code&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;最近将博客的 highlight.js + Pygments 的高亮方案替换为 &lt;code&gt;github.com/shikijs/shiki&lt;/code&gt;，这里记几个我觉得有意思、最实用的效果。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Diff 效果&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在行尾写注释 &lt;code&gt;// [!code --]&lt;/code&gt; 和 &lt;code&gt;// [!code ++]&lt;/code&gt;，无行号和有行号两种场景效果不同。&lt;/p&gt;
&lt;p&gt;无行号 &lt;code&gt;-&lt;/code&gt; / &lt;code&gt;+&lt;/code&gt; 悬在行首：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-go"&gt;func greet(name string) string {
    return &amp;quot;Hello, &amp;quot; + name // [!code --]
    return &amp;quot;Hi, &amp;quot; + name   // [!code ++]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;开启行号时符号合并进行号列，颜色跟随变化：&lt;/p&gt;
&lt;p&gt;```go ln
func greet(name string) string {
    return "Hello, " + name // [!code --]
    return "Hi, " + name   // [!code ++]
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
&amp;lt;!--more--&amp;gt;

**Focus 聚焦效果**

非焦点行淡出，突出当前关注的逻辑。

```go
func login() {
    validate()   // [!code focus]
    requestToken()
    saveSession()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;语义高亮&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[!code highlight]&lt;/code&gt; 是无语义的通用版；&lt;code&gt;info&lt;/code&gt; / &lt;code&gt;warning&lt;/code&gt; / &lt;code&gt;error&lt;/code&gt; 是有语义的递进版，适合标注关键路径、潜在问题和错误。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-go"&gt;func insertionSort(nums []int) {
    for i := 1; i &amp;lt; len(nums); i++ { // [!code highlight]
        key := nums[i]
        j := i - 1
        for j &amp;gt;= 0 &amp;amp;&amp;amp; nums[j] &amp;gt; key {
            nums[j+1] = nums[j]
            j--
        }
        nums[j+1] = key // [!code info]
    }
}

func sortAndPrint(data []int) {
    if data == nil { // [!code warning]
        return
    }
    insertionSort(data)
    fmt.Println(data[len(data)]) // [!code error]
}

func main() {
    nums := []int{5, 3, 8, 1, 9, 2}
    sortAndPrint(nums)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Hover 装饰效果&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;鼠标悬停才高亮，适合标注 "需要关注但不需要一直突出" 的行。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-go"&gt;func div(a, b int) int {
    result := a / b
    logValue(result) // [!code hover]
    return result
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;行号（Line Numbers）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;使用 &lt;code&gt;```go ln&lt;/code&gt;，&lt;code&gt;ln&lt;/code&gt; 关键字开启行号，适合引用具体行或展示较长代码片段。&lt;/p&gt;
&lt;p&gt;```go ln
package main&lt;/p&gt;
&lt;p&gt;import "fmt"&lt;/p&gt;
&lt;p&gt;func fibonacci(n int) int {
    if n &amp;lt;= 1 {
        return n
    }
    return fibonacci(n-1) + fibonacci(n-2)
}&lt;/p&gt;
&lt;p&gt;func main() {
    fmt.Println(fibonacci(10))
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
**范围行高亮效果**

在 info 字符串里声明高亮行，不在代码内容里留注释标记，适合引用第三方代码。`ln` 和 `{范围}` 可以组合使用。

示例中的标签是：`` ```go ln {6,8-10} ``

```go ln {6,8-10}
package main

import &amp;quot;fmt&amp;quot;

func main() {
    nums := []int{1, 2, 3, 4, 5}
    sum := 0
    for _, v := range nums {
        sum += v
    }
    fmt.Println(sum)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然而，估计我还是会用默认效果，不带行号、不带高亮，避免代码过于&lt;span class="hl hl-marker hl-pink"&gt;花里胡哨&lt;/span&gt;，遵循 ‘非必要则不使用’ 的原则。&lt;/p&gt;</content><category term="Memos"></category><category term="博客配置"></category></entry><entry><title>Memos: 博客新增划线、重点及荧光笔效果支持</title><link href="https://blog.yasking.org/a/1772770236.html" rel="alternate"></link><published>2026-03-06T23:34:00+08:00</published><updated>2026-03-06T23:34:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-06:/a/1772770236.html</id><summary type="html">&lt;p&gt;这是普通文字，&lt;span class="u-line"&gt;这是划线重点&lt;/span&gt;。
这是 &lt;span class="u-line u-line-blue"&gt;蓝色划线重点&lt;/span&gt;，
这是 &lt;span class="u-line u-line-violet"&gt;紫色划线重点&lt;/span&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;span class=&amp;quot;u-line&amp;quot;&amp;gt;这是划线重点&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;u-line u-line-blue&amp;quot;&amp;gt;蓝色划线重点&amp;lt;/span&amp;gt;
&amp;lt;span …&lt;/code&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;这是普通文字，&lt;span class="u-line"&gt;这是划线重点&lt;/span&gt;。
这是 &lt;span class="u-line u-line-blue"&gt;蓝色划线重点&lt;/span&gt;，
这是 &lt;span class="u-line u-line-violet"&gt;紫色划线重点&lt;/span&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;span class=&amp;quot;u-line&amp;quot;&amp;gt;这是划线重点&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;u-line u-line-blue&amp;quot;&amp;gt;蓝色划线重点&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;u-line u-line-violet&amp;quot;&amp;gt;紫色划线重点&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是 &lt;span class="hl hl-yellow"&gt;黄色高亮&lt;/span&gt;，
这是 &lt;span class="hl hl-green"&gt;绿色高亮&lt;/span&gt;，
这是 &lt;span class="hl hl-pink"&gt;粉色高亮&lt;/span&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;span class=&amp;quot;hl hl-yellow&amp;quot;&amp;gt;黄色高亮&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-green&amp;quot;&amp;gt;绿色高亮&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-pink&amp;quot;&amp;gt;粉色高亮&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-blue&amp;quot;&amp;gt;蓝色高亮&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-lavender&amp;quot;&amp;gt;薰衣草高亮&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-peach&amp;quot;&amp;gt;蜜桃高亮&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-mint&amp;quot;&amp;gt;薄荷高亮&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-coral&amp;quot;&amp;gt;珊瑚高亮&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-lemon&amp;quot;&amp;gt;柠檬高亮&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是 &lt;span class="hl hl-marker"&gt;记号笔风格高亮&lt;/span&gt;，&lt;span class="hl hl-marker hl-green"&gt;绿色记号笔&lt;/span&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;span class=&amp;quot;hl hl-marker hl-yellow&amp;quot;&amp;gt;Marker Yellow&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-marker hl-green&amp;quot;&amp;gt;Marker Green&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-marker hl-pink&amp;quot;&amp;gt;Marker Pink&amp;lt;/span&amp;gt;
&amp;lt;span class=&amp;quot;hl hl-marker hl-lavender&amp;quot;&amp;gt;Marker Lavender&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;</content><category term="Memos"></category><category term="博客配置"></category></entry><entry><title>记录博客字体分包与字体子集化</title><link href="https://blog.yasking.org/a/blog-font-split.html" rel="alternate"></link><published>2026-03-05T14:16:48+08:00</published><updated>2026-03-05T14:16:48+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-05:/a/blog-font-split.html</id><summary type="html">&lt;p&gt;本博客中文字体采用了一段时间的字体分包方案，又尝试调整为按需字体子集化的方案，整理记录如下。&lt;/p&gt;
&lt;h3&gt;字体分包&lt;/h3&gt;
&lt;p&gt;博客使 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;本博客中文字体采用了一段时间的字体分包方案，又尝试调整为按需字体子集化的方案，整理记录如下。&lt;/p&gt;
&lt;h3&gt;字体分包&lt;/h3&gt;
&lt;p&gt;博客使用 Oppo Sans 4.0 字体：&lt;a href="https://www.coloros.com/article/A00000074/"&gt;https://www.coloros.com/article/A00000074/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使用 cn-font-split 工具分包&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ pnpx cn-font-split --input &amp;quot;OPPO Sans 4.0.ttf&amp;quot; --outDir dist-font
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;生成内容如下&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/technology/1772691408/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;其中 &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;index.html 是预览调试一个一个 Demo 网页&lt;/li&gt;
&lt;li&gt;index.proto 是 Protocol Buffers 接口定义文件&lt;/li&gt;
&lt;li&gt;reporter.bin 记录字体拆分的详细信&lt;/li&gt;
&lt;li&gt;result.css 是引入的拆分字体的入口定义样式文件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用的话，将拆分后的众多 &lt;em&gt;.woff2&lt;/em&gt; 字体文件放到 OPPOSans4（自定义）目录，添加到博客静态目录中，编辑 result.css 文件，注意批量编辑 URL 中的路径。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;@font-face{font-family:&amp;quot;OPPO Sans 4.0&amp;quot;;src:local(&amp;quot;OPPO Sans 4.0&amp;quot;),url(&amp;quot;./fonts/OPPOSans4/b8d45a4b1842853318f4cdd5ba6ef8a4.woff2&amp;quot;)format(&amp;quot;woff2&amp;quot;);font-style:normal;font-display:swap;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;例如我的字体放在 css 当前目录的 fonts/OPPOSans4 下，路径就是 &lt;em&gt;./fonts/OPPOSans4/b8d45a4b1842853318f4cdd5ba6ef8a4.woff2&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/technology/1772691408/02.webp"&gt;&lt;/p&gt;
&lt;p&gt;博客加载过程中，会按需加载，以 OPPO Sans 字体为例，默认命令参数下拆分为 400+ 个字体文件，每篇文章动态加载了 10-30 个字体文件，比较零散。&lt;/p&gt;
&lt;h3&gt;按需字体子集化&lt;/h3&gt;
&lt;p&gt;这是另一个思路，把博客使用到文字汇总，将字体精简，精简后的字体文件只包含用到的字体，也能大幅减少字体文件的体积。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;brew install fonttools
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;收集&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;find content -name &amp;quot;*.md&amp;quot; -exec cat {} \; &amp;gt; all_text.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;过滤&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sed -e 's/```.*//g' \  
-e 's/`[^`]*`//g' \  
-e 's/!\[[^]]*\](\([^)]*\))//g' \  
-e 's/\[[^]]*\](\([^)]*\))/\1/g' \  
all_text.txt &amp;gt; clean_text.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;生成&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;pyftsubset &amp;quot;OPPO Sans 4.0.ttf&amp;quot; \  
--text-file=clean_text.txt \  
--output-file=opposans-blog.woff2 \  
--flavor=woff2 \  
--layout-features='*' \  
--no-hinting \  
--desubroutinize
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-css"&gt;@font-face {
    font-family: 'OPPO Sans 4.0';
    src: url('fonts/OppoSans-Blog.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

:root {
    --font-sans: 'OPPO Sans 4.0', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
    --font-mono: 'JetBrains Mono', 'Roboto Mono', Consolas, Monaco, 'Courier New', monospace;
    --font-ui: var(--font-sans);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;就只需要加载一个精简后字体文件。&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.webp" src="https://images.yasking.org/technology/1772691408/03.webp"&gt;&lt;/p&gt;
&lt;p&gt;字体子集化方案较麻烦的是需要定期执行脚本生成字体，好在未匹配到的字体会自动降级为系统字体，偶尔两个中文降级到系统字体显示并非不可接受。&lt;/p&gt;
&lt;p&gt;P.S. 经过几次调整，OPPO Sans 中文字体 + JetBrains Mono 代码显示效果是我目前最喜欢的搭配！&lt;/p&gt;</content><category term="Technology"></category><category term="博客配置"></category></entry><entry><title>Memos: 邻座吃饭的一家三口</title><link href="https://blog.yasking.org/a/1772379158.html" rel="alternate"></link><published>2026-03-01T23:34:00+08:00</published><updated>2026-03-01T23:34:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-01:/a/1772379158.html</id><summary type="html">&lt;p&gt;吃饭时邻座一对夫妻和孩子对话，对话内容让我印象较深，如下：&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;对话一&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;（夫妻俩吃完了面条，女孩买了奶茶回来）&lt;/p&gt;
&lt;p&gt;女孩妈：你排 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;吃饭时邻座一对夫妻和孩子对话，对话内容让我印象较深，如下：&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;对话一&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;（夫妻俩吃完了面条，女孩买了奶茶回来）&lt;/p&gt;
&lt;p&gt;女孩妈：你排那么长时间，怎么不给我俩带一杯&lt;/p&gt;
&lt;p&gt;女孩：（无声）&lt;/p&gt;
&lt;!--more--&gt;

&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;对话二&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;女孩妈：那边炸鸡排看着挺好吃&lt;/p&gt;
&lt;p&gt;女孩爸：… 滚，不给你俩买&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;对话三&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;（女孩爸在跟女儿侃侃而谈，女孩妈起身走开）&lt;/p&gt;
&lt;p&gt;女孩爸：你干什么去啊&lt;/p&gt;
&lt;p&gt;女孩妈：用不着你管&lt;/p&gt;
&lt;p&gt;女孩爸：快回来，坐在这块&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;对话四&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;（女孩爸继续跟女儿侃侃而谈）&lt;/p&gt;
&lt;p&gt;女孩爸：… 就是这点好，你他妈就是个傻逼，也能 XXX…&lt;/p&gt;</content><category term="Memos"></category><category term="人类相处模式观察"></category></entry><entry><title>人在囧途之哈囧</title><link href="https://blog.yasking.org/a/harbin-return-trip.html" rel="alternate"></link><published>2026-03-01T23:12:58+08:00</published><updated>2026-03-01T23:12:58+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-03-01:/a/harbin-return-trip.html</id><summary type="html">&lt;p&gt;春节回家返京的车票提交候补一直未能成功兑现，跟去年一样，我和媳妇提前一天到车站周边等候补，尝试在临近发车时 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;春节回家返京的车票提交候补一直未能成功兑现，跟去年一样，我和媳妇提前一天到车站周边等候补，尝试在临近发车时捡漏。&lt;/p&gt;
&lt;h3&gt;误信媒体巴士宣传&lt;/h3&gt;
&lt;p&gt;看到朋友转发的媒体文章《龙江巴士开通哈尔滨至北京定制班车》，哈尔滨西站发车、正规车辆、哈尔滨日报报道宣传，心想着龙江巴士可真贴心！&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1772377978/01.webp" width="52.00%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1772377978/02.webp" width="52.00%" /&gt;&lt;/p&gt;
&lt;p&gt;初八上班，初六中午我就赶到哈尔滨西站，一边候补着高铁和火车，想着如果没候补到，就购买 下午 16:00 的 “五人座定制车型”，对自己狠点，18 小时铁腚回北京。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1772377978/03.webp" width="52.00%" /&gt;&lt;/p&gt;
&lt;p&gt;在手机下单后，我正打算去二楼候车，一个私人手机电话打过来，跟我确认是不是订购了大巴车票，说坐车等他一会儿联系，我说不是在车站里坐车吗？“不是，在车站附近”，又得知并非 5 座定制，而是 50 座的大巴。信息出现严重偏差且当天下雪，就跟他说我不坐了。&lt;/p&gt;
&lt;p&gt;问哈西客运站的工作人员，他表示特意查询了下站内，没有到北京的巴士，最近几天得有上百人跟他问这个事情，他不清楚怎么回事，表示可能是龙江巴士平台录入错误。&lt;/p&gt;
&lt;p&gt;赶快想把票退了，别过了时间，看到平台上退款会收一百多元手续费，打龙江巴士的客服电话打不通，客服联系不上，遂拨打 12345 反馈问题，诉求是全额退票。&lt;/p&gt;
&lt;p&gt;大概两个小时后，龙江客服联系我并在后台操作退了票。这事儿搞的，媒体的价值，建立在事实的准确上，哈尔滨日报显然有较大的提升空间，另外第一次拨打黑龙江的 12345 反馈问题，快速有效的解决了我的问题，服务很值得点赞！&lt;/p&gt;
&lt;h3&gt;18 小时的无座你怕了吗&lt;/h3&gt;
&lt;p&gt;大巴车方案作废后，赶忙使用 12306 ByPass 软件提交了一堆候补，又实时抢票，心说初六可一定要走上，别管什么车票，初七回去能休息下，于是跟媳妇在哈尔滨西站安检口（外）就一直刷，去年就这样操作，先上车后补的票。&lt;/p&gt;
&lt;p&gt;刷了许久，饿了点了份麻辣烫吃，还真抢到两张票，绿皮 K4044，18 小时 15 分钟的无座，有些难顶，“硬座我都不敢，更何况无座...”&lt;/p&gt;
&lt;p&gt;考虑再三，我没退票，哈尔滨东站发车，那就去附近住下，躺在床上，电脑充上电，闲着没事儿又想抢下看有没有更好的车次， 同时下单买了折叠椅做最坏的打算。&lt;/p&gt;
&lt;p&gt;12306 ByPass 在忙着，我也没闲着，用 12306 刷中转，冥冥中我感觉有戏，跟媳妇商量了下，K4044 还是先退了吧，避免行程冲突候补失败，还是有机会抢到更好票的（也是飘了）。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1772377978/04.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;退了票，努力了半天，还真让我刷到了 “更好” 的车次，一看 22:42 发车，不到一个小时，赶忙拉上媳妇从哈尔滨东站往哈尔滨站赶。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1772377978/05.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;上了地铁腾出时间仔细一看，&lt;strong&gt;时间不对啊&lt;/strong&gt;，不是一会儿发车，明晚的 22:42 发车，要等一天不说还要请假一天（请假困难）&lt;/p&gt;
&lt;p&gt;脑袋冷静下来，像哈尔滨的乍暖还寒。咋整，继续在哈尔滨站安检门外刷票吧...&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1772377978/06.webp" width="72.00%" /&gt;&lt;/p&gt;
&lt;p&gt;挺好，我媳妇没埋冤我看错时间，跟我一起刷中转，我俩笑着打趣说：“咱们这是图啥呢，在旅馆躺床上刷多好”，四处张望下，也还有一些人在安检外，同是天涯没票人。&lt;/p&gt;
&lt;p&gt;在我们坚强的努力和媳妇的运气加持下，真抢到一个性价比不错的长春中转方案，初七晚上哈尔滨硬座凌晨一点多到长春，两个小时后高铁无座到朝阳站，高铁无座比 K4044 的 18 小时无座还是好很多，也不想挣扎了，至少有能接受的保底方案。&lt;/p&gt;
&lt;p&gt;媳妇儿说回住宿的地方吧，我总担心万一有票，今晚就能走上多好，或者提前 20 分钟候补到，那在东站的酒店也赶不上哈站的车呀，就这样硬挺，23 点、24 点、01 点，我俩靠（东北话）走了所有从哈站发的车和安检门外的无票人。&lt;/p&gt;
&lt;p&gt;打车回旅店，这个出租车晃晃悠悠的，旅店老板看到我俩说以为我们不回来住，房间让给别人住了，还没等我说话，他稍微考虑了下就又给我们安排了一间稍好一丢丢的屋子。&lt;/p&gt;
&lt;p&gt;最终又回到东站的旅馆，看了下 12306 上显示 01 点到 05 点进行系统维护，就算在哈站挣扎也没有机会，回来的时间刚好。&lt;/p&gt;
&lt;h3&gt;总之、还是先吃饭&lt;/h3&gt;
&lt;p&gt;一觉过后，又躺了一上午，一是折腾的很累，二是想着上了火车就没得躺。&lt;/p&gt;
&lt;p&gt;中午饿了在「莱福双城杀猪菜(红旗总店)」吃了东北菜，人爆满，溜肉段非常好吃！干煸豆角还好，水煮肉片中规中矩比较一般，分量都很大。&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.webp" src="https://images.yasking.org/moments/1772377978/07.webp"&gt;&lt;/p&gt;
&lt;p&gt;努力吃掉 2/3，花费用 99 元。&lt;/p&gt;
&lt;h3&gt;旅行折叠椅救了我的老腰&lt;/h3&gt;
&lt;p&gt;初七晚 23 点踏上途经长春的 K322 列车。&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.webp" src="https://images.yasking.org/moments/1772377978/08.webp"&gt;&lt;/p&gt;
&lt;p&gt;熟悉的绿皮车，大家都红着眼硬坐着，好在我就两个半小时，下了车在长春站大口喝水。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1772377978/09.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;上了高铁后我在上车门对侧坐下，本来跟媳妇计划两人换着坐折叠椅，她正在那摆弄皮箱寻找舒服的坐姿。&lt;/p&gt;
&lt;p&gt;列车员过来说：“有一个 XX 号的二等座位空着，看你们谁去做”，旁边的一个小伙没表示要去，我就跟媳妇说让她去，那个二等座位到朝阳站都没人来，我媳妇这运气真是额度充足。&lt;/p&gt;
&lt;p&gt;我就瘫在折叠椅上，该说不说，折叠椅真是无座神器，比小马扎强一万倍，傍边高铁的暖风吹的舒服，就是每次到站开门，后腰凉飕飕的。&lt;/p&gt;
&lt;p&gt;总之还是顺利回到了北京，困的不行，在附近的如家订了 4 小时 100 元的钟点房洗漱，下年春节真就在北京和媳妇两个人过了 （手动摊手）&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>哈尔滨・乡村的冬季</title><link href="https://blog.yasking.org/a/photos-heilongjiang-mulanxian-2026.html" rel="alternate"></link><published>2026-02-18T20:33:00+08:00</published><updated>2026-02-18T20:33:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-02-18:/a/photos-heilongjiang-mulanxian-2026.html</id><summary type="html">&lt;hr&gt;
&lt;p&gt;想触摸到粗盐粒般的白雪，看到成片的白色，唯有在东北的相间，干燥、寒冷又宁静，看不到几个人，唯有山野。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/photos/1771412857/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《雪地的松树林》&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/photos/1771412857/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《白 …&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;p&gt;想触摸到粗盐粒般的白雪，看到成片的白色，唯有在东北的相间，干燥、寒冷又宁静，看不到几个人，唯有山野。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/photos/1771412857/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《雪地的松树林》&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/photos/1771412857/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《白平衡》&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.jpg" src="https://images.yasking.org/photos/1771412857/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《云、村庄与雪》&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.jpg" src="https://images.yasking.org/photos/1771412857/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《白雪覆盖的苞米地》&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/photos/1771412857/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《小村庄1》&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/photos/1771412857/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《小村庄2》&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/photos/1771412857/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《铁塔》&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.jpg" src="https://images.yasking.org/photos/1771412857/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《日落》&lt;/p&gt;
&lt;p&gt;&lt;img alt="09.jpg" src="https://images.yasking.org/photos/1771412857/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《雪地车辙》&lt;/p&gt;
&lt;p&gt;&lt;img alt="10.jpg" src="https://images.yasking.org/photos/1771412857/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《家人》&lt;/p&gt;
&lt;p&gt;&lt;img alt="11.jpg" src="https://images.yasking.org/photos/1771412857/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《猎户座》&lt;/p&gt;</content><category term="Photos"></category><category term="Photos"></category></entry><entry><title>查看香烟生产日期</title><link href="https://blog.yasking.org/a/tobacco-production-date.html" rel="alternate"></link><published>2026-02-17T11:38:00+08:00</published><updated>2026-02-17T11:38:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-02-17:/a/tobacco-production-date.html</id><summary type="html">&lt;p&gt;过年回家前买了几条中南海流水音，感觉包装有些旧，自己不抽烟，对烟草知之甚少，查了下怎么看生产日期，发现每条香烟 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;过年回家前买了几条中南海流水音，感觉包装有些旧，自己不抽烟，对烟草知之甚少，查了下怎么看生产日期，发现每条香烟上都有编码（有时候不清晰，需要仔细找找）&lt;/p&gt;
&lt;p&gt;编码有两排：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;第一排的 60125 代表出场日期，6 代表年份的结尾数字，即这盒香烟是 2026 年生产（不排除是2016 年，但商店里几乎不会有十年的香烟存货，有理由认为是 2026 产），0125 表示一月二十五号。&lt;/p&gt;
&lt;p&gt;第二排的 BJYC 表示 “北京烟草”，表示哪个地区销售的。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;商店老板拿给我的这盒是最近日期的&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1771295268/01.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;下边两盒都是 2025-01-07 日的&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1771295268/02.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1771295268/03.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;经验总结：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;香烟在北方一般来说，一两年内味道差别不会特别大，但是过度干燥的环境会导致口感辛辣刺喉；&lt;/li&gt;
&lt;li&gt;购买香烟跟老板要最近时间段生产的，学会看编码能避免老板新旧掺着卖；&lt;/li&gt;
&lt;/ol&gt;</content><category term="Skill"></category></entry><entry><title>哈尔滨・东北虎林园</title><link href="https://blog.yasking.org/a/photos-harbin-dongbeihulinyuan.html" rel="alternate"></link><published>2026-02-16T19:54:00+08:00</published><updated>2026-02-16T19:54:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-02-16:/a/photos-harbin-dongbeihulinyuan.html</id><summary type="html">&lt;hr&gt;
&lt;p&gt;虎林园是全球最大的东北虎人工繁育基地，里面的东北虎超多，颜值能打，大饱眼福，唯一的缺憾是人工繁育的东北虎缺少 …&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;p&gt;虎林园是全球最大的东北虎人工繁育基地，里面的东北虎超多，颜值能打，大饱眼福，唯一的缺憾是人工繁育的东北虎缺少了百兽之王的霸气，缺少压迫感，不过话说回来，野生的东北虎也不是一般人能遇到的。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/photos/1744197383/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《东北虎》&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/photos/1744197383/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《夫妻俩》——左侧的东北虎体型巨大，武松当年打的老虎八成不是这种&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.jpg" src="https://images.yasking.org/photos/1744197383/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《超爱卫生的“金渐层”》&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.jpg" src="https://images.yasking.org/photos/1744197383/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《小jio像毛绒玩具的埋汰虎》&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/photos/1744197383/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《跟车的年轻小虎》&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/photos/1744197383/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《一家人的午后时光》&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/photos/1744197383/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《自助餐车》&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.jpg" src="https://images.yasking.org/photos/1744197383/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《冬日暖阳》&lt;/p&gt;
&lt;p&gt;&lt;img alt="09.jpg" src="https://images.yasking.org/photos/1744197383/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《在光中，在阴影中》&lt;/p&gt;
&lt;p&gt;&lt;img alt="10.jpg" src="https://images.yasking.org/photos/1744197383/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《镜像》&lt;/p&gt;
&lt;p&gt;&lt;img alt="11.jpg" src="https://images.yasking.org/photos/1744197383/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《可以吃的“豆沙千层面包”》&lt;/p&gt;
&lt;p&gt;&lt;img alt="12.jpg" src="https://images.yasking.org/photos/1744197383/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《乌鸦哥的“残羹剩饭”》&lt;/p&gt;
&lt;p&gt;&lt;img alt="14.jpg" src="https://images.yasking.org/photos/1744197383/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;《投喂》&lt;/p&gt;</content><category term="Photos"></category><category term="Photos"></category></entry><entry><title>Memos: 来自日本的 ndjp 提供免费的三级子域名</title><link href="https://blog.yasking.org/a/1770372647.html" rel="alternate"></link><published>2026-02-06T18:11:00+08:00</published><updated>2026-02-06T18:11:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-02-06:/a/1770372647.html</id><summary type="html">&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/memos/1770372647/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;网站：&lt;a href="https://ndjp.net/"&gt;https://ndjp.net/&lt;/a&gt;&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;注册流程非常丝滑，一个账号下可以添加多个三级域名：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;{your-customize}.ndjp.net
{your-customize-2}.ndjp.net
{your-customize-3}.ndjp.net
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在子域名下，可以管理四级域名 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/memos/1770372647/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;网站：&lt;a href="https://ndjp.net/"&gt;https://ndjp.net/&lt;/a&gt;&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;注册流程非常丝滑，一个账号下可以添加多个三级域名：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;{your-customize}.ndjp.net
{your-customize-2}.ndjp.net
{your-customize-3}.ndjp.net
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在子域名下，可以管理四级域名解析 A、CNAME 等 DNS 记录&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;blog.{your-customize}.ndjp.net
index.{your-customize}.ndjp.net
tools.{your-customize}.ndjp.net
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;三位的子域还有很多，我注册了个 &lt;code&gt;ddx.ndjp.net&lt;/code&gt;，适合临时的学习、测试使用，风险提示：&lt;strong&gt;严肃场景下仍建议自己注册付费域名&lt;/strong&gt;。&lt;/p&gt;</content><category term="Memos"></category><category term="FreeDomain"></category></entry><entry><title>Memos: 刚听说 autojump, 真的好用</title><link href="https://blog.yasking.org/a/1770358727.html" rel="alternate"></link><published>2026-02-06T04:19:00+08:00</published><updated>2026-02-06T04:19:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-02-06:/a/1770358727.html</id><summary type="html">&lt;p&gt;这个工具出现在 18 年前，&lt;a href="https://github.com/wting/autojump"&gt;wting/autojump&lt;/a&gt;，我火星了刚听说。&lt;/p&gt;
&lt;p&gt;安装之后，使用终端 &lt;code&gt;cd&lt;/code&gt; 访问过的路径都会被记录，之后使用 &lt;code&gt;j + [模糊字符]&lt;/code&gt; 就能 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;这个工具出现在 18 年前，&lt;a href="https://github.com/wting/autojump"&gt;wting/autojump&lt;/a&gt;，我火星了刚听说。&lt;/p&gt;
&lt;p&gt;安装之后，使用终端 &lt;code&gt;cd&lt;/code&gt; 访问过的路径都会被记录，之后使用 &lt;code&gt;j + [模糊字符]&lt;/code&gt; 就能快速跳转：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ cd ~/Documents/blog-yasking-images/photos

# 之后使用 j 命令就可以跳转过去
$ j pho
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果有多个 photos 目录：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;/Users/joecovert/Documents/blog-yasking-images/photos
/Users/joecovert/Downloads/photos
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以使用 &lt;code&gt;j Down pho&lt;/code&gt; 跳转。&lt;/p&gt;
&lt;p&gt;另外，&lt;code&gt;jc&lt;/code&gt; 可以限制在当前目录下匹配跳转，&lt;code&gt;jo&lt;/code&gt; 是打开文件夹，对我来说是刚需。&lt;/p&gt;</content><category term="Memos"></category><category term="Tools"></category></entry><entry><title>Memos: 体验 OpenCode + Superpowers + GPT 5.2 开发需求</title><link href="https://blog.yasking.org/a/1770255240.html" rel="alternate"></link><published>2026-02-05T09:34:00+08:00</published><updated>2026-02-05T09:34:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-02-05:/a/1770255240.html</id><summary type="html">&lt;p&gt;最近使用 OpenCode + Superpowers Skills + GPT 5.2 开发了一个中等复杂度的需求，相比之前使用 Cursor 依赖 Sonnet 4.5 Thinking 模型硬聊硬写，效率和代码质量明 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;最近使用 OpenCode + Superpowers Skills + GPT 5.2 开发了一个中等复杂度的需求，相比之前使用 Cursor 依赖 Sonnet 4.5 Thinking 模型硬聊硬写，效率和代码质量明显提升！&lt;/p&gt;
&lt;p&gt;记录下需求开发流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先使用 Cursor 协助构想需求的目标，心中对需求的实现有个预期；&lt;/li&gt;
&lt;li&gt;整理需求的描述（关注重点信息，而非实现的细枝末节）；&lt;/li&gt;
&lt;li&gt;使用 OpenCode Plan 模式设计实现方案；&lt;/li&gt;
&lt;li&gt;切换 OpenCode Build 模式按照 Plan 计划严格实施；&lt;/li&gt;
&lt;li&gt;最终人工初审 Review 代码 + Cursor Review 代码；&lt;/li&gt;
&lt;li&gt;提测 &amp;amp; 联调；&lt;/li&gt;
&lt;/ol&gt;
&lt;!--more--&gt;

&lt;p&gt;第一、二步应该多花些时间，自己要清楚需求的目标和边界，第二步描述的信息应准确，但无需关注过多细节（表字段、接口字段等），需求清晰则字段必然是清晰的；Plan 模式不会修改本地文件，这个模式下借助 Superpowers 的规划能力，交互式确认问题，答复几轮后，Plan 会主动 “完结” 事项，提供详实的设计文档，使用者最终确认没问题后，即可切换 Build 模式开始实现&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;Do not redesign.
Do not change the plan.
Only implement according to the plan above.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输入以上描述，告知模型严格按照 Plan 实现代码，代码质量相当高，之前使用 Cursor 开发需求，总是需要反复对话纠正它的错误逻辑和代码风格，特消耗精力！&lt;/p&gt;
&lt;p&gt;同需求重复实现的一些对照测试（依据最终产出代码的主观评分）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用 Cursor 依赖模型 Thinking 模式（旧有使用方式）：70 分&lt;/li&gt;
&lt;li&gt;使用 Cursor Cli 搭配 Superpowers + GPT 5.2：85 分&lt;/li&gt;
&lt;li&gt;使用 OpenCode 搭配 Superpowers + GPT 5.2：92 分&lt;/li&gt;
&lt;li&gt;使用 OpenCode 搭配 Superpowers + GLM-4.7：58 分&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;我的结论&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cursor 搭配 Skills 有较大提升，但 OpenCode 能最大程度发挥 Superpowers 的能力，买了智谱的套餐，只能说 GLM-4.7 还得 “再炼”，实际开发依然推荐 Sonnet 4.5 / Opus 4.5 / GPT-5.2。&lt;/p&gt;
&lt;p&gt;同样的需求描述，OpenCode + Superpowers Skills + 优质模型可以产出更好的方案和代码，&lt;strong&gt;三者相辅相成&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;我理解，并非 Cursor 和 Antigravity 本身能力不足，而是它们对于 Skills 的使用侧重于参考和协助，而 OpenCode 对 Skills 的约束更强，更容易形成稳定、高质量的输出。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;补充：我没有条件测试 Claude Code，所以无法做比较，另外同事测试了 Antigravity 搭配 Superpowers，产出的效果跟 Cursor 搭配 Superpowers 效果相似。&lt;/em&gt;&lt;/p&gt;</content><category term="Memos"></category><category term="Vibe Coding"></category></entry><entry><title>Memos: 杰我睿爆雷</title><link href="https://blog.yasking.org/a/1769488127.html" rel="alternate"></link><published>2026-01-27T14:18:59+08:00</published><updated>2026-01-27T14:18:59+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-01-27:/a/1769488127.html</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;杰我睿是水贝一家黄金回收交易商家，通过他们的微信小程序可以充值（支付宝、微信、银行卡转账到个人账户）、然后在小程 …&lt;/p&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;杰我睿是水贝一家黄金回收交易商家，通过他们的微信小程序可以充值（支付宝、微信、银行卡转账到个人账户）、然后在小程序上可以购买金条、板料，也可以把自己的首饰邮寄给他们，余额也可提现，支持 “做空做多” 等玩法。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;近日爆雷。&lt;br&gt;
有传言称其做空白银导致巨额亏损，也有人说人未跑路但资金已出海。当前情况是：&lt;strong&gt;大量用户账户中的余额、板料沦为数字，提现不打款，提料不发货。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;爆雷前两天，他们仍在大力宣传 “免工费”，诱导用户邮寄金银。规则要求签收人填写其自身姓名，目前给出的说法是：&lt;strong&gt;该行为视为“赠予”杰我睿，分毛不返。&lt;/strong&gt;&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;随后提出所谓“解决方案”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可在小程序内登记并签署协议，&lt;strong&gt;可能返还 1–2 折本金&lt;/strong&gt;，也可能经其律师测算后被认定&lt;strong&gt;倒欠平台资金&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;不登记，基本没有任何说法。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;看小红书上的受害者很多，被套金额少则千百八，多至几百万。有省吃俭用的攒金一夜返贫的大学生，有投资亏损不敢告诉家人的宝妈，也有借嫂子首饰卖金给母亲看病邮寄过去就被骗的不幸儿女，真的很惨烈。&lt;/p&gt;
&lt;p&gt;小红书等平台上已有大量受害者发声，被套金额从几千元到数百万元不等。  &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;有省吃俭用攒金的大学生，一夜返贫；  &lt;/li&gt;
&lt;li&gt;有投资亏损不敢告诉家人的宝妈；  &lt;/li&gt;
&lt;li&gt;有失业人员、抑郁症患者；&lt;/li&gt;
&lt;li&gt;有借来嫂子首饰、卖金为母亲治病，却因邮寄而被骗的不幸子女。  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;场面非常惨烈。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这次爆雷与传统 P2P 并不完全相同。&lt;br&gt;
它不只是利用人的贪婪，而是&lt;strong&gt;将自己包装成“良心、本分、懂行的黄金商家”&lt;/strong&gt;，通过日常化运营建立信任，让用户产生粘性并自发宣传，逐步吸纳了买金小白、稳健储蓄者、投机交易者等不同人群，最终统一收割。&lt;/p&gt;
&lt;p&gt;风险信号一直都在，但用户信任他们高于反诈风控，前一段时间小红书的风向还是有人吐槽警察把她的卡冻结不能充值，解锁后继续充值被锁，再解、再充！&lt;/p&gt;
&lt;p&gt;每个人都会认为自己不会被骗，是别人不懂，对个人商家信用无条件的信任，最终成为收割自己的镰刀。&lt;/p&gt;
&lt;p&gt;投资，风险永远是第一考虑因素：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;不要碰私有盘&lt;/strong&gt;，你图它克价便宜、免工费，它图你的本金。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;贵重金属尽量当面交易&lt;/strong&gt;，一手交钱一手交货，买卖通过正规渠道。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无监管平台不要充值&lt;/strong&gt;，钱进去后只是显示数字，提出来的钱干不干净也都不好说。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;凡是 “看起来不像金融行为的金融行为”，都要加倍警惕。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;很多时候它不是骗你不懂，&lt;strong&gt;而是骗你懂&lt;/strong&gt;，你以为懂他的盈利模式，懂他的运作方式。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当前经济环境下，&lt;strong&gt;捂紧口袋，不要盲目投资。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;（本来截了一些图，想来还是不放了，人和人的悲喜也不相通，反倒像看他们的乐子，本文主要目的是为提醒读者在商家 “私有平台” 有存金、存银、存钱，尽快取出，规避风险）&lt;/p&gt;</content><category term="Memos"></category><category term="杰我睿"></category><category term="爆雷"></category></entry><entry><title>GoReleaser 自动发布 Go 镜像到 DockerHub &amp; GitHub Release</title><link href="https://blog.yasking.org/a/goreleaser.html" rel="alternate"></link><published>2026-01-23T11:40:22+08:00</published><updated>2026-01-23T11:40:22+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-01-23:/a/goreleaser.html</id><summary type="html">&lt;p&gt;差不多两年前学习记录过《&lt;a href="https://blog.yasking.org/a/github-action-auto-release.html"&gt;使用 Github Action 自动构建 Release 版本&lt;/a&gt;》，也研究过《&lt;a href="https://blog.yasking.org/a/docker-multi-arch-with-buildx.html"&gt;使用 Docker 构建多架构镜像&lt;/a&gt;》，手动推镜像到 DockerHub，其实一直还差最 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;差不多两年前学习记录过《&lt;a href="https://blog.yasking.org/a/github-action-auto-release.html"&gt;使用 Github Action 自动构建 Release 版本&lt;/a&gt;》，也研究过《&lt;a href="https://blog.yasking.org/a/docker-multi-arch-with-buildx.html"&gt;使用 Docker 构建多架构镜像&lt;/a&gt;》，手动推镜像到 DockerHub，其实一直还差最后一公里 —— 提交代码到 Github 自动构建 Release 二进制成品，并构建镜像推送到 DockerHub 仓库。&lt;/p&gt;
&lt;p&gt;而这就是 Goreleaser 所擅长的，本文记录了相关配置和使用方式。&lt;/p&gt;
&lt;h3&gt;本地安装 Goreleaser&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;brew install goreleaser
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Go Releaser 配置&lt;/h3&gt;
&lt;p&gt;在项目根目录执行初始化，生成 &lt;em&gt;.goreleaser.yaml&lt;/em&gt; 配置文件&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;goreleaser init
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按需修改，我的示例配置如下&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;version: 2

project_name: passkey-demo

before:
  hooks:
    - go mod tidy

builds:
  - id: server
    main: .
    binary: passkey-demo
    env:
      - CGO_ENABLED=0
    goos:
      - linux
      - darwin
    goarch:
      - amd64
      - arm64
    ldflags:
      - -s -w
      - -X main.version={{ .Version }}
      - -X main.commit={{ .Commit }}

archives:
  - id: default
    formats: [tar.gz]
    name_template: &amp;gt;-
      {{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}

checksum:
  name_template: checksums.txt

changelog:
  use: github
  sort: asc
  filters:
    exclude:
      - &amp;quot;^docs:&amp;quot;
      - &amp;quot;^test:&amp;quot;
      - &amp;quot;^chore:&amp;quot;

release:
  draft: true
  prerelease: auto
  footer: |
    ---
    Released by GoReleaser.

dockers_v2:
  - id: server
    ids:
      - server
    dockerfile: Dockerfile
    platforms:
      - linux/amd64
      - linux/arm64
    images:
      - &amp;quot;{{ .Env.DOCKERHUB_USERNAME }}/passkey-demo&amp;quot;
    tags:
      - &amp;quot;{{ .Version }}&amp;quot;
      - latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意需要替换 “your-docker-hub-username” 为你的 DockerHub 的用户名，登录后在 URL 中的就是用户名&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1769139622/01.webp" width="80.00%" /&gt;&lt;/p&gt;
&lt;h3&gt;Github Action 配置&lt;/h3&gt;
&lt;p&gt;创建/修改 &lt;em&gt;.github/workflows/release.yml&lt;/em&gt; 文件，内容如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - uses: actions/setup-go@v6
        with:
          go-version: '1.25'
          check-latest: true

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Run GoReleaser
        uses: goreleaser/goreleaser-action@v6
        with:
          version: latest
          args: release --clean
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上配置的 &lt;code&gt;secrets.GITHUB_TOKEN&lt;/code&gt; 无需手动配置，Docker 的两个环境变量需要配置。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;获取 Docker User Access Token&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;点击右上角头像，点击 “Account Settings” -  “Settings” 下的 “Personal access tokens”，创建一个 “Read &amp;amp; Write” 权限的 Token&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/technology/1769139622/02.webp"&gt;&lt;/p&gt;
&lt;p&gt;生成的 Token 只展示一次，复制下来使用，即 &lt;code&gt;secrets.DOCKERHUB_TOKEN&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在 Github 上配置 Secrets&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;点击 Github 仓库的 “Settings”，侧边栏找到 “Secrets and variables”，我这里添加的是 Repository secrets 类型&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.webp" src="https://images.yasking.org/technology/1769139622/03.webp"&gt;&lt;/p&gt;
&lt;h3&gt;Dockerfile 配置参考&lt;/h3&gt;
&lt;p&gt;放到项目根目录&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-Dockerfile"&gt;FROM alpine:3.23

RUN apk add --no-cache ca-certificates

WORKDIR /app

# 使用构建参数获取目标架构
ARG TARGETARCH

# GoReleaser 将二进制文件放在 linux/&amp;lt;arch&amp;gt;/ 目录下
COPY linux/${TARGETARCH}/passkey-demo /app/passkey-demo

EXPOSE 8080

ENTRYPOINT [&amp;quot;/app/passkey-demo&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;本地测试构建&lt;/h3&gt;
&lt;p&gt;注意替换 DOCKERHUB_USERNAME 为你的用户名&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;DOCKERHUB_USERNAME=your-username goreleaser release --snapshot --clean
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="04.webp" src="https://images.yasking.org/technology/1769139622/04.webp"&gt;&lt;/p&gt;
&lt;p&gt;查看构建的镜像&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker images | grep passkey-demo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;已构建出镜像&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.webp" src="https://images.yasking.org/technology/1769139622/05.webp"&gt;&lt;/p&gt;
&lt;p&gt;如果想进一步运行测试镜像，可以运行：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker run --rm -p 8080:8080 kissbug8720/passkey-demo:latest
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;推送标签触发构建&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;git tag v0.0.12

git push origin v0.0.12
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在仓库的 Action 可以看到构建任务。&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.webp" src="https://images.yasking.org/technology/1769139622/06.webp"&gt;&lt;/p&gt;
&lt;p&gt;构建完成后，在 Github 仓库的 releases 可以看到一个 &lt;code&gt;Draft&lt;/code&gt; 类型的发布，点击编辑，可修改描述，二进制成品也可以编辑，发布后即对外部可见。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Github Release&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.webp" src="https://images.yasking.org/technology/1769139622/07.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Docker Hub 镜像&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;访问：&lt;a href="https://hub.docker.com/r/kissbug8720/passkey-demo/tags"&gt;https://hub.docker.com/r/kissbug8720/passkey-demo/tags&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.webp" src="https://images.yasking.org/technology/1769139622/08.webp"&gt;&lt;/p&gt;
&lt;p&gt;可以看到 0.0.12 标签后 latest 标签的镜像。&lt;/p&gt;
&lt;h3&gt;最后&lt;/h3&gt;
&lt;p&gt;从「手动便携难以维护的脚本」到「封装良好的现代化发布方案」，Golang 项目&lt;strong&gt;非常推荐&lt;/strong&gt;使用 Goreleaser 进行发布。&lt;/p&gt;</content><category term="Technology"></category><category term="Golang"></category><category term="Github"></category></entry><entry><title>初识 Volta &amp; Corepack 前端版本管理工具</title><link href="https://blog.yasking.org/a/volta-and-corepack.html" rel="alternate"></link><published>2026-01-13T14:00:00+08:00</published><updated>2026-01-13T14:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-01-13:/a/volta-and-corepack.html</id><summary type="html">&lt;p&gt;前些天在 macOS 上启动 Strapi，发现它依赖特定的 Node.js TLS 版本，之前电脑 node 使用 Brew 安装，切换起来也不是太方便，遂尝试了解前端版 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;前些天在 macOS 上启动 Strapi，发现它依赖特定的 Node.js TLS 版本，之前电脑 node 使用 Brew 安装，切换起来也不是太方便，遂尝试了解前端版本管理工具。&lt;/p&gt;
&lt;p&gt;发现 &lt;a href="https://volta.sh/"&gt;Volta&lt;/a&gt;（管理 Node 版本） + &lt;a href="https://github.com/nodejs/corepack"&gt;Corepack&lt;/a&gt;（管理依赖安装工具的版本）正式我要找的，笔记记录如下：&lt;/p&gt;
&lt;h3&gt;Volta 工具&lt;/h3&gt;
&lt;p&gt;使用 Brew 安装 Volta&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install volta
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装不同版本的 Node&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 安装 Node.js 22 版本
$ volta install node@22

# 安装 Node.js 24 版本
$ volta install node@24
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装 Tools&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 作为演示，暂时先安装，后文有更适合的安装方式
$ volta install pnpm
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看已经安装的工具&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ volta list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出默认版本&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/technology/1768284189/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;查看已安装的全部 Node 版本&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ volta list node
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到多个 Node 版本&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/technology/1768284189/02.webp"&gt;&lt;/p&gt;
&lt;p&gt;设置全局默认 Node 版本 &amp;amp; 设置项目固定的版本&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ volta install node@24 --default

# 在前端项目根目录下执行，需要有 package.json 否则报错
$ volta pin node@22
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pin 之后，Volta 会根据项目自动切换 Node 版本！&lt;/p&gt;
&lt;p&gt;另外，可临时指定 Node 版本运行脚本&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ echo &amp;quot;console.log('node version:', process.version)&amp;quot; &amp;gt; app.js

$ volta run --node 22 node app.js
node version: v22.21.1

$ volta run --node 24 node app.js
node version: v24.12.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;卸载 Node 版本&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ volta uninstall node@22     # 卸载特定版本
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看当前使用的 node 路径&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ volta which node         
/Users/dongdong/.volta/tools/image/node/24.12.0/bin/node
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;volta 常用的命令如上，我使用它切换、锁定 Node 版本，很方便！&lt;/p&gt;
&lt;p&gt;在项目中，除了锁 Node 版本，对应的依赖工具的版本也推荐锁定，因为 volta 无法锁定 pnpm 的版本，所以使用另外的工具&lt;/p&gt;
&lt;h3&gt;Corepack 工具&lt;/h3&gt;
&lt;p&gt;这个 corepack 我是刚听说的工具，它在 Node 16.9 版本中引入，安装了 Node.js 就有。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GPT: Corepack 是 Node 官方内置的工具，用于管理和锁定包管理器（如 pnpm、yarn）的版本，确保项目使用固定的包管理器而不依赖全局安装。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 卸载 pnpm（之前是由 volta 安装的，无法切换锁定）
$ volta uninstall pnpm

# 安装（使用 volta 统一管理）
$ volta install corepack
success: installed corepack@0.34.5 with executables: corepack, pnpm, pnpx, yarn, yarnpkg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启用 Corepack&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 查看版本
$ corepack -v
0.34.5

$ corepack enable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用 Corepack 安装 pnpm（准备并激活）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ corepack prepare pnpm@10.28.0 --activate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;（或者）在启用 Corepack 后，直接运行 pnpm 命令也会触发其安装提醒&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.webp" src="https://images.yasking.org/technology/1768284189/03.webp"&gt;&lt;/p&gt;
&lt;p&gt;安装后会打印 pnpm 版本&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ pnpm -v
10.28.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果项目中已经有 package.json 文件，可以执行命令设置 pnpm 的版本值，需要三位准确版本号&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ pnpm pkg set packageManager=pnpm@10.28.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行后会写入 &lt;code&gt;packageManager&lt;/code&gt; 字段声明 pnpm 版本，示例 JSON 如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;volta-test&amp;quot;,
  &amp;quot;private&amp;quot;: true,
  &amp;quot;version&amp;quot;: &amp;quot;0.1.0&amp;quot;,
  &amp;quot;scripts&amp;quot;: {
    &amp;quot;dev&amp;quot;: &amp;quot;node index.js&amp;quot;
  },
  &amp;quot;volta&amp;quot;: {
    &amp;quot;node&amp;quot;: &amp;quot;22.21.1&amp;quot;
  },
  &amp;quot;packageManager&amp;quot;: &amp;quot;pnpm@10.28.0&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;补充说明：Corepack 并非只能管理 pnpm，Yarn、Npm 包管理器也都支持，非常适合多项目的管理。&lt;/p&gt;
&lt;p&gt;至此，项目中 Volta 锁 Node，Corepack 锁 pnpm，他们的关系如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;Volta
 ├─ node
 └─ corepack
       └─ pnpm@10.28.0（按项目）
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;最后总结&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;GPT：Volta 是 Node 与工具版本管理的核心，Corepack 是包管理器版本管理的核心，两者结合后可以实现项目级、团队级、跨机器环境一致性。&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Technology"></category><category term="Volta"></category><category term="Corepack"></category></entry><entry><title>部署 Beszel 把 “小鸡们” 归拢起来</title><link href="https://blog.yasking.org/a/deploy-beszel.html" rel="alternate"></link><published>2026-01-07T18:37:16+08:00</published><updated>2026-01-07T18:37:16+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-01-07:/a/deploy-beszel.html</id><summary type="html">&lt;p&gt;懒得折腾。但还是部署了，因为足够简单、轻量。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/technology/1767782236/01.webp"&gt;&lt;/p&gt;
&lt;h3&gt;安装 Beszel 服务端&lt;/h3&gt;
&lt;p&gt;找一台 Linux 机器安装 Beszel 服务&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;mkdir -p /opt/service/beszel/ &amp;amp;&amp;amp; cd /opt/service/beszel/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;编辑&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;vim /opt/service/beszel …&lt;/code&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;懒得折腾。但还是部署了，因为足够简单、轻量。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/technology/1767782236/01.webp"&gt;&lt;/p&gt;
&lt;h3&gt;安装 Beszel 服务端&lt;/h3&gt;
&lt;p&gt;找一台 Linux 机器安装 Beszel 服务&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;mkdir -p /opt/service/beszel/ &amp;amp;&amp;amp; cd /opt/service/beszel/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;编辑&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;vim /opt/service/beszel/docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配置内容&lt;/p&gt;
&lt;p&gt;配置通常可以直接使用，不用管配置中的 &amp;lt;令牌&amp;gt; 和 &amp;lt;密钥&amp;gt; 值，稍后启动服务后，通过 Console 页面可以获取到 Agent 的 KEY 和 Token&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;services:
  beszel:
    image: henrygd/beszel:latest
    container_name: beszel
    restart: unless-stopped
    ports:
      - 8090:8090
    volumes:
      - ./beszel_data:/beszel_data
      - ./beszel_socket:/beszel_socket

  beszel-agent:
    image: henrygd/beszel-agent:latest
    container_name: beszel-agent
    restart: unless-stopped
    network_mode: host
    volumes:
      - ./beszel_agent_data:/var/lib/beszel-agent
      - ./beszel_socket:/beszel_socket
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      LISTEN: /beszel_socket/beszel.sock
      HUB_URL: http://localhost:8090
      TOKEN: &amp;quot;&amp;lt;令牌&amp;gt;&amp;quot;
      KEY: &amp;quot;&amp;lt;密钥&amp;gt;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;docker compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;稍等下请求本地端口&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ curl -I http://localhost:8090
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预期打印&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
Date: Wed, 07 Jan 2026 10:03:22 GMT
Content-Length: 761
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;安装 Caddy 代理&lt;/h3&gt;
&lt;p&gt;以往一直使用 Nginx，这还是第一次使用 Caddy，为了 Auto HTTPS 特性。&lt;/p&gt;
&lt;p&gt;安装文档：&lt;a href="https://caddyserver.com/docs/install"&gt;https://caddyserver.com/docs/install&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;编辑配置文件&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;vim /etc/caddy/Caddyfile

# 格式化
caddy fmt --overwrite /etc/caddy/Caddyfile
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配置内容&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;beszel.yasking.org {
    reverse_proxy 127.0.0.1:8090
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;校验&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sudo caddy validate --config /etc/caddy/Caddyfile

# 重载
sudo systemctl reload caddy

# 查看状态
sudo systemctl status caddy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将域名地址指向服务器 IP，给 DNS 解析生效留点儿时间&lt;/p&gt;
&lt;p&gt;而后在服务器上请求验证&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl -I -L --header &amp;quot;Host: beszel.yasking.org&amp;quot; http://localhost
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预期输出&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;HTTP/1.1 308 Permanent Redirect
Connection: close
Location: https://beszel.yasking.org/
Server: Caddy
Date: Wed, 07 Jan 2026 10:09:33 GMT

HTTP/2 200
alt-svc: h3=&amp;quot;:443&amp;quot;; ma=2592000
content-type: text/html; charset=utf-8
date: Wed, 07 Jan 2026 10:09:33 GMT
vary: Origin
via: 1.1 Caddy
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
content-length: 761
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时部署完成，可以访问：&lt;a href="https://beszel.yasking.org/"&gt;https://beszel.yasking.org/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;添加 Agent&lt;/h3&gt;
&lt;p&gt;你要监控哪个服务器，就在哪个机器上安装 Agent&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;添加本机&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在部署 Beszel 服务的时候已经同时启动了 Beszel Agent，只是最初的 YAML 配置中 TOKEN 和 KEY 没有设置。&lt;/p&gt;
&lt;p&gt;在 Console 上点击「添加客户端」，填入机器名称、主机填写&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;名称：（自定义名称）
主机：/beszel_socket/beszel.sock（不要修改）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1767782236/02.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;保存后重启服务&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ docker compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;添加其它服务器&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;也还是点击「添加客户端」&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;名称：（自定义名称）
主机：11.22.33.44（要监控指标的服务器 IP）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;复制 Compose 文件或者 Docker run 命令到要监控指标的服务器上执行。&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.webp" src="https://images.yasking.org/technology/1767782236/03.webp"&gt;&lt;/p&gt;
&lt;h3&gt;Beszel 效果&lt;/h3&gt;
&lt;p&gt;页面美观，部署简单、Golang 开发的也足够轻量。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;首页&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.webp" src="https://images.yasking.org/technology/1767782236/04.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;详情&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.webp" src="https://images.yasking.org/technology/1767782236/05.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;移动端兼容良好&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1767782236/06.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;另外还支持 Webhook 推送告警信息，我暂时不需要就没继续设置了。&lt;/p&gt;</content><category term="Technology"></category><category term="Caddy"></category><category term="Software"></category></entry><entry><title>Memos: Claude Code in Action 中文版教程</title><link href="https://blog.yasking.org/a/1767680250.html" rel="alternate"></link><published>2026-01-06T14:18:59+08:00</published><updated>2026-01-06T14:18:59+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2026-01-06:/a/1767680250.html</id><summary type="html">&lt;p&gt;前两天刷 V2EX 看到站长推荐「Claude Code in Action」教程，收藏了还没看，刚发现有网友翻译整理了中文版：&lt;/p&gt;
&lt;p&gt;官方教程地址：&lt;a href="https://anthropic.skilljar.com/claude-code-in-action"&gt;https://anthropic.skilljar.com/claude-code-in-action&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;中文 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;前两天刷 V2EX 看到站长推荐「Claude Code in Action」教程，收藏了还没看，刚发现有网友翻译整理了中文版：&lt;/p&gt;
&lt;p&gt;官方教程地址：&lt;a href="https://anthropic.skilljar.com/claude-code-in-action"&gt;https://anthropic.skilljar.com/claude-code-in-action&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;中文翻译地址：&lt;a href="https://cholf5.com/claude-code-in-action/index.html"&gt;https://cholf5.com/claude-code-in-action/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Github 仓库：&lt;a href="https://github.com/cholf5/claude-code-in-action"&gt;https://github.com/cholf5/claude-code-in-action&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/memos/1767680250/01.webp"&gt;&lt;/p&gt;</content><category term="Memos"></category><category term="Claude"></category></entry><entry><title>2025 年度回顾</title><link href="https://blog.yasking.org/a/2025-summary.html" rel="alternate"></link><published>2025-12-31T19:30:00+08:00</published><updated>2025-12-31T19:30:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-31:/a/2025-summary.html</id><summary type="html">&lt;p&gt;想了想，还是记录一下。&lt;/p&gt;
&lt;h3&gt;阅读习惯&lt;/h3&gt;
&lt;p&gt;今年下半年重拾了阅读习惯，准确的说是从八月份开始，利用碎片化的时间在微信读书上 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;想了想，还是记录一下。&lt;/p&gt;
&lt;h3&gt;阅读习惯&lt;/h3&gt;
&lt;p&gt;今年下半年重拾了阅读习惯，准确的说是从八月份开始，利用碎片化的时间在微信读书上阅读，也看了一些纸质书，平均每天不到一小时。&lt;/p&gt;
&lt;p&gt;微信读书上领取体验卡，攒够 60 张 + 6 元可以兑换 30 天的会员（最近我发现如果 30 天会员每天都读书，30 天刚好能攒够 60 张体验卡，一年 72 元是微信读书会员最经济的开通方式）&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.yasking.org/pages/books.html?year=2025"&gt;2025 我阅读的书籍目录&lt;/a&gt;，其中《丰乳肥臀》、《一个名叫欧维的男人决定去死》、《置身事内》是我很推荐的书籍。&lt;/p&gt;
&lt;h3&gt;编程思考&lt;/h3&gt;
&lt;p&gt;今年初从手写代码转向 AI 辅助编程，使用 Cursor 刚好满一年，Cursor 提供的 2025 年终报告中显示我一年消耗了 1.57B 的 Token（Tab 用的较少），全年新增代码约 15+ 万行（保守统计），而在前两年，每年的编码行数都在 5 万行左右。&lt;/p&gt;
&lt;p&gt;看了最近开发的需求，假设一年多前到现在，在编码速度上我没有显著变快的前提下，以下是开发两个需求的统计信息对比：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;比对项&lt;/th&gt;
&lt;th&gt;2025 项目 A（AI Assisted）&lt;/th&gt;
&lt;th&gt;2024 项目 B（Manual）&lt;/th&gt;
&lt;th&gt;备注信息&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;开发时长&lt;/td&gt;
&lt;td&gt;7d&lt;/td&gt;
&lt;td&gt;23d&lt;/td&gt;
&lt;td&gt;借助 AI 显著压缩了开发时间。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;新增行数&lt;/td&gt;
&lt;td&gt;11,240&lt;/td&gt;
&lt;td&gt;6,335&lt;/td&gt;
&lt;td&gt;这两个需求难度差异不大，代码量差异主要跟需求大小有关。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;删除行数&lt;/td&gt;
&lt;td&gt;2,869&lt;/td&gt;
&lt;td&gt;83&lt;/td&gt;
&lt;td&gt;项目 A 新增模块的同时重构了旧有模块&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;日均净新增&lt;/td&gt;
&lt;td&gt;≈1,196&lt;/td&gt;
&lt;td&gt;≈272&lt;/td&gt;
&lt;td&gt;单位时间产出显著提升。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;日均变动量&lt;/td&gt;
&lt;td&gt;≈2,015&lt;/td&gt;
&lt;td&gt;≈279&lt;/td&gt;
&lt;td&gt;“吞吐量” 约 &lt;strong&gt;7.2× 提升&lt;/strong&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;代码重构率&lt;/td&gt;
&lt;td&gt;≈25.5%&lt;/td&gt;
&lt;td&gt;≈1.3%&lt;/td&gt;
&lt;td&gt;使用 AI 开发 “持续重构” 的主观意愿更强。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;近一年时间使用 AI 编程最大的感受是模型的能力越来越强，开发者可以越来越 “省力”，手不酸了，等 AI 写代码期间可以冲杯咖啡歇息下。&lt;/p&gt;
&lt;p&gt;但 “省力” 不等于 “不费脑”，根据 “Garbage in, garbage out” 原理，代码的质量上限完全取决于使用的人，对使用者的工程化实践和软件架构能力会有更高的要求，编程的核心进一步从 “编” 代码偏向于架构设计，AI 并没有让编程更 “简单”，而是让 “&lt;strong&gt;会不会做工程&lt;/strong&gt;” 这件事更赤裸。&lt;/p&gt;
&lt;h3&gt;博客改造&lt;/h3&gt;
&lt;p&gt;以往在博客主要是技术笔记，今年陆续增加了“阅读”、“生活”、“生活技巧” 类别，很多时候适当的记录也有助于思考，技术如此，生活亦是如此，写博客也保持了一定的克制，避免博客内容过于零散、碎片化。&lt;/p&gt;
&lt;p&gt;博客的样式在不改变主题的情况下，借助 AI 对样式进行了调优，这在以前对于后端工程师来说是很困难的。&lt;/p&gt;
&lt;p&gt;写了一个 Obsidian 插件用于导出文章，这样博文中添加图像与发布能在一定程度上自动化，方便很多。&lt;/p&gt;
&lt;h3&gt;年度报告&lt;/h3&gt;
&lt;p&gt;年末各家都出了年度报告，想了下自己就微信读书、B 站、QQ 音乐用的多。&lt;/p&gt;
&lt;p&gt;在哔哩哔哩天均半小时，主要看了一些 UP 主自制的熊猫人动画，追一些动漫及纪录片，预计明年会因为读书的等效替代而降低刷视频时间；&lt;/p&gt;
&lt;p&gt;中国移动 APP 每个月能领一个月的 QQ 音乐会员（网龄礼），所以今年听歌使用的是 QQ 音乐，2025 年听歌时长 100 小时，年度歌手是 G.E.M 邓紫棋，但是第二名杨瑜婷和第三名程响，对我来说后两者是很陌生的名字，单曲循环最多是《旅人》，出自《凡人修仙传》，这个动漫现在真的是国漫独一档，为了看它我开了 B 站会员。&lt;/p&gt;
&lt;h3&gt;资源整理&lt;/h3&gt;
&lt;p&gt;最近的思考是资源如果不整理，那么只会占用磁盘而没有太多的意义。&lt;/p&gt;
&lt;p&gt;近五年的照片，有几百 GB 存储在 OneDrive，另外还有一些分散在电脑、存储卡、移动硬盘、还有百度网盘中，大多处于无序的状态；对于重要的内容，加密后遵循 3-2-1 原则进行备份，文字笔记使用 Obsidian 记录。&lt;/p&gt;
&lt;p&gt;这两个月在抽空将图像视频去重、归档，需要备份的资料也在分门别类。将已经有序化的数据存储到一个 4TB 的机械硬盘中（使用带有独立电源的硬盘盒），每个月也将上个月手机产生的图像视频进行备份后从手机删除。&lt;/p&gt;
&lt;p&gt;对于在 macOS 上从 OneDrive 网盘下载回来的数据，我先导入到相机的 SD 卡，然后再从 SD 卡通过 Windows 电脑导入到 NTFS 格式的机械硬盘中，这个速度其实有些慢，所以妻子问我在做什么，我总是在导数据，我就说 “在备份照片”，并答应她以后也将她的手机照片备份。&lt;/p&gt;
&lt;h3&gt;难忘记忆&lt;/h3&gt;
&lt;p&gt;一年中有欢笑、有悲伤，最难过的莫过于 11.27 日，爷爷走了。&lt;/p&gt;
&lt;p&gt;突闻噩耗，我手忙脚乱，这是我第一次面对亲人的离世，爷爷今年 79 岁，这两年一直卧床，身体状况越来越差，只能喂流食，过了年的阴历二月就是爷爷八十岁的生日，没人想到在一个寻常的下午，爷爷没了气息，爸爸给我打了电话，妻子陪我回的老家。&lt;/p&gt;
&lt;p&gt;想起小时候的关于爷爷的记忆总会心里难受，看他日渐衰残的状态更让人心疼，但也明白爷爷这样每天的生活很遭罪，家人照料也很辛苦，爷爷忘记了所有人，更没办法说话表达，不能抽颗烟，也喝不了他爱的酒。&lt;/p&gt;
&lt;p&gt;思绪总在闲暇时上涌，写着写着眼泪又在眼中打转，想起那天，告别仪式我努力想记住爷爷的样子，火化后众人将骨灰埋入坟莹，那天天气晴朗，山上的雪很白，落叶满地，我拾了两叶，就好像能回到那天...&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>Memos: 体验 tanaos-text-anonymizer-v1 NER 模型</title><link href="https://blog.yasking.org/a/1766716089.html" rel="alternate"></link><published>2025-12-26T10:51:59+08:00</published><updated>2025-12-26T10:51:59+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-26:/a/1766716089.html</id><summary type="html">&lt;p&gt;在网上看到有人推荐 &lt;code&gt;tanaos/tanaos-text-anonymizer-v1&lt;/code&gt; 可用于信息脱敏，496 MB 大小很适合本地使用。&lt;/p&gt;
&lt;p&gt;一开始我还以为它是大语言模型（LLM），想着用 Ollama 拉起 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;在网上看到有人推荐 &lt;code&gt;tanaos/tanaos-text-anonymizer-v1&lt;/code&gt; 可用于信息脱敏，496 MB 大小很适合本地使用。&lt;/p&gt;
&lt;p&gt;一开始我还以为它是大语言模型（LLM），想着用 Ollama 拉起来跑，之后发现完全不是一回事。它本质上是一个用于 NER（命名实体识别）任务的模型。&lt;/p&gt;
&lt;p&gt;用人话说就是：&lt;strong&gt;输入一段文本，模型会扫描其中的实体，并返回命中的内容和对应的标签。&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;PERSON          John Smith      
EMAIL           john.smith@company.com  
PHONE_NUMBER    +1-202-555-0199  
LOCATION        New York  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;测试后感觉英文人名和地址识别还不错，&lt;strong&gt;不支持中文&lt;/strong&gt;，另外想要识别数据库链接、AK/SK 等敏感信息也还是需要搭配正则表达式使用，之前我把它理解成了 “万能脱敏器”。🤷 &lt;/p&gt;
&lt;p&gt;Python3 的示例代码在：&lt;a href="https://gist.github.com/sincerefly/288808ea15d23db8c8f57896852dd465"&gt;Gist&lt;/a&gt;&lt;/p&gt;</content><category term="Memos"></category><category term="Model"></category></entry><entry><title>Memos: 查询 Google 账号注册时间</title><link href="https://blog.yasking.org/a/1766126435.html" rel="alternate"></link><published>2025-12-19T14:41:59+08:00</published><updated>2025-12-19T14:41:59+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-19:/a/1766126435.html</id><summary type="html">&lt;p&gt;查询 Google 账号的注册时间：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;访问 &lt;a href="https://takeout.google.com/"&gt;https://takeout.google.com/&lt;/a&gt;；&lt;/li&gt;
&lt;li&gt;只勾选 「Google 账号」选项后提交导出；&lt;/li&gt;
&lt;li&gt;半分钟后刷新页面，页面最上方可以看到「您的最新 …&lt;/li&gt;&lt;/ol&gt;</summary><content type="html">&lt;p&gt;查询 Google 账号的注册时间：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;访问 &lt;a href="https://takeout.google.com/"&gt;https://takeout.google.com/&lt;/a&gt;；&lt;/li&gt;
&lt;li&gt;只勾选 「Google 账号」选项后提交导出；&lt;/li&gt;
&lt;li&gt;半分钟后刷新页面，页面最上方可以看到「您的最新导出作业」，点击下载；&lt;/li&gt;
&lt;li&gt;解压缩 zip 包，&lt;em&gt;.ChangeHistory.html&lt;/em&gt; 和 &lt;em&gt;.SubscriberInfo.html&lt;/em&gt; 网页内有注册时间。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我的 Google 账号注册时间是 &lt;em&gt;2015-01-24&lt;/em&gt;，一个寻常的午后。&lt;/p&gt;</content><category term="Memos"></category><category term="Google"></category></entry><entry><title>Memos: 关于 Z30 在室内摄像被手机降维打击这点儿事儿</title><link href="https://blog.yasking.org/a/1766052343.html" rel="alternate"></link><published>2025-12-18T18:40:59+08:00</published><updated>2025-12-18T18:40:59+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-18:/a/1766052343.html</id><summary type="html">&lt;p&gt;周末拍摄一场室内的活动，带了独脚架，设备是 &lt;strong&gt;Nikon Z30 + DX 12-28mm 镜头&lt;/strong&gt;，录制过程中从相机屏幕上看到画面良好，导出到电脑查看发 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;周末拍摄一场室内的活动，带了独脚架，设备是 &lt;strong&gt;Nikon Z30 + DX 12-28mm 镜头&lt;/strong&gt;，录制过程中从相机屏幕上看到画面良好，导出到电脑查看发现画面惨不忍睹：对焦飘忽、噪点严重且暗角明显。&lt;/p&gt;
&lt;p&gt;首次在活动中尝试使用 Z30 录制视频宣告失败，直面 “入门相机” 在复杂光线下被 “高度优化的计算摄影手机” &lt;strong&gt;降维打击&lt;/strong&gt;这档子事儿，在室内场景也体验到了半画幅天黑就回家！&lt;/p&gt;
&lt;p&gt;反而&lt;strong&gt;手持 iPhone 16 数字版&lt;/strong&gt;录制的一段视频效果还不错，虽然没纵深，但是曝光通过算法控制的很好，视频体积也不大！&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;极端爆论&lt;/strong&gt;：&lt;strong&gt;普通用户无脑使用苹果手机录像能获得到性价比最高的视频质量&lt;/strong&gt;，整机一万出头的预算，主要场景是视频拍摄，请放弃相机，闭眼买一台 iPhone，记得钱加在存储空间上！&lt;/p&gt;</content><category term="Memos"></category><category term="半画幅"></category></entry><entry><title>阅读《我与地坛》</title><link href="https://blog.yasking.org/a/reading-the-temple-of-earth.html" rel="alternate"></link><published>2025-12-13T18:34:48+08:00</published><updated>2025-12-13T18:34:48+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-13:/a/reading-the-temple-of-earth.html</id><summary type="html">&lt;p&gt;读过史铁生《我与地坛》，久久没写读书笔记，划线很多，但一味的摘录我觉着不合适。&lt;/p&gt;
&lt;p&gt;作者从地坛公园讲起，不同以往的清幽与 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;读过史铁生《我与地坛》，久久没写读书笔记，划线很多，但一味的摘录我觉着不合适。&lt;/p&gt;
&lt;p&gt;作者从地坛公园讲起，不同以往的清幽与宁静，被开发为景区的地坛公园，接待了有许多游客，多了几分热闹和喧嚣，单从个人的理解出发：地坛是铁生在现实世界的陪伴者，亦是他心中的地坛，承载着他生命的坚韧和思考。&lt;/p&gt;
&lt;p&gt;这本书最让我感动的部分是作者对于母亲的记录，铁生患病后脾气不好，常一个人到公园，母亲总悄悄的来找他，怕被铁生发现、也担心打扰到他，时而铁生看到母亲也当作没瞧见，让母亲一顿好找。母亲几次为铁生的工作奔波，被别人说呛回来，路上拾了个花枝种在院落，母亲走后些许年，枝条长大竟是合欢树，文中字字不提思念，又句句都是想念。“寻常”的文字能承载诸多的情绪，不经意间就能被戳中泪点。&lt;/p&gt;
&lt;p&gt;书中还有几篇章节适合多次品读，印象颇深的还有对照顾残障人士思辨，按我的理解，社会有义务在公共场所提供便利的设施，重要的是除掉异样的目光和偏见，身体的残疾无法避免，也不是罪大恶极，世界有时并不美好，但我们总可以修修补补。&lt;/p&gt;
&lt;p&gt;此外，儿时的小学堂凸显人性的拉帮结派、紧张时期小姑娘M分众人糖豆事件，庄子那激荡又短暂的人生，都让人印象深刻。&lt;/p&gt;
&lt;p&gt;之前没去过地坛公园，有机会我想去看看铁生走过的角落，去看那一如从前的树，跨越着时间，它不言不语，且听风声，或许时间也能让我遇见属于自己的地坛。&lt;/p&gt;
&lt;p&gt;最后，“铁生是一个极细腻、温柔，善良的人。” 这是我关于本书推荐语。&lt;/p&gt;</content><category term="Reading"></category></entry><entry><title>Memos: Ghostty + Neovim + LazyVim</title><link href="https://blog.yasking.org/a/1765538459.html" rel="alternate"></link><published>2025-12-12T19:20:59+08:00</published><updated>2025-12-12T19:20:59+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-12:/a/1765538459.html</id><content type="html">&lt;p&gt;安装了 Ghostty + Neovim + LazyVim，开箱即用、配色舒适，果断放弃了自己配置的 Oh My Zsh 方案，又是迈向现代化的一天。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/memos/1765538459/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;使用 &lt;code&gt;nvim&lt;/code&gt; 打开文件:&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/memos/1765538459/02.webp"&gt;&lt;/p&gt;</content><category term="Memos"></category><category term="Terminal"></category><category term="Software"></category></entry><entry><title>Memos: 找到 Cursor 运行巨慢的一个原因</title><link href="https://blog.yasking.org/a/1765505478.html" rel="alternate"></link><published>2025-12-12T10:14:45+08:00</published><updated>2025-12-12T10:14:45+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-12:/a/1765505478.html</id><summary type="html">&lt;p&gt;这两天一直没有办法 Vibe Coding&lt;/p&gt;
&lt;p&gt;Cursor 巨慢到一定程度，17:45 提交的任务，18:21 还在 “吭哧瘪肚” 的输出。&lt;/p&gt;
&lt;p&gt;以至于我不得不使用网页版，降 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;这两天一直没有办法 Vibe Coding&lt;/p&gt;
&lt;p&gt;Cursor 巨慢到一定程度，17:45 提交的任务，18:21 还在 “吭哧瘪肚” 的输出。&lt;/p&gt;
&lt;p&gt;以至于我不得不使用网页版，降级到手动复制粘贴的方式调优代码。&lt;/p&gt;
&lt;p&gt;排查了网络、换用了模型都不行，想到要不重建下索引试试，然后问题就这样解决了 🤷&lt;/p&gt;</content><category term="Memos"></category><category term="Cursor"></category></entry><entry><title>Memos: 京东家政</title><link href="https://blog.yasking.org/a/176542029.html" rel="alternate"></link><published>2025-12-11T19:21:00+08:00</published><updated>2025-12-11T19:21:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-11:/a/176542029.html</id><summary type="html">&lt;p&gt;前些天发现京东 PLUS 快过期了，还能兑换家政服务，于是预约了 2 小时的日常清洁。&lt;/p&gt;
&lt;p&gt;“阿姨”来了后，跟我沟通清洁哪里，想了下，就 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;前些天发现京东 PLUS 快过期了，还能兑换家政服务，于是预约了 2 小时的日常清洁。&lt;/p&gt;
&lt;p&gt;“阿姨”来了后，跟我沟通清洁哪里，想了下，就跟她说厨房和卫生间，没什么特别需要清理的地方，按她的方式就好，就去客厅窗边歇息了，厨房大概清洁一小时20分钟，另外40分钟清理卫生间，我看时间到了，就去提醒她，也聊了几句天，得知：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;她们属于京东家政的员工；&lt;/li&gt;
&lt;li&gt;派单模式，每天三四单，在选定地点的几公里范围内派单；&lt;/li&gt;
&lt;li&gt;每周休息一天，可以灵活选择休息日。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;清洁的非常干净，搞定了很多卫生死角！咸鱼之前 39.9 元两小时，最近已经涨价到 49.9 左右，&lt;strong&gt;感觉家政服务有依赖性啊&lt;/strong&gt;，现在完全不想自己 “大扫除”，只想「专业的事情交给专业的人」&lt;del&gt;可能是因为懒&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;P.S. 这个工作蛮辛苦的，纯体力劳动、非固定工作区域，每家情况都不同，也无法灵活的像骑手一样兼职，好在月月有稳定的工资，还蛮不错。&lt;/p&gt;</content><category term="Memos"></category><category term="京东家政"></category></entry><entry><title>哈尔滨灵活就业人员医保退休待遇申领条件</title><link href="https://blog.yasking.org/a/harbin-linghuojiuye-yibao.html" rel="alternate"></link><published>2025-12-09T19:41:16+08:00</published><updated>2025-12-09T19:41:16+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-09:/a/harbin-linghuojiuye-yibao.html</id><summary type="html">&lt;p&gt;以下信息咨询医保热线得知，任何疑问咨询哈尔滨市医疗保障服热线：&lt;strong&gt;0451-12393&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;达到国家规定的法定退休年龄（&lt;a href="https://m12333.cn/cat/age"&gt;退休年龄计算器 …&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;</summary><content type="html">&lt;p&gt;以下信息咨询医保热线得知，任何疑问咨询哈尔滨市医疗保障服热线：&lt;strong&gt;0451-12393&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;达到国家规定的法定退休年龄（&lt;a href="https://m12333.cn/cat/age"&gt;退休年龄计算器&lt;/a&gt;）；&lt;/li&gt;
&lt;li&gt;以灵活就业人员身份办理完成基本养老保险退休手续（医保和养老保险退休身份需要一致）；&lt;/li&gt;
&lt;li&gt;实缴医疗保险费满 15 年（男女不限），其中哈尔滨地区最低需缴纳 10 年。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;补充说明&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;曾参加单位职工医保的缴费年限可计入上述 15 年实际缴费年限；&lt;/li&gt;
&lt;li&gt;在其他省、市参加职工医疗保险的实际缴费年限亦可合并计算（最多使用 5 年）；&lt;/li&gt;
&lt;li&gt;以上规定为哈尔滨市当前执行口径，&lt;strong&gt;政策可能随时间调整，仅对近年具有参考意义&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;养老保险最低缴纳年限在 2030 年后会逐年提高（&lt;a href="https://www.hlj.gov.cn/hlj/c116413/202502/c00_31808307.shtml"&gt;政策&lt;/a&gt;），医保最低缴纳 15 年不受影响。&lt;/li&gt;
&lt;/ol&gt;</content><category term="Skill"></category></entry><entry><title>记地暖不热的维修过程</title><link href="https://blog.yasking.org/a/repair-underfloor-heating.html" rel="alternate"></link><published>2025-12-06T20:34:47+08:00</published><updated>2025-12-06T20:34:47+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-06:/a/repair-underfloor-heating.html</id><summary type="html">&lt;p&gt;前段时间哈尔滨进入供暖季，地热供暖的房屋，供热后地面摸着不太对，有些区域温热，有些区域摸着冰凉。&lt;/p&gt;
&lt;p&gt;先电话联系了物 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;前段时间哈尔滨进入供暖季，地热供暖的房屋，供热后地面摸着不太对，有些区域温热，有些区域摸着冰凉。&lt;/p&gt;
&lt;p&gt;先电话联系了物业，物业维修的师傅说这事儿得找供暖公司，地暖不热由他们负责排查和维修，打通了供暖公司的服务电话，约好了时间上门排查。&lt;/p&gt;
&lt;p&gt;一般情况，供暖不热，可能是地暖管道有气体空腔，水流没有很好的循环，这个供暖公司师傅就在地暖出口开始放水，放了一阵后有温水出来后就说 “没问题了”，测了室内的温度 22 度，算是达标了就不想再管。&lt;/p&gt;
&lt;p&gt;问题是同小区别家同户型卧室能达到 28 度，显然不能都归结到 ‘房屋气密性’ 问题，供暖费不能花了受冻不是。&lt;/p&gt;
&lt;p&gt;了解了一圈，发现地暖不热还可能有几个原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;分水器坏了；&lt;/li&gt;
&lt;li&gt;地暖管道污垢太多，水流通不畅；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;想着在网上找个维修地暖的师傅去看看，也是几年没有清洗地暖管道，顺便清洗一遍。&lt;/p&gt;
&lt;p&gt;先联系的这位师傅是咸鱼上的个人中介给找的，没介绍费，这个师傅就 “厉害” 了，人还没去就说那是分水器坏了，要给我换一套，他说 “用的都是日丰品牌，纯铜的质量过硬”，提供给我的报价是 180/路，我家是 4 路，那么就是 720 元一套，我说那清洗地热多少钱，300 元/次，都下来的话收一千块抹个零。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1765024487/01.webp" width="58.00%" /&gt;&lt;/p&gt;
&lt;p&gt;（日丰四路分水器）&lt;/p&gt;
&lt;p&gt;放下电话，直觉上这价格就不合理，淘宝一搜果然，日丰四路分水器 220 元一套，这师傅狮子大开口过分真实了，就跟他说不用上门了，就在淘宝上又找个师傅咨询。&lt;/p&gt;
&lt;p&gt;都说货比三家，找维修师傅也得多问问。新的师傅清洗地热报价 230 元，让他上门看看地暖不热的原因，还真给找到了—— &lt;strong&gt;下图中红色的那个球形止水阀损坏，出水管有往回的水压，导致入户热水无法正常流出，阻塞水循环，进而部分区域不热，出水管处冰凉。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1765024487/02.webp" width="58.00%" /&gt;&lt;/p&gt;
&lt;p&gt;这个日丰止水阀门师傅报价 120 元，是一对拆开卖的，工 + 料最后付师傅 318 元，算是比较合理的价格。&lt;/p&gt;
&lt;p&gt;维修完我也让他清洗了地暖，我爸也说地暖水不脏，我是比较好奇这地热管路到底有没有污垢，供暖公司说管线没事儿（可能是利益相关，供暖公司的入户热水脏是他们的问题）&lt;/p&gt;
&lt;p&gt;请看 VCR：&lt;/p&gt;
&lt;video id="video" controls="" preload="none" poster="https://images.yasking.org/moments/1765024487/03.jpg" width=420&gt;
  &lt;source id="mp4" src="https://images.yasking.org/moments/1765024487/03.mp4" type="video/mp4"&gt;
  &lt;p&gt;Your user agent does not support the HTML5 Video element.&lt;/p&gt;
&lt;/video&gt;

&lt;p&gt;在我维修完成后，大开口师傅又给我发来消息：“你要是嫌贵，那不换分水器光清洗地热也行。”&lt;/p&gt;
&lt;p&gt;这师傅怕不是把我当傻子了 🤔&lt;/p&gt;
&lt;h3&gt;经验记录&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;能淘宝尽量远离咸鱼个人中介（省下‘中介费’找到的人也容易不靠谱）；&lt;/li&gt;
&lt;li&gt;地暖间隔几年需要清洗，入户水可能携带杂质，如果地暖彻底堵塞，会很麻烦；&lt;/li&gt;
&lt;li&gt;找维修师傅也要货比三家，避免被宰；&lt;/li&gt;
&lt;li&gt;分水器很不容易损坏，三五年完全没问题，除非十多年的老设备需要注意；&lt;/li&gt;
&lt;/ol&gt;</content><category term="Moments"></category></entry><entry><title>Memos: 赛博菩萨 Cloudflare 又挂了</title><link href="https://blog.yasking.org/a/1764925292.html" rel="alternate"></link><published>2025-12-05T17:08:45+08:00</published><updated>2025-12-05T17:08:45+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-05:/a/1764925292.html</id><summary type="html">&lt;p&gt;Jenkins 部署打包前端报错&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;npm ERR! code E500
npm ERR! 500 Internal Server Error - GET https://registry.npmjs.org/vue-emoji-picker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/memos/1764925292/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;网上一搜，Cloudflare 出问题，Status 状态页：&lt;a href="https://www.cloudflarestatus.com/"&gt;https://www.cloudflarestatus.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/memos/1764925292/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;检测服务是否挂掉的 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Jenkins 部署打包前端报错&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;npm ERR! code E500
npm ERR! 500 Internal Server Error - GET https://registry.npmjs.org/vue-emoji-picker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/memos/1764925292/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;网上一搜，Cloudflare 出问题，Status 状态页：&lt;a href="https://www.cloudflarestatus.com/"&gt;https://www.cloudflarestatus.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/memos/1764925292/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;检测服务是否挂掉的服务因为使用 CF 也挂了 &lt;a href="https://downdetector.com/"&gt;https://downdetector.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;好家伙，看到网友分享了一个神奇的网站，独立监控这一块：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://downdetectorsdowndetectorsdowndetectorsdowndetector.com/"&gt;https://downdetectorsdowndetectorsdowndetectorsdowndetector.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://downdetectorsdowndetectorsdowndetector.com/"&gt;https://downdetectorsdowndetectorsdowndetector.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://downdetectorsdowndetector.com/"&gt;https://downdetectorsdowndetector.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://downdetector.com/"&gt;https://downdetector.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Memos"></category><category term="Cloudflare"></category></entry><entry><title>AnyTLS 软件的配置与使用</title><link href="https://blog.yasking.org/a/anytls-software-usage.html" rel="alternate"></link><published>2025-12-04T08:49:39+08:00</published><updated>2025-12-04T08:49:39+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-12-04:/a/anytls-software-usage.html</id><summary type="html">&lt;p&gt;本文内容仅用于计算机网络与信息安全的学习与研究，不构成任何形式的技术服务或操作建议，亦不鼓励将相关信息用 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;本文内容仅用于计算机网络与信息安全的学习与研究，不构成任何形式的技术服务或操作建议，亦不鼓励将相关信息用于非学术目的。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;项目地址：&lt;a href="https://github.com/anytls/anytls-go"&gt;https://github.com/anytls/anytls-go&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;项目介绍：一个试图缓解嵌套的 TLS 握手指纹(TLS in TLS) 问题的代理协议。&lt;code&gt;anytls-go&lt;/code&gt; 是该协议的参考实现。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;在服务器运行 AnyTLS Server&lt;/h3&gt;
&lt;p&gt;实验环境下，临时关闭防火墙，放行端口&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;iptables -F
firewall-cmd --permanent --add-port 8443/tcp
firewall-cmd --reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;到 Release 获取最新版并下载运行&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ wget -O anytls_0.0.11_linux_amd64.zip https://github.com/anytls/anytls-go/releases/download/v0.0.11/anytls_0.0.11_linux_amd64.zip

$ unzip anytls_0.0.11_linux_amd64.zip

$ ./anytls-server -l 0.0.0.0:8443 -p 密码
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;本地运行 AnyTLS Client&lt;/h3&gt;
&lt;p&gt;替换服务器的 IP、端口以及连接密码&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;./anytls-client -l 127.0.0.1:1080 -s 服务器IP:8443 -p 密码
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;本地访问测试&lt;/h3&gt;
&lt;p&gt;不使用转发&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl https://ip.me
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用 AnyTLS 转发请求&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl -x socks5://127.0.0.1:1080 https://ip.me
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预期会打印出服务器的 IP&lt;/p&gt;
&lt;h3&gt;服务端使用 Mihomo 启动运行&lt;/h3&gt;
&lt;p&gt;Mihomo 是个高性能、跨平台的代理规则处理核心；&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;安装 Mihomo 服务&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;下载地址：&lt;a href="https://github.com/MetaCubeX/mihomo/releases"&gt;https://github.com/MetaCubeX/mihomo/releases&lt;/a&gt; &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ wget https://github.com/MetaCubeX/mihomo/releases/download/v1.19.17/mihomo-linux-amd64-v2-go123-v1.19.17.gz

$ gzip -d mihomo-linux-amd64-v2-go123-v1.19.17.gz

$ mv mihomo-linux-amd64-v2-go123-v1.19.17 /usr/local/bin/mihomo
$ chmod +x /usr/local/bin/mihomo

# 添加目录到环境变量
$ echo 'export PATH=&amp;quot;/usr/local/bin:$PATH&amp;quot;' &amp;gt;&amp;gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;我下载的 V2 版本，因为使用 V3 版本报错 “This program can only be run on AMD64 processors with v3 microarchitecture support.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;执行测试&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;mihomo -v
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;Mihomo Meta v1.19.17 linux amd64 with go1.23.12 Mon Dec  1 01:06:20 UTC 2025
Use tags: with_gvisor
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;生成自签证书&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;
openssl req -x509 -newkey ec:&amp;lt;(openssl ecparam -name prime256v1) \
  -keyout server.key \
  -out server.crt \
  -days 825 \
  -nodes \
  -sha256 \
  -subj &amp;quot;/CN=bing.com&amp;quot; \
  -addext &amp;quot;subjectAltName=DNS:bing.com,DNS:www.bing.com&amp;quot;

# 移动到配置目录
mkdir -p /etc/mihomo
mv server.key /etc/mihomo
mv server.crt /etc/mihomo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中 server.crt 是自签证书，server.key 是 EC 私钥。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;生成 Mihomo 配置文件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;（注意替换配置文件中的用户名密码）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;cat &amp;gt; config.yaml &amp;lt;&amp;lt; 'EOF'
listeners:
- name: anytls-in-1
  type: anytls
  port: 8443
  listen: 0.0.0.0
  users:
    username1: 密码1
    username2: 密码2
  certificate: /etc/mihomo/server.crt
  private-key: /etc/mihomo/server.key
  padding-scheme: |
   stop=8
   0=30-30
   1=100-400
   2=400-500,c,500-1000,c,500-1000,c,500-1000,c,500-1000
   3=9-9,500-1000
   4=500-1000
   5=500-1000
   6=500-1000
   7=500-1000
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将配置文件移动到配置目录&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;mkdir -p /etc/mihomo

mv config.yaml /etc/mihomo/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;运行测试&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-d&lt;/code&gt; 参数是 mihomo 的工作目录，会在其中查找配置文件、规则文件等&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-shell"&gt;mihomo -d /etc/mihomo

# 后台运行
nohup /usr/local/bin/mihomo -d /etc/mihomo &amp;gt; /var/log/mihomo.log 2&amp;gt;&amp;amp;1 &amp;amp;

# 结束进程
pkill -f mihomo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动后使用 &lt;code&gt;tail -f /var/log/mihomo.log&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;time=&amp;quot;2025-08-15T11:06:20.771313086Z&amp;quot; level=info msg=&amp;quot;Start initial configuration in progress&amp;quot;                                  
time=&amp;quot;2025-08-15T11:06:20.771797889Z&amp;quot; level=info msg=&amp;quot;Geodata Loader mode: memconservative&amp;quot;                                     
time=&amp;quot;2025-08-15T11:06:20.771829776Z&amp;quot; level=info msg=&amp;quot;Geosite Matcher implementation: succinct&amp;quot;                                 
time=&amp;quot;2025-08-15T11:06:20.772283187Z&amp;quot; level=info msg=&amp;quot;Initial configuration complete, total time: 0ms&amp;quot;                          
time=&amp;quot;2025-08-15T11:06:20.812756242Z&amp;quot; level=info msg=&amp;quot;Sniffer is closed&amp;quot;         
time=&amp;quot;2025-08-15T11:06:20.814453853Z&amp;quot; level=info msg=&amp;quot;AnyTLS[anytls-in-1] proxy listening at: [::]:8443&amp;quot;                        
time=&amp;quot;2025-08-15T11:06:20.814654607Z&amp;quot; level=info msg=&amp;quot;Start initial compatible provider default&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mihomo 服务端启动完毕，在本地 anytls-client 客户端启动的情况下，可以在本地请求获取自己的 IP，预期为服务器的 IP&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl -x socks5://127.0.0.1:1080 https://ip.me
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;本地 Clash Verge 加载配置&lt;/h3&gt;
&lt;p&gt;目前不太会配置本地 Clash Verge 客户端的 config 配置，用 AI 精简了一个订阅的配置，勉强能用&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;mode: rule
mixed-port: 7897
allow-lan: false
log-level: warning
ipv6: true
unified-delay: true
external-controller-unix: /var/tmp/verge/verge-mihomo.sock

bind-address: '*'

profile:
  store-selected: true

proxies:
  - name: &amp;quot;Mihomo-anytls&amp;quot;
    type: anytls
    server: 23.xx.xx.xx   # 替换为你的 Mihomo 服务器 IP/域名
    port: 8443            # 替换为你的 Mihomo 配置端口
    username: dong        # 替换为 Mihomo 用户名
    password: qq123456    # 替换为 Mihomo 密码
    tls: true
    skip-cert-verify: true # 自签证书保留 true，可信证书可去掉

proxy-groups:
  - name: &amp;quot;Mihomo-Group&amp;quot;
    type: select
    proxies:
      - &amp;quot;Mihomo-anytls&amp;quot;

rules:
  - MATCH,Mihomo-Group
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Firefox 浏览器使用的 SmartProxy 扩展，Clash Verge 使用系统代理模式。&lt;/p&gt;
&lt;p&gt;访问  &lt;a href="https://www.ipaddress.my/"&gt;https://www.ipaddress.my/&lt;/a&gt; ，已显示为服务器 IP，可以有效的保护个人隐私。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/technology/1764812979/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;PS：之前有忘记了这个 VPS 是在哪里买的，感谢其显示了 VPS 的 ISP 信息。&lt;/em&gt;&lt;/p&gt;</content><category term="Technology"></category><category term="网络安全"></category><category term="Software"></category><category term="Yxorp"></category></entry><entry><title>阅读《在巴东》</title><link href="https://blog.yasking.org/a/reading-in-badong.html" rel="alternate"></link><published>2025-11-20T19:11:00+08:00</published><updated>2025-11-20T19:11:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-11-20:/a/reading-in-badong.html</id><summary type="html">&lt;p&gt;最开始听说‘陈行甲’这个名字并非源于网络，而是从一友人口中。当年陈老师去他们学校演讲，结束后在校门口，利用上车前 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;最开始听说‘陈行甲’这个名字并非源于网络，而是从一友人口中。当年陈老师去他们学校演讲，结束后在校门口，利用上车前的短暂间歇，友人有幸与他合影。&lt;/p&gt;
&lt;p&gt;前段时间翻微信读书的免费图书馆碰运气，偶然间看到陈行甲的《在巴东》就领取到了书架，开始阅读就深深着迷，读完后仍意犹未尽，进而又搜索了当年的一些视频，别有一番感受。&lt;/p&gt;
&lt;p&gt;《在巴东》是陈行甲《在峡江的转弯处》中最精彩的节选，作者讲述从上任湖北巴东县委书记到五年任期结束这段时间的任职历程，在治理和斗争中政府的公信力得以重建，在温暖和关怀中巴东县的民心也再次凝聚。&lt;/p&gt;
&lt;p&gt;作者文笔流畅而富有亲和力，记录详实（得益于作者有写日记的习惯），读来朗朗上口。通读下来，我感觉最难得的是作者面对困难时的心态和担当，难以界定的人情关系、重金诱惑以及切实的家人安全的威胁，很能感受到坚守本心之难，之弥足珍贵，艰难之时，中途一度抑郁住院，清官不易，有作为则更是难上加难！&lt;/p&gt;
&lt;p&gt;推荐《在巴东》，短短三万字，能看到陈老师直面困境，守住本心的坚持，看到黑暗中仍有人发光，无形中带给人如火的力量，最终的激流勇退于人民和国家来说是极大的损失，但对个人是智慧而勇敢的抉择，所幸陈书记投身公益，仍能发光发热，身体力行的影响着许多人。&lt;/p&gt;
&lt;p&gt;这本书另一个有趣的地方在于可以查考，例如读到一处人名，读者可以通过网络了解到他们的近况，十多年时间，艳平从接班县委书记，现已升任州委常委，成为高级领导干部：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我今天和大家谈这些，是希望大家都放下这个沉重的包袱。我和艳平同志深入沟通过这个问题，我们有决心有信心带好巴东的风气！大家想啊，如果我不收，艳平不收，书记县长都不收了，那么你给别的领导送钱干什么呀？有什么用啊？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;而另一位给出陈行甲以下评价的「原湖北省委巡视组组长」樊仁富已经于2023年10月，涉嫌严重违法，接受湖北省监察委员会监察调查。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;陈行甲 “一身正气、一身杀气、一身朝气”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;最后，摘录两段收藏的佳句，展现了陈老师细腻而温柔，坚定且无愧的人生信念：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“我不敢说自己不负苍生，但我敢说自己不负本心，敢说自己是个不收钱的县委书记，敢说自己已经拼尽全力。”&lt;/p&gt;
&lt;p&gt;“轻轻地我走了，正如我轻轻地来；我挥一挥衣袖，不带走一片云彩。”再见了，我的巴东！天空中没有翅膀的痕迹，而我已飞过。此去经年，山长水阔，你在我的心里，在我的梦里。”&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Reading"></category></entry><entry><title>Memos: Web Archive 暂时离线</title><link href="https://blog.yasking.org/a/1763632394.html" rel="alternate"></link><published>2025-11-20T17:54:45+08:00</published><updated>2025-11-20T17:54:45+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-11-20:/a/1763632394.html</id><summary type="html">&lt;p&gt;想缓存个网页，发现 Web Archive 离线了&lt;/p&gt;
&lt;p&gt;地址: &lt;a href="https://web.archive.org/sry"&gt;https://web.archive.org/sry&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/memos/1763632394/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;最近总能感受到互联网的脆弱 🤷&lt;/p&gt;
&lt;!--more--&gt;

&lt;h3&gt;2025-11-21 更新&lt;/h3&gt;
&lt;p&gt;目前，服务已经恢复: &lt;a href="https://web.archive.org/"&gt;https://web.archive.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;官方 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;想缓存个网页，发现 Web Archive 离线了&lt;/p&gt;
&lt;p&gt;地址: &lt;a href="https://web.archive.org/sry"&gt;https://web.archive.org/sry&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/memos/1763632394/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;最近总能感受到互联网的脆弱 🤷&lt;/p&gt;
&lt;!--more--&gt;

&lt;h3&gt;2025-11-21 更新&lt;/h3&gt;
&lt;p&gt;目前，服务已经恢复: &lt;a href="https://web.archive.org/"&gt;https://web.archive.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;官方 Mastodon 发布&lt;a href="https://mastodon.archive.org/@internetarchive/115583852434614027"&gt;公告&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Status update: fiber cut between data centers - trucks are rolling. Services are slow but functional, except for the Wayback Machine, which is still offline.&lt;/p&gt;
&lt;p&gt;状态更新：数据中心之间的光纤被切断 - 抢修车辆已出动。除Wayback Machine仍处于离线状态外，各项服务运行缓慢但功能正常。&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Memos"></category><category term="Archive"></category></entry><entry><title>忆时光：十五年前我的家（动迁前夕）</title><link href="https://blog.yasking.org/a/the-old-house-from-fifteen-years-ago.html" rel="alternate"></link><published>2025-11-02T22:53:15+08:00</published><updated>2025-11-02T22:53:15+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-11-02:/a/the-old-house-from-fifteen-years-ago.html</id><summary type="html">&lt;p&gt;家族群里叔叔发了几张老照片，看着破旧、熟悉的小二楼，记忆瞬间被拉回到小时候，动迁前的那些记忆时光。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1762095195/01.webp" width="71.64%" /&gt;&lt;/p&gt;
&lt;p&gt;照片的小二楼 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;家族群里叔叔发了几张老照片，看着破旧、熟悉的小二楼，记忆瞬间被拉回到小时候，动迁前的那些记忆时光。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1762095195/01.webp" width="71.64%" /&gt;&lt;/p&gt;
&lt;p&gt;照片的小二楼是我的家，当初盖房子的时候，它可是这片顶时髦的房子，周边都是清一色的平房，照片中的人是我爷爷，90年代初期，爷爷带领十几二十来岁的爸爸以及一些亲戚一砖一瓦将房子盖起来，几年后我出生，这就是我生长的地方。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1762095195/02.webp" width="71.64%" /&gt;&lt;/p&gt;
&lt;p&gt;小二楼的背面有一个二层的阳台，七八岁正式淘气又安静的我会在栏杆上绑上绳子，然后从二楼一点点降下来，现在想来我胆子还蛮大的，大人竟也不觉得危险。&lt;/p&gt;
&lt;p&gt;照片右侧的平房是爷爷奶奶家的位置，爷爷家是火炕，小二楼是暖气，烧锅炉的时候，我们家、叔叔家都统一供暖，奶奶负责烧炉子，我最喜欢的事情就是找点稀奇古怪的东西，然后赶在奶奶添柴的时候扔到桔红色的火焰中，感觉一切都会被焚烧。&lt;/p&gt;
&lt;p&gt;当然大人们不让我乱扔，‘小孩儿玩火尿炕’；灶坑会 ‘打枪’。我从小就总听说。&lt;/p&gt;
&lt;p&gt;阳台上另外一个印象深刻的场景就是叔叔家的鱼缸，叔叔喜欢养鱼，就会 “发酵” 一些鱼食或是其它什么散发出味道的东西，每次上外阳台都会感觉臭臭的。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1762095195/03.webp" width="71.64%" /&gt;&lt;/p&gt;
&lt;p&gt;这幅照片中，阔门的小平房是爷爷家的猪圈，正上方有一个外置 ‘全景天窗’ 用于采光和通风，大门是可以下拉的卷帘门，早年爸爸跑邮政送件的车停在里面，平房中大概养了四五头猪，奶奶负责喂养，主要的饲料是糠和酒糟，以及各种青草，猪圈很臭、苍蝇多多，无聊时我就拿个棍子去给猪抓痒，它们总是乐意被挠痒痒，能看猪猪们舒服的笑着，跟它说说话，它并不回答。&lt;/p&gt;
&lt;p&gt;再早一些，爷爷还养过山羊养过狗，想来有二十几只，据说养狗赔了钱，童年中，我印象最深的一条狗叫 “四眼”，他的眼睛上方有两撮跟体毛不一样颜色的毛发，看起来像是四个眼睛，故名四眼。&lt;/p&gt;
&lt;p&gt;四眼跟我的关系最好，狗圈栅栏不高，支个板子我就能跳进去，然后一群狗围着我，我吼着它们也不听，我把四眼带出来，给它吃小灶，跟它玩耍，它是我最好的动物朋友。&lt;/p&gt;
&lt;p&gt;印象中奶奶挑了我的理，原因是我花了几毛钱给四眼买了淀粉肠，奶奶说她还没吃过，我不言语，也不好意思，印象深刻。&lt;/p&gt;
&lt;p&gt;一天上学，听说爷爷要卖狗，我再三恳求要留下四眼，甚至把四眼抱到了我的屋子让妈妈帮忙照看，结果回来时四眼还是被卖了，我难受了好些天。现在想来，家人们着实没有太多心力来替我养一只‘宠物狗’。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1762095195/04.webp" width="71.64%" /&gt;&lt;/p&gt;
&lt;p&gt;北面的 ‘几趟杆’(街巷旁一横排的房屋称为‘一趟杆’，东北话中 ‘我们住一趟杆’ 即我们是邻里)，已经动迁盖上了楼房，我们这排动迁的时候，爷爷是很期盼的，都说那时候的拆迁户都会赚的盆满钵满，爷爷没多要什么，几个儿女几间房，就同意了拆迁。&lt;/p&gt;
&lt;p&gt;现在想来，顺利的拆迁就是最大的福，除去煤炭价格年年上升每年烧 “钱” 的经济负担外，奶奶年岁渐长，从院子里一桶桶的抬煤也有些力不从心，这片土地开发完，南侧的几趟平房这些许年都没等来开发，他们常说爷爷保守，但十五年的商品房供暖，实打实的解放了奶奶，二十年的老房子，也迎来了它最后的安歇。&lt;/p&gt;
&lt;p&gt;照片未及之地，有奶奶种满豆角茄子绿辣椒的菜园；有一条同样跟我友谊深厚的老狗 ‘大黄’；有我用铁锹亲手挖掘的 ‘地道’；也有冬天让人 ‘举步维艰’ 角落里的旱厕。&lt;/p&gt;
&lt;p&gt;十五年后看它，样子是陈旧过时的，是漏风也是坚毅的；&lt;/p&gt;
&lt;p&gt;再看它，是记忆时光、是童年美好、也是来时的路。&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>macOS 系统部署 Valkey 集群模式</title><link href="https://blog.yasking.org/a/macos-install-valkey-cluster.html" rel="alternate"></link><published>2025-10-31T11:38:27+08:00</published><updated>2025-10-31T11:38:27+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-10-31:/a/macos-install-valkey-cluster.html</id><summary type="html">&lt;p&gt;两年多前记录了一篇博客《&lt;a href="https://blog.yasking.org/a/macos-install-redis-cluster.html" title="Permalink to macOS 系统安装 Redis 并启用集群模式"&gt;macOS 系统安装 Redis 并启用集群模式&lt;/a&gt;》，本机使用 bash 脚本启动多个 Redis 实例组成集群，操作较为繁琐&lt;/p&gt;
&lt;p&gt;整理 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;两年多前记录了一篇博客《&lt;a href="https://blog.yasking.org/a/macos-install-redis-cluster.html" title="Permalink to macOS 系统安装 Redis 并启用集群模式"&gt;macOS 系统安装 Redis 并启用集群模式&lt;/a&gt;》，本机使用 bash 脚本启动多个 Redis 实例组成集群，操作较为繁琐&lt;/p&gt;
&lt;p&gt;整理了基于 macOS OrbStack 的 Valkey 的本地集群部署方式，记录如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;本文基于 OrbStack 软件部署，非 OrbStack 环境未经测试验证&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;获取配置&lt;/h3&gt;
&lt;p&gt;创建本地目录并获取配置&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ mkdir -p ~/Portable &amp;amp; cd ~/Portable
$ git clone https://github.com/sincerefly/conf-valkey-cluster.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加权限&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ cd conf-valkey-cluster
$ chmod +x ./init.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;运行服务&lt;/h3&gt;
&lt;p&gt;初始化并运行，默认镜像 &lt;code&gt;valkey/valkey:7.2-alpine&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# valkey/valkey:7.2-alpine
$ ./init.sh

# valkey/valkey:9.0-alpine
$ VALKEY_IMAGE=8.0-alpine ./init.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;稍等片刻可以看到&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;[2025-10-30 19:29:08] Cluster is healthy
[2025-10-30 19:29:08] Valkey cluster initialized successfully!
[2025-10-30 19:29:08] Cluster nodes:
940fbd29e31707348db33d030ec40ec927c13712 192.168.97.2:7001@17001 master - 0 1761823748351 2 connected 5461-10922
5a74931fdf31a55eebfea8f0fb04cde5c50bce0a 192.168.97.5:7002@17002 master - 0 1761823747118 3 connected 10923-16383
9c49963d7285875867c86e3f033c279bce6a951f 192.168.97.3:7004@17004 slave efe7608d5a60031d02f3d239d5cc06aa8bfa2708 0 1761823747941 1 connected
290e3d428b7df6511fabee0b1510d1ab4ebac8e9 192.168.97.6:7003@17003 slave 5a74931fdf31a55eebfea8f0fb04cde5c50bce0a 0 1761823747000 3 connected
3882a00169987d638b1a628f38e8d00c328873aa 192.168.97.7:7005@17005 slave 940fbd29e31707348db33d030ec40ec927c13712 0 1761823746906 2 connected
efe7608d5a60031d02f3d239d5cc06aa8bfa2708 192.168.97.4:7000@17000 myself,master - 0 1761823746000 1 connected 0-5460
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;连接测试&lt;/h3&gt;
&lt;p&gt;OrbStack 软件页面&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/technology/1761881907/03.webp"&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ redis-cli -c -h 127.0.0.1 -p 7000 ping
PONG
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询集群信息&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;&amp;gt; CLUSTER INFO
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/technology/1761881907/04.webp"&gt;&lt;/p&gt;
&lt;h3&gt;服务启停&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 停止
# VALKEY_IMAGE=valkey/valkey:7.2-alpine docker compose down
$ ./stop.sh

# 启动
# VALKEY_IMAGE=valkey/valkey:7.2-alpine docker compose up -d
$ ./start.sh

# 如果使用了 ENV 需要
VALKEY_IMAGE=9.0-alpine ./start.sh
VALKEY_IMAGE=9.0-alpine ./stop.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;先这样，目前我用着还比较顺手，有时间可以再进行一些更通用化的完善&lt;/p&gt;</content><category term="Technology"></category><category term="Software"></category><category term="笔记"></category></entry><entry><title>阅读《一个名叫欧维的男人决定去死》</title><link href="https://blog.yasking.org/a/reading-a-man-called-ove.html" rel="alternate"></link><published>2025-10-29T18:11:00+08:00</published><updated>2025-10-29T18:11:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-10-29:/a/reading-a-man-called-ove.html</id><summary type="html">&lt;p&gt;最开始决定阅读《一个名叫欧维的男人决定去死》是因为在网上有人问了个问题 ‘你把哪个作家的作品都读过一遍’，我留意 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;最开始决定阅读《一个名叫欧维的男人决定去死》是因为在网上有人问了个问题 ‘你把哪个作家的作品都读过一遍’，我留意到一位名叫&lt;a href="https://www.douban.com/personage/27573226/"&gt;弗雷德里克·巴克曼&lt;/a&gt;的作家&lt;/p&gt;
&lt;p&gt;在微信读书上看有好些本他写的书，问了 GPT 老师推荐先阅读哪一本，它强烈建议我从这本读起，我没理由拒绝&lt;/p&gt;
&lt;p&gt;读了前几十页，发现这本书没吸引到我，一个守旧派，脾气也不太好的毒舌老头有什么好看的呢？&lt;/p&gt;
&lt;p&gt;相较于同期阅读的《丰乳肥臀》，虽感 “没深度”，但我还是愿意阅读下去，这么畅销的书，肯定不像我想的那样简单&lt;/p&gt;
&lt;p&gt;继续读着就有意思起来，我划线了不少 ‘金句’，摘抄几句如下&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;奔驰男狂摁喇叭。“傻逼。” 欧维心想。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;—— 果然最饱满的文学表达就是要用最直接的文字。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;就像欧维太太常说的那样：“要是有什么值得写进欧维的讣告，那就是‘无论如何，此人还算省油’。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;—— 没忍住笑&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;欧维家隔壁住着个体重近四分之一吨的二十五岁男人。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;—— 高矮胖瘦，欧维对所有人的 ‘毒舌’ 一视同仁，后来发现对他的妻子也不能例外&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;每个人的生命中总有那么一刻决定他们将成为什么样的人。要是你不了解那个故事，就不了解那个人。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;—— 偶尔冒出的小哲思恰到好处&lt;/p&gt;
&lt;p&gt;作者很会使用比喻，精准又形象&lt;/p&gt;
&lt;p&gt;就像描述心跳的厉害，我脑子里就冒出 “心怦怦跳” 等小学生词汇&lt;/p&gt;
&lt;p&gt;而作者会写下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;胸口在外套下沉重地起伏着&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;也有&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;心脏猛烈地砰砰作响，就像他的胸腔是世界上最后一座还能用的公厕门&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这比喻秒极！&lt;/p&gt;
&lt;p&gt;本书写作手法也比较有意思，第一章讲现在的故事，那么下一章就讲到回忆，再下一章再回到现在，时间的交错，让人物变的丰满，欧维这个 “不讨喜的固执老头”，身上的光芒再也无法被掩盖&lt;/p&gt;
&lt;p&gt;面对指控，也要秉持不在背后说人闲话的铁律；在邻居家火灾即将蔓延到父亲留给自己的房屋时，选择冲进火海救人；嘴上冷漠但心里总是将邻里拜托的事儿记在心上；连想要自杀都要考虑不给任何人，包括 ‘那只不属于自己的猫’ 带来影响；&lt;/p&gt;
&lt;p&gt;对欧维来说，是即是，非即非。诚实、勇敢讲原则，嘴硬搭配一颗柔软的心，这个老头无比可爱！&lt;/p&gt;
&lt;p&gt;轻松、简单、治愈，作者通过这本书带给人美好的东西，刚开始阅读本书时对于欧维比较无感，在阅读后很自然的爱上了这个老头，这没什么可说的&lt;/p&gt;
&lt;p&gt;欧维的世界非黑即白，她的妻子带给他五颜六色，本书讲诉想要自杀去陪伴妻子的欧维，最终在邻里的 ‘被迫’ 往来中被治愈，人需要关系，也需要 ‘被需要’&lt;/p&gt;
&lt;p&gt;推荐给你这本书，希望你也能被温暖到&lt;/p&gt;</content><category term="Reading"></category></entry><entry><title>Memos: Cursor 服务故障部分功能不可用</title><link href="https://blog.yasking.org/a/1761705214.html" rel="alternate"></link><published>2025-10-29T10:34:45+08:00</published><updated>2025-10-29T10:34:45+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-10-29:/a/1761705214.html</id><summary type="html">&lt;p&gt;洋洋洒洒写了几百字的需求提交给 Cursor 干活儿，它撂挑子了&lt;/p&gt;
&lt;p&gt;Cursor Status 地址: &lt;a href="https://status.cursor.com"&gt;https://status.cursor.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/memos/1761705214/01.webp"&gt;&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;目前，服务已经恢复&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Resolved - This incident has been resolved.
Oct 29, 02:33 …&lt;/p&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;p&gt;洋洋洒洒写了几百字的需求提交给 Cursor 干活儿，它撂挑子了&lt;/p&gt;
&lt;p&gt;Cursor Status 地址: &lt;a href="https://status.cursor.com"&gt;https://status.cursor.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/memos/1761705214/01.webp"&gt;&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;目前，服务已经恢复&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Resolved - This incident has been resolved.
Oct 29, 02:33 UTC&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Memos"></category><category term="Cursor"></category></entry><entry><title>阅读《丰乳肥臀》</title><link href="https://blog.yasking.org/a/reading-big-breasts-wide-hips.html" rel="alternate"></link><published>2025-10-25T19:34:00+08:00</published><updated>2025-10-25T19:34:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-10-25:/a/reading-big-breasts-wide-hips.html</id><summary type="html">&lt;p&gt;读过莫言的《不被大风吹倒》，就打定主意阅读久仰大名的《丰乳肥臀》，在这之前，我一直以为这本书是写自几年前，很可能那时 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;读过莫言的《不被大风吹倒》，就打定主意阅读久仰大名的《丰乳肥臀》，在这之前，我一直以为这本书是写自几年前，很可能那时候这本书又火了&lt;/p&gt;
&lt;p&gt;《丰乳肥臀》出版于 1995，构思十余年，不到三个月的写作时间，当真佩服，看到有句书评很有意思，读者感慨道：“不想成为作家了，写不过莫言”，我也这么认为，莫言可太会写了&lt;/p&gt;
&lt;p&gt;三十岁之前及多愁善感的读者不建议阅读，书中讲述的苦难太多，容易道心破碎，也意难平，我阅读了全书 1/7 的内容后，就打算放弃了，个人感情投射到书中人物，内心的难受很真实，找 GPT 老师开导后决定再坚持下&lt;/p&gt;
&lt;p&gt;于是每天阅读《丰乳肥臀》会主动控制时长，从文学角度去感受文字的魅力，同时找了本《一个叫欧维的男人决定去死》篇治愈系的书籍穿插阅读，勉强实现了情感的负载均衡&lt;/p&gt;
&lt;p&gt;先从整书写作手法看来，小说开篇就简述了主要人物的关系和结局，“预叙” 的手法对于看电影想先了解大结局才好安心观看的人来说，十分舒适，即便我看了也根本记不住金童七个姐姐的名字，甚至有些小焦虑，但并不妨碍莫言把这些鲜活的人生经历强行塞进我有限的记忆空间，跟媳妇删繁就简的分享寥寥&lt;/p&gt;
&lt;p&gt;写作手法上另一个让我印象深刻的是开篇讲述鲁氏生产的时刻，驴子也在生产，驴子有人照看，母亲没有，日本鬼子入侵，风雨欲来... 随着鲁氏死在新时代的破败旧教堂的庭院中，一切看似终结，下一篇却又回到起初，从鲁氏出生开始讲起，此时对鲁氏已不再陌生，儿女们的名字也可以倒背如流，仿佛陪着他们走过一生，又来到她们来时的路，心中五味杂陈，跌宕起伏，艰难一生&lt;/p&gt;
&lt;p&gt;鲁氏生于 1900 战乱时期，死于 1995 年，生有九个儿女并拉扯大一箩筐孙辈儿女，最终活下来的只剩几人，全书以金童超越的视角作为观察者，前期姐姐们的故事，后期金童自己成年而无为，无法 “断奶” 的一生，软弱可怜又可气&lt;/p&gt;
&lt;p&gt;莫言说，把这本书献给自己的母亲和母亲们。文字的魅力即真真切切的让人感受到母亲的伟大，艰难之后更艰难，宏大叙事下小人物们的苦难也得以被看见，兴，百姓苦；亡，百姓苦。此刻得以具现化&lt;/p&gt;
&lt;p&gt;我总感觉这本书表达了很多内容，信息密度也很大，寻常的一本书可能一周就读完了，《丰乳肥臀》我读了 49 天，但我只看到了书的第一层，第二层可能关乎 “母亲中国”，“宗教” 等，我不得而知&lt;/p&gt;
&lt;p&gt;但当下我理解有些观点为什么说 “越穷越要多生孩子”，乱世之下多悲苦，半点不由人，传承之事只能交给概率&lt;/p&gt;
&lt;p&gt;艰难时期的 “反革命” 为什么选择 “自我的终结” 也不愿挺过那段时光？“没饭吃的日子” 可以饿死很多人，魔幻与荒诞时期，人性的恶叫人难以直视半分&lt;/p&gt;
&lt;p&gt;日光之下并无新事，真心祈愿这片土地的人们平安&lt;/p&gt;</content><category term="Reading"></category></entry><entry><title>爱人回家送奶奶</title><link href="https://blog.yasking.org/a/wife-grandmother.html" rel="alternate"></link><published>2025-10-22T23:59:00+08:00</published><updated>2025-10-22T23:59:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-10-22:/a/wife-grandmother.html</id><summary type="html">&lt;p&gt;大上一次见到奶奶，是去年的十一，白天与姐夫在老丈人家里掰苞米，临行前媳妇和大姐一行到奶奶家探望，奶奶握着她们 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;大上一次见到奶奶，是去年的十一，白天与姐夫在老丈人家里掰苞米，临行前媳妇和大姐一行到奶奶家探望，奶奶握着她们的手，问候着，也安静着，我站在炕边看着墙上的福字，也望向窗外四大爷家的牛犊，离别时两姐妹两眼泪珠乱转，媳妇跟我说今年感觉奶奶对她们的话多了不少，总问她们下次什么时候再回来&lt;/p&gt;
&lt;p&gt;上一次见到奶奶，是今年的春节，大炕外边儿砌了一个小炕梢，奶奶坐在上面，她满脸岁月的沟壑，吃着软柿子，时而接两句话跟大家说话，奶奶今年九十七岁，大家都说她能活到一百岁&lt;/p&gt;
&lt;p&gt;“奶奶过世了” 妻子发来微信，她下午到的家，奶奶是晚上走的，明早四点起来送她&lt;/p&gt;
&lt;p&gt;我在遥远的北京，前几天妻子说奶奶生病了，不吃不喝，也喂不进食物&lt;/p&gt;
&lt;p&gt;媳妇讲了她大娘头几年走的时候，她以往没什么感觉，最近想到心里会难受，我说以往你还没有这样丰富细腻的情感，奶奶生病，勾起思绪，感情就会像丰饶土地上雨后天晴的青草般生长&lt;/p&gt;
&lt;p&gt;她这些天要准备回家看看，听说很多亲人已经都回去了&lt;/p&gt;
&lt;p&gt;我发给妻子 “抱抱” 的表情安慰她，然后就去吃晚饭，晚上一个人在家坐下来，安静时一股说不出来的感受开始蔓延，碎片化的记忆开始涌现&lt;/p&gt;
&lt;p&gt;听妻子说，因为姑姑 “轮值” 照顾她时间短，提前回去工作，奶奶很不顺心，骂了许多人&lt;/p&gt;
&lt;p&gt;还有段时间，她有些蛮严重 “感冒”，儿女们就为她换上了寿衣，顽强的小老太挺了过来，穿着寿衣那几天，三两个儿孙姑娘们就跟她睡一炕&lt;/p&gt;
&lt;p&gt;算起来奶奶生于 1928 年，经历过抗日战争、解放战争，青春年少时见证了新中国的成立，也跨越千禧年，在口罩三年中也健康而清贫的生活着&lt;/p&gt;
&lt;p&gt;媳妇说奶奶长寿的秘诀是 “不内耗”，是个厉害的不受欺负的老太太，平时听收音机，里面有养生操时常跟着练习，效果不明，但奶奶很能坚持，一坚持就是多年，牙口胃口都好着&lt;/p&gt;
&lt;p&gt;思想中，这就是我对奶奶有限的全部记忆了，人常说老人像小孩子，看着奶奶拿着一个女娃玩具，怅然间，眼角泛红，这个老太可爱、可敬，春节那次，她拿给我一个橘子，也让我嗑瓜子&lt;/p&gt;
&lt;p&gt;没有，没有下个春节去探望奶奶的故事了&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>Memos: AWS 美东可用区 P0 故障（us-east-1）</title><link href="https://blog.yasking.org/a/1760952645.html" rel="alternate"></link><published>2025-10-20T17:30:45+08:00</published><updated>2025-10-20T17:30:45+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-10-20:/a/1760952645.html</id><summary type="html">&lt;p&gt;因 AWS DynamoDB 故障引发众多基础服务不可用，波及众多互联网应用，目前仍未恢复，状态页面：&lt;a href="https://health.aws.amazon.com/health/status"&gt;health/status&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;还有三天霜降，AWS 北美工程师今 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;因 AWS DynamoDB 故障引发众多基础服务不可用，波及众多互联网应用，目前仍未恢复，状态页面：&lt;a href="https://health.aws.amazon.com/health/status"&gt;health/status&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;还有三天霜降，AWS 北美工程师今夜注定要汗流浃背了&lt;/p&gt;
&lt;!--more--&gt;

&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/memos/1760952645/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;影响时间&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;开始： 2025 年 10 月 20 日 14:49（北京时间）
恢复： 2025 年 10 月 21 日 06:01（北京时间）
持续时间： 约 15 小时
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;事件摘要&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;时间（北京时间）&lt;/th&gt;
&lt;th&gt;事件摘要&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月20日 14:11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AWS 发现 US-EAST-1 区多服务错误率、延迟上升。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月20日 16:26&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DynamoDB 请求错误显著增加。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月20日 17:01&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;确认与 DynamoDB API 的 DNS 解析问题有关。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月20日 17:27&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;部分服务开始恢复。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月20日 18:35&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;DNS 故障缓解，但 EC2 实例仍无法启动。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月20日 19:08–21:42&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EC2 启动持续失败，影响 RDS、ECS、Glue；Lambda 出现 SQS 事件延迟。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月20日 22:14&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;出现新一轮网络连通性问题，影响多个服务。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月20日 23:43&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;确认问题源于网络负载均衡（NLB）健康监控子系统。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月21日 00:13–02:22&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;逐步恢复网络与 EC2 启动；Lambda 调用错误减少。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月21日 03:15&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;大部分服务恢复正常。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月21日 04:52&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EC2 启动限流解除，依赖服务（ECS、Glue）恢复。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月21日 05:48&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EC2、Lambda、Connect 等全面恢复。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;10月21日 06:53&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;官方确认：所有 AWS 服务恢复正常运行。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</content><category term="Memos"></category><category term="AWS"></category></entry><entry><title>2025 北京社保下限上调｜个体户缴费随之上涨</title><link href="https://blog.yasking.org/a/beijing-shebao-2025.html" rel="alternate"></link><published>2025-10-10T20:41:16+08:00</published><updated>2025-10-10T20:41:16+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-10-10:/a/beijing-shebao-2025.html</id><summary type="html">&lt;p&gt;相较于 2024 年 6821 社保缴费下限，2025 年社保缴费下限调整为 7162 元，涨幅 5%&lt;/p&gt;
&lt;p&gt;同期，2024 年北京社会平均工资从 11761 元提高到 11937 元/月，上 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;相较于 2024 年 6821 社保缴费下限，2025 年社保缴费下限调整为 7162 元，涨幅 5%&lt;/p&gt;
&lt;p&gt;同期，2024 年北京社会平均工资从 11761 元提高到 11937 元/月，上涨 176 元，涨幅约为 1.50%&lt;/p&gt;
&lt;p&gt;北京最低工资标准每小时不低于 14.6 元、每月不低于2540元&lt;/p&gt;
&lt;p&gt;社保基数上调后，个体工商户最低缴纳费用由 2540.42 元/月上升至 2667.27 元/月（10 月补缴 7、8 月份按新基数计算的差额共计 253.7 元）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;数据来源&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.beijing.gov.cn/zhengce/zcjd/202509/t20250918_4205122.html"&gt;本市发布2025年社保缴费工资基数上下限&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rsj.beijing.gov.cn/bm/ywml/202007/t20200717_1950961.html"&gt;历年北京市全口径城镇单位就业人员平均工资&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.beijing.gov.cn/zhengce/zhengcefagui/202507/t20250728_4159830.html"&gt;北京市人力资源和社会保障局等部门关于调整北京市2025年最低工资标准的通知&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Skill"></category></entry><entry><title>铁锅重生记</title><link href="https://blog.yasking.org/a/iron-wok-reborn.html" rel="alternate"></link><published>2025-08-30T22:36:03+08:00</published><updated>2025-08-30T22:36:03+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-30:/a/iron-wok-reborn.html</id><summary type="html">&lt;p&gt;家里有一个用了有两年的铁锅，媳妇儿炒菜炖菜都用它，前段时间一看，涂层已经面目全非。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/01.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;可以买个新的，但一想，纯铁锅应 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;家里有一个用了有两年的铁锅，媳妇儿炒菜炖菜都用它，前段时间一看，涂层已经面目全非。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/01.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;可以买个新的，但一想，纯铁锅应该可以抢救下，有句话怎么说的 —— “新三年，旧三年，缝缝补补又三年”&lt;/p&gt;
&lt;p&gt;注意：涂层锅不能重新开锅！涂层损坏后建议更换新锅&lt;/p&gt;
&lt;p&gt;使用的是「老东北美食」大舅的教程：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;【原来旧锅也能开锅养锅润锅，老师傅分享实用技巧，旧锅也能变新锅-哔哩哔哩】 &lt;a href="https://b23.tv/4WJDMbz"&gt;https://b23.tv/4WJDMbz&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;全程耗时两小时，过程记录如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/02.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;转着圈干烧铁锅，涂层肉眼可见的开始碳化。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/03.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;烧了好一会儿后，用砂纸刷一刷锅内侧，不太建议用钢丝球（但我只有钢丝球，就用了钢丝球）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/04.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;擦过后，有明显的铁锈痕迹，等会儿用水刷一下就好了，谁家锅底都有灰，刮刮刮刮刮...&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/05.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;而后用水刷锅内侧，可以放洗洁精，洗刷干净擦干后如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/06.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;开火，上猪肥肉润锅！（两遍）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/07.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;擦擦擦！&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/08.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;把过多的油倒掉，可以用水冲干净，先不要用洗洁精。&lt;/p&gt;
&lt;p&gt;（这里缺失了再用食用油油润一遍锅的步骤，用锅铲抵着厨房用纸推着热油再把锅擦一遍）&lt;/p&gt;
&lt;p&gt;倒掉油，清水刷锅后，铁锅重新开锅完成 ✅&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756564563/09.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;养铁锅注意事项：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;炒菜的锅只用来炒菜、不能用来炖煮；&lt;/li&gt;
&lt;li&gt;及时刷锅，并擦干水分，如果不怕麻烦，用厨房用纸沾些油擦一遍；&lt;/li&gt;
&lt;li&gt;刷锅时可以用洗洁精，但不能用钢丝球等坚硬物品清洁，会破坏涂层；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;铁锅满血复活&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;技能 +1&lt;/p&gt;
&lt;p&gt;成就感 +1&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Moments"></category></entry><entry><title>不锈钢盆与放心水源改造计划</title><link href="https://blog.yasking.org/a/stainless-steel-purified-water.html" rel="alternate"></link><published>2025-08-30T12:21:52+08:00</published><updated>2025-08-30T12:21:52+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-30:/a/stainless-steel-purified-water.html</id><summary type="html">&lt;h3&gt;厨房用具更新&lt;/h3&gt;
&lt;p&gt;最近几个月，添置了一些 304、316 不锈钢材质的厨房用具，更早的缘由是前同事群里有人买了检测药水，发现家 …&lt;/p&gt;</summary><content type="html">&lt;h3&gt;厨房用具更新&lt;/h3&gt;
&lt;p&gt;最近几个月，添置了一些 304、316 不锈钢材质的厨房用具，更早的缘由是前同事群里有人买了检测药水，发现家里很多的伪 304、316 不锈钢盆子。&lt;/p&gt;
&lt;p&gt;我也好奇就买了药水检测，真发现了一批假冒伪劣产品，就计划着替换掉，经过一段时间挑选，购买了以下的 ”不锈钢们“&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/moments/1756527712/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;先吐槽下「无印良品」的不锈钢盆子，价格真贵，但除了贵之外没别的毛病，银色的不锈钢小碟子可以在做饭时放葱姜蒜，小号的盆吃面条的时候用，最大号的用来备菜时泡一下蔬菜，沥水盆有些小了，后续应该会补个大号的&lt;/p&gt;
&lt;p&gt;淘汰掉了家里不知道什么材质的 ‘不锈钢盆’，心情很棒&lt;/p&gt;
&lt;p&gt;在「XMAN 小满家外贸尾货」淘宝店买了几个厨房小物件，说是卖的外贸尾货微瑕品，但是瑕疵得仔细才能找见，性价比拉满，捣蒜器用料足，小油锅材质扎实，看着就是能用很久的那种&lt;/p&gt;
&lt;p&gt;电饭煲内胆，最开始下单的「大良印记」家的不锈钢内胆，到家后煮粥，漏气喷的四处都是，客服说可能是尺寸误差，给退了货，下单了另一家也还是漏气，甚至电饭煲憋气后发出砰一声，我都想要换电饭煲了，客服说换个密封圈试试，他家也卖，换上后果然问题解决，最开始没往密封圈上想是因为小米原装内胆不会有这个问题，想来也是学到了&lt;/p&gt;
&lt;h3&gt;”放心水源改造计划“&lt;/h3&gt;
&lt;p&gt;要说注意水质还得从 “直把杭州做汴州” 事件说起，网友们把擦脸巾套在水龙头上，放一段时间水，擦脸巾就黄的不行，本着好奇心，我也在洗手盆的龙头上做了为期一周测试，也是黄的不行，还掺杂着不明杂质。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756527712/02.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;之后两天我再直接用自来水刷牙时，就会有心理和生理上的双重不适，容易恶心干呕，连夜下单了一个水龙头净水器（32元），下图是使用三周后的样子，送了砂纸，滤芯可以打磨后重复使用。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756527712/03.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;又添置了一个过滤花洒（22.9 元）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756527712/04.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;最后是厨房净水器&lt;/p&gt;
&lt;p&gt;观望了一段时间京东京造的净水器，价格便宜，换滤芯会贵一些，最后选择在淘宝买了通用净水器，考量主要是是京东净水器的定制滤芯换一次比较贵，所宣称 5 年使用寿命，我觉着不靠谱，消耗品还是要常换。&lt;/p&gt;
&lt;p&gt;另一个次要因素是研究了一段时间通用净水器，感觉到目前纯水方案都很成熟，完全可以像装电脑一样也组装一台净水器。&lt;/p&gt;
&lt;p&gt;但结合实际情况，还是先买一个半成品，后续再自己改造，这样比较折中，购入价格 1245 元，净水器是整个发过来的，需要自己接到厨下（自备扳手）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1756527712/05.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;75G 同量净水器 + 压力桶方案，两三人的小家庭用起来感觉足够，面板显示 3 PPM，实际测试数值 30+&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;水源&lt;/th&gt;
&lt;th&gt;PPM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;自来水&lt;/td&gt;
&lt;td&gt;230&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;小区制水机&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;某矿物质桶装水水&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;怡宝纯净水&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;净水器&lt;/td&gt;
&lt;td&gt;30+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;（测量日期：2025-07-26）&lt;/p&gt;
&lt;p&gt;计划 PP 棉一季度一换、RO 膜两年一换、其余滤芯的半年一换，因为通量小，滤芯价格便宜，滤芯品牌丰俭由人。&lt;/p&gt;
&lt;p&gt;水龙头是双水的，洗碗用净水、直饮用纯水，对我来说最大的改变就是不用到小区净水机打水，也不用隔几天就在网上下单怡宝纯净水，方便了太多&lt;/p&gt;
&lt;h3&gt;写在最后&lt;/h3&gt;
&lt;p&gt;添置了不锈钢厨具、”放心水源改造计划“ 的实施，得到了媳妇儿的高度评价。&lt;/p&gt;
&lt;p&gt;另外也更换了马桶盖、下水道防臭管，感觉出租房也可以适度折腾，“花小钱办大事”，很大程度提升了幸福指数。&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>阅读《不被大风吹倒》</title><link href="https://blog.yasking.org/a/reading-not-blown-over-by-the-storm.html" rel="alternate"></link><published>2025-08-29T21:37:48+08:00</published><updated>2025-08-29T21:37:48+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-29:/a/reading-not-blown-over-by-the-storm.html</id><summary type="html">&lt;p&gt;阅读莫言老师的第一本书是《不被大风吹倒》&lt;/p&gt;
&lt;p&gt;不记得最开始听说莫言是什么时候，大概率是网友发的两只狗狗合影，神回复 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;阅读莫言老师的第一本书是《不被大风吹倒》&lt;/p&gt;
&lt;p&gt;不记得最开始听说莫言是什么时候，大概率是网友发的两只狗狗合影，神回复是“莫言和余华”，也可能因为莫言荣获了诺贝尔文学奖，很小的几率是因为《丰乳肥臀》这本标题有些“劲爆”的大作。&lt;/p&gt;
&lt;p&gt;然后从史铁生的这段金句开始了解到余华和莫言，以及他们之间的友谊：&lt;/p&gt;
&lt;p&gt;自从我腿残疾后，
家人们都很忌讳提起我的腿。
只有余华
他带我去踢球，让我守门。
他没把我当残疾人，也没把我当人。
                       —— 史铁生&lt;/p&gt;
&lt;p&gt;《不被大风吹倒》这本书加到微信读书的书架有大几个月了，分几次才读完，最开始阅读时，其实我还没下定决心要开始阅读，只是在书店看到这本“畅销书”，好奇想看看写的什么，单从这本书来看，对莫言有了初步的了解—— 性格平和，善于观察、学习，铭记自己来自哪里，能往前看的人&lt;/p&gt;
&lt;p&gt;这本书是多篇不同时期写作文章的合集，我觉得蛮有意思的是不同时期写的文章，组合到一起，风格是一致的，简单说就是 “有种质朴感的乡土情怀”。阅读时有一种轻松感，有很多片段，细想下藏着不少艰难，但作者巧妙的叙事，没有将担子放到读者肩上。&lt;/p&gt;
&lt;p&gt;书中有作者儿时的回忆，有对阅读的热爱，有关于写作的心得，以及文学大家那里学到的东西，前几些天刚读过卡夫卡的《审判》，莫言老师书中也提到卡夫卡的的好几本书，说来也是很巧，感觉过一阵儿可以再选几本卡夫卡的小说读起来。&lt;/p&gt;
&lt;p&gt;这本书很像是作者跟年轻大学生分享交流时的分享，我认为很适合作为阅读莫言老师书籍的入门之选。&lt;/p&gt;
&lt;p&gt;写下这篇笔记的时候，我已经选择好了下一本书——《丰乳肥臀》，去看看莫言老师的“高密东北乡”，都诉说着怎样的故事。&lt;/p&gt;</content><category term="Reading"></category></entry><entry><title>基于 Supabase 构建示例应用（中篇）：实现 Vue 前端页面</title><link href="https://blog.yasking.org/a/supabase-demo-app-step2.html" rel="alternate"></link><published>2025-08-29T18:55:12+08:00</published><updated>2025-08-29T18:55:12+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-29:/a/supabase-demo-app-step2.html</id><summary type="html">&lt;h3&gt;构建 Vue 项目&lt;/h3&gt;
&lt;p&gt;Supabase 服务的 Vue 构建官方文档：&lt;a href="https://supabase.com/docs/guides/getting-started/quickstarts/vue"&gt;https://supabase.com/docs/guides/getting-started/quickstarts/vue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;创建了一个 Github 仓库，用来存放 Vue 前端项目&lt;/p&gt;
&lt;p&gt;克隆项目&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;git clone git@github.com …&lt;/code&gt;&lt;/pre&gt;</summary><content type="html">&lt;h3&gt;构建 Vue 项目&lt;/h3&gt;
&lt;p&gt;Supabase 服务的 Vue 构建官方文档：&lt;a href="https://supabase.com/docs/guides/getting-started/quickstarts/vue"&gt;https://supabase.com/docs/guides/getting-started/quickstarts/vue&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;创建了一个 Github 仓库，用来存放 Vue 前端项目&lt;/p&gt;
&lt;p&gt;克隆项目&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;git clone git@github.com:sincerefly/vuebase-posty.git
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;初始化 Vue 项目&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;cd vuebase-posty
npm create vue@latest .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;选项&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1756464912/01.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;回车确认后的 Oxlint（试验阶段）和 rolldown-vite（试验阶段）都不选择，示例代码也不需要&lt;/p&gt;
&lt;p&gt;运行三连&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 安装依赖
npm install

# 格式化代码
npm run format

# 启动
npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;引入 Supabase 依赖&lt;/h3&gt;
&lt;p&gt;安装库&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;npm install @supabase/supabase-js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;创建环境变量文件&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;touch .env.local
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将服务地址和 Supabase Publishable Key 填入（注意替换为自己的地址和密钥）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;VITE_SUPABASE_URL=&amp;lt;SUBSTITUTE_SUPABASE_URL&amp;gt;
VITE_SUPABASE_PUBLISHABLE_KEY=&amp;lt;SUBSTITUTE_SUPABASE_PUBLISHABLE_KEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里有一些容易混淆的地方需要注意&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/technology/1756464912/02.webp"&gt;&lt;/p&gt;
&lt;p&gt;Supabase 教程页面上显示出用户的 Anon Key，看着需要使用这个 key 作为&lt;code&gt;SUBSTITUTE_SUPABASE_PUBLISHABLE_KEY&lt;/code&gt;，那上篇中的 “sb_publishable_JToCFTxxxxxx” 又是什么，用哪个呢？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这个以 &lt;code&gt;sb_publishable_&lt;/code&gt; 开头的密钥，&lt;strong&gt;实际上就是 &lt;code&gt;anon key&lt;/code&gt;（匿名公钥）&lt;/strong&gt;，只是 Supabase 在不同时期使用了不同的命名格式。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;结论就是用谁都行，sb_publishable_ 是旧的，JWT 格式的密钥是更新的格式&lt;/p&gt;
&lt;p&gt;新建 &lt;em&gt;src/lib/supabaseClient.js&lt;/em&gt; 文件&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;import { createClient } from '@supabase/supabase-js'

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY

export const supabase = createClient(supabaseUrl, supabaseAnonKey)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改 &lt;em&gt;src/App.vue&lt;/em&gt; 文件&lt;/p&gt;
&lt;p&gt;根据我的表 Posts 做了相应调整&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;script setup&amp;gt;
import { ref, onMounted } from 'vue'
import { supabase } from './lib/supabaseClient'

const posts = ref([])

async function getPosts() {
  const { data } = await supabase.from('posts').select()
  posts.value = data
}

onMounted(async () =&amp;gt; {
  await getPosts()
})
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li v-for=&amp;quot;post in posts&amp;quot; :key=&amp;quot;post.id&amp;quot;&amp;gt;{{ post.title }}&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;显示出来三篇已发布文章（标题相同）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1756464912/03.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;h3&gt;导出表 Types&lt;/h3&gt;
&lt;p&gt;https://supabase.com/docs/guides/api/rest/generating-types&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果网络抽风，使用本地代理 npm 设置如下
npm config set proxy socks5://127.0.0.1:7897
npm config set https-proxy socks5://127.0.0.1:7897&lt;/p&gt;
&lt;p&gt;使用后清理
npm config delete proxy
npm config delete https-proxy&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 安装命令行工具
npm i supabase@&amp;quot;&amp;gt;=1.8.1&amp;quot; --save-dev

# 打开浏览器登录
npx supabase login
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;登录后，如果之前未执行过初始化，先在项目根目录运行&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;npx supabase init
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按需选择，默认都是 N&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;Generate VS Code settings for Deno? [y/N] 
Generate IntelliJ Settings for Deno? [y/N] 
Finished supabase init.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;获取数据库的类型定义&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;mkdir -p src/types

# 生成 Schema，注意替换 PROJECT_REF，就是服务器 API 地址子域名那串字符
npx supabase gen types typescript --project-id &amp;quot;$PROJECT_REF&amp;quot; --schema public &amp;gt; src/types/database.types.tss
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Vibe Coding 环节&lt;/h3&gt;
&lt;p&gt;好了，Step by Step 到此，接下来开始氛围编程&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;这是一个 Vue 项目，后端是 Supabase 服务，请实现以下功能：

表结构如下：

CREATE TABLE users (
  id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
  username TEXT UNIQUE CHECK (char_length(username) &amp;gt;= 3),
  email TEXT UNIQUE,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);


CREATE TABLE posts (
  id SERIAL PRIMARY KEY,
  user_id UUID REFERENCES users(id) ON DELETE CASCADE,
  title VARCHAR(255) NOT NULL,
  content TEXT,
  published_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

已经定义了策略，所有用户（匿名、登录）都可以获取到已发布的文章，即 published_at 字段不为空的记录；用户可以创建、修改自己的文章。

以上是服务端一些表结构，另外已经通过 supabase cli 导出了数据库字段类型的 Schema，在 src/types/database.types.tss

前端功能说明

1. 页面顶部有两栏，一个是“广场”，另一个是“我的”栏目，右上角有注册、登录功能，广场展示所有已发布的文章，我的栏目，如果未登录，通过页面上的文字提示请先登录，登录后展示所有用户的文章，登录后的右上角展示用户名，点击弹出下拉，有设置和登出、设置页面目前可以设置语言偏好；
2. 用户我的页面的文章，需要显示是否发布，可以根据单选项过滤全部、已发布、未发布三个状态，文章后方应该有编辑、发布的按钮，支持修改标题和内容；
3. 需要支持多语言，目前仅需要适配中文、英文两种语言，用户选择语言后，应该在浏览器本地进行缓存；

编码风格说明

1.首先，保持现代化、但不要使用过于花哨的颜色，简洁、小清新为主
2.代码实现应注意解耦合和封装，不要多个逻辑放到一个大文件中
3.API 接口和数据库操作需要符合 Supabase 的使用规范和习惯
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;正好打算试试 Trae，不过目前的智能程度，真是爱了... ⬇️&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1756464912/04.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;还是配置 Proxy，使用 Cursor&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1756464912/05.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;3 Hours Later... &lt;/p&gt;
&lt;p&gt;&lt;img alt="06.webp" src="https://images.yasking.org/technology/1756464912/06.webp"&gt;&lt;/p&gt;
&lt;p&gt;页面功能初步完成&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.webp" src="https://images.yasking.org/technology/1756464912/07.webp"&gt;&lt;/p&gt;
&lt;p&gt;多语言也支持的良好&lt;/p&gt;
&lt;h3&gt;调整策略&lt;/h3&gt;
&lt;p&gt;因为&lt;a href="https://blog.yasking.org/a/supabase-demo-app-step1.html"&gt;上篇&lt;/a&gt;实验中，缺少部分策略，可以在 Supabase 面板删除掉所有策略，重新创建本示例所需的策略&lt;/p&gt;
&lt;p&gt;TODO 再核对下：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;-- posts 表

alter policy &amp;quot;允许匿名和登录用户查看所有已发布文章&amp;quot;
on &amp;quot;public&amp;quot;.&amp;quot;posts&amp;quot;
to anon, authenticated
using (
  (published_at IS NOT NULL)
);

create policy &amp;quot;允许登录用户创建自己的文章&amp;quot;
on &amp;quot;public&amp;quot;.&amp;quot;posts&amp;quot;
for insert
to authenticated
with check (
  -- 确保用户只能插入自己的帖子
  user_id = auth.uid() 
);

create policy &amp;quot;允许登录用户删除自己的文章&amp;quot;
on &amp;quot;public&amp;quot;.&amp;quot;posts&amp;quot;
as PERMISSIVE
for DELETE
to authenticated
using (
  auth.uid() = user_id
);

create policy &amp;quot;允许登录用户查看自己所有文章&amp;quot; -- 包含未发布
on &amp;quot;public&amp;quot;.&amp;quot;posts&amp;quot;
as PERMISSIVE
for SELECT
to authenticated
using (
  auth.uid() = user_id
);

alter policy &amp;quot;允许登录用户更新自己的帖子&amp;quot;
on &amp;quot;public&amp;quot;.&amp;quot;posts&amp;quot;
to authenticated
using (
  (auth.uid() = user_id)
with check (
  (auth.uid() = user_id)
);

alter policy &amp;quot;用户每天只能插入10篇文章&amp;quot;
on &amp;quot;public&amp;quot;.&amp;quot;posts&amp;quot;
to authenticated
with check (
  ((auth.uid() = user_id) AND (( SELECT count(*) AS count FROM posts posts_1 WHERE ((posts_1.user_id = auth.uid()) AND (posts_1.created_at &amp;gt; (now() - '1 day'::interval)))) &amp;lt; 10))
);

-- users 表

create policy &amp;quot;允许用户查看自己的用户信息&amp;quot;
on &amp;quot;public&amp;quot;.&amp;quot;users&amp;quot;
for select
to authenticated
using (
(select auth.uid()) = id
);

CREATE POLICY &amp;quot;允许用户更新自己的用户信息&amp;quot; 
ON &amp;quot;public&amp;quot;.&amp;quot;users&amp;quot;
FOR UPDATE 
USING (auth.uid() = id);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;通过 Cloudflare Page 部署&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为编译后是纯前端页面，所以可以托管到 Pages 服务，可选择性很多，优先国外，因为国内 Page 服务可持续性 be like&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.webp" src="https://images.yasking.org/technology/1756464912/08.webp"&gt;&lt;/p&gt;
&lt;p&gt;Github Pages、Cloudflare Pages、Vercel 作为 Demo 放到哪里都足够，根据我的个人习惯，选择部署到 Cloudflare Pages，因为我有一个域名由 Cloudflare 管理，绑定自定义域名时可以纵享丝滑&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;先上传前端代码到 Github，我的仓库是：&lt;a href="https://github.com/sincerefly/vuebase-posty"&gt;sincerefly/vuebase-posty&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;登录 Cloudflare 面板&lt;/p&gt;
&lt;p&gt;&lt;img alt="09.webp" src="https://images.yasking.org/technology/1756464912/09.webp"&gt;&lt;/p&gt;
&lt;p&gt;选择 Workers &amp;amp; Pages，点击创建&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1756464912/10.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;注意先切换到 Pages，然后再点击 Get started&lt;/p&gt;
&lt;p&gt;&lt;img alt="11.webp" src="https://images.yasking.org/technology/1756464912/11.webp"&gt;&lt;/p&gt;
&lt;p&gt;选择项目后下一步&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1756464912/12.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;选择 Vue Framawork，参数默认，应该还记得 &lt;em&gt;.env.local&lt;/em&gt; 文件，将里面的 &lt;code&gt;VITE_SUPABASE_URL&lt;/code&gt; 和 &lt;code&gt;VITE_SUPABASE_PUBLISHABLE_KEY&lt;/code&gt; 设置到此处环境变量&lt;/p&gt;
&lt;p&gt;点击部署，稍后可以看到服务已部署&lt;/p&gt;
&lt;p&gt;&lt;img alt="13.webp" src="https://images.yasking.org/technology/1756464912/13.webp"&gt;&lt;/p&gt;
&lt;p&gt;服务地址：&lt;a href="https://vuebase-posty.pages.dev"&gt;https://vuebase-posty.pages.dev&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;.pages.dev&lt;/em&gt; 是 Cloudflare 提供的域名，子域名是服务名，重复会追加随机字符。&lt;/p&gt;
&lt;p&gt;&lt;img alt="14.webp" src="https://images.yasking.org/technology/1756464912/14.webp"&gt;&lt;/p&gt;
&lt;p&gt;添加自定义域名（可选）&lt;/p&gt;
&lt;p&gt;&lt;img alt="15.webp" src="https://images.yasking.org/technology/1756464912/15.webp"&gt;&lt;/p&gt;
&lt;p&gt;由 CF 托管的域名，无需手动配置&lt;/p&gt;
&lt;p&gt;&lt;img alt="16.webp" src="https://images.yasking.org/technology/1756464912/16.webp"&gt;&lt;/p&gt;
&lt;p&gt;稍等片刻&lt;/p&gt;
&lt;p&gt;&lt;img alt="17.webp" src="https://images.yasking.org/technology/1756464912/17.webp"&gt;&lt;/p&gt;
&lt;p&gt;地址：&lt;a href="https://posty.donx-done.xyz"&gt;https://posty.donx-done.xyz&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;配置 Supabase 服务 URL 地址&lt;/h3&gt;
&lt;p&gt;&lt;img alt="18.webp" src="https://images.yasking.org/technology/1756464912/18.webp"&gt;&lt;/p&gt;
&lt;p&gt;配置完成后，到页面进行注册测试，当头两棒子&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;{&amp;quot;code&amp;quot;:&amp;quot;over_email_send_rate_limit&amp;quot;,&amp;quot;message&amp;quot;:&amp;quot;For security purposes, you can only request this after 49 seconds.&amp;quot;}

{&amp;quot;code&amp;quot;:&amp;quot;over_email_send_rate_limit&amp;quot;,&amp;quot;message&amp;quot;:&amp;quot;email rate limit exceeded&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是一个 Supabase 配置，位置在 Authentication 下的 Rate Limit&lt;/p&gt;
&lt;p&gt;&lt;img alt="19.webp" src="https://images.yasking.org/technology/1756464912/19.webp"&gt;&lt;/p&gt;
&lt;p&gt;改成 20 封邮件后，可以找临时邮箱进行注册验证&lt;/p&gt;
&lt;h3&gt;Supabase 注册 URL 自动登录逻辑&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;用户点击邮件中的确认链接（http://web-host/#access_token=xxx&amp;amp;refresh_token=xxx&amp;amp;type=recovery）&lt;/li&gt;
&lt;li&gt;Supabase 客户端自动检测 URL 参数（detectSessionInUrl: true），自动创建 session 并触发 onAuthStateChange 事件&lt;/li&gt;
&lt;li&gt;认证状态监听器处理 (src/stores/auth.ts)&lt;/li&gt;
&lt;li&gt;应用初始化 (src/App.vue)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;我也没仔细看，因为全程氛围编程，没写几行前端代码&lt;/p&gt;
&lt;h3&gt;记在最后&lt;/h3&gt;
&lt;p&gt;Vibe Coding  一些心得，描述需求时要全面，但让其实现代码时要分步实现。Debug 时，让其添加 Console 日志，将问题日志提交给它，定位会更快、更准确&lt;/p&gt;
&lt;p&gt;前端使用 Vue 开发，部署到了 Cloudflare：&lt;a href="https://posty.donx-done.xyz/"&gt;https://posty.donx-done.xyz&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="20.webp" src="https://images.yasking.org/technology/1756464912/20.webp"&gt;&lt;/p&gt;
&lt;p&gt;前端代码仓库：&lt;a href="https://github.com/sincerefly/vuebase-posty"&gt;sincerefly/vuebase-posty&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;本文阶段性的目标已达成，这篇想了想，定为「中篇」，Supabase 还有不少值得探索的功能，放到「下篇」学习记录。&lt;/p&gt;</content><category term="Technology"></category><category term="Supabase"></category></entry><entry><title>基于 Supabase 构建示例应用（上篇）：数据库与接口</title><link href="https://blog.yasking.org/a/supabase-demo-app-step1.html" rel="alternate"></link><published>2025-08-23T18:07:16+08:00</published><updated>2025-08-23T18:07:16+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-23:/a/supabase-demo-app-step1.html</id><summary type="html">&lt;p&gt;目标：实现一个文章发布 Web 应用（Demo），包含用户注册、编辑、发布文章的功能，同时有广场（展示所有已发布文章、所有用户可以查 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;目标：实现一个文章发布 Web 应用（Demo），包含用户注册、编辑、发布文章的功能，同时有广场（展示所有已发布文章、所有用户可以查看）、并使用管理员进行维护，技术架构是 Supabase + Vue，Vue 部署在哪里还未计划，以此为契机学习了解 Supabase 服务&lt;/p&gt;
&lt;p&gt;本篇学习和记录了如下内容&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;体验 Supabase Console 建表、执行 SQL&lt;/li&gt;
&lt;li&gt;创建 RLS 行级安全策略&lt;/li&gt;
&lt;li&gt;了解不同的 API Key 类型、创建 API Key、Curl 命令调用接口&lt;/li&gt;
&lt;li&gt;了解 Supabase 的 Users 和业务表的 Users 表关联方式（通过触发器）&lt;/li&gt;
&lt;li&gt;模拟用户注册、登陆、创建文章、查看广场文章的接口使用场景&lt;/li&gt;
&lt;li&gt;Edge Functions 配置一些封控策略（未测试）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;设计表&lt;/h3&gt;
&lt;p&gt;用户表&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;CREATE TABLE users (
  id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
  username TEXT UNIQUE CHECK (char_length(username) &amp;gt;= 3),
  email TEXT UNIQUE,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;users&lt;/code&gt; 表通过 &lt;code&gt;id&lt;/code&gt; 字段&lt;strong&gt;扩展&lt;/strong&gt;了 Supabase 内置的&lt;code&gt;auth.users&lt;/code&gt;表&lt;/p&gt;
&lt;p&gt;文章表&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;CREATE TABLE posts (
  id SERIAL PRIMARY KEY,
  user_id UUID REFERENCES users(id) ON DELETE CASCADE,
  title VARCHAR(255) NOT NULL,
  content TEXT,
  published_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;users&lt;/code&gt; 表和 &lt;code&gt;posts&lt;/code&gt; 表之间存在&lt;strong&gt;一对多&lt;/strong&gt;的关系，即一个用户可以拥有多篇文章。&lt;/p&gt;
&lt;p&gt;触发器&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;-- 首先创建一个函数来更新 updated_at 字段
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ language 'plpgsql';

-- 为 users 表创建触发器
CREATE TRIGGER update_users_updated_at 
    BEFORE UPDATE ON users 
    FOR EACH ROW 
    EXECUTE FUNCTION update_updated_at_column();

-- 为 posts 表创建触发器
CREATE TRIGGER update_posts_updated_at 
    BEFORE UPDATE ON posts 
    FOR EACH ROW 
    EXECUTE FUNCTION update_updated_at_column();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Supabase 建表&lt;/h3&gt;
&lt;p&gt;点击 SQL Editor 侧边栏，右侧输入框执行 SQL 语句，执行后来到 Table Editor，可以看到已经成功创建两张表&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.webp" src="https://images.yasking.org/technology/1755943636/01.webp"&gt;&lt;/p&gt;
&lt;p&gt;但是上方都有 &lt;code&gt;Unrestricted&lt;/code&gt; 标注，没有开启 RLS 策略，可以点击页面上的黄色 “RLS disabled” 按钮，或是运行以下 SQL 语句均可开启。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启用行级策略后，我们可以设置一些策略，例如：&lt;/p&gt;
&lt;p&gt;允许用户&lt;strong&gt;只能插入（INSERT）属于自己的文章&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;CREATE POLICY &amp;quot;用户只能发表自己的文章&amp;quot; 
ON posts 
FOR INSERT 
WITH CHECK (auth.uid() = user_id); 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样，用户尝试插入文章时，Supabase 会检查要插入的 &lt;code&gt;user_id&lt;/code&gt; 是否等于当前登录用户的 ID&lt;/p&gt;
&lt;p&gt;备注：策略也可以在 Authentication 模块的 Policies 子模块中，点击表后进行可视化创建。&lt;/p&gt;
&lt;h3&gt;创建用户&lt;/h3&gt;
&lt;p&gt;Supabase 提供邮件邀请和手动创建的方式&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/technology/1755943636/02.webp"&gt;&lt;/p&gt;
&lt;p&gt;可以手动创建用户&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1755943636/03.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;也可以点击 “Send invitation” 发送邀请到邮箱。&lt;/p&gt;
&lt;h3&gt;获取免费的 SMPT Server（可选）&lt;/h3&gt;
&lt;p&gt;最开始我以为 Supabase 发送邮件需要自己提供服务，就在网上找了一个 Brevo 这个服务，有免费额度，注册过程很丝滑，记录如下，这步可以跳过，直接使用 Supabase 的邮件服务就好，也不用设置。&lt;/p&gt;
&lt;p&gt;服务地址：&lt;a href="https://www.brevo.com/free-smtp-server/"&gt;Free SMTP Server | Deliver to the Inbox Every Time&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;免费套餐每天 300 封，测试使用足够了&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.webp" src="https://images.yasking.org/technology/1755943636/04.webp"&gt;&lt;/p&gt;
&lt;p&gt;注册后点击右上角的组织，选择 “SMTP &amp;amp; API”&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.webp" src="https://images.yasking.org/technology/1755943636/05.webp"&gt;&lt;/p&gt;
&lt;p&gt;可以看到 SMTP 服务的服务器地址、用户名密码&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.webp" src="https://images.yasking.org/technology/1755943636/06.webp"&gt;&lt;/p&gt;
&lt;p&gt;还需要添加 Sender，否则发不出邮件&lt;/p&gt;
&lt;p&gt;这里我起的应用名字是 “Reader Bot”，邮箱就是我的 Gmail 邮箱，需要真实的邮箱地址，稍后会发送验证码验证。&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.webp" src="https://images.yasking.org/technology/1755943636/07.webp"&gt;&lt;/p&gt;
&lt;p&gt;点击添加&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1755943636/08.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;提示我们的免费邮箱可能大概率进入收件人的垃圾邮箱，建议绑定域名，因为是测试，当然是 Anyway&lt;/p&gt;
&lt;p&gt;验证完成后，可以看到新的 Sender 添加成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="09.webp" src="https://images.yasking.org/technology/1755943636/09.webp"&gt;&lt;/p&gt;
&lt;p&gt;此时 Brevo 提供的邮箱服务已可用&lt;/p&gt;
&lt;h3&gt;在 Supabase 配置自己的 Email SMPT 服务（可选）&lt;/h3&gt;
&lt;p&gt;如果你申请了邮箱，可以在 Authentication 模块进行配置&lt;/p&gt;
&lt;p&gt;&lt;img alt="10.webp" src="https://images.yasking.org/technology/1755943636/10.webp"&gt;&lt;/p&gt;
&lt;p&gt;填入 Brevo 获取到的邮箱服务信息&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;Sender email：k********0@gmail.com
Sender name：Reader Bot
Host：smtp-relay.brevo.com
Port number：587
Username：954923002@smtp-brevo.com
Password：(YOUR-SMTP key value)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时，再回到 Authentication 下的 Users 表中发送邮件邀请用户，就可以收到邮件&lt;/p&gt;
&lt;p&gt;&lt;img alt="11.webp" src="https://images.yasking.org/technology/1755943636/11.webp"&gt;&lt;/p&gt;
&lt;p&gt;内容如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1755943636/12.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;其中的邮件内容模板在 “Emails - Templates” 内进行配置，访问的链接在 “URL Configuration - Site URL” 进行配置，暂时先不用修改&lt;/p&gt;
&lt;h3&gt;初识 API &amp;amp; Keys&lt;/h3&gt;
&lt;p&gt;在 Project Settings 的 API Keys 页面可以创建项目 Key&lt;/p&gt;
&lt;p&gt;&lt;img alt="13.webp" src="https://images.yasking.org/technology/1755943636/13.webp"&gt;&lt;/p&gt;
&lt;p&gt;创建后有一个 Publishable key 可以在浏览器使用，格外注意，需要搭配 RLS 策略使用，它是可以公开的&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sb_publishable_JToCFTBwo4urIOPnE9cIFg_1Wo-6WYj
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;页面下方还可以看到一个名为 default 的 Server Key 用于服务端机器、或者 Function、Workers 等&lt;/p&gt;
&lt;p&gt;点击页面左侧的 API Docs 来到 API 页面&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这里有一个知识点：Supabase 通过原生集成的 PostgREST，为数据库提供开箱即用的 Auto API，使开发者无需部署后端即可安全地进行基础的 CRUD 操作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;API 文档很细致，API 分为 Client API 和 Server API，Clinet API 可以&lt;/p&gt;
&lt;h3&gt;通过 API 注册登陆读写表数据&lt;/h3&gt;
&lt;p&gt;以下命令的 apikey 就是刚生成的 Publishable key（测试时可以使用临时邮箱, e.g. &lt;a href="https://temp-mail.org"&gt;TEMP MAIL&lt;/a&gt;）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl -X POST 'https://iurlblwfhmulfdysyqdz.supabase.co/auth/v1/signup' \
-H &amp;quot;apikey: sb_publishable_JToCFTBwo4urIOPnE9cIFg_1Wo-6WYj&amp;quot; \
-H &amp;quot;Content-Type: application/json&amp;quot; \
-d '{
  &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;123456&amp;quot;
}'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;返回（已格式化）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{  
    &amp;quot;id&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;,  
    &amp;quot;aud&amp;quot;: &amp;quot;authenticated&amp;quot;,  
    &amp;quot;role&amp;quot;: &amp;quot;authenticated&amp;quot;,  
    &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;,  
    &amp;quot;phone&amp;quot;: &amp;quot;&amp;quot;,  
    &amp;quot;confirmation_sent_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.840305897Z&amp;quot;,  
    &amp;quot;app_metadata&amp;quot;: {  
        &amp;quot;provider&amp;quot;: &amp;quot;email&amp;quot;,  
        &amp;quot;providers&amp;quot;: [  
            &amp;quot;email&amp;quot;  
        ]  
    },  
    &amp;quot;user_metadata&amp;quot;: {  
        &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;,  
        &amp;quot;email_verified&amp;quot;: false,  
        &amp;quot;phone_verified&amp;quot;: false,  
        &amp;quot;sub&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;  
    },  
    &amp;quot;identities&amp;quot;: [  
        {  
            &amp;quot;identity_id&amp;quot;: &amp;quot;c9527fc9-13c9-4c85-a2c1-5b776663f22e&amp;quot;,  
            &amp;quot;id&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;,  
            &amp;quot;user_id&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;,  
            &amp;quot;identity_data&amp;quot;: {  
                &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;,  
                &amp;quot;email_verified&amp;quot;: false,  
                &amp;quot;phone_verified&amp;quot;: false,  
                &amp;quot;sub&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;  
            },  
            &amp;quot;provider&amp;quot;: &amp;quot;email&amp;quot;,  
            &amp;quot;last_sign_in_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.817329844Z&amp;quot;,  
            &amp;quot;created_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.81738Z&amp;quot;,  
            &amp;quot;updated_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.81738Z&amp;quot;,  
            &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;  
        }  
    ],  
    &amp;quot;created_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.772681Z&amp;quot;,  
    &amp;quot;updated_at&amp;quot;: &amp;quot;2025-08-23T07:19:44.000369Z&amp;quot;,  
    &amp;quot;is_anonymous&amp;quot;: false  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;会收到 Supabase 注册邮件，目前地址会跳转到 localhost:3000 地址，我们的前端 Demo 还没开发部署（但是需要点击一下确认链接进行 Supabase 的用户激活）&lt;/p&gt;
&lt;p&gt;此处仅体验使用 Publishable key 调用 Supabase 后端 API，注册用户后登陆：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl -X POST 'https://iurlblwfhmulfdysyqdz.supabase.co/auth/v1/token?grant_type=password' \
-H &amp;quot;apikey: sb_publishable_JToCFTBwo4urIOPnE9cIFg_1Wo-6WYj&amp;quot; \
-H &amp;quot;Content-Type: application/json&amp;quot; \
-d '{
  &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;123456&amp;quot;
}'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;返回&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{  
    &amp;quot;access_token&amp;quot;: &amp;quot;eyJhbGaciOiJ...NULE72KZGcdu6-LfeUdSbp8&amp;quot;,  
    &amp;quot;token_type&amp;quot;: &amp;quot;bearer&amp;quot;,  
    &amp;quot;expires_in&amp;quot;: 3600,  
    &amp;quot;expires_at&amp;quot;: 1755937882,  
    &amp;quot;refresh_token&amp;quot;: &amp;quot;u4jw6puieja6&amp;quot;,  
    &amp;quot;user&amp;quot;: {  
        &amp;quot;id&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;,  
        &amp;quot;aud&amp;quot;: &amp;quot;authenticated&amp;quot;,  
        &amp;quot;role&amp;quot;: &amp;quot;authenticated&amp;quot;,  
        &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;,  
        &amp;quot;email_confirmed_at&amp;quot;: &amp;quot;2025-08-23T07:21:22.503059Z&amp;quot;,  
        &amp;quot;phone&amp;quot;: &amp;quot;&amp;quot;,  
        &amp;quot;confirmation_sent_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.840305Z&amp;quot;,  
        &amp;quot;confirmed_at&amp;quot;: &amp;quot;2025-08-23T07:21:22.503059Z&amp;quot;,  
        &amp;quot;last_sign_in_at&amp;quot;: &amp;quot;2025-08-23T07:31:22.263515322Z&amp;quot;,  
        &amp;quot;app_metadata&amp;quot;: {  
            &amp;quot;provider&amp;quot;: &amp;quot;email&amp;quot;,  
            &amp;quot;providers&amp;quot;: [  
                &amp;quot;email&amp;quot;  
            ]  
        },  
        &amp;quot;user_metadata&amp;quot;: {  
            &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;,  
            &amp;quot;email_verified&amp;quot;: true,  
            &amp;quot;phone_verified&amp;quot;: false,  
            &amp;quot;sub&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;  
        },  
        &amp;quot;identities&amp;quot;: [  
            {  
                &amp;quot;identity_id&amp;quot;: &amp;quot;c9527fc9-13c9-4c85-a2c1-5b776663f22e&amp;quot;,  
                &amp;quot;id&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;,  
                &amp;quot;user_id&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;,  
                &amp;quot;identity_data&amp;quot;: {  
                    &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;,  
                    &amp;quot;email_verified&amp;quot;: true,  
                    &amp;quot;phone_verified&amp;quot;: false,  
                    &amp;quot;sub&amp;quot;: &amp;quot;b0fec5be-879d-4912-863e-b7495a8906b9&amp;quot;  
                },  
                &amp;quot;provider&amp;quot;: &amp;quot;email&amp;quot;,  
                &amp;quot;last_sign_in_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.817329Z&amp;quot;,  
                &amp;quot;created_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.81738Z&amp;quot;,  
                &amp;quot;updated_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.81738Z&amp;quot;,  
                &amp;quot;email&amp;quot;: &amp;quot;nasovec941@chaublog.com&amp;quot;  
            }  
        ],  
        &amp;quot;created_at&amp;quot;: &amp;quot;2025-08-23T07:19:42.772681Z&amp;quot;,  
        &amp;quot;updated_at&amp;quot;: &amp;quot;2025-08-23T07:31:22.270377Z&amp;quot;,  
        &amp;quot;is_anonymous&amp;quot;: false  
    }  
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以上都是 GETTING STARTED 的内容，接下来可以看下业务表相关的 API&lt;/p&gt;
&lt;p&gt;&lt;img alt="14.webp" src="https://images.yasking.org/technology/1755943636/14.webp"&gt;&lt;/p&gt;
&lt;p&gt;翻到 Insert 语句，“创建一篇文章”&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl -X POST 'https://iurlblwfhmulfdysyqdz.supabase.co/rest/v1/posts' \
-H &amp;quot;apikey: sb_publishable_JToCFTBwo4urIOPnE9cIFg_1Wo-6WYj&amp;quot; \
-H &amp;quot;Authorization: Bearer eyJhbGaciOiJ...NULE72KZGcdu6-LfeUdSbp8&amp;quot; \
-H &amp;quot;Content-Type: application/json&amp;quot; \
-H &amp;quot;Prefer: return=minimal&amp;quot; \
-d '{ &amp;quot;title&amp;quot;: &amp;quot;你好，世界！&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;北京今日天气：22-29度 多云 西北风3级&amp;quot; }'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;报错&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;{&amp;quot;code&amp;quot;:&amp;quot;42501&amp;quot;,&amp;quot;details&amp;quot;:null,&amp;quot;hint&amp;quot;:null,&amp;quot;message&amp;quot;:&amp;quot;new row violates row-level security policy for table \&amp;quot;posts\&amp;quot;&amp;quot;}%
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;RLS 行级策略不允许，执行以下策略：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;-- 用户只能插入自己的帖子
CREATE POLICY &amp;quot;允许认证用户插入帖子&amp;quot;
ON posts
FOR INSERT
TO authenticated
WITH CHECK (true);

-- 用户只能更新自己的帖子
CREATE POLICY &amp;quot;用户只能更新自己的帖子&amp;quot;
ON posts
AS PERMISSIVE
FOR UPDATE
TO authenticated
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再次调用，没有返回任何内容，查看 Table Editor 可以看到已经多了一条记录&lt;/p&gt;
&lt;p&gt;&lt;img alt="15.webp" src="https://images.yasking.org/technology/1755943636/15.webp"&gt;&lt;/p&gt;
&lt;p&gt;然后我发现 users 表也没有记录，即 Supabase 的 auth.users 和我的 public.users 表没有关联，同时 posts 表的 user_id 也是空；&lt;/p&gt;
&lt;p&gt;分别解决这两个问题，对于 users 未同步，可以创建一个触发器&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;-- 创建函数
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO public.users (id, email, username)
  VALUES (
    NEW.id,
    NEW.email,
    COALESCE(NEW.raw_user_meta_data-&amp;gt;&amp;gt;'username', SPLIT_PART(NEW.email, '@', 1))
  );
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 创建触发器
CREATE OR REPLACE TRIGGER on_auth_user_created
  AFTER INSERT ON auth.users
  FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;好了，再注册个用户试试！&lt;/p&gt;
&lt;p&gt;用户：&lt;code&gt;oyentreng@deepyinc.com&lt;/code&gt;
密码：&lt;code&gt;123456&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;注册、登陆不再重复粘贴代码，控制台已经可以看到用户&lt;/p&gt;
&lt;p&gt;&lt;img alt="16.webp" src="https://images.yasking.org/technology/1755943636/16.webp"&gt;&lt;/p&gt;
&lt;p&gt;解决 posts 的 user_id 为空的问题可以创建如下触发器&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;-- 启用 uuid 扩展（如果尚未启用）
CREATE EXTENSION IF NOT EXISTS &amp;quot;uuid-ossp&amp;quot;;

-- 创建触发器函数
CREATE OR REPLACE FUNCTION public.set_post_user_id()
RETURNS TRIGGER AS $$
BEGIN
  -- 从 JWT 中获取用户 ID 并设置
  NEW.user_id = auth.uid();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 创建触发器
CREATE OR REPLACE TRIGGER set_post_user_id_trigger
  BEFORE INSERT ON posts
  FOR EACH ROW
  EXECUTE FUNCTION public.set_post_user_id();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用新的用户 Token 创建文章&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl -X POST 'https://iurlblwfhmulfdysyqdz.supabase.co/rest/v1/posts' \
-H &amp;quot;apikey: sb_publishable_JToCFTBwo4urIOPnE9cIFg_1Wo-6WYj&amp;quot; \
-H &amp;quot;Authorization: Bearer eyJhbGaciOiJ...YNGEpJM2MkFp0pj4Hj45RY-h9L06M4&amp;quot; \
-H &amp;quot;Content-Type: application/json&amp;quot; \
-H &amp;quot;Prefer: return=minimal&amp;quot; \
-d '{ &amp;quot;title&amp;quot;: &amp;quot;你好，世界！&amp;quot;, &amp;quot;content&amp;quot;: &amp;quot;北京今日天气：22-29度 多云 西北风3级（下起了小雨）&amp;quot; }'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;解决了&lt;/p&gt;
&lt;p&gt;&lt;img alt="17.webp" src="https://images.yasking.org/technology/1755943636/17.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;查看 “广场” 文章&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以用户身份分页请求 10 篇文章 &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;curl 'https://iurlblwfhmulfdysyqdz.supabase.co/rest/v1/posts?published_at=not.is.null&amp;amp;select=*' \
-H &amp;quot;apikey: sb_publishable_JToCFTBwo4urIOPnE9cIFg_1Wo-6WYj&amp;quot; \
-H &amp;quot;Authorization: Bearer eyJhbGaciOiJ...YNGEpJM2MkFp0pj4Hj45RY-h9L06M4&amp;quot; \
-H &amp;quot;Range: 0-9&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查询出来 &lt;code&gt;[]&lt;/code&gt; 空数组，因为文章最开始我们定义了一个 “只能查询（SELECT）到已发布的文章” 的策略&lt;/p&gt;
&lt;p&gt;现在正好试试 Server Key 的管理员 Key 的威力，批量更新 published_at 字段为当前时间（Server Key 要藏好）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;curl -X PATCH 'https://iurlblwfhmulfdysyqdz.supabase.co/rest/v1/posts?id=in.(3,4,5)' \
-H &amp;quot;apikey: sb_secret_Xr48DdK*************pmR1XA_xLeM45LH&amp;quot; \
-H &amp;quot;Content-Type: application/json&amp;quot; \
-H &amp;quot;Prefer: return=minimal&amp;quot; \
-d '{ &amp;quot;published_at&amp;quot;: &amp;quot;now()&amp;quot; }'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;apikey 设置为 sb_secret_xxxx 管理员密钥，无需 Authorization Header&lt;/p&gt;
&lt;p&gt;&lt;img alt="18.webp" src="https://images.yasking.org/technology/1755943636/18.webp"&gt;&lt;/p&gt;
&lt;p&gt;已更新，预期应该是可以查询到了，但是依然返回 &lt;code&gt;[]&lt;/code&gt;，到 Supabase 翻翻，发现还是 RLS 策略缺失的问题；&lt;/p&gt;
&lt;p&gt;Supabase SQL 执行页面有个功能，可以选择作为哪个 ROLE 执行&lt;/p&gt;
&lt;p&gt;&lt;img alt="19.webp" src="https://images.yasking.org/technology/1755943636/19.webp"&gt;&lt;/p&gt;
&lt;p&gt;默认使用 postgres，也可以切换为匿名角色或是 authenticated role，选择后可以选择特定的用户，到表的 RLS policies 页面，添加策略&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1755943636/20.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;using 条件就是发布时间不为空，允许了匿名和已登陆用户查看；&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;[  
    {  
        &amp;quot;id&amp;quot;: 3,  
        &amp;quot;user_id&amp;quot;: null,  
        &amp;quot;title&amp;quot;: &amp;quot;你好，世界！&amp;quot;,  
        &amp;quot;content&amp;quot;: &amp;quot;北京今日天气：22-29度 多云 西北风3级&amp;quot;,  
        &amp;quot;published_at&amp;quot;: &amp;quot;2025-08-23T08:38:44.481162+00:00&amp;quot;,  
        &amp;quot;created_at&amp;quot;: &amp;quot;2025-08-23T07:58:08.479927+00:00&amp;quot;,  
        &amp;quot;updated_at&amp;quot;: &amp;quot;2025-08-23T08:38:44.481162+00:00&amp;quot;  
    },  
    {  
        &amp;quot;id&amp;quot;: 4,  
        &amp;quot;user_id&amp;quot;: null,  
        &amp;quot;title&amp;quot;: &amp;quot;你好，世界！&amp;quot;,  
        &amp;quot;content&amp;quot;: &amp;quot;北京今日天气：22-29度 多云 西北风3级（下起了小雨）&amp;quot;,  
        &amp;quot;published_at&amp;quot;: &amp;quot;2025-08-23T08:38:44.481162+00:00&amp;quot;,  
        &amp;quot;created_at&amp;quot;: &amp;quot;2025-08-23T08:18:26.565641+00:00&amp;quot;,  
        &amp;quot;updated_at&amp;quot;: &amp;quot;2025-08-23T08:38:44.481162+00:00&amp;quot;  
    },  
    {  
        &amp;quot;id&amp;quot;: 5,  
        &amp;quot;user_id&amp;quot;: &amp;quot;badab300-959f-42f7-ae75-99d74f937804&amp;quot;,  
        &amp;quot;title&amp;quot;: &amp;quot;你好，世界！&amp;quot;,  
        &amp;quot;content&amp;quot;: &amp;quot;北京今日天气：22-29度 多云 西北风3级（下起了小雨）&amp;quot;,  
        &amp;quot;published_at&amp;quot;: &amp;quot;2025-08-23T08:38:44.481162+00:00&amp;quot;,  
        &amp;quot;created_at&amp;quot;: &amp;quot;2025-08-23T08:25:13.986663+00:00&amp;quot;,  
        &amp;quot;updated_at&amp;quot;: &amp;quot;2025-08-23T08:38:44.481162+00:00&amp;quot;  
    }  
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;“广场” 功能没问题，通过接口查询到了所有已发布的文章；&lt;/p&gt;
&lt;h3&gt;最后增加些安全策略&lt;/h3&gt;
&lt;p&gt;RLS 策略：用户每天最多发表 10 篇文章&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;CREATE POLICY &amp;quot;用户每天只能插入10篇文章&amp;quot;
ON posts 
FOR INSERT 
TO authenticated
WITH CHECK (
  auth.uid() = user_id AND
  -- 可以添加其他限制条件，比如每天最多10篇
  (SELECT COUNT(*) FROM posts 
   WHERE user_id = auth.uid() 
   AND created_at &amp;gt; NOW() - INTERVAL '1 day') &amp;lt; 10
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 Edge Functions 可以配置函数，以下的限制借助边缘函数实现&lt;/p&gt;
&lt;p&gt;&lt;img alt="21.webp" src="https://images.yasking.org/technology/1755943636/21.webp"&gt;&lt;/p&gt;
&lt;p&gt;rate-limiter（30 请求每分钟）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;import &amp;quot;jsr:@supabase/functions-js/edge-runtime.d.ts&amp;quot;;

// 内存存储速率限制
const rateLimitMap = new Map&amp;lt;string, { count: number; resetTime: number }&amp;gt;();

Deno.serve(async (req: Request) =&amp;gt; {
  // 获取客户端IP
  const clientIP = req.headers.get('x-forwarded-for') || 'unknown';

  // 速率限制检查
  const now = Date.now();
  const limitData = rateLimitMap.get(clientIP) || { count: 0, resetTime: now + 60000 };

  // 重置计数器（每分钟）
  if (now &amp;gt; limitData.resetTime) {
    limitData.count = 0;
    limitData.resetTime = now + 60000;
  }

  // 检查限制（每分钟30次）
  if (limitData.count &amp;gt;= 30) {
    return new Response(
      JSON.stringify({ error: 'Rate limit exceeded' }),
      { status: 429 }
    );
  }

  // 增加计数
  limitData.count++;
  rateLimitMap.set(clientIP, limitData);

  // 返回成功响应
  return new Response(
    JSON.stringify({ 
      success: true,
      method: req.method,
      remaining: 30 - limitData.count 
    }),
    { headers: { 'Content-Type': 'application/json' } }
  );
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;post-content-size（限制 content 字段 10kb 大小）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;import &amp;quot;jsr:@supabase/functions-js/edge-runtime.d.ts&amp;quot;;

Deno.serve(async (req: Request) =&amp;gt; {
  try {
    // 读取请求内容
    const content = await req.text();

    // 计算内容大小（字节数）
    const contentSize = new TextEncoder().encode(content).length;

    // 检查大小限制（10KB = 10240字节）
    if (contentSize &amp;gt; 10240) {
      return new Response(
        JSON.stringify({ 
          error: 'Content too large',
          max_size: '10KB',
          actual_size: `${(contentSize / 1024).toFixed(2)}KB`
        }),
        { status: 413 }
      );
    }

    // 内容大小合格
    return new Response(
      JSON.stringify({ 
        success: true,
        size: `${contentSize} bytes`,
        size_kb: `${(contentSize / 1024).toFixed(2)}KB`
      }),
      { headers: { 'Content-Type': 'application/json' } }
    );

  } catch (error) {
    return new Response(
      JSON.stringify({ error: 'Invalid request' }),
      { status: 400 }
    );
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;reg-user-limiter（每天限制最多 100 人注册）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-javascript"&gt;import &amp;quot;jsr:@supabase/functions-js/edge-runtime.d.ts&amp;quot;;
import { createClient } from &amp;quot;jsr:@supabase/supabase-js@2&amp;quot;;

const supabase = createClient(
  Deno.env.get(&amp;quot;SUPABASE_URL&amp;quot;)!,
  Deno.env.get(&amp;quot;SUPABASE_SERVICE_ROLE_KEY&amp;quot;)!
);

Deno.serve(async (req: Request) =&amp;gt; {
  try {
    // 查询今日注册数量
    const today = new Date().toISOString().split('T')[0];
    const { count, error } = await supabase
      .from('auth.users')
      .select('*', { count: 'exact', head: true })
      .gte('created_at', `${today}T00:00:00`)
      .lte('created_at', `${today}T23:59:59`);

    if (error) throw error;

    // 检查是否超过限制
    if (count &amp;gt;= 100) {
      return new Response(
        JSON.stringify({ 
          error: 'Daily registration limit reached',
          limit: 100,
          today_count: count
        }),
        { status: 429 }
      );
    }

    // 允许注册
    return new Response(
      JSON.stringify({ 
        allowed: true,
        remaining: 100 - count,
        today_count: count
      }),
      { headers: { 'Content-Type': 'application/json' } }
    );

  } catch (error) {
    return new Response(
      JSON.stringify({ error: 'Internal server error' }),
      { status: 500 }
    );
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;AI 提供的 Function 函数，我配置上，但没测试是否能正常工作 🤷&lt;/p&gt;
&lt;p&gt;不知不觉记录了不少内容，后端目前先了解这些，已覆盖 Demo 所需功能，Web 前端的开发放到下篇文章进行记录。&lt;/p&gt;
&lt;p&gt;下篇会根据 Supabase 的文档示例，使用 Vue 开发前端页面，也会调研部署在哪个免费服务比较好。&lt;/p&gt;</content><category term="Technology"></category><category term="Supabase"></category></entry><entry><title>阅读《三体》之地球往事</title><link href="https://blog.yasking.org/a/reading-the-three-body-problem.html" rel="alternate"></link><published>2025-08-20T20:24:00+08:00</published><updated>2025-08-20T20:24:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-20:/a/reading-the-three-body-problem.html</id><summary type="html">&lt;p&gt;三体可能是我阅读的第一本科幻小说&lt;/p&gt;
&lt;p&gt;三部曲之一的地球往事通过片段化的故事连接，将现实与科幻柔和在一起，将‘上世 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;三体可能是我阅读的第一本科幻小说&lt;/p&gt;
&lt;p&gt;三部曲之一的地球往事通过片段化的故事连接，将现实与科幻柔和在一起，将‘上世纪六七十年代的社会运动’、现代环保等主题围绕着三体故事的主线逐一展开。&lt;/p&gt;
&lt;p&gt;动荡年代的苦难，引人反思人性中的善与恶，对地球文明生态破坏的惋惜，以及对宇宙秩序的大胆想象。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1755671438/01.webp" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;书中人物都做着符合自己人生经历的抉择，叶文洁主动联系外星文明，能感受到她对人类秩序和道德的彻底失望，也在对“高级”文明的盲目崇拜中下了赌注，以至暴露太阳系坐标，引发不可逆的后果。她既是受害者，也是推动历史走向未知的关键人物。 &lt;/p&gt;
&lt;p&gt;第一部的叙事和铺垫很棒，大名鼎鼎的《三体》，我也算是 ‘已窥’ 一二了&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;科幻小说的定义 &lt;/p&gt;
&lt;p&gt;GPT: 科幻小说是一种以科学或未来技术为基础，结合合理想象来探讨人类、社会与宇宙关系的文学体裁。它强调科学逻辑的可能性，同时通过虚构情境反映现实问题与思想。 &lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Reading"></category></entry><entry><title>Oracle Free 实例重装系统</title><link href="https://blog.yasking.org/a/oracle-instance-reinstall-the-system.html" rel="alternate"></link><published>2025-08-15T21:00:00+08:00</published><updated>2025-08-15T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-15:/a/oracle-instance-reinstall-the-system.html</id><summary type="html">&lt;p&gt;之前申请了两台 x86 架构的 Oracle 机器，偶尔用来测试使用，有一台在调试 SSH 配置相关功能时 “变砖”，网上看重装系统发现很繁琐 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;之前申请了两台 x86 架构的 Oracle 机器，偶尔用来测试使用，有一台在调试 SSH 配置相关功能时 “变砖”，网上看重装系统发现很繁琐就没去打理，近期又想到这个机器，发现去年就有了官方重装方法，简单配置下，继续让其发光发热；&lt;/p&gt;
&lt;h3&gt;’替换引导卷‘ 重装系统&lt;/h3&gt;
&lt;p&gt;这是官方提供的方式，在实例详情中点击 “操作” - “更多操作” - “替换引导卷”。&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/technology/1755246091/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;无需开启 “保留引导卷开关”，选择 “映像” 和 “输入 OCID” 选项&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1755246091/02.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;在 &lt;a href="https://docs.oracle.com/en-us/iaas/images/"&gt;https://docs.oracle.com/en-us/iaas/images/&lt;/a&gt; 可以找到 OCID，注意只能选择同系统的不同版本，例如 Ubuntu 从 20.04 到 24.04 Minimal，不能从 Centos 7 到 Oracle 9&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.jpg" src="https://images.yasking.org/technology/1755246091/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;粘贴后可以看到它自动显示了镜像的信息，保持引导卷大小不变。&lt;/p&gt;
&lt;p&gt;如想使用新的 SSH Key，可以在高级选项中添加 &lt;code&gt;ssh_authorized_keys&lt;/code&gt;，值为公钥内容。&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/technology/1755246091/04.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;让 Ubuntu 24.04 看起来很忙&lt;/h3&gt;
&lt;p&gt;忙起来，别闲着&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade

sudo apt install htop git build-essential

curl -o lookbusy-1.4.tar.gz https://devin.com/lookbusy/download/lookbusy-1.4.tar.gz

tar xvf lookbusy-1.4.tar.gz

cd lookbusy-1.4

chmod a+x configure

./configure

make

sudo make install

nohup lookbusy -c 5-15 -r curve &amp;gt; lookbusy.log 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Centos 7 尚能饭否&lt;/h3&gt;
&lt;p&gt;太久没登录，Yum 安装软件都开始报错&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;Cannot find a valid baseurl for repo: base/7/x86_64
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;是因为官方不再支持 Centos 7 的镜像源，编辑 &lt;em&gt;/etc/yum.repos.d/CentOS-Base.repo&lt;/em&gt; 文件&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;取消所有 &lt;code&gt;baseurl&lt;/code&gt; 开头的注释。&lt;/li&gt;
&lt;li&gt;将所有 &lt;code&gt;mirrorlist.centos.org&lt;/code&gt; 替换为 &lt;code&gt;vault.centos.org&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;将所有 &lt;code&gt;mirror.centos.org&lt;/code&gt; 替换为 &lt;code&gt;vault.centos.org&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;清理缓存，执行 &lt;code&gt;sudo yum clean all&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;编辑后的内容示例如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;[base]
name=CentOS-$releasever - Base
mirrorlist=http://vault.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=os&amp;amp;infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#released updates 
[updates]
name=CentOS-$releasever - Updates
mirrorlist=http://vault.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=updates&amp;amp;infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://vault.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=extras&amp;amp;infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
mirrorlist=http://vault.centos.org/?release=$releasever&amp;amp;arch=$basearch&amp;amp;repo=centosplus&amp;amp;infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而后更新下软件&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sudo yum update -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本想参考 &lt;a href="https://blogs.oracle.com/scoter/post/upgrade-centos-7-to-oracle-linux-8"&gt;https://blogs.oracle.com/scoter/post/upgrade-centos-7-to-oracle-linux-8&lt;/a&gt; 升级下系统&lt;/p&gt;
&lt;p&gt;升级预检给出的报告，一眼就看到了 “Minimum memory request...”&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.jpg" src="https://images.yasking.org/technology/1755246091/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;只好放弃&lt;/p&gt;
&lt;h3&gt;让 Centos 7 也忙起来&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;sudo yum -y update

sudo yum -y install htop git 

yum groupinstall &amp;quot;Development Tools&amp;quot;

curl -o lookbusy-1.4.tar.gz https://devin.com/lookbusy/download/lookbusy-1.4.tar.gz

tar xvf lookbusy-1.4.tar.gz

cd lookbusy-1.4

chmod a+x configure

./configure

make

sudo make install

nohup lookbusy -c 5-15 -r curve &amp;gt; lookbusy.log 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;题外话&lt;/h3&gt;
&lt;p&gt;Ubuntu 24.04 Minimal 占用磁盘少很多，安装一些软件后，还剩 46 GB&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/technology/1755246091/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;“完整版” Centos 7 安装同样的软件后，还剩 35 GB&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/technology/1755246091/07.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cnboy.org/2961"&gt;甲骨文云Oracle Cloud官方重装系统/官方救砖教程&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/franzwong/fix-cannot-find-a-valid-baseurl-for-repo-in-centos-1h07"&gt;Fix "Cannot find a valid baseurl for repo" in CentOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Oracle"></category></entry><entry><title>非京籍个体户缴纳社保(补充)：“无有效的汇总预处理信息” 解决办法</title><link href="https://blog.yasking.org/a/self-employed-append-one.html" rel="alternate"></link><published>2025-08-15T21:00:00+08:00</published><updated>2025-08-15T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-15:/a/self-employed-append-one.html</id><summary type="html">&lt;p&gt;8 月份缴纳社保时，进入日常申报提示 “无有效的汇总预处理信息”，如图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1755248027/01.webp" width="80.00%" /&gt;&lt;/p&gt;
&lt;p&gt;到 ”我要办税“ - ”社保业务“ - ”年度缴费工资调整“&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/skills/1755248027/02.webp"&gt;&lt;/p&gt;
&lt;p&gt;选择 ”生效 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;8 月份缴纳社保时，进入日常申报提示 “无有效的汇总预处理信息”，如图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1755248027/01.webp" width="80.00%" /&gt;&lt;/p&gt;
&lt;p&gt;到 ”我要办税“ - ”社保业务“ - ”年度缴费工资调整“&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.webp" src="https://images.yasking.org/skills/1755248027/02.webp"&gt;&lt;/p&gt;
&lt;p&gt;选择 ”生效年度“ 为当前 2025&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.webp" src="https://images.yasking.org/skills/1755248027/03.webp"&gt;&lt;/p&gt;
&lt;p&gt;确定后提示数据初始化成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.webp" src="https://images.yasking.org/skills/1755248027/04.webp"&gt;&lt;/p&gt;
&lt;p&gt;注意看页面的提示&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.webp" src="https://images.yasking.org/skills/1755248027/05.webp"&gt;&lt;/p&gt;
&lt;p&gt;因为我只需要添加一个，所以选择的 ”单个添加“&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1755248027/06.webp" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;输入 ”姓名“、”身份证“，设置缴费工资后保存。&lt;/p&gt;
&lt;p&gt;回到列表后勾选记录，提交申报，问题解决。&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>阅读《芯片简史》</title><link href="https://blog.yasking.org/a/reading-brief-history-of-chips.html" rel="alternate"></link><published>2025-08-10T17:42:00+08:00</published><updated>2025-08-10T17:42:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-10:/a/reading-brief-history-of-chips.html</id><summary type="html">&lt;p&gt;之前读过曹天元的《上帝掷骰子吗？量子物理史话》，书里讲的是 20 世纪初到三四十年代，量子物理从无到有的故事——普朗克、爱 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;之前读过曹天元的《上帝掷骰子吗？量子物理史话》，书里讲的是 20 世纪初到三四十年代，量子物理从无到有的故事——普朗克、爱因斯坦、玻尔、海森堡、薛定谔等巨匠在理论迷雾中试探前行，至今回想仍让人心潮澎湃。&lt;/p&gt;
&lt;p&gt;这次读《芯片简史》，顿感“故事”都连上了！从 1940 年代起，又一个辉煌的三十年：晶体管问世、集成电路出现、微处理器诞生… &lt;/p&gt;
&lt;p&gt;书里让我印象最深的是那一批推动半导体革命的人——肖克利、诺伊斯、巴丁、布拉顿、摩尔、法金、霍夫……还有早已熟悉的图灵、冯·诺伊曼、香农。以前只知道“摩尔定律”，却不知道摩尔本人就是“仙童八叛逆”之一，还与诺伊斯一起创立了英特尔；而仙童半导体公司比印象中更厉害，这里堪称是硅谷的“黄埔军校”，从这里走出的工程师后来几乎撑起了整个产业。&lt;/p&gt;
&lt;p&gt;我一直做软件相关的工作，对操作系统之下的硬件世界了解有限，像隔着雾看山。这本书以硬件从无到有的视角，帮我把零散的知识串起来，也看到每个硬件的出现都伴随着艰辛，有欢呼、有遗憾，更有争分夺秒的激烈竞争，无形中对技术演进多了一份敬畏之心。&lt;/p&gt;
&lt;p&gt;如果我有一个书架，会把它放在上面，等过几年再翻一翻。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1754818750/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;（第一颗 CPU，Intel 4004）&lt;/p&gt;
&lt;h3&gt;摘抄&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;1952 年 4 月，贝尔实验室召开了第二次研讨会，26 家美国公司和 14 家外国公司的代表参加了为期9天的研讨、参观和制作演示。这些公司包括 IBM、通用电气、飞利浦、西门子、索尼、德州仪器以及一些小公司，如斯普拉格电气公司（Sprague Electric）和中心实验室（Central Lab）。每家公司都收到了一本 792 页的《晶体管：特性与应用参考资料》，大家戏称它为价值 “25 000美元的书”。&lt;/li&gt;
&lt;li&gt;蒂尔最后说，大厅后面有他的论文的复印件，大家可以自取。听众立马抢着离开座位去取论文，在一片嘈杂声中，雷神公司（Raytheon）的一位代表在走廊里拿起电话大声叫道：“德州仪器公司做出了硅晶体管！”&lt;/li&gt;
&lt;li&gt;信件几经辗转，最后到达了投资人阿瑟·洛克（Arthur Rock）手上。他读完信后，被其中的一点打动了，那就是诺贝尔物理学奖得主肖克利选择了他们这件事本身，足以说明这个团队值得投资。&lt;/li&gt;
&lt;li&gt;接下来，洛克火速地赶回纽约，寻觅合适的投资公司。但大部分公司都婉拒了，只有一家仙童摄影器材公司的老板谢尔曼·费尔柴尔德（Sherman Fairchild）表现出浓厚的兴趣。费尔柴尔德的父亲曾是IBM公司最大的个人股东，后来把股票转移给了儿子。费尔柴尔德充满活力，很有想象力，对半导体器件很感兴趣。之前他的公司调研了制造半导体元件的可能性，但一直找不到合适的团队，而此时诺伊斯一行 8 个人正好找上门来，于是他们一拍即合。&lt;/li&gt;
&lt;li&gt;在洛克的协调下，仙童摄影器材公司派人来到加州。最后达成的协议规定，公司划分成 1325 股，8位联合创始人每人只需缴纳 500 美元就可以获得 100 股原始股，洛克所属的海登斯通公司占有 225股，剩下的 300 股用于今后招揽人才。仙童摄影器材公司在 18 个月内投资 138 万美元，成立名为“仙童半导体公司” 的子公司。在仙童半导体公司连续三年的利润超过 30 万美元之前，母公司仙童摄影器材公司有权以 300 万美元的价格在任何时候收购它。“这是一个让双方都满意的协议。” 其中一位创始人说。&lt;/li&gt;
&lt;li&gt;肖克利在贝尔实验室的同事查尔斯·汤斯（Charles Townes）后来对摩尔说：“肖克利太聪明了，他明白所有的事情，除了人。”&lt;/li&gt;
&lt;li&gt;就这样，在这短短的一年时间里，基尔比首先提出并实现了单片集成技术，而诺伊斯首先提出并实现了互连技术，莱霍韦茨则首先提出了电气隔离技术，这三项技术组合起来，成为集成电路技术的基石。&lt;/li&gt;
&lt;li&gt;每次听到自己被称作科学家时，基尔比总说自己是一名工程师，是在尝试解决实际问题。在诺贝尔奖领奖礼的演讲中，基尔比展示了自己手工做出的第一颗带着飞线的芯片的照片，并说道：“如果我知道这个电路将来会帮我赢得诺贝尔奖，我会多花些时间好好装点一下。”&lt;/li&gt;
&lt;li&gt;摩尔曾说：“仙童半导体公司的可贵之处在于它的组织上是不成熟的。类似的想法也会出现在其他更‘成熟’的大公司，但是一定会被认为在经济上不值得而被否决掉。”&lt;/li&gt;
&lt;li&gt;那时萨支唐跟巴丁重新取得了联系，开始兼职去伊利诺伊大学教授晶体管课程，他经常往返于加州和伊利诺伊州之间，几个星期才回一趟公司。这让万拉斯更加不受约束，创造力得以充分施展。&lt;/li&gt;
&lt;li&gt;万拉斯刚刚加入仙童半导体公司才几个月，就和萨支唐一起提出了一种新的电路，把一个PMOS场效晶体管和一个 NMOS 场效晶体管组合起来，两者互补形成一个CMOS场效晶体管开关。&lt;/li&gt;
&lt;li&gt;接着，主持人抛出了一个犀利的问题：“在这50年中，戈登·摩尔从摩尔定律中学到的最大教训是什么？“， “哦，这个问题挺难回答的。”摩尔沉思了一两秒钟后说道，“对我来说，最大的教训就是：既然已经做出了一个这么准的预测，那么我最好避免再做出第二个预测。”观众席中顿时爆发出一阵笑声。&lt;/li&gt;
&lt;li&gt;与其说摩尔定律是一个定律，不如说是一种信仰。正是这种“不待证明而相信”的信仰，推动着摩尔定律不断获得验证。摩尔定律展示的不是永恒不变的物理定律，而是人的想象力和创造力在不同阶段所能达到的极限。&lt;/li&gt;
&lt;li&gt;开关也能做计算？不能，但是开关很适合表达逻辑关系。例如，两个开关可以组成“与”“或”等逻辑。我们只要采用二进制，就能把代数计算转化为逻辑计算，从而用开关来实现代数计算。&lt;/li&gt;
&lt;li&gt;1948 年，香农在贝尔实验室工作时发现了一种更加小巧、快速的开关。当年上半年的一天，香农拐进了肖克利小组的实验室，他灰色的眼眸立刻被一个只有三根导线的小玩意儿给吸引了。“这是一个固态放大器。”肖克利解释说，那时晶体管还没有正式对外发布。&lt;/li&gt;
&lt;li&gt;彼时，仙童半导体公司已经有一大波人出走创业。公司几乎每周都有人跳槽出去创业。这种出走创业模式已蔚然成风，以至于仙童半导体公司成了硅谷培养半导体人才的摇篮，从仙童半导体公司出走的员工总共创立了400多家公司，它们大多坐落于硅谷，被称为 “小仙童们”。&lt;/li&gt;
&lt;li&gt;诺伊斯和摩尔开始张罗新公司，他们想仿照硅谷的先驱惠普公司，将创始人的姓氏首字母组成新公司的名字“MN”（Moore Noyce）。但它读起来像是“More Noise”（更多噪声），这对电路来说无疑是个灾难。不久，一个简洁的名字英特尔（Intel）脱颖而出，它是三年前摩尔提出摩尔定律的文章最初的名字“集成电子学”（Integrated Electronics）的缩写。&lt;/li&gt;
&lt;li&gt;于是，霍夫大刀阔斧地精简了整体系统的架构，只保留了4颗芯片。这 4 颗芯片分别是 4001（ROM）、4002（RAM）、4003（寄存器）和4004（CPU）。它们的数据总线是4位的，因此以4开头，名为“4000系列”。这些芯片构成了“冯·诺伊曼结构”，前 3 颗组成了存储系统，而4004构成了最关键的计算单元和控制系统。这样一来，英特尔公司承担的整体设计任务就大大减轻了。&lt;/li&gt;
&lt;li&gt;诺伊斯后来把英特尔公司的策略归结为：“我无法实现你的要求，所以我想出了一种更简单的方法来绕过它。这就是可编程芯片想法的起源，也正是微处理器芯片想法的精华：完成电路设计，赋予它可编程的能力。这样你就可以有很多不同的应用。”&lt;/li&gt;
&lt;li&gt;终于，比吉康公司接受了霍夫的新架构。此后，嶋正利回日本继续完善新架构，他们要求英特尔公司在未来的几个月内完成所有的芯片设计。&lt;/li&gt;
&lt;li&gt;然而，英特尔公司的开发承诺却落空了，它卡在了具体的电路设计上。霍夫只熟悉处理器架构和指令集，并不懂逻辑电路设计，而且他还接到了新任务，为CTC公司设计8位处理器架构。于是他把“4000系列”芯片的设计任务转交给了MOS场效晶体管研究部的莱斯利·沃达斯。&lt;/li&gt;
&lt;li&gt;然而，沃达斯同样不懂电路设计，他需要招聘一位既懂芯片架构，又懂电路设计，最好还懂MOS场效晶体管的工程师。但是集这些素质于一身的工程师凤毛麟角，要在短时间内找到无异于大海捞针。&lt;/li&gt;
&lt;li&gt;不得已，沃达斯想到了在仙童半导体公司的前同事法金，他是完成这项挑战的不二人选：既懂计算机架构，又有计算芯片设计经验，还懂最先进的硅栅MOS场效晶体管工艺。&lt;/li&gt;
&lt;li&gt;法金将 4004 放在一台显微镜下面仔细观察，竟发现有整整一层材料没有添加到芯片上，难怪芯片不工作。原来，是技术人员在制造芯片时遗漏了其中一层。法金距离成功如此之近，又是如此失望。直到1971年1月下旬寒冷的一天，法金再一次收到了新的4004样片。他小心翼翼地拿起装着样片的盒子，就好像捧着自己的孩子，把它们轻轻地安放到测试平台上。当他把芯片连接到测试仪器上时，他感到自己的手指在微微颤抖。法金测试了第一个点，波形正常！又测试了几个点，波形正常，并且完全符合预期。他简直不敢相信，在这颗小小的芯片上，一切都按照预期的结果显示在他面前，速度比他19岁时用锗晶体管搭建的计算机还快10倍，而功耗只有0.75瓦，仅仅是锗晶体管计算机的1/1 000，这真是工程技术上的奇迹。&lt;/li&gt;
&lt;li&gt;凌晨4点，法金完成所有的测试，拖着疲惫的身子回到家中。妻子已经入睡了，但瞬间被惊醒，她在朦胧中看到了丈夫，问道：“芯片怎么样了？”，“成功了！”法金激动地喊道，和妻子相拥在一起，欣喜若狂的情绪包围着他们，将法金身上的寒气一扫而空。这时他们才意识到，他们见证了一个历史性事件——世界上第一颗CPU芯片诞生了。&lt;/li&gt;
&lt;li&gt;接下来，英特尔公司将样片寄往比吉康公司，嶋正利把它装到一台内置纸带打印机的计算器上。他在键盘上敲下了一个加法算式，屏住呼吸，只听纸带打印机在一阵振动后输出了结果。嶋正利内心非常激动，这是4004芯片的第一个成功应用。然而，英特尔公司却没有人对此欢呼庆祝。公司内部对是否大规模销售这颗 CPU 芯片产生了严重分歧。&lt;/li&gt;
&lt;/ul&gt;</content><category term="Reading"></category></entry><entry><title>阅读《简约至上：交互式设计四策略（第2版）》</title><link href="https://blog.yasking.org/a/reading-simple-and-usable-web-mobile-and-interaction-design.html" rel="alternate"></link><published>2025-08-06T20:24:00+08:00</published><updated>2025-08-06T20:24:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-06:/a/reading-simple-and-usable-web-mobile-and-interaction-design.html</id><summary type="html">&lt;h3&gt;简介&lt;/h3&gt;
&lt;p&gt;《简约至上》提出了四个策略：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;删除 - 删除多余的文字、按钮、功能。&lt;/li&gt;
&lt;li&gt;组织 - 将功能整合，更容易让用户关注到重点功能。&lt;/li&gt;
&lt;li&gt;隐藏 - 将重 …&lt;/li&gt;&lt;/ol&gt;</summary><content type="html">&lt;h3&gt;简介&lt;/h3&gt;
&lt;p&gt;《简约至上》提出了四个策略：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;删除 - 删除多余的文字、按钮、功能。&lt;/li&gt;
&lt;li&gt;组织 - 将功能整合，更容易让用户关注到重点功能。&lt;/li&gt;
&lt;li&gt;隐藏 - 将重要但非高频的功能隐藏起来，简化应用操作逻辑。&lt;/li&gt;
&lt;li&gt;转移 - 多平台应用，应有所侧重，不是每一个功能都要在多端实现。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;内容比较基础但融会贯通不易，只看标题就可以猜到这个章节讲的内容，这本书适合快速阅读，如果你在书店恰巧看到它，1 到 2 个小时就可以翻阅一遍。&lt;/p&gt;
&lt;p&gt;如果书就在那里，建议翻翻看，不推荐购买收藏实体书。&lt;/p&gt;
&lt;h3&gt;摘抄&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;如果你是赛道上唯一的参赛选手，那只要“足够好”就行。但多数情况下，我们都会面临激烈的竞争。这时候，边际效用——细节—就变得重要了。正如查尔斯•埃姆斯（Charles Eames）所说：“细节并不是细节。它们构成了设计。”&lt;/li&gt;
&lt;li&gt;最好与其他的差别在于细节。&lt;/li&gt;
&lt;li&gt;传统的观点认为，功能越多，能力就越强，产品的用途也就越广。传统的观点还认为，功能多的产品能打败功能少的产品。但相对简单的产品却频繁地替代更复杂的产品。&lt;/li&gt;
&lt;li&gt;删除杂乱的特性可以让设计师专注于把有限的重要问题解决好，而且也有助于用户心无旁骛地完成自己的目标。&lt;/li&gt;
&lt;li&gt;法国作家、飞行员安托万•德•圣埃克絮佩里（Antoine de Saint-Exupery）说过：“完美并非加无可加，而是减无可减。”删除作为一个策略难就难在明白怎样做到这一点。&lt;/li&gt;
&lt;li&gt;项目经理因为这个功能太难做而砍掉了它… 交工日期迫近，预算资金紧张，都可能导致功能被砍掉。设计团队经常会以提供尽可能多的功能为目标。那些耗时而不容易实现的功能通常会被砍掉。如果有人强烈反对，得到的答复一般是他们的功能会在“第二期”或“第三期”实现。结果呢，无非就是得到一个由简单的功能叠加起来的毫无特色的产品，与市面上现有的平庸货色别无二致。&lt;/li&gt;
&lt;li&gt;如果你发现自己（或别人）说：“假如用户需要…”那么只有一个答菜：搞清楚这个功能对用户是否真的重要。问一间：“我的目标用户经常会遇到这个问题吗？”如果回答是“几乎没有遇到过”时论下一个。那么，请放弃这个想法，不要再“假如”了，还是去发现问题吧。&lt;/li&gt;
&lt;li&gt;消除错误的来源是简化体验的一个重要思路。&lt;/li&gt;
&lt;li&gt;功能多对于没有机会试用的消费者有吸引力。但是消费者使用了产品之后，他们的偏好就会改变，一下子从重视功能变成了更重视可用性。&lt;/li&gt;
&lt;li&gt;如果一个元素的重要性为1/2，那就把它的大小做成 1/4。&lt;/li&gt;
&lt;li&gt;简单的体验优先于完整的服务。&lt;/li&gt;
&lt;li&gt;只有明白推荐的理由、赞同推荐的标准、接受可能的风险，用户才会接受计算机的推荐。如果推荐的结果没有满足上述要求，人们就不会信任它。&lt;/li&gt;
&lt;li&gt;让用户感觉简单的一个重要前提，就是先搞清楚把什么工作交给计算机，把什么工作留给用户。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/reading/1754482443/01.jpg"&gt;&lt;/p&gt;</content><category term="Reading"></category></entry><entry><title>阅读《审判》</title><link href="https://blog.yasking.org/a/reading-the-trial.html" rel="alternate"></link><published>2025-08-03T17:27:00+08:00</published><updated>2025-08-03T17:27:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-08-03:/a/reading-the-trial.html</id><summary type="html">&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1754212831/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;（《审判》主人公 K —— Gen by GPT-4o）&lt;/p&gt;
&lt;h3&gt;初读体验&lt;/h3&gt;
&lt;p&gt;第一次读类似题材的长篇小说，我带着 ‘先看两章、能读进去就继续’ 的想法开始阅读。&lt;/p&gt;
&lt;p&gt;虽然我 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1754212831/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;（《审判》主人公 K —— Gen by GPT-4o）&lt;/p&gt;
&lt;h3&gt;初读体验&lt;/h3&gt;
&lt;p&gt;第一次读类似题材的长篇小说，我带着 ‘先看两章、能读进去就继续’ 的想法开始阅读。&lt;/p&gt;
&lt;p&gt;虽然我不清楚作者所在的十九世纪的奥匈帝国的背景和当时的司法氛围，但读《审判》时，我能感受到作者、K，乃至读者都深陷 ‘困惑’ 之中。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GPT：“当K试图询问罪名时，官员只回答‘你被捕了，但可以继续生活’ —— 这种逻辑的断裂，正是困惑的根源。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;作者对司法的思考深刻，小说文笔精炼、刻画细致，让我有种感觉，书中的 K 就是作者，作者也是 K，卡夫卡将自己融入到了小说中。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GPT：“作为法学出身并长期任职于保险局的卡夫卡，笔下官僚系统的 ‘无意义严谨’，或许正是他对体制的观察。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;文字信息密度很大，每段对话都可能隐藏着作者的思考，等待读者去发掘 —— 这是令人上瘾的阅读体验。&lt;/p&gt;
&lt;p&gt;我渐渐意识到，这本小说的品鉴维度是多样的&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;一个被宣判有罪的个体，从 ‘拒不认罪’，到觉得需要做些什么，借助女人，再到主动周旋，全力以赴，去找可能与法官有私下交情的律师，去找给法官画肖像了解隐秘司法 ‘内幕’ 的画师，从玄学再到一个深奥的 ‘法的大门’ 的教士的论述... 隐秘的司法，充满荒诞。 &lt;/li&gt;
&lt;li&gt;从 K 的人格角度，从最开始的严谨，轻松，到最终 ‘对抗’ 命运，却毫无一点胜算，坦然接受死亡，从 K 的生日开始，到 K 的生日结束，仅仅只是一年的时间。&lt;/li&gt;
&lt;li&gt;K 的生活，某种程度上是作者的映射，得以窥探作者甚至是那个时代对于工作、性、司法的看法和观念，另外隐隐觉着，书中的女性角色总是跟司法相关联，有着不正当的关系，次要角色（如律师、画师）也都是官僚机器的具象化零件，是司法大机器的外部延伸。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;司法荒诞&lt;/h3&gt;
&lt;p&gt;K 遇见画师的章节蛮有意思，K 算是 ‘真正’ 窥探到了法院的一丝隐秘，了解到有三个办法可以 ‘解决问题’。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;真正的无罪开释&lt;/li&gt;
&lt;li&gt;诡称宣判无罪&lt;/li&gt;
&lt;li&gt;无限期延缓审理&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;真正的无罪开释&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;是最理想的结果，但仅限于高级法官特权，普通人几乎无法获得&lt;/p&gt;
&lt;p&gt;无罪开释首先排除，因为这是大人物——高级司法部门才能享有的特权，低级别预审法官没有这项权力，无罪开释如果成立，那么关于案子的当事人的所有诉讼、案卷都要通通销毁。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;诡称宣判无罪&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;表面“无罪”，实则是一次极度依赖人脉与机会的繁复流程，一旦失败，后续尝试更为艰难&lt;/p&gt;
&lt;p&gt;通过关系，联系到几个法官，他们在无罪辩护声明上签字，‘背书’ 的作用，然后提交到案子的主审法官处，他才敢于签署 ‘宣判无罪’，提交到上级部门，这个案卷可能流转到各种不同层级的部门和人员手中，如果有一个人偶然看到，认定其有罪，那么就会被驳回重新审理，这个时间可能在一天内，也可能几年时间，当事人就要重新赶快再疏通关系，走一遍这个流程，而第二次、第三次的 ‘诡称宣判无罪’ 肯定会更加困难，这是显然的，走进诡称宣判无罪流程，也就意味着无法再真正的无罪开释，意味着案子当事人需要集中精力、快速响应眼下的问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;无限期延缓审理&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过不停“活动”保留自由，代价是持续的精力投入和精神焦虑，实则是被困于系统的慢性折磨&lt;/p&gt;
&lt;p&gt;案子当事人需要 ‘持续的输出’ 精力，要跟主审法官保持紧密的联系，经常到审理机关 ‘报道’，以便能够顺利的、缓慢的走着毫无意义的流程，这将是持续性的努力，最终的目的是保有自由，因为未宣判，就没有罪，也就可以一直为自由努力，显然，这两种方式都无法被真正解决。&lt;/p&gt;
&lt;p&gt;理解完这三种方案后，我们对这套司法系统的本质，也可想而知了。&lt;/p&gt;
&lt;h3&gt;思考未竟&lt;/h3&gt;
&lt;p&gt;正如卡夫卡曾要求销毁手稿，K 那场“未完成的辩护”也未能实现，他们共同构成了这部作品戏剧性的终章。&lt;/p&gt;
&lt;p&gt;最后的最后&lt;/p&gt;
&lt;p&gt;对于本书，可能留给读者一些思考：如果连 ‘罪名’ 都无法得知，那我们还如何为自己辩护？进一步的，在这个困惑又荒诞的司法体系下，在不可知权力面前，所做的努力会有多少用处呢？&lt;/p&gt;
&lt;p&gt;但是转念一想，抗争永远有用，总会有用。&lt;/p&gt;
&lt;p&gt;在绝对权力的黑幕下，我们可能永远无法得知自己“错在哪里”，但只要我们还愿意提出质疑、尝试抗争，那就还未完全失去自由的可能。&lt;/p&gt;
&lt;p&gt;《审判》值得一读，更值得反复咀嚼，我放弃了到网上或者询问 GPT 了解更多 “正确又细致” 解读的机会，相信以后重读，可以有更多属于自己的思考。&lt;/p&gt;</content><category term="Reading"></category></entry><entry><title>阅读《统计数字会撒谎》</title><link href="https://blog.yasking.org/a/reading-how-to-lie-with-statistics.html" rel="alternate"></link><published>2025-07-28T21:00:00+08:00</published><updated>2025-07-28T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-07-28:/a/reading-how-to-lie-with-statistics.html</id><summary type="html">&lt;h3&gt;Chapter 1：内在有偏的样本&lt;/h3&gt;
&lt;p&gt;案例：“记者在火车上调查大家都买到了回家过节的车票”&lt;/p&gt;
&lt;p&gt;第一章讲的是样本因自身特性或选择方式 …&lt;/p&gt;</summary><content type="html">&lt;h3&gt;Chapter 1：内在有偏的样本&lt;/h3&gt;
&lt;p&gt;案例：“记者在火车上调查大家都买到了回家过节的车票”&lt;/p&gt;
&lt;p&gt;第一章讲的是样本因自身特性或选择方式而无法代表总体，导致统计结果失真。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;最基本的样本是随机样本，它是指完全遵循随机原则从总体中选出的样本。总体即形成样本的母体。
随机样本的检验方法是：总体中的每个名字或每个事物是否具有相同的几率被选进样本？
纯随机样本是惟一有足够把握经受统计理论审查的样本。但它也有不足之处，在很多情况下，获得这种样本的难度很大并且十分昂贵，以至于单纯考虑成本就会排除它。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Chapter 2：精心挑选的平均数&lt;/h3&gt;
&lt;p&gt;案例：一个富豪年薪 1000 万，他有 9 个朋友穷光蛋，平均一看，各个年薪百万。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当你听到公司执行总裁或企业所有者宣称，在他的企业中员工的平均收人是多少时，你应该好好思考一下其中的原因。如果这个数是中位数，你可以获得一些显而易见的信息：一半员工赚得比它多，一半比它少。但如果是均值（请相信我，没有确切指出它的种类时，多半是均值），它仅仅是所有者 25000 英镑的高收入与全体工人低水平收入的平均数，根本没有什么意义。“平均年收入为 3800 英镑”既隐瞒了1400英镑的低收人，又隐瞒了所有者以巨额薪金形式抽取的高额利润。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1753701224/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;所以，当你被告知某个数是平均数时，除非能说出它的具体种类——均值，中位数，还是众数，否则你对它的具体涵义仍知之甚少。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Chapter 3：没有披露的数据&lt;/h3&gt;
&lt;p&gt;案例：某人宣称抛硬币正反面的比例是 5：1，但是没有披露他做了 100 次试验，只选择了其中的 5 次试验结果作为样本进行统计&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;还有另一类没有透露的数据，它的遗漏也同样具有破坏性。这类数据表明了事物的变动范围以及与给定平均数的偏离水平。通常情况下，单凭一个平均数来描述事物过于简单，起不到作用，不管这个平均数是均值还是中位数，也不管平均数的具体类型是否已知。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Chapter 4：毫无意义的工作&lt;/h3&gt;
&lt;p&gt;案例：某公司投入巨额资金，部署了多条国际专线，调整了 BGP 路由策略，优化了跨境访问链路，最终成功地将国际网络访问速度从 300 毫秒降低了 2% —— 相当于 6 毫秒的提升。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;只有当差别有意义时才能称之为差别&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;换句话说：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;只有在毫无意义时，这个差别才如此值得强调&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Chapter 5：令人惊奇的图形&lt;/h3&gt;
&lt;p&gt;案例：（见以下图像）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;只需要改变横坐标与纵坐标的比例关系，将纵坐标的每一个刻度缩减为原来的1/10即可，没有人规定不能这么做，而这将会产生一张更加完美的图形。&lt;/p&gt;
&lt;p&gt;显然图形比文字更有效，因为图形中不存在任何形容词和副词来破坏它所具有的客观性幻觉，而且谁也无法指责你。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;搜索到某龙江省历年出生率数据（21 世纪），这是一个稀疏平常的折线统计图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1753701224/02.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;已经可以看到出生率下降比较多，如果我修改为下图的形式，宽高对调，同时 Y 轴间隔从 0.2 调整为 0.05，图像将更有震撼效果&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1753701224/03.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;h3&gt;Chapter 6：一维图的滥用&lt;/h3&gt;
&lt;p&gt;案例：（见以下 AI 提供的说明）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1753701224/04.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在图表的世界里，只要敢缩轴、敢立体、敢堆图标，你就能让“微涨”看起来像“暴涨”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;跟「令人惊奇的图形」类似，一维图像想要突出或降低一些视觉效果，可以做的文章很多&lt;/p&gt;
&lt;h3&gt;Chapter 7：不完全匹配的资料&lt;/h3&gt;
&lt;p&gt;案例：某诺贝尔奖得主每天都喝这种牛奶，但没有提及他也吃面包、鸡肉和沙拉，每天晨跑、骑自行车&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你想要人相信 “结论A”，但拿不出证据，就展示一个听起来很像、但其实只是“相关”的 B。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这就是“不完全匹配的资料” —— &lt;strong&gt;一种披着数据外衣的偷换概念&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Chapter 8：相关关系的误解&lt;/h3&gt;
&lt;p&gt;案例：研究发现冰淇淋销量高的时候，溺水事件也多。&lt;/p&gt;
&lt;p&gt;实际上是因为夏天到了，吃冰淇淋的人变多，游泳的人也变多，共同原因是 “气温升高”，不是冰淇淋和溺水互为因果。&lt;/p&gt;
&lt;p&gt;重要的概念即：&lt;strong&gt;相关 ≠ 因果&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“相关性”（correlation）只是两个变量&lt;strong&gt;一同变化&lt;/strong&gt;，而“因果性”（causation）意味着&lt;strong&gt;一个是另一个的原因&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;但是，很多时候人们会误把 “同时发生” 当作 “有因果关系”——这是一个&lt;strong&gt;统计思维中的致命误区&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Chapter 9：如何进行统计操控&lt;/h3&gt;
&lt;p&gt;案例：产品满意率达到 100%，其实只调查了 5 个人，这五个人还是公司的员工&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;任何建立在小样本容量上的百分数都可能产生误导，直接给出调查对象规模（样本容量）的大小将更有价值。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1753701224/05.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;案例：股票跌了 10%，但是需要上涨百分之 11.11% 才能回到原来水平，下跌的越多，涨回去越难&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;50%的削减量需要通过提高100%才能加以补偿。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1753701224/06.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;案例：商场打折，折上折的数字陷阱&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;份“50%折扣再打20%折扣”的报价单时，那并不意味着70%的折扣，实际上只有60%&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1753701224/07.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;案例：（这个案例就很经典）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;人们询问他的兔肉三明治为什么能卖到如此便宜的价格时，“哦，”他说，“我当然得掺一些马肉，但我的比例是一比一：一匹马，一只兔子。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/reading/1753701224/08.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;h3&gt;Chapter 10：如何反驳统计资料&lt;/h3&gt;
&lt;p&gt;省流：数字不是事实，只是说故事的工具，别轻信涨幅和图标，多问问数据怎么来的，多问问 AI 怎么看&lt;/p&gt;</content><category term="Reading"></category></entry><entry><title>达达秒送骑士</title><link href="https://blog.yasking.org/a/dada-takeaway-rider.html" rel="alternate"></link><published>2025-07-23T21:00:00+08:00</published><updated>2025-07-23T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-07-23:/a/dada-takeaway-rider.html</id><summary type="html">&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1753268722/01.jpg" width="62%" /&gt;&lt;/p&gt;
&lt;h3&gt;单价略高 &amp;amp; 定位差&lt;/h3&gt;
&lt;p&gt;刚跑外卖时，我同时下载了美团众包和达达秒送骑士，后者两个月前被京东收购了，我跑了几周的美团众 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1753268722/01.jpg" width="62%" /&gt;&lt;/p&gt;
&lt;h3&gt;单价略高 &amp;amp; 定位差&lt;/h3&gt;
&lt;p&gt;刚跑外卖时，我同时下载了美团众包和达达秒送骑士，后者两个月前被京东收购了，我跑了几周的美团众包后，也过了新手期，就想着换达达试试&lt;/p&gt;
&lt;p&gt;网上说达达定位不准，结果第一单就体验到了，是真不准&lt;/p&gt;
&lt;p&gt;距目的地差了有两百米，我给用户打了两遍电话才找到，直接导致我手里拿着的第二单被迫超时，好在可以用新手免罚卡抵扣&lt;/p&gt;
&lt;p&gt;如何避免定位不准出问题？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;别用达达 APP 内的点击跳转到地图功能（错误的坐标，在哪里显示都是错误的），直接打开高德地图，手动输入目的地，开启导航&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;达达单价整体上感觉比美团众包能高个一两块，但也不能无脑接单，广场挂着没人抢均价还不到1块钱每公里的单可别接，妥妥的甄纯牛马&lt;/p&gt;
&lt;p&gt;公里均价能到2元以上的单，对我来说都还算不错（取货送货都是几百米，公里均价3+元的单是真不好抢）&lt;/p&gt;
&lt;p&gt;达达近期有个活动，跑一单达标就送 15元奖励，也是被我白嫖到了&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1753268722/02.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;说回来配送，跑达达第一天，就送到两个让我蛮开心的单，一个配送到我现在住的小区，另一个配送到前些年住过的城中村公寓，这两单不用开导航&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.jpg" src="https://images.yasking.org/moments/1753268722/03.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;女骑手变多了&lt;/h3&gt;
&lt;p&gt;最近发现，女骑手好像多起来了，网上买菜送货员、上班去地铁的路上、商场电梯间，都有看见过女骑手，明显比前两年多，不知道有没有关于骑手的数据报告支持主观感受&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2025-07-24 更新&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;还真找到了美团的骑手报告，在 &lt;a href="https://www.meituan.com/newsroom/rider-protection"&gt;https://www.meituan.com/newsroom/rider-protection&lt;/a&gt; 找到《美团骑手年度职业报告（2024-2025）》&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(2) 性别特征：男性占比超九成，“夫妻档”稳定性强&lt;/p&gt;
&lt;p&gt;2022-2024 年，男性骑手在平台月活骑手中占比始终超过 90%。虽然女性骑手占比不足 10%，但数量
稳步上升：2022-2024 年，在美团平台上获得收入的女骑手数量从 51.7 万人增长至 70.1 万人。田野
调查显示，女骑手以已婚中年女性为主，其中很多女骑手职业选择受配偶影响，即丈夫先成为骑手，后
和妻子组成“夫妻档”。因样本量有限，夫妻档骑手占比难以衡量，但已有样本显示，“夫妻档”骑手
的就业稳定性更强，且女性略强于男性。调研中，多对夫妻档做骑手时间超过 3 年，二人中至少有一人
实现晋升，成为小组长、站长等。除夫妻档外，女骑手的职业选择理由与男骑手无异，收入高、自由度
高是其选择做骑手的主要原因。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;报告提及到女骑手人数变多，但比例并没有提升&lt;/p&gt;
&lt;p&gt;除了「信息公开」板块，美团网站上的「公益」板块也很好，为公益操场捐款时可以选择到家乡，然后看到正在筹集资金的幼儿园，建设完成后可以获知 "捐赠的每一块地板放到了哪个操场的哪一行哪一列"&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>日本关西系列｜在动物园前站找到海南本线</title><link href="https://blog.yasking.org/a/osaka-jinxingong-hainan-subway.html" rel="alternate"></link><published>2025-07-19T23:06:00+08:00</published><updated>2025-07-19T23:06:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-07-19:/a/osaka-jinxingong-hainan-subway.html</id><summary type="html">&lt;p&gt;大阪今新宫、动物园前是个交通很便利的地方，北上可到难波、心斋桥，往东南方向一站可达天王寺，在附近住了两天，交通很 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;大阪今新宫、动物园前是个交通很便利的地方，北上可到难波、心斋桥，往东南方向一站可达天王寺，在附近住了两天，交通很便利&lt;/p&gt;
&lt;p&gt;在我返程的最后一天，到 Daikoku Locker 取行李，顺便逛了下附近的唐吉诃德，根据 Google Map 地图，打算坐南海本线往关西机场走&lt;/p&gt;
&lt;p&gt;下着小雨直接钻进了「JR 今新宫」站（下图），上站台后走了好长一段，刷卡时错误，被站务拦住，他有一个小对讲机，在跟我确认是 Chinese 后，切换为中文输出，告知我不能从这里过去，但是他没告诉我要怎么走，于是我又掏出手机中文转日语，但是我他表情有些迷茫，然后又打字问他&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/skills/1752937401/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;耽搁了一会儿，我大概理解了他说的，然后从图 ① 位置又出来，冒雨沿路走到图 ② 位置 &lt;/p&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/skills/1752937401/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;惯性思维容易害人，这两个站其实不互通&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.jpg" src="https://images.yasking.org/skills/1752937401/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;看到 “NANKAI” 字样，就是走对了&lt;/p&gt;
&lt;p&gt;坐车前，我还有些分不清海南本线和南海特急，以为是同一车型，后来发现差别很大，一下是南海本线和南海特级的列车&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/skills/1752937401/04.jpg"&gt;
（有些像北京地铁的是海南本线）&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.jpg" src="https://images.yasking.org/skills/1752937401/05.jpg"&gt;
（网图：酷酷的是南海特急 - 忍者号 Rapit）&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>观影《长安的荔枝》</title><link href="https://blog.yasking.org/a/movie-changan-litchi.html" rel="alternate"></link><published>2025-07-19T22:56:00+08:00</published><updated>2025-07-19T22:56:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-07-19:/a/movie-changan-litchi.html</id><summary type="html">&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/moments/1752936796/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;之前没读过《长安的荔枝》原著，直接看的电影，观影上整体感觉良好，节奏比较快，没有彩蛋&lt;/p&gt;
&lt;p&gt;剧中大鹏饰演的李善德，被媳妇每 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/moments/1752936796/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;之前没读过《长安的荔枝》原著，直接看的电影，观影上整体感觉良好，节奏比较快，没有彩蛋&lt;/p&gt;
&lt;p&gt;剧中大鹏饰演的李善德，被媳妇每天来个大逼斗，着实有些不理解，不知是否要塑造出 “妻管严” 的人设，感觉老实人+爱媳妇的形象的主角，观众都很喜欢&lt;/p&gt;
&lt;p&gt;剧中圣人只是想讨皇后的欢心，执行的人就得脑袋别裤腰带上跑断腿，底层的老百姓就要为这些权贵买单，并附上沉重的代价，真就是时代的灰尘… 牛马们能一秒对上号，高台上的权贵们也从不管底层死活（电影中）&lt;/p&gt;
&lt;p&gt;电影表达的内容，字谜都在谜面上，所以可挖掘的深度有限&lt;/p&gt;
&lt;p&gt;说回大鹏，他拍的影片，都有很强烈的流量风格，从屌丝男士，到后来看过他拍的《年会不能停》 ，都带着幽默、职场、Happy Ending 的标签&lt;/p&gt;
&lt;p&gt;大鹏是导演也是主演，可以感觉到演技有所提升，但大鹏的电影目前看还是主打快销&lt;/p&gt;
&lt;p&gt;提一嘴白客，从《万万没想到》的王大锤时期积攒了好感度，个人觉着白客演电影很有表现力，荔枝园主阿僮（庄达菲 饰）的率真仗义也让人印象深刻&lt;/p&gt;
&lt;p&gt;这个电影适合平时不太看太多电影的观众，许久未去影院，偶尔去看个电影，有泪点、有笑点、有故事也有还不错的结局，对于我这种一年看两三场电影的人来说是友好的&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>Memos: 记录两个在线工具</title><link href="https://blog.yasking.org/a/1752749544.html" rel="alternate"></link><published>2025-07-17T19:41:00+08:00</published><updated>2025-07-17T19:41:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-07-17:/a/1752749544.html</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;稍微调整了博客的代码，支持了 “Memos” 功能，用来记录一些零碎的想法和备忘录。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;线上实施，准备了脚本（是 Pod 的 Yaml 配置文件）用来 …&lt;/p&gt;</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;稍微调整了博客的代码，支持了 “Memos” 功能，用来记录一些零碎的想法和备忘录。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;线上实施，准备了脚本（是 Pod 的 Yaml 配置文件）用来导出数据，测试环境验证的很完美，正式环境一提交，Pod 起不来，一看日志被 Dockerhub 限流了，想到前两天刚看到个国内镜像源 &lt;a href="https://docker.aityp.com/"&gt;https://docker.aityp.com/&lt;/a&gt; ，虽然机器在国外，但问题不大，替换了镜像地址，救我老命&lt;/p&gt;
&lt;p&gt;导出数据容易，从 k8s 中下载数据到本地有些麻烦，数据量不大，压缩后几十MB，想到可以加密后上传到免登录的公共临时存储，找了 &lt;a href="https://0x0.st/"&gt;https://0x0.st/&lt;/a&gt; 和 &lt;a href="https://catbox.moe/"&gt;https://catbox.moe/&lt;/a&gt; 前者限制了我的机房 IP，后者用着着实不错&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ zip -r -P &amp;quot;$ZIP_PASSWORD&amp;quot; data.zip data/

$ curl -F &amp;quot;reqtype=fileupload&amp;quot; -F &amp;quot;fileToUpload=@data.zip&amp;quot; https://catbox.moe/user/api.php
https://files.catbox.moe/y1xzwa.zip%
&lt;/code&gt;&lt;/pre&gt;</content><category term="Memos"></category><category term="备忘录"></category><category term="在线网站"></category></entry><entry><title>地球 Online：外卖骑手体验报告</title><link href="https://blog.yasking.org/a/meituan-crowdsourcing-takeaway-rider.html" rel="alternate"></link><published>2025-07-15T21:00:00+08:00</published><updated>2025-07-15T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-07-15:/a/meituan-crowdsourcing-takeaway-rider.html</id><summary type="html">&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1752572278/01.jpg" width="90.00%" /&gt;&lt;/p&gt;
&lt;p&gt;有天我在网上闲逛，看到一个「船新」版本的地球 Online 游戏思路&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你想玩开放世界大作，可以弄个外卖工作做做，有大地图，有 …&lt;/p&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;p&gt;&lt;img src="https://images.yasking.org/moments/1752572278/01.jpg" width="90.00%" /&gt;&lt;/p&gt;
&lt;p&gt;有天我在网上闲逛，看到一个「船新」版本的地球 Online 游戏思路&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你想玩开放世界大作，可以弄个外卖工作做做，有大地图，有每日任务，有随机事件，有动态天气变化，有NPC，有攻略，有打法，除了战斗系统外一应俱全，完成任务委托还能获得对应奖励，为何不来试试呢&lt;/p&gt;
&lt;p&gt;外卖是现代冒险者，有任务中心，有结算，有冒险地图，这就是冒险者工会。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;研究后发现确实值得一试，在真实物理引擎的加持下，体验肯定会不一样&lt;/p&gt;
&lt;p&gt;新手上手最简单的是「美团众包」服，在上号的前几天先下载游戏，注册，学习了解游戏规则，游戏外设至少要准备「电动自行车」和「头盔」以及「外卖箱」&lt;/p&gt;
&lt;p&gt;自行车和步行也是可以的，只是能接的任务有限，影响游戏体验，因为游戏过于真实，头盔也必不可少，外卖箱我是在淘宝 18.8 买的，可以使用泡沫箱替代，箱子不是强制的，主要是为了保温和避免餐损&lt;/p&gt;
&lt;p&gt;另外电动车上的手机支架，也十分建议配备，路线不熟时，频繁停车看手机很浪费时间，超时罚款会很影响心情（新手期赠送了三张免罚券）&lt;/p&gt;
&lt;p&gt;需要缴纳 100 元押金，用来解锁更多类型的订单任务，健康证非强制，一个月新手保护期过后会提示上传，不上传会限制同时挂单数量&lt;/p&gt;
&lt;p&gt;新手玩家不建议以挂单量和任务奖励为主要目标，这会增加些焦虑情绪，也能避免任务超时触发惩罚机制，先稳稳当当，一次接个一两单&lt;/p&gt;
&lt;p&gt;新手期有时会派发新人专属，绑在一起的两个订单，取餐都在一个区域，送达地点也不远，这种单很好，不要错过&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;不建议接的任务&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;送货地址描述不清&lt;/li&gt;
&lt;li&gt;就近代买的，费时费力易有纠纷&lt;/li&gt;
&lt;li&gt;取货和送货都较远，单公里价格低&lt;/li&gt;
&lt;li&gt;蛋糕这类容易给自己过生日的易损品&lt;/li&gt;
&lt;li&gt;高峰期的写字楼和医院，写字楼上不去下不来的&lt;/li&gt;
&lt;li&gt;不接远单，路线不熟，容易超时，回程空跑浪费时间&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;就接点正常的任务，在新手村慢慢攒经验&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;游戏感受&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;平时下班儿晚，都是赶在周末上号，每次两到三小时，最近总共游戏时常 9小时，报酬124.5 元（把头盔和外卖箱钱赚了回来），平均时薪 13.8元/小时，后期陆续达到 15元/小时（跟职业玩家没法比）&lt;/p&gt;
&lt;p&gt;近单模式下，平均四块钱左右一单，六块钱以上要骑的比较久，十块钱以上我就不接了，对我来说性价比不高，更适合专业骑手，他们的设备，一脚油就到了&lt;/p&gt;
&lt;p&gt;第一次配送的时候，找不到商家，明明定位就在那里，但是看不到店面，可以询问同为「骑手」职业的玩家，问过几次路，发现大家都很乐意帮忙，不要用“您好”，直接叫“大哥”，融入进去&lt;/p&gt;
&lt;p&gt;配送过程最多三单在手，在时间的催促下，不时有闯红灯的冲动&lt;/p&gt;
&lt;p&gt;晚上穿梭在车流人群中，感觉人从世界中抽离出来，对时间的感知不再明显，灯火、热闹也都跟自己没有任何关系，只有 “从哪里取，送哪里去” 的最简单又朴素的使命感&lt;/p&gt;
&lt;p&gt;外卖送达时，成就感即时反馈&lt;/p&gt;
&lt;p&gt;如果你在夏日下午四五点钟点开始送外卖，日光渐隐，热浪还在，辛苦了两个小时后，偶然接到一个林荫路的单，那一刻能体会到凉爽的风是对辛劳者最好的馈赠&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/moments/1752572278/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;游戏收获&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;对周边更加熟悉，地图 “战争迷雾” 不断在消散，发现商圈中不显眼的外卖档口，进到的城中村感受喧嚣，也送货到千万元别墅区体会宁静&lt;/p&gt;
&lt;p&gt;然后，生活中减少了点外卖的次数，且更加慎重，没有实地去过的实体店外卖几乎不再买，宣称 “绝无预制菜” 的小商家不可能厨师现炒，大概率是提前分装好的菜品，小份菜摞成一摞，放在微波炉中加热，两分钟后伴随着“滴”声出餐&lt;/p&gt;
&lt;p&gt;实付十来块的外卖，配送费三四元、扣除平台抽成，再扣除商家的房租水电燃气及人力成本，最后想要盈利，一定是在餐盒和食材上能省尽省，高油盐本就不健康，还可以用来掩盖掉食材不新鲜的味道&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;实体餐饮很难&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;想起前些天一个朋友弟弟来北京开店，主营山西肉夹馍和凉皮面食，在热门区域租了一个小门市，可以堂食，也接入了外卖，因为我们公司就在附近，就点了吃，肉夹馍里瘦肉多、汁水足，味道正宗&lt;/p&gt;
&lt;p&gt;没想到在二十多天后，就听说不做了，了解得知房租每月几万块，我听着都顿感压力，这得卖多少单才能挣回来&lt;/p&gt;
&lt;p&gt;美团外卖上显示订单 100+/月，饿了么 24 单，总应该不超过 200 单，按照线下线上 3:1 估计，月总 800 单，均价 25 元/单，毛利润八元算（已经是很高的估算），入账六千四，不算人力成本，房租月亏几万，怎么算都太亏&lt;/p&gt;
&lt;p&gt;突然有个不成熟的想法，感觉做餐饮小本经营的个体户，可以跑一个季度的外卖，对于周边消费者的喜好、客单价，会有一个不同的看见，在选址上也会有更多的选择&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;游戏之外&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;外卖骑手可能是跟程序员很互补的职业，虽说大多时候在骑车，但是去往商家与送餐过程中，也会走路和小跑，不必排斥接到送货到七楼的单，不赶时间爬爬楼也是锻炼身体&lt;/p&gt;
&lt;p&gt;称呼 “游戏”，并非因骑手是容易的，相反，这个职业被称为 “铁人三项”之一，是高强度的体力劳动，我是选择西山的太阳才敢出门，正午的太阳只想在家躺平，只是送外卖这个工作，具体到个人来说，是营生，还是生活的调味剂，心态自不相同&lt;/p&gt;
&lt;p&gt;跑外卖想赚钱，真的需要靠着铁人的身体素质和意志，月入一两万的单王是极少数人，春夏秋冬高强度跑外卖，身体也容易落下病，只有体验过才知道辛苦&lt;/p&gt;
&lt;p&gt;对于我来说，参与了体力劳动换取报酬，对于消费习惯会有影响，送了几单林里手打柠檬茶后，回家的路上也想要犒劳自己一杯，然后想到要跑一个多小时才能赚回来，就算了，到超市买了两个柠檬回家&lt;/p&gt;
&lt;p&gt;闲暇时，我想我还会偶尔上号继续前行，感受并探索世界&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>杜师傅夜话：附身与归途</title><link href="https://blog.yasking.org/a/du-tales-possession-and-homecoming.html" rel="alternate"></link><published>2025-07-08T21:00:00+08:00</published><updated>2025-07-08T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-07-08:/a/du-tales-possession-and-homecoming.html</id><summary type="html">&lt;blockquote&gt;
&lt;p&gt;借喉说话的亡者，无人应答的归途&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;杜师傅有五十多岁，已退休的老一辈程序员，发际线 “后缩”，精干强健，爬山总是在第一梯队 …&lt;/p&gt;</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;借喉说话的亡者，无人应答的归途&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;杜师傅有五十多岁，已退休的老一辈程序员，发际线 “后缩”，精干强健，爬山总是在第一梯队上到山顶，见多识广，总能讲述些轶闻趣事&lt;/p&gt;
&lt;p&gt;杜师傅说她的岳母亲历过她们村里一个很匪夷所思的怪事，记在如下&lt;/p&gt;
&lt;p&gt;村里有一个男人进山打猎，按现在的话说，这个人很衰，生活也不得志，进山后可能是摔了或是怎样，猎枪打到了自己的头，结果就这样死了，因为死的实在窝囊，下葬的过程中就不顺利&lt;/p&gt;
&lt;p&gt;下葬当天，村里有个瘦弱的女人，在路旁观望，突然就张嘴开口说话，是男人的声音，神情神态，都跟这个死者一样，都说是被这个死人附了，抓狂暴躁，胡言乱语，有几个年轻人不了解情况，过去想要抓住她，不想她力气却是奇大，几个人也按不住&lt;/p&gt;
&lt;p&gt;村里有个老人可能看出些门道，就说把死者的妻子找来，她还有孩子，就一同过来，众人对她说那个人就是你的丈夫，你去劝劝他&lt;/p&gt;
&lt;p&gt;这女人就对着瘦弱的女子哭骂，就说“你在世的时候我们娘俩跟着你受苦，现在死了丢下我们也不让人安生”，过了一阵儿，瘦弱女子倒在地上，像生了大病，一连躺在床上几天都起不来&lt;/p&gt;
&lt;p&gt;想来被鬼附要透支人的生命力，不然哪里来的那么大力气，称奇的是女人没有喉结，却能发出男人的声音，杜师傅感慨着&lt;/p&gt;
&lt;p&gt;……&lt;/p&gt;
&lt;p&gt;杜师傅又说起关于他岳父去世时候的事，那时候他和一些亲人都在照看他岳父&lt;/p&gt;
&lt;p&gt;有一天医生就跟他们说再有三四个小时，病人就要去世了，看你们要是需要转院就赶紧，当时是在长沙，病人去世要火化，回到村里就还能土葬，杜师傅一行人就驱车火急火燎的往家赶&lt;/p&gt;
&lt;p&gt;后来才听说，她的岳母独自在家的时候，那时她还不知道丈夫病危，在床上午间休息，就听见有人按门铃的声音，这个门铃在一个很偏的位置，没人知道位置平时也不会有人按&lt;/p&gt;
&lt;p&gt;又听到院子里的脚步声，这个声音她很熟悉，她确定那就是她丈夫的声音，杜师傅岳母还问：“你回来了”，没有人应答&lt;/p&gt;
&lt;p&gt;后来得知，她丈夫在回来的路上就去世了，这是他跟妻子最后的道别&lt;/p&gt;</content><category term="Moments"></category></entry><entry><title>日本关西系列｜使用投放硬币的行李寄存箱</title><link href="https://blog.yasking.org/a/coin-locker-usage.html" rel="alternate"></link><published>2025-06-23T21:00:00+08:00</published><updated>2025-06-23T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-06-23:/a/coin-locker-usage.html</id><summary type="html">&lt;p&gt;出行前在小红薯上看攻略，有人分享使用行李寄存箱没搞明白花了两份钱，有点好奇，实地使用过一次后发现蛮容易的，只 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;出行前在小红薯上看攻略，有人分享使用行李寄存箱没搞明白花了两份钱，有点好奇，实地使用过一次后发现蛮容易的，只是跟国内寄存箱的逻辑有些差别&lt;/p&gt;
&lt;p&gt;简单总结即&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;先放包, 再投币, 锁门拔钥匙&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1750673879/01.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;京都蹴上站的行李寄存箱，工作日来空闲箱很多，没有硬币可以到旁边人工窗口换取&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1750673879/02.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;500 日元的存储柜存放一个二十寸行李箱+一个背包，空余空间还很大&lt;/p&gt;
&lt;p&gt;请看 VCR ⬇️&lt;/p&gt;
&lt;video id="video" controls="" preload="none" poster="https://images.yasking.org/skills/1750673879/03.jpg" width=420&gt;
  &lt;source id="mp4" src="https://images.yasking.org/skills/1750673879/03.mp4" type="video/mp4"&gt;
  &lt;p&gt;Your user agent does not support the HTML5 Video element.&lt;/p&gt;
&lt;/video&gt;</content><category term="Skill"></category></entry><entry><title>日本关西系列｜将多余零钱充值到西瓜卡</title><link href="https://blog.yasking.org/a/recharge-change.html" rel="alternate"></link><published>2025-06-07T21:00:00+08:00</published><updated>2025-06-07T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-06-07:/a/recharge-change.html</id><summary type="html">&lt;p&gt;在日本，零钱有很多使用场景，街边的售卖机、乘坐公交车等，但零钱过多，随身携带会不方便，如果你在地铁站看到 “のりこし …&lt;/p&gt;</summary><content type="html">&lt;p&gt;在日本，零钱有很多使用场景，街边的售卖机、乘坐公交车等，但零钱过多，随身携带会不方便，如果你在地铁站看到 “のりこし精算機” 机器，可以将过多的零钱充值到 IC 卡（西瓜卡）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749390480/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;页面支持中文，下一步、下一步即可，如果担心不太会操作，请看 VCR ⬇️&lt;/p&gt;
&lt;video id="video" controls="" preload="none" poster="https://images.yasking.org/skills/1749390480/02.jpg" width=420&gt;
  &lt;source id="mp4" src="https://images.yasking.org/skills/1749390480/02.mp4" type="video/mp4"&gt;
  &lt;p&gt;Your user agent does not support the HTML5 Video element.&lt;/p&gt;
&lt;/video&gt;</content><category term="Skill"></category></entry><entry><title>日本关西系列｜网上购买大阪往返白滨高速巴士</title><link href="https://blog.yasking.org/a/osaka-shirahama-highway-bus.html" rel="alternate"></link><published>2025-06-06T18:55:00+08:00</published><updated>2025-06-06T18:55:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-06-06:/a/osaka-shirahama-highway-bus.html</id><summary type="html">&lt;h3&gt;高速巴士概览&lt;/h3&gt;
&lt;p&gt;日本很多巴士同一条线路的不同班次会由不同公司运营，以大阪南纪白滨高速巴士线为例，本次出行，去程 …&lt;/p&gt;</summary><content type="html">&lt;h3&gt;高速巴士概览&lt;/h3&gt;
&lt;p&gt;日本很多巴士同一条线路的不同班次会由不同公司运营，以大阪南纪白滨高速巴士线为例，本次出行，去程乘坐的 JR 巴士，回程是明光巴士&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;需要提前买票，不支持西瓜卡等 IC 卡，网上购票后，上车前给司机看电子票&lt;/li&gt;
&lt;li&gt;巴士中途会在一个叫 Kinokawa Service Area (Southbound) 的服务区停留半个小时，发车前司机会数人数&lt;/li&gt;
&lt;li&gt;巴士上有免费的 WIFI 网络&lt;/li&gt;
&lt;li&gt;巴士干净，乘坐较为舒适&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/01.jpg" width="48.00%" /&gt;&lt;/p&gt;
&lt;p&gt;（去程 JR 巴士）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/02.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;（回程明光巴士）&lt;/p&gt;
&lt;h3&gt;高速巴士运行时刻表&lt;/h3&gt;
&lt;p&gt;链接：&lt;a href="https://meikobus.jp/highway/osaka/"&gt;https://meikobus.jp/highway/osaka/&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;点击上方地址链接进入查看最新时刻表，以下截图仅供说明：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;出发站可以是 “アドベンチャーワールド（环球影城）、大阪駅ＪＲ高速バスターミナル（大阪站）”、ＪＲなんば駅（ＯＣＡＴ）（湊町 OCAT）、りんくうタウン駅（临空城）&lt;/p&gt;
&lt;p&gt;“土休日” 指代周末，“↓” 符号代表本站不停&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;根据运行表，结合出行时间，我选择了 10:10 分在 OCAT 发车（难波站附近）前往白滨的巴士，13:41 到达新湯崎站&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/03.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;h3&gt;线上购票&lt;/h3&gt;
&lt;p&gt;日本高速巴士网：&lt;a href="https://www.kousokubus.net"&gt;https://www.kousokubus.net&lt;/a&gt; （支持中文）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/04.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;点击切换语言后，会跳转到 &lt;a href="https://www.kousokubus.net/JpnBus/zhcn"&gt;https://www.kousokubus.net/JpnBus/zhcn&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/05.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;如上图所示，选择出发地为 “大阪”，去白滨选择 “和歌山”，路线会自动填充为 “大阪 &amp;lt;=&amp;gt; 白滨”&lt;/p&gt;
&lt;p&gt;大阪的出发站可选 “环球影城”、“大阪站”、“湊町 OCAT”、“临空城”，目的地看你住宿酒店的位置，例如 Seamore 酒店旁边就是 “新汤崎站”&lt;/p&gt;
&lt;p&gt;点击查询&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/06.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;灰色即票已售罄，可以看到往返同时购买会便宜 JPY ¥700，如果选择了往返，会让选择回程的车次&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/07.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;同理，点击查询后选择车次，再次选择&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/08.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “请选择座位” 按钮，出来的弹窗选择可选座位&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/09.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;根据实际情况填写乘客信息（邮箱地址要正确填写，会发送支付邮件）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/10.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;确认后进入价格和车次、作为确认页面&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/11.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;预定完成后，等待邮件&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/12.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;收到支付邮件后，点击其中的链接，输入&lt;strong&gt;信用卡&lt;/strong&gt;信息进行支付（不支持其它支付方式）&lt;/p&gt;
&lt;p&gt;支付成功后的页面可以直接查看 PDF 格式的电子车票&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/13.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;忘记保存无需担心，收到的第二封邮件中有电子票据链接；邮件如果丢失，第二张图右上角，也可以补充发送邮件&lt;/p&gt;
&lt;p&gt;按照目前汇率，双人往返 JPY ¥11800 相当于 CNY ¥588，费用不到 JR 黑潮方案的一半&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/14.jpg" width="52.00%" /&gt;&lt;/p&gt;
&lt;h3&gt;示例电子票&lt;/h3&gt;
&lt;p&gt;去程&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/15.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;回程&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/16.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;h3&gt;乘车位置&lt;/h3&gt;
&lt;p&gt;看到 🍠 上有人说 OCAT 不好找，可以从街道上走到图中绿色箭头位置，进到楼里二楼就是 OCAT 的站台&lt;/p&gt;
&lt;p&gt;&lt;img alt="17.jpg" src="https://images.yasking.org/skills/1749175446/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;图中绿色箭头位置，可以看到车展上有 OCAT 的标志&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/18.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;进到楼里有指示牌，提示位置在一楼，OCAT 在二楼&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/19.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;坐斜梯到二层，可以看到显示屏，我要乘坐的 “白滨”（白滨EX大阪5号）车在 8 站台候车，顺带一提，旁边的 9 号站台可以去关西国际机场，车次很多&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/20.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;等待发车&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1749175446/21.jpg" width="78.00%" /&gt;&lt;/p&gt;
&lt;p&gt;巴士很准时，司机会下车验票，把行李仓打开存放物品；如果不熟悉路线，建议多预留一些时间&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kousokubus.net/JpnBus/Content/howtouse_zh-CN.pdf"&gt;https://www.kousokubus.net/JpnBus/Content/howtouse_zh-CN.pdf&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Skill"></category></entry><entry><title>乌鲁木齐・赛里木湖 “778 老哥” 摄影摘选（转载）</title><link href="https://blog.yasking.org/a/photos-reprint-sailumuhu.html" rel="alternate"></link><published>2025-04-09T15:19:00+08:00</published><updated>2025-04-09T15:19:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-04-09:/a/photos-reprint-sailumuhu.html</id><summary type="html">&lt;hr&gt;
&lt;p&gt;之前加了一个北京的技术微信交流群，当然现在已经 “零活跃”&lt;/p&gt;
&lt;p&gt;群里曾经的 “778 老哥” 会分享自己的旅游照片，吃吃喝喝日常，我 …&lt;/p&gt;</summary><content type="html">&lt;hr&gt;
&lt;p&gt;之前加了一个北京的技术微信交流群，当然现在已经 “零活跃”&lt;/p&gt;
&lt;p&gt;群里曾经的 “778 老哥” 会分享自己的旅游照片，吃吃喝喝日常，我觉得拍的很好，收集了一些，转载于此（侵删）&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/photos/1744195503/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/photos/1744195503/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.jpg" src="https://images.yasking.org/photos/1744195503/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/photos/1744195503/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.jpg" src="https://images.yasking.org/photos/1744195503/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/photos/1744195503/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/photos/1744195503/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.jpg" src="https://images.yasking.org/photos/1744195503/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="09.jpg" src="https://images.yasking.org/photos/1744195503/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="10.jpg" src="https://images.yasking.org/photos/1744195503/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="11.jpg" src="https://images.yasking.org/photos/1744195503/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="12.jpg" src="https://images.yasking.org/photos/1744195503/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="13.jpg" src="https://images.yasking.org/photos/1744195503/13.jpg"&gt;&lt;/p&gt;</content><category term="Photos"></category><category term="Photos"></category></entry><entry><title>使用 Restic 来备份重要数据</title><link href="https://blog.yasking.org/a/obsidian-encrypt-backup-with-restic.html" rel="alternate"></link><published>2025-04-03T21:00:00+08:00</published><updated>2025-04-03T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-04-03:/a/obsidian-encrypt-backup-with-restic.html</id><summary type="html">&lt;p&gt;之前使用了相当长一段时间的 Cryptomator 管理内容，它有个好处是本地数据也需要密码才能访问，加密后的内容放到坚果云、Dropbox 等 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;之前使用了相当长一段时间的 Cryptomator 管理内容，它有个好处是本地数据也需要密码才能访问，加密后的内容放到坚果云、Dropbox 等同步盘，每次添加或修改文件后就可以实时上传到网盘&lt;/p&gt;
&lt;p&gt;如果存储的内容是无需编辑的增量文件，平时也主要是增加、替换资源，那我还是很推荐试试 Cryptomator，它很适合保存电子扫描件、图像、表格文档这类资源&lt;/p&gt;
&lt;p&gt;但在 macOS 下，如果你使用 Obsidian 等软件管理知识库，并且有频繁的编辑需求，使用 Cryptomator 解密后的文本内容编辑就很不友好，为了避免出现异常，编辑纯文本文件时，我不得不把它复制出来，编辑后再替换原有文件，这就很有些麻烦&lt;/p&gt;
&lt;p&gt;无意间了解到 &lt;a href="https://github.com/restic/restic"&gt;Restic&lt;/a&gt;，如果你想要对 Obsidian 等笔记软件的 Vault 进行加密备份、上传到网盘、S3 等云平台，那么 Restic 正适合&lt;/p&gt;
&lt;h3&gt;Quick Start&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;安装 Restic&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;macOS&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install restic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;支持主流操作系统，详见：&lt;a href="https://restic.readthedocs.io/en/latest/020_installation.html"&gt;https://restic.readthedocs.io/en/latest/020_installation.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;初始化本地存储库&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;存储库简单来说就是一个文件夹，用来存储加密后的文件，初始化的过程会生成一些元数据&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic init --repo ~/Documents/NoteE2EE
enter password for new repository:
enter password again:
created restic repository 0a40262533 at /Users/xxxxx/Documents/NoteE2EE

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;记住密码，遗忘后加密数据将再无解密途径&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;备份数据&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;执行命令将 &lt;em&gt;~/Note&lt;/em&gt; 文件夹备份到 &lt;em&gt;~/Documents/NoteE2EE&lt;/em&gt; 存储库&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup ~/Documents/Note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;首次运行可以看到他备份的文件和目录数，回显了 “snapshot” 快照的 ID &lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/02.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;命令可以多次运行（每运行一次创建一个快照）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/03.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;因为是增量创建，无需担心快照会占用过大空间&lt;/p&gt;
&lt;p&gt;使用以下命令可以查看存储库中的快照列表&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE snapshots
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个存储库文件夹 “NoteE2EE” 是加密后的内容，可以根据 3-2-1 原则，安全的存放在本地硬盘、移动硬盘、网盘中，无需担心数据泄露&lt;/p&gt;
&lt;h3&gt;备份命令参数优化&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup ~/Documents/Note \
    --pack-size 32 \
    --exclude=&amp;quot;*.tmp&amp;quot; \
    --iexclude=&amp;quot;*.LOG&amp;quot; \
    --limit-upload 1024 \
    --json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;善用 &lt;code&gt;--pack-size&lt;/code&gt; 参数可以有效控制目标文件数量，避免大文件被拆成特别多的小文件，历史文件不会受到影响，只会影响当次增量的备份&lt;/p&gt;
&lt;p&gt;与 &lt;code&gt;--limit-upload&lt;/code&gt; 相对应的，有一个 &lt;code&gt;--limit-download&lt;/code&gt; 参数，用于限制下载速度&lt;/p&gt;
&lt;p&gt;如果基于 Restic 开发一些小工具，那么 &lt;code&gt;--json&lt;/code&gt; 参数很有必要&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:29,&amp;quot;total_bytes&amp;quot;:204482794}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0.2808864315308279,&amp;quot;total_files&amp;quot;:41,&amp;quot;files_done&amp;quot;:13,&amp;quot;total_bytes&amp;quot;:333776710,&amp;quot;bytes_done&amp;quot;:93753349}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:1,&amp;quot;total_files&amp;quot;:41,&amp;quot;files_done&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710,&amp;quot;bytes_done&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;summary&amp;quot;,&amp;quot;files_new&amp;quot;:0,&amp;quot;files_changed&amp;quot;:0,&amp;quot;files_unmodified&amp;quot;:41,&amp;quot;dirs_new&amp;quot;:0,&amp;quot;dirs_changed&amp;quot;:2,&amp;quot;dirs_unmodified&amp;quot;:8,&amp;quot;data_blobs&amp;quot;:0,&amp;quot;tree_blobs&amp;quot;:2,&amp;quot;data_added&amp;quot;:756,&amp;quot;data_added_packed&amp;quot;:608,&amp;quot;total_files_processed&amp;quot;:41,&amp;quot;total_bytes_processed&amp;quot;:333776710,&amp;quot;total_duration&amp;quot;:5.552792709,&amp;quot;backup_start&amp;quot;:&amp;quot;2025-04-02T18:30:04.949151+08:00&amp;quot;,&amp;quot;backup_end&amp;quot;:&amp;quot;2025-04-02T18:30:10.501995+08:00&amp;quot;,&amp;quot;snapshot_id&amp;quot;:&amp;quot;74e465ed71f7fb5b7abb562d4cb9d067f20d89a1a9f3ed4ed32a0bc73e8abab1&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;基于这些数据可以做进度条、展示备份文件的数据量&lt;/p&gt;
&lt;h3&gt;更多 Backends 存储类型&lt;/h3&gt;
&lt;p&gt;通过 &lt;code&gt;restic init --repo ~/Documents/NoteE2EE&lt;/code&gt; 命令，创建了一个本地的存储库&lt;/p&gt;
&lt;p&gt;以下是一个 S3-compatible Storage 兼容 S3 协议存储的示例&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 设置环境变量
$ export AWS_ACCESS_KEY_ID=id7O9M0H****tXJ2romrN
$ export AWS_SECRET_ACCESS_KEY=bFA0dL0u********ndnxVcrwPh31u
$ export AWS_DEFAULT_REGION=cn-east-1

# 初始化存储库并备份
$ restic -r s3:https://s3.bitiful.net/note-e2ee init
$ restic -r s3:https://s3.bitiful.net/note-e2ee --verbose backup ~/Documents/NoteE2EE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：&lt;code&gt;AWS_DEFAULT_REGION&lt;/code&gt; 环境变量不设置默认会使用 &lt;em&gt;us-east-1&lt;/em&gt; 作为默认值&lt;/p&gt;
&lt;p&gt;其它平台和存储例如如 Amazon S3、Backblaze B2、Google Cloud 等，可参考文档：&lt;a href="https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html"&gt;https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;快照管理&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;保留最近的快照&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我们可能定时/定期运行 &lt;code&gt;backup&lt;/code&gt; 进行备份，但过多的备份会让人困扰，运行以下命令只保留最近的 7 个快照&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r [仓库路径] forget --keep-last 7 --prune
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;快照的标签&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;可以在备份的同时指定多个标签（&lt;em&gt;--tag "v1.0" --tag "daily"&lt;/em&gt;）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup --tag &amp;quot;v1.0&amp;quot; ~/Documents/Note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以对已存在的快照标签进行修改&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 追加标签
$ restic -r ~/Documents/NoteE2EE tag --add &amp;quot;important&amp;quot; 8c5c9d50

# 移除标签
$ restic -r ~/Documents/NoteE2EE tag --remove &amp;quot;important&amp;quot; 43547193

# 设置多个标签
$ restic -r ~/Documents/NoteE2EE tag --set &amp;quot;important,project2&amp;quot; a1ff1a78
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;值得注意的是，每次修改后，快照的 ID 会发生变化&lt;/p&gt;
&lt;h3&gt;备份完整性核对&lt;/h3&gt;
&lt;p&gt;存储在网盘上的备份，并不能保证文件百分百不丢失或损毁，通过 check 命令可以进行核对&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/technology/1743676450/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;现在人为“损坏”，例如找到 NoteE2EE 目录内 data 目录下的一个文件，修改文件名，在前方添加一个下划线，模拟文件损坏/丢失&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/05.jpg" width="42.00%" /&gt;&lt;/p&gt;
&lt;p&gt;再次运行 check 命令，提示存储库异常，需要修复，符合预期&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/technology/1743676450/06.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;下载快照到指定目录&lt;/h3&gt;
&lt;p&gt;查看现有快照&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE snapshots
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;导出指定快照&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE restore 5fcd966f --target ~/Downloads/NoteRestore/
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;5fcd966f 为快照 ID，通过 snapshots 命令可以查询到；另外 NoteRestore 目录如果不存在会自动创建&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;当你的存储库很大，只想要导出部分文件、目录，使用以下命令&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE restore 5fcd966f --target ~/Downloads/NoteRestore/ --include Epub电子书
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;其中的「--include Epub电子书」，这个目录是存储库根目录下的一个文件夹&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;此时使用 copy 而非 backup&lt;/h3&gt;
&lt;p&gt;如果你仅有一个加密后的存储库，那么每次备份使用 backup 即可，如果根据 3-2-1 原则备份，存在多个加密后的存储库，那么肯定不适合重复运行 backup 多次提交到不同的存储库&lt;/p&gt;
&lt;p&gt;这时候需要使用 &lt;code&gt;copy&lt;/code&gt;，它会保证严格数据一致性，且性能很好&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic init --repo ~/Documents/NoteE2EE-copy

$ restic -r ~/Documents/NoteE2EE-copy copy --from-repo ~/Documents/NoteE2EE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;来自 AI 的总结（我觉着说的挺好）：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果需要在多个Restic仓库间同步数据，&lt;code&gt;copy&lt;/code&gt; 永远是首选——它像专业的仓库间「数据搬运工」，而 &lt;code&gt;backup&lt;/code&gt; 则是面向原始数据的「采集器」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;不妨试试 Restic Brower&lt;/h3&gt;
&lt;p&gt;如果你不是很喜欢命令行操作，那么可以试试这个开源小工具：&lt;a href="https://github.com/emuell/restic-browser"&gt;emuell/restic-browser&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/technology/1743676450/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;使用 Rust + TypeScript 开发，只有几兆大小，只有只读功能，正如工具名中的 “Brower”，可以浏览加密后的存储库，再从快照中翻文件的时候会方便些&lt;/p&gt;
&lt;h3&gt;可能你也需要 Autorestic&lt;/h3&gt;
&lt;p&gt;文档地址：&lt;a href="https://autorestic.vercel.app/"&gt;Autorestic&lt;/a&gt; &lt;a href="https://autorestic.vercel.app/quick"&gt;Quick Start&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Autorestic is a wrapper around the amazing &lt;a href="https://restic.net/"&gt;restic&lt;/a&gt;. While being amazing the restic cli can be a bit overwhelming and difficult to manage if you have many different location that you want to backup to multiple locations. This utility is aimed at making this easier 🙂&lt;/p&gt;
&lt;p&gt;Autorestic 是基于卓越的 restic 工具开发的封装器。尽管 restic 命令行工具本身非常出色，但当您需要将多个不同位置的备份数据同步至多个存储目标时，其操作可能会显得复杂且难以管理。本工具旨在简化这一流程，让多目标备份管理变得更加轻松便捷。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;安装&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install autorestic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;配置文件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;创建配置文件，内容如下&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;version: 2
backends:
  note_primary:
    type: local
    path: &amp;quot;~/Documents/NoteE2EE&amp;quot;
    env:
      RESTIC_PASSWORD: &amp;quot;your-restic-vault-passowrd&amp;quot;
  note_backup:
    type: local
    path: &amp;quot;~/Documents/NoteE2EE-copy&amp;quot;
    env:
      RESTIC_PASSWORD: &amp;quot;your-restic-vault-passowrd&amp;quot;

locations:
  notes:
    from: &amp;quot;~/Documents/Note&amp;quot;
    to:
      - note_primary
      - note_backup
    options:
      forget:
        keep-last: 7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改配置文件权限（建议）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ chmod 600 ~/.autorestic.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Location 与 Backend&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 Autorestic 中，Location 描述了备份的内容和目标（from / to），Backend 定义了备份的目标&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;配置检验&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/08.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Everything is fine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;手动执行备份&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;全部备份&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic backup -a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;特定 Location 备份&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic backup -l notes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/09.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;目前这个方案很切合我的需求，且足够易用，后续使用一段时间有补充再更新&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://restic.readthedocs.io/en/stable/"&gt;Restic Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://autorestic.vercel.app/quick"&gt;Autorestic Quick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Software"></category></entry><entry><title>Backing Up Important Data with Restic</title><link href="https://blog.yasking.org/en/a/obsidian-encrypt-backup-with-restic.html" rel="alternate"></link><published>2025-04-03T21:00:00+08:00</published><updated>2025-04-03T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-04-03:/en/a/obsidian-encrypt-backup-with-restic.html</id><summary type="html">&lt;p&gt;I had been using Cryptomator for quite a long time to manage my content. Its advantage is that local data also requires a password to access. After encryption, the content can be placed on sync drives like Nutstore, Dropbox, etc., and uploaded to the cloud in real-time after each file …&lt;/p&gt;</summary><content type="html">&lt;p&gt;I had been using Cryptomator for quite a long time to manage my content. Its advantage is that local data also requires a password to access. After encryption, the content can be placed on sync drives like Nutstore, Dropbox, etc., and uploaded to the cloud in real-time after each file addition or modification.&lt;/p&gt;
&lt;p&gt;If you're storing content that doesn't need editing and you mainly add or replace resources, I would still highly recommend trying Cryptomator. It's well-suited for saving electronic scans, images, and spreadsheet documents.&lt;/p&gt;
&lt;p&gt;However, on macOS, if you use software like Obsidian to manage your knowledge base and frequently need to edit content, editing text files after decrypting with Cryptomator becomes quite unfriendly. To avoid issues, when editing plain text files, I had to copy them out, edit them, and then replace the original files, which was quite cumbersome.&lt;/p&gt;
&lt;p&gt;I happened to learn about &lt;a href="https://github.com/restic/restic"&gt;Restic&lt;/a&gt;. If you want to encrypt and backup your Obsidian or other note-taking software vaults and upload them to cloud drives or S3-compatible platforms, then Restic is perfect for that.&lt;/p&gt;
&lt;h3&gt;Quick Start&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Installing Restic&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;macOS&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install restic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It supports mainstream operating systems. For details, see: &lt;a href="https://restic.readthedocs.io/en/latest/020_installation.html"&gt;https://restic.readthedocs.io/en/latest/020_installation.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Initializing a Local Repository&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Simply put, a repository is a folder for storing encrypted files. The initialization process generates some metadata.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic init --repo ~/Documents/NoteE2EE
enter password for new repository:
enter password again:
created restic repository 0a40262533 at /Users/xxxxx/Documents/NoteE2EE

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember your password. Once forgotten, there's no way to decrypt the data.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Backing Up Data&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Execute the command to back up the &lt;em&gt;~/Note&lt;/em&gt; folder to the &lt;em&gt;~/Documents/NoteE2EE&lt;/em&gt; repository.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup ~/Documents/Note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the first run, you can see the number of files and directories backed up, and the "snapshot" ID is displayed.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/02.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;The command can be run multiple times (each run creates a snapshot).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/03.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;Since it creates incremental backups, you don't need to worry about snapshots taking up too much space.&lt;/p&gt;
&lt;p&gt;Use the following command to view the list of snapshots in the repository:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE snapshots
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This repository folder "NoteE2EE" contains encrypted content. Following the 3-2-1 principle, it can be safely stored on local hard drives, external drives, and cloud storage without worrying about data leaks.&lt;/p&gt;
&lt;h3&gt;Optimizing Backup Command Parameters&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup ~/Documents/Note \
    --pack-size 32 \
    --exclude=&amp;quot;*.tmp&amp;quot; \
    --iexclude=&amp;quot;*.LOG&amp;quot; \
    --limit-upload 1024 \
    --json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Good use of the &lt;code&gt;--pack-size&lt;/code&gt; parameter can effectively control the number of target files, preventing large files from being split into too many small files. Historical files won't be affected; it only impacts the current incremental backup.&lt;/p&gt;
&lt;p&gt;Corresponding to &lt;code&gt;--limit-upload&lt;/code&gt;, there's a &lt;code&gt;--limit-download&lt;/code&gt; parameter for limiting download speed.&lt;/p&gt;
&lt;p&gt;If you're developing small tools based on Restic, the &lt;code&gt;--json&lt;/code&gt; parameter is quite necessary:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:29,&amp;quot;total_bytes&amp;quot;:204482794}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0.2808864315308279,&amp;quot;total_files&amp;quot;:41,&amp;quot;files_done&amp;quot;:13,&amp;quot;total_bytes&amp;quot;:333776710,&amp;quot;bytes_done&amp;quot;:93753349}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:1,&amp;quot;total_files&amp;quot;:41,&amp;quot;files_done&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710,&amp;quot;bytes_done&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;summary&amp;quot;,&amp;quot;files_new&amp;quot;:0,&amp;quot;files_changed&amp;quot;:0,&amp;quot;files_unmodified&amp;quot;:41,&amp;quot;dirs_new&amp;quot;:0,&amp;quot;dirs_changed&amp;quot;:2,&amp;quot;dirs_unmodified&amp;quot;:8,&amp;quot;data_blobs&amp;quot;:0,&amp;quot;tree_blobs&amp;quot;:2,&amp;quot;data_added&amp;quot;:756,&amp;quot;data_added_packed&amp;quot;:608,&amp;quot;total_files_processed&amp;quot;:41,&amp;quot;total_bytes_processed&amp;quot;:333776710,&amp;quot;total_duration&amp;quot;:5.552792709,&amp;quot;backup_start&amp;quot;:&amp;quot;2025-04-02T18:30:04.949151+08:00&amp;quot;,&amp;quot;backup_end&amp;quot;:&amp;quot;2025-04-02T18:30:10.501995+08:00&amp;quot;,&amp;quot;snapshot_id&amp;quot;:&amp;quot;74e465ed71f7fb5b7abb562d4cb9d067f20d89a1a9f3ed4ed32a0bc73e8abab1&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Based on this data, you can create progress bars and display the volume of backed-up files.&lt;/p&gt;
&lt;h3&gt;More Backend Storage Types&lt;/h3&gt;
&lt;p&gt;Using the command &lt;code&gt;restic init --repo ~/Documents/NoteE2EE&lt;/code&gt;, we created a local repository.&lt;/p&gt;
&lt;p&gt;Below is an example of an S3-compatible storage:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# Setting environment variables
$ export AWS_ACCESS_KEY_ID=id7O9M0H****tXJ2romrN
$ export AWS_SECRET_ACCESS_KEY=bFA0dL0u********ndnxVcrwPh31u
$ export AWS_DEFAULT_REGION=cn-east-1

# Initializing repository and backup
$ restic -r s3:https://s3.bitiful.net/note-e2ee init
$ restic -r s3:https://s3.bitiful.net/note-e2ee --verbose backup ~/Documents/NoteE2EE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: If the &lt;code&gt;AWS_DEFAULT_REGION&lt;/code&gt; environment variable is not set, &lt;em&gt;us-east-1&lt;/em&gt; will be used as the default value.&lt;/p&gt;
&lt;p&gt;For other platforms and storage options like Amazon S3, Backblaze B2, Google Cloud, etc., refer to the documentation: &lt;a href="https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html"&gt;https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Snapshot Management&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Keeping Recent Snapshots&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We might run &lt;code&gt;backup&lt;/code&gt; on a schedule, but too many backups can be overwhelming. Run the following command to keep only the 7 most recent snapshots:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r [repository path] forget --keep-last 7 --prune
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Snapshot Tags&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can specify multiple tags when backing up (&lt;em&gt;--tag "v1.0" --tag "daily"&lt;/em&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup --tag &amp;quot;v1.0&amp;quot; ~/Documents/Note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also modify tags for existing snapshots:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# Add a tag
$ restic -r ~/Documents/NoteE2EE tag --add &amp;quot;important&amp;quot; 8c5c9d50

# Remove a tag
$ restic -r ~/Documents/NoteE2EE tag --remove &amp;quot;important&amp;quot; 43547193

# Set multiple tags
$ restic -r ~/Documents/NoteE2EE tag --set &amp;quot;important,project2&amp;quot; a1ff1a78
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's worth noting that after each modification, the snapshot ID will change.&lt;/p&gt;
&lt;h3&gt;Verifying Backup Integrity&lt;/h3&gt;
&lt;p&gt;Backups stored in the cloud can't guarantee 100% file preservation or prevent damage. You can verify integrity using the check command:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/technology/1743676450/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Now let's simulate "damage". For example, find a file in the data directory within the NoteE2EE directory, modify its filename by adding an underscore at the beginning to simulate file damage/loss.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/05.jpg" width="42.00%" /&gt;&lt;/p&gt;
&lt;p&gt;Running the check command again shows that the repository is abnormal and needs repair, which is expected.&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/technology/1743676450/06.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;Restoring Snapshots to a Specific Directory&lt;/h3&gt;
&lt;p&gt;View existing snapshots:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE snapshots
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Export a specific snapshot:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE restore 5fcd966f --target ~/Downloads/NoteRestore/
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;5fcd966f is the snapshot ID, which can be found using the snapshots command; additionally, the NoteRestore directory will be created automatically if it doesn't exist.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If your repository is large and you only want to export certain files or directories, use the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE restore 5fcd966f --target ~/Downloads/NoteRestore/ --include Epub电子书
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;In this case, "--include Epub电子书" refers to a folder in the root directory of the repository.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Using "copy" Instead of "backup"&lt;/h3&gt;
&lt;p&gt;If you only have one encrypted repository, using backup each time works fine. However, if you follow the 3-2-1 principle for backups and have multiple encrypted repositories, running backup multiple times to different repositories is inefficient.&lt;/p&gt;
&lt;p&gt;In this case, you need to use &lt;code&gt;copy&lt;/code&gt;, which ensures strict data consistency and performs well:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic init --repo ~/Documents/NoteE2EE-copy

$ restic -r ~/Documents/NoteE2EE-copy copy --from-repo ~/Documents/NoteE2EE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From an AI summary (which I think is quite good):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you need to synchronize data between multiple Restic repositories, &lt;code&gt;copy&lt;/code&gt; is always the preferred choice—it acts like a professional "data mover" between repositories, while &lt;code&gt;backup&lt;/code&gt; is like a "collector" for original data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Give Restic Browser a Try&lt;/h3&gt;
&lt;p&gt;If you're not a fan of command-line operations, you can try this open-source tool: &lt;a href="https://github.com/emuell/restic-browser"&gt;emuell/restic-browser&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/technology/1743676450/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Developed with Rust + TypeScript, it's only a few megabytes in size and has read-only functionality. As the name "Browser" suggests, it allows you to browse encrypted repositories and makes it more convenient to look for files in snapshots.&lt;/p&gt;
&lt;h3&gt;You Might Also Need Autorestic&lt;/h3&gt;
&lt;p&gt;Documentation: &lt;a href="https://autorestic.vercel.app/"&gt;Autorestic&lt;/a&gt; &lt;a href="https://autorestic.vercel.app/quick"&gt;Quick Start&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Autorestic is a wrapper around the amazing &lt;a href="https://restic.net/"&gt;restic&lt;/a&gt;. While being amazing the restic cli can be a bit overwhelming and difficult to manage if you have many different location that you want to backup to multiple locations. This utility is aimed at making this easier 🙂&lt;/p&gt;
&lt;p&gt;Autorestic is a wrapper developed around the excellent restic tool. Although the restic command-line tool itself is outstanding, when you need to synchronize backup data from multiple different locations to multiple storage targets, its operation can seem complex and difficult to manage. This tool aims to simplify this process, making multi-target backup management easier and more convenient.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install autorestic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Configuration File&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Create a configuration file with the following content:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;version: 2
backends:
  note_primary:
    type: local
    path: &amp;quot;~/Documents/NoteE2EE&amp;quot;
    env:
      RESTIC_PASSWORD: &amp;quot;your-restic-vault-passowrd&amp;quot;
  note_backup:
    type: local
    path: &amp;quot;~/Documents/NoteE2EE-copy&amp;quot;
    env:
      RESTIC_PASSWORD: &amp;quot;your-restic-vault-passowrd&amp;quot;

locations:
  notes:
    from: &amp;quot;~/Documents/Note&amp;quot;
    to:
      - note_primary
      - note_backup
    options:
      forget:
        keep-last: 7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Change the configuration file permissions (recommended):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ chmod 600 ~/.autorestic.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Locations and Backends&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In Autorestic, Location describes the backup content and target (from / to), and Backend defines the backup destination.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Configuration Verification&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/08.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Everything is fine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Manual Backup Execution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Complete backup:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic backup -a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Specific Location backup:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic backup -l notes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/09.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;Currently, this solution perfectly fits my needs and is easy to use. I'll update this post with any additional information after using it for a while.&lt;/p&gt;
&lt;h3&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://restic.readthedocs.io/en/stable/"&gt;Restic Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://autorestic.vercel.app/quick"&gt;Autorestic Quick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Software"></category></entry><entry><title>Sauvegarder des données importantes avec Restic</title><link href="https://blog.yasking.org/fr/a/obsidian-encrypt-backup-with-restic.html" rel="alternate"></link><published>2025-04-03T21:00:00+08:00</published><updated>2025-04-03T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-04-03:/fr/a/obsidian-encrypt-backup-with-restic.html</id><summary type="html">&lt;p&gt;J'ai utilisé Cryptomator pendant assez longtemps pour gérer mes contenus. Son avantage est que les données locales nécessitent également un mot de passe pour y accéder. Une fois chiffrées, ces données peuvent être synchronisées vers Nutstore, Dropbox ou d'autres services cloud, avec un téléversement en temps réel après chaque modification …&lt;/p&gt;</summary><content type="html">&lt;p&gt;J'ai utilisé Cryptomator pendant assez longtemps pour gérer mes contenus. Son avantage est que les données locales nécessitent également un mot de passe pour y accéder. Une fois chiffrées, ces données peuvent être synchronisées vers Nutstore, Dropbox ou d'autres services cloud, avec un téléversement en temps réel après chaque modification.&lt;/p&gt;
&lt;p&gt;Si vous stockez des fichiers qui ne nécessitent pas d'édition fréquente et que vous ajoutez ou remplacez principalement des ressources, je recommande vivement Cryptomator. Il est idéal pour sauvegarder des documents numérisés, des images et des tableaux.&lt;/p&gt;
&lt;p&gt;Cependant, sous macOS, si vous utilisez des logiciels comme Obsidian pour gérer votre base de connaissances et que vous modifiez fréquemment vos fichiers, l'édition de texte avec Cryptomator devient peu pratique. Pour éviter les problèmes, je devais copier le contenu, le modifier, puis remplacer le fichier original, ce qui était assez fastidieux.&lt;/p&gt;
&lt;p&gt;J'ai découvert par hasard &lt;a href="https://github.com/restic/restic"&gt;Restic&lt;/a&gt;. Si vous souhaitez sauvegarder et chiffrer votre coffre-fort Obsidian pour l'envoyer vers un cloud ou une plateforme S3, Restic est parfaitement adapté.&lt;/p&gt;
&lt;h3&gt;Quick Start&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Installation de Restic&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;macOS&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install restic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Compatible avec la plupart des systèmes d'exploitation, voir : &lt;a href="https://restic.readthedocs.io/en/latest/020_installation.html"&gt;https://restic.readthedocs.io/en/latest/020_installation.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Initialisation d'un dépôt local&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Un dépôt est simplement un dossier qui stocke vos fichiers chiffrés. L'initialisation crée des métadonnées nécessaires.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic init --repo ~/Documents/NoteE2EE
enter password for new repository:
enter password again:
created restic repository 0a40262533 at /Users/xxxxx/Documents/NoteE2EE

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;N'oubliez pas votre mot de passe, car les données chiffrées seront irrécupérables en cas d'oubli.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sauvegarde des données&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Exécutez cette commande pour sauvegarder le dossier &lt;em&gt;~/Note&lt;/em&gt; dans le dépôt &lt;em&gt;~/Documents/NoteE2EE&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup ~/Documents/Note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;À la première exécution, vous verrez le nombre de fichiers et répertoires sauvegardés, ainsi que l'ID du "snapshot" (instantané) créé.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/02.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;La commande peut être exécutée plusieurs fois (chaque exécution crée un nouveau snapshot)&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/03.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;Comme les sauvegardes sont incrémentielles, ne vous inquiétez pas de l'espace disque.&lt;/p&gt;
&lt;p&gt;Utilisez cette commande pour afficher la liste des snapshots dans le dépôt:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE snapshots
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Le dossier "NoteE2EE" contient vos données chiffrées. Vous pouvez le stocker en toute sécurité sur votre disque dur local, un disque externe ou un cloud, selon le principe 3-2-1, sans craindre de fuites de données.&lt;/p&gt;
&lt;h3&gt;Optimisation des paramètres de sauvegarde&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup ~/Documents/Note \
    --pack-size 32 \
    --exclude=&amp;quot;*.tmp&amp;quot; \
    --iexclude=&amp;quot;*.LOG&amp;quot; \
    --limit-upload 1024 \
    --json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;L'option &lt;code&gt;--pack-size&lt;/code&gt; permet de contrôler efficacement le nombre de fichiers cibles, évitant que les gros fichiers ne soient divisés en trop de petits fichiers. Les fichiers historiques ne sont pas affectés, seule la sauvegarde incrémentielle actuelle l'est.&lt;/p&gt;
&lt;p&gt;En complément de &lt;code&gt;--limit-upload&lt;/code&gt;, il existe un paramètre &lt;code&gt;--limit-download&lt;/code&gt; pour limiter la vitesse de téléchargement.&lt;/p&gt;
&lt;p&gt;Si vous développez des outils basés sur Restic, le paramètre &lt;code&gt;--json&lt;/code&gt; est très utile:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:29,&amp;quot;total_bytes&amp;quot;:204482794}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0.2808864315308279,&amp;quot;total_files&amp;quot;:41,&amp;quot;files_done&amp;quot;:13,&amp;quot;total_bytes&amp;quot;:333776710,&amp;quot;bytes_done&amp;quot;:93753349}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:1,&amp;quot;total_files&amp;quot;:41,&amp;quot;files_done&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710,&amp;quot;bytes_done&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;summary&amp;quot;,&amp;quot;files_new&amp;quot;:0,&amp;quot;files_changed&amp;quot;:0,&amp;quot;files_unmodified&amp;quot;:41,&amp;quot;dirs_new&amp;quot;:0,&amp;quot;dirs_changed&amp;quot;:2,&amp;quot;dirs_unmodified&amp;quot;:8,&amp;quot;data_blobs&amp;quot;:0,&amp;quot;tree_blobs&amp;quot;:2,&amp;quot;data_added&amp;quot;:756,&amp;quot;data_added_packed&amp;quot;:608,&amp;quot;total_files_processed&amp;quot;:41,&amp;quot;total_bytes_processed&amp;quot;:333776710,&amp;quot;total_duration&amp;quot;:5.552792709,&amp;quot;backup_start&amp;quot;:&amp;quot;2025-04-02T18:30:04.949151+08:00&amp;quot;,&amp;quot;backup_end&amp;quot;:&amp;quot;2025-04-02T18:30:10.501995+08:00&amp;quot;,&amp;quot;snapshot_id&amp;quot;:&amp;quot;74e465ed71f7fb5b7abb562d4cb9d067f20d89a1a9f3ed4ed32a0bc73e8abab1&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ces données permettent de créer des barres de progression et d'afficher le volume des fichiers sauvegardés.&lt;/p&gt;
&lt;h3&gt;Plus de types de stockage (Backends)&lt;/h3&gt;
&lt;p&gt;La commande &lt;code&gt;restic init --repo ~/Documents/NoteE2EE&lt;/code&gt; a créé un dépôt local.&lt;/p&gt;
&lt;p&gt;Voici un exemple pour un stockage compatible S3:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# Configuration des variables d'environnement
$ export AWS_ACCESS_KEY_ID=id7O9M0H****tXJ2romrN
$ export AWS_SECRET_ACCESS_KEY=bFA0dL0u********ndnxVcrwPh31u
$ export AWS_DEFAULT_REGION=cn-east-1

# Initialisation du dépôt et sauvegarde
$ restic -r s3:https://s3.bitiful.net/note-e2ee init
$ restic -r s3:https://s3.bitiful.net/note-e2ee --verbose backup ~/Documents/NoteE2EE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: Si la variable &lt;code&gt;AWS_DEFAULT_REGION&lt;/code&gt; n'est pas définie, &lt;em&gt;us-east-1&lt;/em&gt; sera utilisé par défaut.&lt;/p&gt;
&lt;p&gt;Pour d'autres plateformes comme Amazon S3, Backblaze B2, Google Cloud, consultez: &lt;a href="https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html"&gt;https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Gestion des snapshots&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Conservation des snapshots récents&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Si vous exécutez &lt;code&gt;backup&lt;/code&gt; régulièrement, vous pouvez avoir trop de sauvegardes. Cette commande permet de ne conserver que les 7 derniers snapshots:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r [chemin_du_dépôt] forget --keep-last 7 --prune
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Étiquettes de snapshot&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Vous pouvez spécifier plusieurs étiquettes lors de la sauvegarde (&lt;em&gt;--tag "v1.0" --tag "daily"&lt;/em&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup --tag &amp;quot;v1.0&amp;quot; ~/Documents/Note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Vous pouvez également modifier les étiquettes des snapshots existants:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# Ajouter une étiquette
$ restic -r ~/Documents/NoteE2EE tag --add &amp;quot;important&amp;quot; 8c5c9d50

# Supprimer une étiquette
$ restic -r ~/Documents/NoteE2EE tag --remove &amp;quot;important&amp;quot; 43547193

# Définir plusieurs étiquettes
$ restic -r ~/Documents/NoteE2EE tag --set &amp;quot;important,project2&amp;quot; a1ff1a78
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notez que l'ID du snapshot change après chaque modification.&lt;/p&gt;
&lt;h3&gt;Vérification de l'intégrité des sauvegardes&lt;/h3&gt;
&lt;p&gt;Les sauvegardes stockées sur le cloud ne sont pas garanties à 100% contre la perte ou la corruption. La commande check permet de vérifier l'intégrité:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/technology/1743676450/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Simulons maintenant une "corruption" en modifiant le nom d'un fichier dans le répertoire data de NoteE2EE, en ajoutant un underscore au début pour simuler une perte ou corruption:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/05.jpg" width="42.00%" /&gt;&lt;/p&gt;
&lt;p&gt;En exécutant à nouveau la commande check, un message indique que le dépôt est anormal et nécessite une réparation, comme prévu:&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/technology/1743676450/06.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;Restauration d'un snapshot dans un répertoire spécifique&lt;/h3&gt;
&lt;p&gt;Visualisation des snapshots existants:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE snapshots
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exportation d'un snapshot spécifique:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE restore 5fcd966f --target ~/Downloads/NoteRestore/
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;5fcd966f est l'ID du snapshot, que vous pouvez trouver avec la commande snapshots. Le répertoire NoteRestore sera créé automatiquement s'il n'existe pas.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Si votre dépôt est volumineux et que vous souhaitez restaurer uniquement certains fichiers ou dossiers:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE restore 5fcd966f --target ~/Downloads/NoteRestore/ --include Epub电子书
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;"Epub电子书" est un dossier situé à la racine du dépôt.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Utiliser copy plutôt que backup&lt;/h3&gt;
&lt;p&gt;Si vous n'avez qu'un seul dépôt chiffré, utilisez simplement backup à chaque fois. Mais si vous suivez le principe 3-2-1 avec plusieurs dépôts chiffrés, il n'est pas efficace d'exécuter backup plusieurs fois vers différents dépôts.&lt;/p&gt;
&lt;p&gt;Dans ce cas, utilisez &lt;code&gt;copy&lt;/code&gt;, qui garantit une cohérence stricte des données avec d'excellentes performances:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic init --repo ~/Documents/NoteE2EE-copy

$ restic -r ~/Documents/NoteE2EE-copy copy --from-repo ~/Documents/NoteE2EE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Résumé de l'IA (que je trouve pertinent):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Si vous devez synchroniser des données entre plusieurs dépôts Restic, &lt;code&gt;copy&lt;/code&gt; est toujours le meilleur choix — il fonctionne comme un "transporteur de données" professionnel entre dépôts, tandis que &lt;code&gt;backup&lt;/code&gt; est un "collecteur" orienté vers les données brutes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Essayez Restic Browser&lt;/h3&gt;
&lt;p&gt;Si vous n'aimez pas les opérations en ligne de commande, essayez cet outil open source: &lt;a href="https://github.com/emuell/restic-browser"&gt;emuell/restic-browser&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/technology/1743676450/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Développé avec Rust + TypeScript, il ne pèse que quelques mégaoctets et offre uniquement des fonctions de lecture. Comme son nom "Browser" l'indique, il permet de parcourir les dépôts chiffrés et facilite la recherche de fichiers dans les snapshots.&lt;/p&gt;
&lt;h3&gt;Vous pourriez aussi avoir besoin d'Autorestic&lt;/h3&gt;
&lt;p&gt;Documentation: &lt;a href="https://autorestic.vercel.app/"&gt;Autorestic&lt;/a&gt; &lt;a href="https://autorestic.vercel.app/quick"&gt;Quick Start&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Autorestic est un wrapper autour de l'étonnant &lt;a href="https://restic.net/"&gt;restic&lt;/a&gt;. Bien qu'étant remarquable, l'interface en ligne de commande de restic peut être un peu intimidante et difficile à gérer si vous avez plusieurs emplacements différents que vous souhaitez sauvegarder vers plusieurs destinations. Cet utilitaire vise à faciliter ce processus 🙂&lt;/p&gt;
&lt;p&gt;Autorestic est un wrapper développé autour de l'excellent outil restic. Bien que l'outil en ligne de commande restic soit exceptionnel, il peut devenir complexe et difficile à gérer lorsque vous devez synchroniser des sauvegardes de plusieurs emplacements vers différentes destinations. Cet utilitaire vise à simplifier ce processus, rendant la gestion des sauvegardes multi-cibles plus facile et plus agréable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install autorestic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Fichier de configuration&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Créez un fichier de configuration avec le contenu suivant:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;version: 2
backends:
  note_primary:
    type: local
    path: &amp;quot;~/Documents/NoteE2EE&amp;quot;
    env:
      RESTIC_PASSWORD: &amp;quot;your-restic-vault-passowrd&amp;quot;
  note_backup:
    type: local
    path: &amp;quot;~/Documents/NoteE2EE-copy&amp;quot;
    env:
      RESTIC_PASSWORD: &amp;quot;your-restic-vault-passowrd&amp;quot;

locations:
  notes:
    from: &amp;quot;~/Documents/Note&amp;quot;
    to:
      - note_primary
      - note_backup
    options:
      forget:
        keep-last: 7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Modifiez les permissions du fichier de configuration (recommandé):&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ chmod 600 ~/.autorestic.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Location et Backend&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dans Autorestic, Location décrit le contenu et la destination de la sauvegarde (from / to), tandis que Backend définit la destination de sauvegarde.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Vérification de la configuration&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/08.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Everything is fine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Exécution manuelle de la sauvegarde&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sauvegarde complète:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic backup -a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sauvegarde d'une Location spécifique:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic backup -l notes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sortie:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/09.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;Cette solution répond parfaitement à mes besoins actuels et est suffisamment facile à utiliser. Je mettrai à jour cet article après l'avoir utilisée pendant un certain temps si j'ai des compléments à ajouter.&lt;/p&gt;
&lt;h3&gt;Références&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://restic.readthedocs.io/en/stable/"&gt;Restic Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://autorestic.vercel.app/quick"&gt;Autorestic Quick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Software"></category></entry><entry><title>Resticで重要なデータをバックアップする</title><link href="https://blog.yasking.org/ja/a/obsidian-encrypt-backup-with-restic.html" rel="alternate"></link><published>2025-04-03T21:00:00+08:00</published><updated>2025-04-03T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-04-03:/ja/a/obsidian-encrypt-backup-with-restic.html</id><summary type="html">&lt;p&gt;以前はかなり長い間、Cryptomatorを使ってコンテンツを管理していました。Cryptomatorの利点は、ローカルデータにアクセスするにもパスワードが必要なことです。暗号化されたコンテン …&lt;/p&gt;</summary><content type="html">&lt;p&gt;以前はかなり長い間、Cryptomatorを使ってコンテンツを管理していました。Cryptomatorの利点は、ローカルデータにアクセスするにもパスワードが必要なことです。暗号化されたコンテンツはNutstore、Dropboxなどの同期ドライブに置いておけば、ファイルを追加または変更するたびにリアルタイムでクラウドにアップロードできます。&lt;/p&gt;
&lt;p&gt;保存するコンテンツが編集する必要のない増分ファイルで、主に追加・置換するだけなら、私はCryptomatorを試すことを強くお勧めします。電子スキャン、画像、スプレッドシートなどのリソースを保存するのに適しています。&lt;/p&gt;
&lt;p&gt;しかし、macOSでObsidianなどのソフトウェアを使って知識ベースを管理し、頻繁に編集する必要がある場合、Cryptomatorで復号化した後のテキストファイルの編集は非常に不便です。問題を避けるために、プレーンテキストファイルを編集するときは、コピーして編集した後、元のファイルを置き換える必要がありました。これはかなり面倒です。&lt;/p&gt;
&lt;p&gt;偶然、&lt;a href="https://github.com/restic/restic"&gt;Restic&lt;/a&gt;について知りました。ObsidianなどのノートソフトウェアのVaultを暗号化してバックアップし、クラウドドライブやS3などのクラウドプラットフォームにアップロードしたい場合、Resticが最適です。&lt;/p&gt;
&lt;h3&gt;クイックスタート&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Resticのインストール&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;macOS&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install restic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;主要なオペレーティングシステムをサポートしています。詳細は：&lt;a href="https://restic.readthedocs.io/en/latest/020_installation.html"&gt;https://restic.readthedocs.io/en/latest/020_installation.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ローカルリポジトリの初期化&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;リポジトリは簡単に言えば、暗号化されたファイルを保存するためのフォルダです。初期化プロセスでは、いくつかのメタデータが生成されます。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic init --repo ~/Documents/NoteE2EE
enter password for new repository:
enter password again:
created restic repository 0a40262533 at /Users/xxxxx/Documents/NoteE2EE

Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;パスワードを覚えておいてください。一度忘れると、暗号化されたデータを復号化する方法はなくなります。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/01.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;データのバックアップ&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;コマンドを実行して、&lt;em&gt;~/Note&lt;/em&gt;フォルダを&lt;em&gt;~/Documents/NoteE2EE&lt;/em&gt;リポジトリにバックアップします。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup ~/Documents/Note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;初回実行時には、バックアップされたファイルとディレクトリの数が表示され、「スナップショット」IDがエコーされます。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/02.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;コマンドは複数回実行できます（実行するたびに新しいスナップショットが作成されます）。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/03.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;増分バックアップなので、スナップショットが大量のスペースを占めることを心配する必要はありません。&lt;/p&gt;
&lt;p&gt;以下のコマンドを使用して、リポジトリ内のスナップショットリストを表示できます。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE snapshots
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このリポジトリフォルダ「NoteE2EE」は暗号化されたコンテンツです。3-2-1原則に従って、ローカルディスク、外部ディスク、クラウドドライブに安全に保存でき、データ漏洩を心配する必要はありません。&lt;/p&gt;
&lt;h3&gt;バックアップコマンドパラメータの最適化&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup ~/Documents/Note \
    --pack-size 32 \
    --exclude=&amp;quot;*.tmp&amp;quot; \
    --iexclude=&amp;quot;*.LOG&amp;quot; \
    --limit-upload 1024 \
    --json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;--pack-size&lt;/code&gt;パラメータを上手く使用すると、ターゲットファイルの数を効果的に制御でき、大きなファイルが多くの小さなファイルに分割されるのを防ぎます。履歴ファイルは影響を受けず、現在の増分バックアップにのみ影響します。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--limit-upload&lt;/code&gt;に対応して、ダウンロード速度を制限するための&lt;code&gt;--limit-download&lt;/code&gt;パラメータもあります。&lt;/p&gt;
&lt;p&gt;Resticをベースに小さなツールを開発する場合は、&lt;code&gt;--json&lt;/code&gt;パラメータが非常に重要です。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:29,&amp;quot;total_bytes&amp;quot;:204482794}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0,&amp;quot;total_files&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:0.2808864315308279,&amp;quot;total_files&amp;quot;:41,&amp;quot;files_done&amp;quot;:13,&amp;quot;total_bytes&amp;quot;:333776710,&amp;quot;bytes_done&amp;quot;:93753349}
{&amp;quot;message_type&amp;quot;:&amp;quot;status&amp;quot;,&amp;quot;percent_done&amp;quot;:1,&amp;quot;total_files&amp;quot;:41,&amp;quot;files_done&amp;quot;:41,&amp;quot;total_bytes&amp;quot;:333776710,&amp;quot;bytes_done&amp;quot;:333776710}
{&amp;quot;message_type&amp;quot;:&amp;quot;summary&amp;quot;,&amp;quot;files_new&amp;quot;:0,&amp;quot;files_changed&amp;quot;:0,&amp;quot;files_unmodified&amp;quot;:41,&amp;quot;dirs_new&amp;quot;:0,&amp;quot;dirs_changed&amp;quot;:2,&amp;quot;dirs_unmodified&amp;quot;:8,&amp;quot;data_blobs&amp;quot;:0,&amp;quot;tree_blobs&amp;quot;:2,&amp;quot;data_added&amp;quot;:756,&amp;quot;data_added_packed&amp;quot;:608,&amp;quot;total_files_processed&amp;quot;:41,&amp;quot;total_bytes_processed&amp;quot;:333776710,&amp;quot;total_duration&amp;quot;:5.552792709,&amp;quot;backup_start&amp;quot;:&amp;quot;2025-04-02T18:30:04.949151+08:00&amp;quot;,&amp;quot;backup_end&amp;quot;:&amp;quot;2025-04-02T18:30:10.501995+08:00&amp;quot;,&amp;quot;snapshot_id&amp;quot;:&amp;quot;74e465ed71f7fb5b7abb562d4cb9d067f20d89a1a9f3ed4ed32a0bc73e8abab1&amp;quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このデータに基づいて、進捗バーを作成したり、バックアップファイルのデータ量を表示したりできます。&lt;/p&gt;
&lt;h3&gt;その他のバックエンドストレージタイプ&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;restic init --repo ~/Documents/NoteE2EE&lt;/code&gt;コマンドを使用して、ローカルリポジトリを作成しました。&lt;/p&gt;
&lt;p&gt;以下はS3互換ストレージの例です。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 環境変数の設定
$ export AWS_ACCESS_KEY_ID=id7O9M0H****tXJ2romrN
$ export AWS_SECRET_ACCESS_KEY=bFA0dL0u********ndnxVcrwPh31u
$ export AWS_DEFAULT_REGION=cn-east-1

# リポジトリの初期化とバックアップ
$ restic -r s3:https://s3.bitiful.net/note-e2ee init
$ restic -r s3:https://s3.bitiful.net/note-e2ee --verbose backup ~/Documents/NoteE2EE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：&lt;code&gt;AWS_DEFAULT_REGION&lt;/code&gt;環境変数が設定されていない場合、デフォルトとして&lt;em&gt;us-east-1&lt;/em&gt;が使用されます。&lt;/p&gt;
&lt;p&gt;Amazon S3、Backblaze B2、Google Cloudなどの他のプラットフォームとストレージについては、以下のドキュメントを参照してください：&lt;a href="https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html"&gt;https://restic.readthedocs.io/en/latest/030_preparing_a_new_repo.html&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;スナップショット管理&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;最近のスナップショットを保持する&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;定期的に&lt;code&gt;backup&lt;/code&gt;を実行してバックアップすることがありますが、バックアップが多すぎると煩わしくなります。以下のコマンドを実行すると、最新の7つのスナップショットのみを保持できます。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r [リポジトリパス] forget --keep-last 7 --prune
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;スナップショットのタグ&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;バックアップ時に複数のタグを指定できます（&lt;em&gt;--tag "v1.0" --tag "daily"&lt;/em&gt;）。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE backup --tag &amp;quot;v1.0&amp;quot; ~/Documents/Note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;既存のスナップショットのタグを変更することもできます。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# タグを追加
$ restic -r ~/Documents/NoteE2EE tag --add &amp;quot;important&amp;quot; 8c5c9d50

# タグを削除
$ restic -r ~/Documents/NoteE2EE tag --remove &amp;quot;important&amp;quot; 43547193

# 複数のタグを設定
$ restic -r ~/Documents/NoteE2EE tag --set &amp;quot;important,project2&amp;quot; a1ff1a78
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注目すべきは、変更するたびにスナップショットIDが変わることです。&lt;/p&gt;
&lt;h3&gt;バックアップの整合性チェック&lt;/h3&gt;
&lt;p&gt;クラウドに保存されたバックアップは、ファイルが100％失われないことや損傷しないことを保証できません。checkコマンドを使用して検証できます。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/technology/1743676450/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;ここで「損傷」をシミュレートしてみましょう。例えば、NoteE2EEディレクトリ内のdataディレクトリにあるファイルを見つけ、ファイル名を変更して、先頭にアンダースコアを追加し、ファイルの損傷/損失をシミュレートします。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/05.jpg" width="42.00%" /&gt;&lt;/p&gt;
&lt;p&gt;checkコマンドを再度実行すると、リポジトリが異常であり、修復が必要であることが表示されます。これは予想通りです。&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/technology/1743676450/06.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;スナップショットを特定のディレクトリに復元する&lt;/h3&gt;
&lt;p&gt;既存のスナップショットを表示：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE snapshots
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;特定のスナップショットをエクスポート：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE restore 5fcd966f --target ~/Downloads/NoteRestore/
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;5fcd966fはスナップショットIDで、snapshotsコマンドで確認できます。また、NoteRestoreディレクトリが存在しない場合は自動的に作成されます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;リポジトリが大きく、特定のファイルやディレクトリのみをエクスポートしたい場合は、次のコマンドを使用します。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic -r ~/Documents/NoteE2EE restore 5fcd966f --target ~/Downloads/NoteRestore/ --include Epub电子书
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;ここでの「--include Epub电子书」は、リポジトリのルートディレクトリにあるフォルダを指します。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;「copy」を使用して「backup」の代わりに&lt;/h3&gt;
&lt;p&gt;暗号化されたリポジトリが1つしかない場合は、毎回backupを使用すれば問題ありません。しかし、3-2-1原則に従ってバックアップし、複数の暗号化リポジトリがある場合、異なるリポジトリに対して複数回backupを実行するのは効率的ではありません。&lt;/p&gt;
&lt;p&gt;この場合、&lt;code&gt;copy&lt;/code&gt;を使用する必要があります。これにより、データの厳密な一貫性が保証され、パフォーマンスも優れています。&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ restic init --repo ~/Documents/NoteE2EE-copy

$ restic -r ~/Documents/NoteE2EE-copy copy --from-repo ~/Documents/NoteE2EE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;AIからの要約（私は良いと思います）：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;複数のResticリポジトリ間でデータを同期する必要がある場合、&lt;code&gt;copy&lt;/code&gt;は常に最適な選択です—それはリポジトリ間のプロフェッショナルな「データ移動者」のように機能し、&lt;code&gt;backup&lt;/code&gt;は元のデータの「コレクター」のようなものです。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Restic Browserを試してみる&lt;/h3&gt;
&lt;p&gt;コマンドライン操作が好きでない場合は、このオープンソースツールを試してみることができます：&lt;a href="https://github.com/emuell/restic-browser"&gt;emuell/restic-browser&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/technology/1743676450/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Rust + TypeScriptで開発され、サイズは数メガバイトしかなく、読み取り専用機能しかありません。「Browser」という名前が示すように、暗号化されたリポジトリを閲覧でき、スナップショット内のファイルを探すのに便利です。&lt;/p&gt;
&lt;h3&gt;Autoresticも必要かもしれません&lt;/h3&gt;
&lt;p&gt;ドキュメント：&lt;a href="https://autorestic.vercel.app/"&gt;Autorestic&lt;/a&gt; &lt;a href="https://autorestic.vercel.app/quick"&gt;クイックスタート&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Autorestic is a wrapper around the amazing &lt;a href="https://restic.net/"&gt;restic&lt;/a&gt;. While being amazing the restic cli can be a bit overwhelming and difficult to manage if you have many different location that you want to backup to multiple locations. This utility is aimed at making this easier 🙂&lt;/p&gt;
&lt;p&gt;Autoresticは、優れたresticツールを基に開発されたラッパーです。resticコマンドラインツール自体は素晴らしいですが、複数の異なる場所からのバックアップデータを複数のストレージターゲットに同期する必要がある場合、その操作は複雑で管理が難しくなる可能性があります。このツールは、このプロセスを簡素化し、マルチターゲットバックアップ管理をより簡単で便利にすることを目的としています。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;インストール&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ brew install autorestic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;設定ファイル&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以下の内容で設定ファイルを作成します：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;version: 2
backends:
  note_primary:
    type: local
    path: &amp;quot;~/Documents/NoteE2EE&amp;quot;
    env:
      RESTIC_PASSWORD: &amp;quot;your-restic-vault-passowrd&amp;quot;
  note_backup:
    type: local
    path: &amp;quot;~/Documents/NoteE2EE-copy&amp;quot;
    env:
      RESTIC_PASSWORD: &amp;quot;your-restic-vault-passowrd&amp;quot;

locations:
  notes:
    from: &amp;quot;~/Documents/Note&amp;quot;
    to:
      - note_primary
      - note_backup
    options:
      forget:
        keep-last: 7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;設定ファイルのパーミッションを変更（推奨）：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ chmod 600 ~/.autorestic.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;LocationとBackend&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Autoresticでは、Locationはバックアップのコンテンツとターゲット（from / to）を記述し、Backendはバックアップの宛先を定義します。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;設定の検証&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic check
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/08.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Everything is fine.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;手動バックアップの実行&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;完全バックアップ：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic backup -a
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;特定のLocationバックアップ：&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ autorestic backup -l notes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;出力：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1743676450/09.jpg" width="60.00%" /&gt;&lt;/p&gt;
&lt;p&gt;現在、このソリューションは私のニーズに完全に合っており、使いやすいです。しばらく使用した後、追加情報があれば更新します。&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://restic.readthedocs.io/en/stable/"&gt;Restic Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://autorestic.vercel.app/quick"&gt;Autorestic Quick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Software"></category></entry><entry><title>Cursor 开发 Obsidian 插件记录</title><link href="https://blog.yasking.org/a/obsidian-plugin-development-with-cursor.html" rel="alternate"></link><published>2025-02-24T21:00:00+08:00</published><updated>2025-02-24T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-02-24:/a/obsidian-plugin-development-with-cursor.html</id><summary type="html">&lt;p&gt;最近想到整理笔记、发布博客的自动化程序还不够（需要手动替换 Markdown 格式文章中的图像地址为图床地址），另外不同的图像 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;最近想到整理笔记、发布博客的自动化程序还不够（需要手动替换 Markdown 格式文章中的图像地址为图床地址），另外不同的图像，显示时需要手动调整下 Width 宽度，这就很枯燥&lt;/p&gt;
&lt;p&gt;使用了 Cursor 一段时间，Tab Tab Tab...，突然想到，可以让 AI 协助写一个 Obsidian 插件，编写文章使用 Obsidian，导出即为博客所需的文章格式，开搞！以下是使用 Cursor 编写插件的记录，同时使用到了 DeepSeek&lt;/p&gt;
&lt;h3&gt;环境准备&lt;/h3&gt;
&lt;h4&gt;确认 Node 环境&lt;/h4&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/technology/1740393250/01.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;Step.1 下载示例插件&lt;/h3&gt;
&lt;h4&gt;从示例开始&lt;/h4&gt;
&lt;p&gt;https://docs.obsidian.md/Plugins/Getting+started/Build+a+plugin&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新建一个空白的仓库（Vault）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;到仓库的插件目录并 Clone 示例插件&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ cd ~/Documents/donx-notes/
$ mkdir .obsidian/plugins
$ cd .obsidian/plugins
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step.2 构建插件&lt;/h3&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ cd obsidian-sample-plugin
$ npm install
$ npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step.3 启用插件&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;In Obsidian, open &lt;strong&gt;Settings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the side menu, select &lt;strong&gt;Community plugins&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Turn on community plugins&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Installed plugins&lt;/strong&gt;, enable the &lt;strong&gt;Sample Plugin&lt;/strong&gt; by selecting the toggle button next to it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt="02.jpg" src="https://images.yasking.org/technology/1740393250/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;开启插件&lt;/p&gt;
&lt;p&gt;&lt;img alt="03.jpg" src="https://images.yasking.org/technology/1740393250/03.jpg"&gt;&lt;/p&gt;
&lt;h4&gt;使用 Cursor 打开插件目录&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;建议：先在 Github 等代码托管仓库创建一个仓库，例如我的仓库名叫 &lt;code&gt;obsidian-article-exportor&lt;/code&gt; ，本地路径是 &lt;code&gt;~/Documents/donx-notes/.obsidian/plugins/obsidian-article-exportor/&lt;/code&gt;，我将新的仓库的 .git 目录替换掉 Demo 的，然后将 Demo 的目录名和 &lt;em&gt;manifest.json&lt;/em&gt; 文件修改，编写代码随时提交，后续 AI 生成如果不满意可以随时撤销代码&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="04.jpg" src="https://images.yasking.org/technology/1740393250/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;特别留意的是，修改后重载插件使其生效的方式是 &lt;code&gt;Commond + P&lt;/code&gt;，搜索并点击 “重新加载...”&lt;/p&gt;
&lt;p&gt;&lt;img alt="05.jpg" src="https://images.yasking.org/technology/1740393250/05.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;Step.4 那么，接下来交给 AI&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;描述：请帮助我修改 obsidian 的 Plugin 插件，它的功能是导出当前文章（笔记）和这个文章内置的图像，存储到指定目录，点击插件的按钮，自动导出，默认导出到用户的 Downloads 目录， 另外导出到目录可以通过配置来修改，或者是点击导出的时候选择目录，都是可以的，由你选择，暂时提供导出文章的代码即可，图像后续再处理&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;重载插件后，点击插件图标弹出提示，并没有真实的导出文章到用户 Downloads 目录&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;描述：请不要再保留默认导出到 Downloads 目录的逻辑，如果用户未设置，抛出提示：“请先设置插件的导出目录”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;看了下代码，发现它没有修改点击插件图标的事件，而是添加了一个命令去做，键盘 &lt;code&gt;Command + P&lt;/code&gt; 调出，搜索执行命令 “Export Current Note”&lt;/p&gt;
&lt;p&gt;&lt;img alt="06.jpg" src="https://images.yasking.org/technology/1740393250/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;正确提示了 “请先设置插件的导出目录”&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/technology/1740393250/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;设置目录&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.jpg" src="https://images.yasking.org/technology/1740393250/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;再次执行导出笔记，在下载目录已经可以看到 MD 文件&lt;/p&gt;
&lt;p&gt;&lt;img alt="09.jpg" src="https://images.yasking.org/technology/1740393250/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;修改代码可用性还是很高的，继续优化，增加功能&lt;/p&gt;
&lt;p&gt;&lt;img alt="10.jpg" src="https://images.yasking.org/technology/1740393250/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;先写一个示例笔记，然后描述需求如下&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;请完善其功能，需要在导出文章的同时导出图片，需要做转换，图像需要根据其在文章内的位置重命名为 01.jpg, 02.jpg, 03.jpg 这样，另外导出的图像要放在一个以时间戳命名的目录中，例如 1740276438，然后相对的路径就变为了 1740276438/01.jpg，替换掉导出文章内的图像地址&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;存在问题，未正确替换文本内容，也没有复制/重命名图像&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;代码有一些问题，因为是 Obsidian 的特有的 “[[” 写法，”Pasted image 20250223095948.png“ 并没有被替换掉，同时正确生成了时间戳命名的目录并创建，但是没有将图像复制到目标目录下&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;然后 Cursor 提供了正确的代码，插件能够正确工作&lt;/p&gt;
&lt;p&gt;&lt;img alt="11.jpg" src="https://images.yasking.org/technology/1740393250/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;继续提出一些优化需求&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;我们知道，在 Obsidian 的图片链接中，会有 “|420” 这样的写法，表示图片设置为 420px 的宽度，这样有助于显示更好的效果，但是在正常的 Markdown 语法中，不支持这种写法，一个折中的方式是使用 HTML image 标签，例如：&amp;lt; img src="..." width = "78%" / &amp;gt; 这样，我希望进行判断，如果 Obsidian 的链接没有 "|xxx" 这样的描述，你获得图像沿用现在的转换逻辑，如果包含 "|xxx" 这样的语法，那么将导出后的链接修改为 &amp;lt; img ...&amp;gt; 这样的链接，width 需要根据实际图像的宽度和 |xxx 这样的数值动态计算出来，例如 "|420"，实际宽度是 1000px，那么目标是 &amp;lt; img ... width = "42%" &amp;gt; 请提供修改后的代码&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Cursor 修改了代码，再次运行，生成的文件内容如下&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Icons

![[1740317458/01.jpg]]

缩小显示尺寸的图像示例

![[Pasted image 20250223095948.png|360]]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我刚发现导出的文件内的链接地址不对，让 Cursor 再修改下&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;导出的文件内容不对，首先，需要将 “[[” 这样的链接修改为 ![01](1740317458/01.jpg) 这样的标准 Markdown 图像链接语法，注意我举例中的 \ 符号，是转意用的，另外还有一处错误，|360 这样的描述，需要转换为 &amp;lt; img ... &amp;gt; 这种链接，请修改代码&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;无法正确输出... 看起来简单的描述它没办法理解我的意思&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这个是 Obsidian 的笔记内容&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;Icons

![[Pasted image 20250223095948.png]]

缩小显示尺寸的图像示例

![[Pasted image 20250223095948.png|360]]
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;我希望导出后的内容是以下的格式&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;Icons

![01.jpg](1740318018/01.jpg)

缩小显示尺寸的图像示例

&amp;lt;img src=&amp;quot;1740318018/02.jpg&amp;quot; width = &amp;quot;78%&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你理解了我的意思，请重新生成代码&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我感觉 Cursor 快冒烟了，输出一直是 &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Icons

![[Pasted image 20250223095948.png]]

缩小显示尺寸的图像示例

!![01.jpg](1740318460/01.jpg)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;没办法，懒得改哪怕一行代码，我把 &lt;em&gt;main.ts&lt;/em&gt; 粘贴给了 DeepSeek，给它的内容如下&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
以下是 obsidian 的插件代码，ts 格式的 

省略代码...

它的作用是导出笔记和图像，笔记的图像地址按照一定规则转换，规则描述如下

这个是 Obsidian 的笔记内容

Icons 

![[Pasted image 20250223095948.png]] 

缩小显示尺寸的图像示例 

![[Pasted image 20250223095948.png|360]] 

我希望导出后的内容是以下的格式

Icons 

![01.jpg](1740318018/01.jpg) 

缩小显示尺寸的图像示例 

&amp;lt;img src=&amp;quot;1740318018/02.jpg&amp;quot; width = &amp;quot;78%&amp;quot; /&amp;gt; 

注意这里的 width 比例是根据图像和 “|360” 比例计算出来的，现在的 ts 代码不正确请提供修复后的代码
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后把返回结果粘贴回来&lt;/p&gt;
&lt;p&gt;&lt;img alt="12.jpg" src="https://images.yasking.org/technology/1740393250/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;重新运行，可以了！生成的代码符合预期&lt;/p&gt;
&lt;p&gt;&lt;img alt="13.jpg" src="https://images.yasking.org/technology/1740393250/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;继续完善，因为最终的文章链接是 URL，需要增加配置&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;请帮助我修改代码，我希望添加一个设置，名为 host，如果配置了 host，那么生成图像的链接不是现在的 1740390067/02.jpg，而是 http://xxx.com/1740390067/02.jpg 这样的地址&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在老的 Chat 聊天感觉它已经神经错乱了 🤪 &lt;/p&gt;
&lt;p&gt;让 DeepSeek 继续调整了代码，它正确新增了配置项&lt;/p&gt;
&lt;p&gt;&lt;img alt="14.jpg" src="https://images.yasking.org/technology/1740393250/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;同时文本内容正确处理（图像未显示符合预期，因为我还没上传到存储）&lt;/p&gt;
&lt;p&gt;&lt;img alt="15.jpg" src="https://images.yasking.org/technology/1740393250/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;新建一个 Cursor Chat 聊天窗口，给它个简单的任务找回信心&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;为代码增加注释&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;至此，我才开始阅读代码，在插件开发完成之后&lt;/p&gt;
&lt;h3&gt;一些收获&lt;/h3&gt;
&lt;p&gt;除了最开始的环境准备参考的官方说明，后续编码全都由 AI 编写，没手写一行功能代码，对程序员来说，AI 辅助编程在开发者进入新领域、使用新语言时，能提供极大的助力&lt;/p&gt;
&lt;p&gt;例如我不会 Typescript、也没去了解 Obsidian 的开发文档，但不影响我开发一个满足需求的插件，这真的很棒&lt;/p&gt;
&lt;p&gt;另外，本次使用 Cursor 程度依然较低，还有不少 Cursor 的技巧没有去学习和使用，本篇先到这里，本篇文章已借助 Obsidian 插件导出后发布：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;枯燥-- &lt;/p&gt;
&lt;p&gt;效率++&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;2025-02-25 补充&lt;/h3&gt;
&lt;p&gt;P.S. 昨天脑袋卡了，Cursor 已经内置了 DeepSeek V3
模型，我还复制到 DeepSeek 网页 Chat 做什么呢...?&lt;/p&gt;
&lt;p&gt;另外 Cursor 已可使用
claude-3.7-sonnet 和 claude-3.7-connet-thinking，值的一试&lt;/p&gt;
&lt;p&gt;昨天一直用的是默认的 gpt-4o (无奈脸&lt;/p&gt;</content><category term="Technology"></category></entry><entry><title>非京籍个体户缴纳社保(十)：新增并缴纳个人所得税-工资薪金</title><link href="https://blog.yasking.org/a/self-employed-part-tenth.html" rel="alternate"></link><published>2025-02-24T21:00:00+08:00</published><updated>2025-02-24T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-02-24:/a/self-employed-part-tenth.html</id><summary type="html">&lt;p&gt;申请工资薪金缴纳个税其中之一的用途是车牌摇号，目前线上不能开通，需到线下办理，如果你没有明确的需求，则无需办 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;申请工资薪金缴纳个税其中之一的用途是车牌摇号，目前线上不能开通，需到线下办理，如果你没有明确的需求，则无需办理&lt;/p&gt;
&lt;h3&gt;线上申请（此路不通）&lt;/h3&gt;
&lt;p&gt;当前无法线上申请，记录一下，万一后续系统又支持了呢&lt;/p&gt;
&lt;p&gt;&lt;img alt="01.jpg" src="https://images.yasking.org/skills/1740394614/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “补充税（费）种”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1740394614/02.jpg" width="78%" /&gt;&lt;/p&gt;
&lt;p&gt;选择 “个人所得税”，然后选择 “税目”，如果可用，应该会出现 “工资薪金”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1740394614/03.jpg" width="78%" /&gt;&lt;/p&gt;
&lt;p&gt;如上图，没有「个人所得税」选项，即此路不通，需要到线下办理&lt;/p&gt;
&lt;h3&gt;添加办税人&lt;/h3&gt;
&lt;p&gt;自己办理就添加自己，代办人办理则授权代办人&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;办税人注册&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首先，办税人需要先注册，推荐下载使用「电子税务局 APP」注册&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;重要 Tips：人脸识别时候手机从下往上照，向着鼻孔，容易成功&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果 APP 一直不成功，可以用 Web 版电子税务局注册试试&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1740394614/04.jpg" width="68%" /&gt;&lt;/p&gt;
&lt;p&gt;点击右上角头像&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1740394614/05.jpg" width="68%" /&gt;&lt;/p&gt;
&lt;p&gt;点击弹出的 “账户中心”，跳转后点击 “添加办税人员”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1740394614/06.jpg" width="68%" /&gt;&lt;/p&gt;
&lt;p&gt;添加办税人后，选择个人所得税 APP 扫码认证 &lt;strong&gt;（个体户法人、企业所有者扫）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="07.jpg" src="https://images.yasking.org/skills/1740394614/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;扫码后，添加成功！&lt;/p&gt;
&lt;p&gt;&lt;img alt="08.jpg" src="https://images.yasking.org/skills/1740394614/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;退出登录&lt;/strong&gt;，再从网页上以「办税人身份」登录，同样来到 “账户中心”&lt;/p&gt;
&lt;p&gt;&lt;img alt="09.jpg" src="https://images.yasking.org/skills/1740394614/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;到 “企业授权管理” - “待确认授权” - 点击 “确认”&lt;/p&gt;
&lt;h3&gt;线下办理需携带的资料&lt;/h3&gt;
&lt;p&gt;携带以下资料，到个体户所属的税务所，不知道在哪里可以打税务局的电话咨询下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;办税人身份证&lt;/li&gt;
&lt;li&gt;营业执照正副本及复印件（A4黑白复印件即可）&lt;/li&gt;
&lt;li&gt;公章&lt;/li&gt;
&lt;li&gt;劳动合同（北京有些区需要工资流水，昌平区目前不需要）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;线下办理很快，不超过半小时&lt;/p&gt;
&lt;h3&gt;办理后线上即时可查&lt;/h3&gt;
&lt;p&gt;在 “北京电子税务局” - “我要查询” - “一户式查询” - ”纳税人信息查询“ - “税费种认定信息”，已经可以看到税种/税目&lt;/p&gt;
&lt;p&gt;&lt;img alt="10.jpg" src="https://images.yasking.org/skills/1740394614/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;重要提醒&lt;/strong&gt;：开通「个人所得税 - 工资薪金所得」后，每月都需要申报缴纳，否则会有罚款！&lt;/p&gt;
&lt;h3&gt;个税缴纳步骤&lt;/h3&gt;
&lt;p&gt;以法人身份登录到 “自然人电子税务局（扣缴端）”，点击 “代扣代缴”&lt;/p&gt;
&lt;p&gt;&lt;img alt="11.jpg" src="https://images.yasking.org/skills/1740394614/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “正常工资薪金所得” 后边的录入&lt;/p&gt;
&lt;p&gt;&lt;img alt="12.jpg" src="https://images.yasking.org/skills/1740394614/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;提示如图&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;您本月[2024年12月]还没有生成过正常工资薪金明细数据，需要使用自动导入正常工资薪金数据向导吗？&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="13.jpg" src="https://images.yasking.org/skills/1740394614/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择 “生成零工资记录，用户手工修改”，并点击 “立即生成数据”&lt;/p&gt;
&lt;p&gt;&lt;img alt="14.jpg" src="https://images.yasking.org/skills/1740394614/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;填入工资（应发），然后点击上图中左上角的返回&lt;/p&gt;
&lt;p&gt;&lt;img alt="15.jpg" src="https://images.yasking.org/skills/1740394614/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击「2 税款计算」，新开公司会有个提示，确定即可&lt;/p&gt;
&lt;p&gt;&lt;img alt="16.jpg" src="https://images.yasking.org/skills/1740394614/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;可以看到软件自动计算出了应扣除等个税数据，北京征税起点是 5000 元，扣除后 1000，税率 3%，应缴纳 30 元&lt;/p&gt;
&lt;p&gt;依次点击「3 附表填写」，没有减免事项则点击「4 申报表报送」&lt;/p&gt;
&lt;p&gt;&lt;img alt="17.jpg" src="https://images.yasking.org/skills/1740394614/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “发送申报”&lt;/p&gt;
&lt;p&gt;&lt;img alt="18.jpg" src="https://images.yasking.org/skills/1740394614/18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;提示如下&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;申报反馈信息：申报失败，扣缴单位无有效的税费种认定信息&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;我遇到的这个问题的原因是我在 2 月初操作个税缴纳，软件上显示的都是 12 月份的，2 月可缴纳一月份的个税，所以申报失败&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不清楚为什么进来显示的是 12 月份申报，解决也很简单，关闭软件，重新进入，就显示为 1 月份的申报表了，如下图&lt;/p&gt;
&lt;p&gt;&lt;img alt="19.jpg" src="https://images.yasking.org/skills/1740394614/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;重新开始，点击 “确定”，进入光荣的纳税缴税环节&lt;/p&gt;
&lt;p&gt;&lt;img alt="20.jpg" src="https://images.yasking.org/skills/1740394614/20.jpg"&gt;&lt;/p&gt;
&lt;p&gt;提示新版本纳税功能，当然是 “立即体验”&lt;/p&gt;
&lt;p&gt;&lt;img alt="21.jpg" src="https://images.yasking.org/skills/1740394614/21.jpg"&gt;&lt;/p&gt;
&lt;p&gt;看一眼提示，勾选后点击 “立即缴税”&lt;/p&gt;
&lt;p&gt;&lt;img alt="22.jpg" src="https://images.yasking.org/skills/1740394614/22.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择 “银联在线支付”，点击立即支付&lt;/p&gt;
&lt;p&gt;填写「银联」的银行卡号，输入姓名、身份证，获取手机验证码，点击支付即可付款&lt;/p&gt;
&lt;p&gt;&lt;img alt="23.jpg" src="https://images.yasking.org/skills/1740394614/23.jpg"&gt;&lt;/p&gt;
&lt;p&gt;再次来到综合所得申报，「4 申报表报送」，可以看到申报状态已变为：“申报成功,缴款成功“&lt;/p&gt;
&lt;p&gt;每月缴纳上个月的工资薪金个人所得税 ✅&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(九)：公积金开户增员与缴费</title><link href="https://blog.yasking.org/a/self-employed-part-ninth.html" rel="alternate"></link><published>2025-01-27T21:00:00+08:00</published><updated>2025-01-27T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-27:/a/self-employed-part-ninth.html</id><summary type="html">&lt;p&gt;公积金非强制缴纳，如果无需公积金，本文可以跳过，当前时间点，每月最少缴纳 121 元，不像养老和医保，公司缴纳的部分进统 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;公积金非强制缴纳，如果无需公积金，本文可以跳过，当前时间点，每月最少缴纳 121 元，不像养老和医保，公司缴纳的部分进统筹，公积金公司和个人缴纳后都到自己的个人账户&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;网站地址：&lt;a href="https://gjj.beijing.gov.cn/"&gt;https://gjj.beijing.gov.cn/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gjj.beijing.gov.cn/web/zwfw5/386727/386730/386733/11098838/index.html"&gt;《住房公积金单位登记开户操作详解》&lt;/a&gt; 提供了三种开户方式&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;北京 e 窗通（适合新增企业）&lt;/li&gt;
&lt;li&gt;住房公积金网站&lt;/li&gt;
&lt;li&gt;柜台（线下）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果在 e 窗通平台新增企业时未选择公积金，后续想要开户，可以参照本文，即方式2&lt;/p&gt;
&lt;p&gt;选择住房公积金网上业务系统：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/02.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;登录后，左侧只有登记开户&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/03.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “登记开户” - “单位登记开户”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/04.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;此时页面上没有信息，点击右上角的 “单位信息核验”，然后点击确认，会自动加载可供修改的单位信息。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/05.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;填写无误后点击“下一页”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/06.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;资金来源选择 “单位自筹”，缴存比例选择 5%&lt;/p&gt;
&lt;p&gt;经办人至少填写一位&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/07.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;委托收款信息是选填，如果你办理了对公账户，那么就填写上，没有则留空点击提交即可&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/08.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;没有对公账户到时候使用个人银行卡直接转账也是可以的，后文缴费时记录如何操作&lt;/p&gt;
&lt;p&gt;提交后显示登记完成&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/09.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;没有法人一证通，点击 “不，谢谢”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/10.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;此时回到首页，左上角还是只有一个 “登记开户”，问题不大，明天再看看 ⌛️&lt;/p&gt;
&lt;p&gt;第二天查看，可以了！（如果你遇到问题，打客服电话 12329 咨询，按 0 进入语音助手，跟它说“转人工”）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/11.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;h3&gt;公积金增员&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/12.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “办理 2024年12月增员”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;继续点击 “单笔增员”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;增加职工信息录入&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;2024住房公积金年度继续执行5%至12%的缴存比例政策。&lt;/p&gt;
&lt;p&gt;2024住房公积金年度住房公积金月缴存基数上限为35283元，具体缴存比例对应月缴存额上限见附件；月缴存基数下限为2420元，领取基本生活费职工的月缴存基数下限为1694元，新受理的住房公积金个人住房贷款，计算借款申请人贷款金额所使用的月基本生活费标准按1694元执行。&lt;/p&gt;
&lt;p&gt;—— &lt;a href="https://gjj.beijing.gov.cn/web/zwgk61/2024zcwj/436433461/543368452/index.html"&gt;《关于2024住房公积金年度缴存有关问题的通知》&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;根据公积金规定，月缴存基数下限为2420 元，填写上，这样公司缴纳 121，个人无缴纳，如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/15.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “确定” 保存&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/16.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;已保存的增员名单可以看到新增信息，确认无误后点击 “提交增员名单”，弹出提示 “请您认真核对信息，确保姓名、证件号码、月工资收入准确无误。”，继续点击 “确认提交”&lt;/p&gt;
&lt;p&gt;此时在页面的「本月已成功增员名单」可以看到增员的信息&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;汇缴&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;“公积金” - “汇补缴”，点击 “增减员”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/17.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;进入页面可以看到 “单位缴存信息”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;继续往下滚动页面，找到 “缴存” 模块&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;注意提示：&lt;strong&gt;&lt;em&gt;如职工缴存基数有误，可通过首页的【个人缴存基数修改】功能调整职工缴存基数（线上渠道住房公积金年度内仅支持修改一次）。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;确认无误点击 “确认申报 2024 年 12 月缴存人员名单”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/20.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;申报成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/21.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;返回后，可以看到 “2018年以来单位缴存明细” 模块中 12 月缴款状态为 “未缴款”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/22.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “缴存” 模块中的 “缴款” 按钮，跳转到个体户选择页面&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/23.jpg"&gt;&lt;/p&gt;
&lt;p&gt;勾选后点击 “下一步”，提示 “此次汇缴清册共1张，您是否确定提交？”，选择 “是”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;弹出 “详细信息：贵单位未选择委托收款缴款，建议使用委托收款方式缴款。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这里只是个提示，先不用管，委托收款需要对公账户，在银行开具对公账户每年要交几百款，可以直接转账缴款（如果你有对公账户，则选择委托收款的方式）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/24.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择中心开户银行，应该是没区别，可以根据自己手里的银行卡选择同样的。&lt;/p&gt;
&lt;p&gt;点击提交&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/25.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “打印缴款通知单”&lt;/p&gt;
&lt;p&gt;此时汇补缴页面 12 月状态未 “缴款中”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/26.jpg"&gt;&lt;/p&gt;
&lt;p&gt;拿出手机，通过网上银行转账到住房公积金的账号，在刚刚的 “打印缴款通知单” 中可以看到&lt;/p&gt;
&lt;p&gt;这是收款公共账号，不过不用担心，公积金中心自有办法知道你是为哪个单位缴纳的&lt;/p&gt;
&lt;p&gt;1 Hour later，再次查看缴款状态已变为 “已缴款”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737959498/27.jpg"&gt;&lt;/p&gt;
&lt;p&gt;缴款后一两个小时后查看，员工公积金已到账。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737959498/28.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;后续每月缴款重复 “确认申报XX年YY月缴存人员名单”，然后 “缴款” ✅&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(八)：税务申报与工商年报</title><link href="https://blog.yasking.org/a/self-employed-part-eighth.html" rel="alternate"></link><published>2025-01-24T21:00:00+08:00</published><updated>2025-01-24T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-24:/a/self-employed-part-eighth.html</id><summary type="html">&lt;p&gt;不正常申报纳税，轻则收到罚款通知、重则经营异常... 需重视&lt;/p&gt;
&lt;p&gt;那如果我没有卖出去东西，还需要报税吗？需要，即 “零申报”，本篇记 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;不正常申报纳税，轻则收到罚款通知、重则经营异常... 需重视&lt;/p&gt;
&lt;p&gt;那如果我没有卖出去东西，还需要报税吗？需要，即 “零申报”，本篇记录北京个体户需要申报的税种和操作流程，Let's Go！&lt;/p&gt;
&lt;h3&gt;先弄清楚要报什么税&lt;/h3&gt;
&lt;p&gt;网站：&lt;a href="https://etax.beijing.chinatax.gov.cn:8443/"&gt;https://etax.beijing.chinatax.gov.cn:8443/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使用 “电子营业执照” 扫码进行登录，在 “我要查询” 模块，选择 “一户式查询” - “纳税人信息查询”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择 “税费种认定信息”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;可以看到 6 个征收项目&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;也就是对应着以下几个申报项目&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1）增值税及附加税费申报（小规模纳税人）- 每年的 1月 / 4月 / 7月 / 10 月申报，15日前&lt;/p&gt;
&lt;p&gt;2）个人所得税（经营所得）- 每年的 1月 / 4月 / 7月 / 10 月申报（A 表）&lt;/p&gt;
&lt;p&gt;3）个人所得税（经营所得）年度申报 - 每年的 3月31日前（B 表）&lt;/p&gt;
&lt;p&gt;4）工商年报（工商年检）- 每年6月30日前&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;特别注意：因为当前为 1月份初，本文小标题中 “个人所得税 - 经营所得（xx）” 同时包含了 2）和 3）A 表和 B 表的申报，读者需要自己确定当前时间点是否需要申报 B 表，B 表每年只需申报一次&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;增值税及附加税费申报（小规模纳税人）&lt;/h3&gt;
&lt;p&gt;增值税及附加税费申报申报的时间为&lt;strong&gt;季度&lt;/strong&gt;申报，每年 1、4、7、10月份的 1-15 日在 “北京电子税务局” 申报&lt;/p&gt;
&lt;p&gt;当前是 2025 年一月份初，申报 2024 年 10 ～ 12 月的税费&lt;/p&gt;
&lt;p&gt;登录到 “北京市电子税务局” 网站：&lt;a href="https://etax.beijing.chinatax.gov.cn:8443/"&gt;https://etax.beijing.chinatax.gov.cn:8443/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在「我的待办」看到有一个 “增值税及附加税费申报（小规模纳税人）” 事项&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;如果没看到，可以在「我要办税」中选择 “税费申报及缴纳” - “增值税及附加税费申报（小规模纳税人）”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/05.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;进入后，提示 2023 年到 2027 年有税费优惠，不用管，点击确定&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/06.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;进入后页面如下&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;其中可以看到提示这是四季度（2024-10-01 到 2024-12-31）的申报，如果有实际销售额，点击页面右上角的 “我要填表”，你可能需要找更加细致的申报教程跟着操作，本文记录的是未销售出商品的 “零申报”，可以看到 “本期销售情况” 默认都是零&lt;/p&gt;
&lt;p&gt;点击 “下一步”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “提交申报”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/09.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;信息确认，如果你的个体户有实际销售额，不可以零申报，需要如实填写，点击 “确定”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/10.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;点击刷新，可以看到申报成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/11.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;回到首页，我的待办，可以看到状态 “已申报”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/12.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;增值税及附加税费申报 ✅&lt;/p&gt;
&lt;h3&gt;个人所得税 - 经营所得（Web 版）&lt;/h3&gt;
&lt;p&gt;登录到 “自然人电子税务局”，地址：&lt;a href="https://etax.chinatax.gov.cn"&gt;https://etax.chinatax.gov.cn&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;目前 1 月份初，需要申报 “经营所得个人所得税月（季）度申报”（A表） 和 “经营所得个人所得税年度申报”（B表）&lt;/p&gt;
&lt;p&gt;如果是 4、7、10 月份，则只申报前者 A 表， B 表一年仅提交一次。&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;PS：我是后来知道的这个在线网站，1月份的申报已经根据其他教程通过 &lt;em&gt;自然人电子税务局（扣缴端）&lt;/em&gt; 进行了提交&lt;/p&gt;
&lt;p&gt;你可以在 “自然人电子税务局” - “我要办税”，提交 “经营所得（A表）” 和 “经营所得（B表）”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;申报步骤&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;【待补充 Web 端操作步骤】&lt;/p&gt;
&lt;p&gt;等到 4 月份申报 “经营所得个人所得税年度申报” 时我将通过 Web 提交并在这里补充步骤，当前节点，你可以参考本文的「个人所得税 - 经营所得（自然人电子税务局-扣缴端）」 小节，进行提交，或是使用 Web 端都可以的&lt;/p&gt;
&lt;p&gt;在客户端提交并显示成功后，可以在 Web 端查询申报记录&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;查询申报记录&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Web 端使用 “个人所得税 APP” 扫码登录后，点击 “我要查询” - “申报查询”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;如下图所示，“经营所得个人所得税月（季）度申报” 即 A 表，“经营所得个人所得税年度申报” 即 B 表&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/15.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;个人所得税 - 经营所得（自然人电子税务局-扣缴端）&lt;/h3&gt;
&lt;p&gt;注意：客户端跟 Web 端是等效的操作，如果已通过 Web 申报，则不用再使用客户端&lt;/p&gt;
&lt;p&gt;下载页面：&lt;a href="https://etax.chinatax.gov.cn/webstatic/download-service/100001"&gt;https://etax.chinatax.gov.cn/webstatic/download-service/100001&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;下载后进行安装，一路下一步，注意选择 “扣缴单位版”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/17.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;单位录入，选择所在省市为 “北京市”，纳税人识别号即电子营业执照号（统一社会信用代码）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/18.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;下一步，备案办案人员信息，填写自己的信息。&lt;/p&gt;
&lt;p&gt;进入首页后，在代扣代缴模块的 “人员信息采集”，先添加人员（企业经营者）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/19.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;勾选后再点击 “报送”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/20.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;即时弹出报送结果&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;预缴纳税申报（A表）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;来到「经营所得」模块，点击 ”预缴纳税申报“&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/21.jpg"&gt;&lt;/p&gt;
&lt;p&gt;可以看到一条个体户经营者的记录，显示待申报。如果有利润，则点击 “公共信息” 旁的 “修改” 按钮进行修改&lt;/p&gt;
&lt;p&gt;如果你有营业额，可以参考这个文章 &lt;a href="https://mp.weixin.qq.com/s?__biz=MzU3NjY0MzIzMg==&amp;amp;mid=2247610852&amp;amp;idx=1&amp;amp;sn=946241763167d7ddeb404a2510f91369&amp;amp;chksm=fcb05b7c0f6e05bd033aeb97eb260cd8867c5452b98646e7c027f19f2ec4813b43fdc3d96072&amp;amp;scene=27"&gt;《个体户百宝手册（二）——个人所得税经营所得申报操作全流程指引》&lt;/a&gt; &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;此处所说的“收入总额”“成本费用”为累计数，以7月申报期内申报为例，纳税人所填的收入总额及成本费用应当为1-6月的累计数，而非4-6月的合计数。
 —— 《个体户百宝手册（二）——个人所得税经营所得申报操作全流程指引》&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;另外这个糊糊的在网上看到的图片也可以参考&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/22.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;继续回来，点击，填写无误后点击提交申报，因为营业额为 0，所以什么都没有改，直接提交&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/23.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;点击反馈信息可以看到申报成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/24.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择人员后，点击 “导出”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/25.jpg"&gt;&lt;/p&gt;
&lt;p&gt;得到 &lt;em&gt;个人所得税经营所得纳税申报表（A表）.xls&lt;/em&gt;，可以存档&lt;/p&gt;
&lt;p&gt;在 “查询” - "申报记录查询" 中可以看到状态为 “申报成功”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/26.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;年度汇缴申报（B表）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;每年第四个季度申报完成后，需进行 “个人经营所得税年度汇缴申报”（B表）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现在是 1 月份，点击 “年度汇缴申报”，会看到一条 “待申报” 的记录&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/27.jpg"&gt;&lt;/p&gt;
&lt;p&gt;同理，如果有营业额，那么点击修改，保存后点击 “提交申报”，没有则直接提交，申报成功后，状态变为成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/28.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击导出，你将获得一个 &lt;em&gt;个人所得税经营所得纳税申报表（B表）.xls&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;可以到上文记录的 Web 版本 “查询申报记录” &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737729686/29.jpg"&gt;&lt;/p&gt;
&lt;p&gt;看到 A 表 B 表已经成功申报 ✅&lt;/p&gt;
&lt;h3&gt;工商年报（工商年检）&lt;/h3&gt;
&lt;p&gt;登录到 “国家企业信息公示系统(北京)”&lt;/p&gt;
&lt;p&gt;地址：&lt;a href="https://bj.gsxt.gov.cn/index.html"&gt;https://bj.gsxt.gov.cn/index.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;首次使用先点击右上角进行注册，填写个人信息后，需要编辑短信发送，然后点击 “短信验证”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/30.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;完成后使用手机号 + 密码登录进系统&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/31.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;点击企业信息，选择所在地&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/32.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;点击生成登录二维码，使用 “电子营业执照” 登录&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/33.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;登录后点击 “年度报告填写”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/34.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;2024 年度报告，点击确定&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/35.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;弹出 “填写须知”，勾选后确定&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/36.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;本着如实填写，能少写就少写的原则录入，没有的值需要填 0&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/37.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;提交后的提示&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/38.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;可以点击 “预览打印”，保存为 PDF 后你将得到一个： &lt;em&gt;个体工商户年度报告表.pdf&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;确认无误后点击 “提交并公示”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/39.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;提示：您的年报已提交成功，将在48小时内通过全国企业信用信息公示系统、企业信用信息网进行公示！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;点击 “打印结果告知书”，可以看到以下内容&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737729686/40.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;工商年报申报完成 ✅&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(七)：社保费用申报与缴纳</title><link href="https://blog.yasking.org/a/self-employed-part-seventh.html" rel="alternate"></link><published>2025-01-19T21:00:00+08:00</published><updated>2026-01-13T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-19:/a/self-employed-part-seventh.html</id><summary type="html">&lt;p&gt;社保缴费，本文主要以 “社保费客户端” 为例，记录关联、申报与缴纳，并记录了 Web 网页版的申报与缴纳&lt;/p&gt;
&lt;p&gt;特别需要注意：本月进行 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;社保缴费，本文主要以 “社保费客户端” 为例，记录关联、申报与缴纳，并记录了 Web 网页版的申报与缴纳&lt;/p&gt;
&lt;p&gt;特别需要注意：本月进行了员工增员后，下个月 10 号才能开始申报缴纳社保费。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;自2024年1月1日起，用人单位应当于每月10日至25日自行向税务部门申报缴纳社会保险费，职工个人缴费部分由用人单位根据社会保险相关法律法规代扣代缴。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;特别提示：使用 Web 缴纳更加方便，请查看本页面的 “申报与缴费（Web 端）”（推荐） &lt;/p&gt;
&lt;h3&gt;安装并初始化客户端&lt;/h3&gt;
&lt;p&gt;客户端下载地址：&lt;a href="http://download.bjca.org.cn/download/sbgl.zip"&gt;http://download.bjca.org.cn/download/sbgl.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;下载后立即安装&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/01.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;选择地区，务必选择正确地址&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/02.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;自动下载安装包... 等待完成&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/03.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “添加” 用人单位&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/04.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;输入纳税人识别号，即企业社会信用代码&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/05.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;选择用人单位，点击 “去关联”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/06.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;弹出 “用人单位参保缴费信息关联” 点击提交&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/07.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;提示&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;不存在完全正配的待关联登保信息（完全匹配的参保信息系统已自动关联），如需关联非完全匹配的参保信息，请携带相关资料前往前台办理&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/08.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;如果你遇到这个提示，需要等待 ⌛️ 我是 12 月 29 日晚间遇到的这个错误，1 月 1 日下午再次尝试关联，报错消失，说明信息已同步&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/09.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “下一步”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/10.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;上图所提示的路径不对，参考以下最新的重置地址进行设置&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;获取社保客户端密码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;访问北京电子税务局网站：&lt;a href="https://etax.beijing.chinatax.gov.cn:8443/"&gt;https://etax.beijing.chinatax.gov.cn:8443/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;电子税务局改版后的正确路径是：“地方特色” - “社保业务” - “社保费客户端密码重置（首次获取）”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/11.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;弹出页面，填写新密码&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/12.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;设置后&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/13.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;再次回到客户端，勾选 “我已确认无误”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/14.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;对参保登记信息后点击确认，而后自动获取信息&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;而后自动进入客户端页面&lt;/p&gt;
&lt;h3&gt;等待保险同步完成&lt;/h3&gt;
&lt;p&gt;点击职工参保信息管理&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1月1日，元旦没刷出来职工信息

1月2日，在社保客户端查询到员工信息
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;我这里只看到有医保，没有养老、失业和工伤保险。&lt;/p&gt;
&lt;p&gt;网上看也有不少人遇到这个问题，如果已确定社保增员成功（参考：《&lt;a href="https://blog.yasking.org/a/self-employed-part-four.html"&gt;非京籍个体户缴纳社保(四)：北京市社会保险网上服务平台 - 增员与社保卡领取&lt;/a&gt;》），可以先等一等，10 号之前一般都会推送完成，等待两天后再查询试试&lt;/p&gt;
&lt;p&gt;1月4日，可以看到缺失的保险已显示&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/17.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;年度缴费工资调整&lt;/h3&gt;
&lt;p&gt;来到 “缴费工资申报” - “年度缴费工资调整”，选择当前的时间段&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “确定”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “按人申报”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/20.jpg"&gt;&lt;/p&gt;
&lt;p&gt;先输入新缴费工资，例如填写 6000，社保费会自动按照最低档 6821 （2024）基数来计算（不同年度缴费基数不一样），想要缴纳最低档，填写低于 6821 的数字就可以&lt;/p&gt;
&lt;p&gt;勾选上新增社保人员，再点击 “提交申报”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/21.jpg"&gt;&lt;/p&gt;
&lt;p&gt;而后可以再申报记录模块看到申报正在 “处理中”，别傻等，我就是等了两天，然后翻网上的攻略，需要点击一下 “申报结果查询”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/22.jpg"&gt;&lt;/p&gt;
&lt;p&gt;然后它的状态就变为 “全部申报成功” 了&lt;/p&gt;
&lt;p&gt;如果你在社保费申报中的 “日常申报”，只能看到医保的记录&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/23.jpg"&gt;&lt;/p&gt;
&lt;p&gt;需要再次回到 「缴费工资调整」模块，会提示有人员的基数为空，选择 “按险种申报”，可以看到养老、失业、工伤为空，填入跟医保一样的金额&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/24.jpg"&gt;&lt;/p&gt;
&lt;p&gt;勾选人员前的选择框，点击提交申报，确定&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/25.jpg"&gt;&lt;/p&gt;
&lt;p&gt;提交后，直接点击 “申报结果查询”，发现已 “全部申报成功”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/26.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “查看”，可以看到五个险种均已显示且有工资金额&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/27.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;社保费申报&lt;/h3&gt;
&lt;p&gt;点击进入 “申报费申报” - “日常申报” 模块&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/28.jpg"&gt;&lt;/p&gt;
&lt;p&gt;勾选所有的记录&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/29.jpg"&gt;&lt;/p&gt;
&lt;p&gt;当前时间点的月缴费最低金额为 2540.42 元&lt;/p&gt;
&lt;p&gt;拖动横向滚动条，可以看到各个待缴费记录的类别&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/30.jpg"&gt;&lt;/p&gt;
&lt;p&gt;其中划到医保个账加养老个账共计 682.1 会进到自己的个人账户，1800+ 进了统筹，有言道：侠之大者，为国接盘（手动泪目&lt;/p&gt;
&lt;p&gt;先看眼当前日期，社保费申报需要在 10 号及之后申报，当前 7 号，等两天再提交&lt;/p&gt;
&lt;p&gt;（等待中...  10 号已到）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;社保费提交申报&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/31.jpg"&gt;&lt;/p&gt;
&lt;p&gt;确保全选，确认金额没问题后，点击 “提交申报”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/32.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;点击立即提交，弹出提交成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/33.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;申报成功，可以直接去缴费&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/34.jpg"&gt;&lt;/p&gt;
&lt;p&gt;在 “社保费申报” - “申报记录” 可以看到刚刚提交的记录&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/35.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;社保费款缴纳&lt;/h3&gt;
&lt;p&gt;到 “费款缴纳” - “缴费”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/36.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;勾选 “立即缴纳”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/37.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择缴费方式，如果你有 “银行公户”，那么选择 “三方协议交费”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/38.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;没有公户则选 “银行短凭证缴费”，不用跑线下，可以用手机 APP 缴纳&lt;/p&gt;
&lt;p&gt;点击 “人工录入账户账号信息”，输入你的支付银行卡信息&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;1）姓名&lt;/p&gt;
&lt;p&gt;2）银行卡号&lt;/p&gt;
&lt;p&gt;3）开户行&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;保存后点击下一步，弹出的页面点击 “确认缴费”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/39.jpg"&gt;&lt;/p&gt;
&lt;p&gt;出现的打印页面可以保存为 PDF，记录上的 “银行端查询缴税凭证序号” 和 “纳税人识别码”、“税务机关代码” 稍后会用到&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;银行线上缴款&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在银行 APP 上搜索 “缴税通”（我看了招商和交行都可以找到这个应用模块）&lt;/p&gt;
&lt;p&gt;进入后需要输入上面记录的 “银行端查询缴税凭证序号” 和 “纳税人识别码”、“税务机关代码” &lt;/p&gt;
&lt;p&gt;缴费成功后，过一会儿刷新记录可以看到 “缴费成功”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/40.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;申报与缴费（Web 端）&lt;/h3&gt;
&lt;p&gt;我是在客户端缴费完才了解到的通过 Web 端 “&lt;a href="https://etax.beijing.chinatax.gov.cn:8443/"&gt;北京电子税务局&lt;/a&gt;” 也可以进行申报和缴费，跟客户端流程是一样的，这里简要介绍，跟客户端申报缴费是二选一的，从大趋势来看，最终可能客户端的功能都会迁移到 Web 端&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;日常申报&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2025-08-11 更新&lt;/strong&gt;： 位置调整，社保业务从 “地方特色” 移动到了 “我要办税”。&lt;/p&gt;
&lt;p&gt;在 “地方特色”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/41.jpg"&gt;&lt;/p&gt;
&lt;p&gt;进入后点击 “社保业务” - “日常申报”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737279634/42.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;税费缴纳&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;进入后点击 “社保业务” - “缴费”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/43.jpg"&gt;&lt;/p&gt;
&lt;p&gt;跳转到金额页面&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/44.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击立即交费，点击确认&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1737279634/45.jpg"&gt;&lt;/p&gt;
&lt;p&gt;参考客户端版本中记录的手机缴款小节：「银行线上缴款」，查看 “银行端查询缴税凭证序号” 和 “纳税人识别码”、“税务机关代码”，此处不再赘述，这里有个细节：“因为没有公户，Web 端没有展示三方协议交费的选项”&lt;/p&gt;
&lt;p&gt;至此，申报与缴费完成 ✅&lt;/p&gt;
&lt;p&gt;离松口气还差一些，需要了解税务申报，否则将面临企业异常和罚款的组合拳法&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mp.weixin.qq.com/s?__biz=MzA4OTE2NzY4OQ==&amp;amp;mid=2651764234&amp;amp;idx=1&amp;amp;sn=629721639be04c73d3ced34016760bc4&amp;amp;chksm=8a0200540c602144c4f8618966649d115fbd3a11368902aff64216d80c3f1ae43742f67505fd&amp;amp;scene=27"&gt;北京昌平税务 - 社保费管理客户端申报缴费操作指引&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(六)：医保公共服务平台 - 增员确认</title><link href="https://blog.yasking.org/a/self-employed-part-sixth.html" rel="alternate"></link><published>2025-01-18T21:00:00+08:00</published><updated>2025-01-18T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-18:/a/self-employed-part-sixth.html</id><summary type="html">&lt;p&gt;员工社保增员后，因为养老和医疗是不同平台，为了确认医保也已自动增员，可以访问北京医保公共服务网上服务大厅进 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;员工社保增员后，因为养老和医疗是不同平台，为了确认医保也已自动增员，可以访问北京医保公共服务网上服务大厅进行确认&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/01.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;地址：&lt;a href="https://fw.ybj.beijing.gov.cn/hallEnter/#/Index"&gt;https://fw.ybj.beijing.gov.cn/hallEnter/#/Index&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;完善单位信息&lt;/h3&gt;
&lt;p&gt;点击单位登录，选择 “北京市统一身份认证平台登录”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/02.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;首次登录提示如下&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;由于一证通反馈的单位信息不完整，不能进入北京医保公共服务平台。您需要在北京医保公共服务平台补填单位信息后才能进入！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/03.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “立即补填”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/04.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;单位账号类似于 “用户名”，建议填写为企业的信用代码，通讯地址我填写的居住证地址&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/05.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;经办人填写自己的信息，提交后显示成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/06.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;另外会收到短信，是单位账号和经办人账号和密码，保存妥当！&lt;/p&gt;
&lt;h3&gt;添加经办人&lt;/h3&gt;
&lt;p&gt;点击前往以单位身份登录&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/07.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;点击经办人管理，并点击右侧权限管理，授权并点击 “确定” 保存&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/08.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;之后退出登录，重新选择单位登录，此处不是用统一身份认证，而是填入刚刚短信发送的经办人账号（手机号、密码）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/09.jpg" width = "68%" /&gt;&lt;/p&gt;
&lt;p&gt;选择个体户并确认登录&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/10.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;h3&gt;员工增员确认&lt;/h3&gt;
&lt;p&gt;登录后选择左侧的 “网上经办” - “职工信息维护”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1737202827/11.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;能查询到，说明之前社保网上服务平台的增员的确已经在医保上自动增员，确认完成！✅&lt;/p&gt;
&lt;p&gt;（备注：如果查询不到，也可以点击左侧的 “职工增员申报” 进行提交）&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(五)：北京电子税务局 - 税务报道</title><link href="https://blog.yasking.org/a/self-employed-part-five.html" rel="alternate"></link><published>2025-01-13T21:00:00+08:00</published><updated>2025-01-13T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-13:/a/self-employed-part-five.html</id><summary type="html">&lt;p&gt;虽然在 e 窗通提交了企业信息，但只是基础数据的流转，后续仍需手动进行关联确认&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;百度搜索：国家税务总局北京市电子 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;虽然在 e 窗通提交了企业信息，但只是基础数据的流转，后续仍需手动进行关联确认&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;百度搜索：国家税务总局北京市电子税务局
网站地址：&lt;a href="https://etax.beijing.chinatax.gov.cn:8443"&gt;https://etax.beijing.chinatax.gov.cn:8443&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;两证整合个体工商户信息确认&lt;/h3&gt;
&lt;p&gt;先别着急登录，先点击页面右侧的 “两证整合个体工商户信息确认”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/02.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;弹出新的确认页面&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;填写个体户营业执照同意社会信用代码、企业负责人的身份证、姓名等信息，填写后点击页面右上方的 “我要开始办理”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;虽然提示红色星号表示必填，但黄色框内都需要补充，否则会提示需要填写&lt;/p&gt;
&lt;p&gt;之后国标行业（附）和家庭经营信息&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;家庭信息这里我填写的个体户所有者，也就是自己的信息&lt;/p&gt;
&lt;p&gt;提交后可以看到 “涉税事项受理系统回执单”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/06.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;之后可以查询进度&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;当前显示正在办理中&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;下午一点多提交，当天下午 6 点查询，已出结果如下&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;这里可以看到 6 个税种认定，“显示密码” 没啥用，直接点击 “立即登录”&lt;/p&gt;
&lt;h3&gt;登录网站&lt;/h3&gt;
&lt;p&gt;选择 “电子营业执照” 方式登录网站&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/10.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;弹出用户协议，弹出 “输入的统一社会心用代码或纳税人识别号错误，请重新输入”，我的情况是没进行 “两证整合个体工商户信息确认” 导致的，如果是其它原因等一两天再试或打税务局电话咨询&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/11.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;点击确认统一协议，然后重新设置密码&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/12.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;成功登录&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;刚才可能你已经注意到了 “签收文书”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;跳转到以下页面&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击签收后显示 “已签收”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;再次回到个人首页，可以看到我要查询，点击 “税务文书送达确认”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;弹出 “税务文书电子送达确认书签订”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/18.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;点击确定&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;跳转后继续点击 “同意签订”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/20.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;能成功登录就算是报道完成了 ✅&lt;/p&gt;
&lt;h3&gt;进一步确认已报道成功（可选）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;方式一：确认纳税人和税种信息&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在输入框输入 “纳税人信息查询”，进入模块&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/21.jpg"&gt;&lt;/p&gt;
&lt;p&gt;能看到纳税人信息和税种信息说明 OK&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/22.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;方式二：确认自然人身份新办纳税人开业信息&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;退出登录，回到登录页面&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/23.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;点击「自然人业务」下的 “用户注册”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/24.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;我在中间过程中提示用户存在，所以我回到首页，点击忘记密码重新设置的密码，使用手机号密码，外加短信验证码的方式登录，在 “热门服务” 中可以看到 “新办纳税人开业”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/25.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “新办纳税人开业”，有个体户信息&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736775284/26.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击蓝色的 “统一社会信用代码” ，会弹出提示如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736775284/27.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;能正常通过 “电子营业执照” 登录到电子税务局，就算是报道完成，同时也进一步通过两种方式进行了确认&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(四)：北京市社会保险网上服务平台 - 增员与社保卡领取</title><link href="https://blog.yasking.org/a/self-employed-part-four.html" rel="alternate"></link><published>2025-01-12T21:00:00+08:00</published><updated>2025-01-12T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-12:/a/self-employed-part-four.html</id><summary type="html">&lt;p&gt;本文内容&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;员工增员（缴纳社保的人员）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;领取实体社保卡（非必需，电子社保卡日常也能用）&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h3&gt;员工增员&lt;/h3&gt;
&lt;p&gt;以单位身份登录北京市社 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;本文内容&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;员工增员（缴纳社保的人员）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;领取实体社保卡（非必需，电子社保卡日常也能用）&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;h3&gt;员工增员&lt;/h3&gt;
&lt;p&gt;以单位身份登录北京市社会保险网上服务平台&lt;/p&gt;
&lt;p&gt;网站地址：&lt;a href="https://fuwu.rsj.beijing.gov.cn/zhrs/yltc/yltc-home"&gt;https://fuwu.rsj.beijing.gov.cn/zhrs/yltc/yltc-home&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在 “在职职工管理” 中，点击 “(增减员)社会保险...”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/01.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “零星新增” 模块&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/02.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;进入有有个提示，可以读一下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/03.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;（后续文章会涉及税务相关知识，此处简单说下，例如 12 月 20 日完成社保人员增员，下个月也就是 1 月 10 日可以为其缴纳社保，医保能正常使用时间时缴纳社保后的次月 1 日，也就是 2 月 1 日）&lt;/p&gt;
&lt;p&gt;填写参保人员信息，如果是为自己办理社保就填写自己的信息，为职工则填写职工信息（如果你在公司在职上班，申请的个体户，不要为自己录入社保登记）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/04.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;填写身份证姓名后，获取共享信息，会自动补充一些内容，变为不可更改，完善剩余信息&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/05.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;补充劳动用工备案信息，劳动合同我填写的是当月营业执照上的日期，三年固定期限合同，岗位选择专业技术岗即可，无电子劳动合同。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/06.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;其他信息选择的 “专业技术人员”&lt;/p&gt;
&lt;p&gt;个体户管理员添加人员时无需上传照片（首次开通北京社保需要照片），参保人需要以个人身份上传照片（如果参保人员就是自己，则以个人身份进行照片上传，见后文）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/07.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;参保信息有三项 “养老”、“失业”、“工商”，此处没有体现 “医保”，通过后会自动开通，无需担心，后文将记录到医保网站进行确认的步骤&lt;/p&gt;
&lt;p&gt;点击提交，提示税务开始缴费时间为 12 月&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/08.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;确认提交后显示受理成功&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/09.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;因为增员无需人工审核，是即时办结事项，点击 “《办结通知单》” 查看详情&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/10.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;同样，不通过原因为空，备注信息显示，医保增员成功&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“该业务为医保协同业务，医保部门反馈的处理结果为：成功。您无需到医保部门重复进行申报。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;回到在职职工管理模块，在 “增减员” 页面点击 “劳动合同人员参保登记列表”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/11.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;可以看到社保增员已成功 ✅&lt;/p&gt;
&lt;h3&gt;实体社保卡申领&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;个体户增员成功后，参保人（职工）需等待短信通知&lt;/strong&gt;，在这之前上传照片会提示 “卡管系统未查询到该人员信息”，大概需要等待几天到一周多时间不等。（我是在增员第二天收到的短信）&lt;/p&gt;
&lt;p&gt;实体社保卡申领过程较慢，整体下来可能一个月的时间，不申领实体卡也 &lt;strong&gt;不影响公司正常缴纳社保&lt;/strong&gt;，在实体卡下来前也可以使用电子社保卡。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;参保人员照片上传&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果使用手机操作，关注 “北京人设” 公众号，点击 “微服务”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/12.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “个人办理”，社会保障下可以看到 “第一二代社保卡照片采集”，点击进入办理&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/13.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;如果是电脑操作，参保人可以在人社局首页 &lt;a href="https://rsj.beijing.gov.cn/"&gt;https://rsj.beijing.gov.cn/&lt;/a&gt; ，找到 “我要办社保卡”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/14.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;然后以 “个人业务 - 个人登录”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/15.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;进入后点击 “立即申请”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/16.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;进入后填入身份证号码，并点击上传照片&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/17.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;（补充）如果提交提示 “卡管系统未查询到该人员信息”，等过些天参保人收到短信要求上传照片后再提交。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/18.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;点击弹出 “确认”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/19.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;会提示 “上传成功”（只能提交一次，再次提交应该会提示报错信息，如果照片不符合，应该会再次收到上传照片的短信提醒）&lt;/p&gt;
&lt;p&gt;提交后可以到 “社会保障卡制卡进度查询” 模块查询进度&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/20.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;当前查看显示状态为 “您的制卡信息还未由参保单位提交（或制卡信息不符合制卡要求），请与当前参保单位联系提交。”，这是正常的状态。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/21.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;此时等待即可 ⌛️，能收到上传照片短信提醒，说明新增员工成功，流程正在进行中，可能需要等待几个工作日到半个月的时间能看到进度，可以隔几天再来看下&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2024-12-25 进度&lt;/strong&gt;（提交照片的 12 天后）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/22.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;卡片已经在制作中... &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2025-01-01 进度&lt;/strong&gt;：卡片制作完成，已寄出&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/23.jpg" width = "88%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2025-01-10 进度&lt;/strong&gt;：收到顺丰快递，用时不到一个月，算挺快的&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736692407/24.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;申领申报卡完成 ✅&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(三)：社会保险网上服务平台 - 单位信息登记</title><link href="https://blog.yasking.org/a/self-employed-part-three.html" rel="alternate"></link><published>2025-01-05T21:00:00+08:00</published><updated>2025-01-05T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-05:/a/self-employed-part-three.html</id><summary type="html">&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;网站地址：&lt;a href="https://fuwu.rsj.beijing.gov.cn/zhrs/yltc/yltc-home"&gt;https://fuwu.rsj.beijing.gov.cn/zhrs/yltc/yltc-home&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;电子营业执照&lt;/h3&gt;
&lt;p&gt;在登录 “社会保险网上服务平台” 之前，先下载电子营业执照&lt;/p&gt;
&lt;p&gt;在支付宝或微信 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;网站地址：&lt;a href="https://fuwu.rsj.beijing.gov.cn/zhrs/yltc/yltc-home"&gt;https://fuwu.rsj.beijing.gov.cn/zhrs/yltc/yltc-home&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;电子营业执照&lt;/h3&gt;
&lt;p&gt;在登录 “社会保险网上服务平台” 之前，先下载电子营业执照&lt;/p&gt;
&lt;p&gt;在支付宝或微信搜索 “电子营业执照” 小程序&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/02.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;首次登录有提醒，点击 “下载执照”，登记地选择 “北京”，可以看到注册的个体户记录，勾选并点击开始下载&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/03.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;下载后会提示修改密码，建议点击修改密码进行修改&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/04.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;后续需要电子营业执照登录的地方，点击页面上的 “扫一扫”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/05.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;单位登录&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/06.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “单位登录” 会跳到统一登录页面，使用 “电子营业执照” 小程序进行扫码登录&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/07.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;首先会弹出登记提示，点击 “去登记”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/08.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/09.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “开始申报”，正常情况，会代入共享信息，但很可能带不过来，提示如下图&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/10.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;别急，可以尝试等待一两天，可能信息就共享成功了（强烈建议等待同步成功）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/11.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;同步成功后，可以发现有一些字段已经自动填写且不可更改，例如 “单位类型” 和 “成立日期”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;“登记注册地址” 我这里填写的居住证地址，一模一样，注册街道按实际地址填写，因为“单位经营(办公)地址” 这里自动代入了网店地址，前面我没有选择。&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;工商执照部分正常填写，往上翻有实例图，可以看到登记机关和经营范围已自动自动代入。&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;所属行业自动代入了 “F5219”&lt;/p&gt;
&lt;p&gt;同理，法定代表人(负责人)信息自动代入了姓名，其它信息补充填写&lt;/p&gt;
&lt;p&gt;信息同步成功后，最大的变化是 &lt;strong&gt;无需再上传要件！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;翻到 “下一页” 继续提交联系人信息，填写手机，填写验证码&lt;/p&gt;
&lt;p&gt;然后点击提交后&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/16.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;点击确定，会重新登录，使用 “电子营业执照” 扫码登录后，点击 “单位中心”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;可以看到已 “即时办结”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “查看详细信息及表单下载” 进入详情页可以看到结果表单&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;在 &lt;em&gt;用人单位信息登记_办结通知单.pdf&lt;/em&gt; 这个文件中，如果审批不通过，会有原因&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736071428/20.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;此时回到登录后的公司首页：&lt;a href="https://fuwu.rsj.beijing.gov.cn/zhrs/yltc/company/index"&gt;https://fuwu.rsj.beijing.gov.cn/zhrs/yltc/company/index&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;可以看到左侧出现功能列表（备注：使用 Chrome 谷歌系列浏览器，Firefox 火狐浏览器存在兼容性问题不显示左侧列表）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736071428/21.jpg"&gt;&lt;/p&gt;
&lt;p&gt;至此，单位信息登记完成，接下来要做的是员工增员、领取社保卡 ✅&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(二)：北京 e 窗通平台提交申请</title><link href="https://blog.yasking.org/a/self-employed-part-two.html" rel="alternate"></link><published>2025-01-04T21:00:00+08:00</published><updated>2025-01-04T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-04:/a/self-employed-part-two.html</id><summary type="html">&lt;p&gt;通过北京 e 窗通，可以办理营业执照，也可以一站式将资料提交到社保部门和税务部门&lt;/p&gt;
&lt;p&gt;北京 e 窗通地址：&lt;a href="https://ect.scjgj.beijing.gov.cn/index"&gt;https://ect.scjgj.beijing.gov.cn/index …&lt;/a&gt;&lt;/p&gt;</summary><content type="html">&lt;p&gt;通过北京 e 窗通，可以办理营业执照，也可以一站式将资料提交到社保部门和税务部门&lt;/p&gt;
&lt;p&gt;北京 e 窗通地址：&lt;a href="https://ect.scjgj.beijing.gov.cn/index"&gt;https://ect.scjgj.beijing.gov.cn/index&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点选「个人服务」并登录，登录后完成实名认证（使用微信小程序 「北京企业服务 e 窗通」进行实名认证）。&lt;/p&gt;
&lt;p&gt;另外办理过程中，有保存的按钮记得点击，这样进度能够保存，中断重新进入办理上一次进度不会丢失&lt;/p&gt;
&lt;h3&gt;名称申报&lt;/h3&gt;
&lt;p&gt;考虑到名称在「立即办理」过程中可能被驳回不通过，我们可以在申请的时候先申请下来名称，名称通过后再点击个体工商户开办的「立即办理」按钮&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择设立申报&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/03.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “我同意”，下一步&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/04.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;再次点击 “个体名称” &lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/05.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;想一个喜欢的字号，检测是否可用（字号就是公司名），因为开设的网店计划售卖服装等，选择的 “商贸中心” 后缀，能经营的品类范围会比较大&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/06.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;如果一些词汇跟现有公司可能存在争议，也可以选择 “继续使用”，由人工审核人员决定是否通过，确定使用这个名称后点击 “继续填写补充信息”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/07.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;提交后，在首页「名称申报」处可以看到审核进度&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;没有争议一会儿就能出结果（如果存在争议可能需要等待工作日进入人工审核环节）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/09.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;个体工商户开办&lt;/h3&gt;
&lt;p&gt;申报名称成功后，接下来开始申请开通个体工商户&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;办理业务&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;您是否使用自主申报通过的名称进行登记 ？如果之前手动申请了名称选择 “是”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;您是否在区政务服务中心办理个体工商户一站式开办 ？选择 “是”，这样可以一站式办理营业执照、刻制印章、涉税事项、员工五险一金备案和银行开户业务。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;您当前是否涉税事项申报（领用发票 ）？是&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;您是否进行银行开户服务 ？否 （开公户每年有几百元的费用，不开不影响缴纳社保，只是不能自动扣款）&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;点击 “申请营业执照”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击进入办理&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;完善经营者信息&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;因为已实名，所以自动代入了一条记录，编辑进行完善&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;其中，「职业状况」可以写 “个体”，我写的 “在职” （按实际填写），「人员类型」选择 “个体户” 后点击下一步&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;填写基本信息&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/14.jpg"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;是否申请网店登记，选择 “是”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;地址填写注册微店或淘宝店的地址，注意必须是 “微店：xxx” 这样的格式，否则会审核不通过&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;经营形式选择 “个体座商”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;资金数额无需实缴，但也应填写合理数额，以免政策调整需要缴纳时无法兜底&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;经营地所处地域，选择 “城镇”&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;经营范围&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;点击 “经营范围规范表述查询” 按钮，对经营内容进行查询&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;按主题选择比较方便&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;如果你想在网店上卖一些东西，那么可以选择 “服装店”、“玩具店” 等你要卖东西的品类，选择「一般事项」的内容，如烟酒需要前置许可，书店需要后置许可，不要选择这些需要多余手续的&lt;/p&gt;
&lt;p&gt;如果你 “不太关心售卖的物品或短期内暂不上架商品”，那么到 “服装店” 类别选择一个主类别即可。&lt;/p&gt;
&lt;p&gt;正常选择，不建议跨多个品类选择多个主营，可能会被拒&lt;/p&gt;
&lt;p&gt;点击右上角的 “生成结果”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;关闭弹窗后可以看到经营范围，点击下一步。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;基本信息 - 补充信息&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;五险一金信息（多证合一）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;如上图选择，根据居住证所在区的机构和单位，我在昌平区所以社保等都选择昌平&lt;/p&gt;
&lt;p&gt;添加新员工（可选）：我在这里没有添加，后续可以单独的办理增员，下图所示，跳过&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;免费的四章全选&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/20.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;涉税事项&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;填写电话和邮编，邮编可以通过 &lt;a href="https://www.youbianku.com/"&gt;https://www.youbianku.com/&lt;/a&gt; 邮编库查询&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/21.jpg"&gt;&lt;/p&gt;
&lt;p&gt;填写经营项目明细调查，不是特别重要，根据预计填写一些&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/22.jpg"&gt;&lt;/p&gt;
&lt;p&gt;企业套餐式信息采集表，不填写，直接点击下一步&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/23.jpg"&gt;&lt;/p&gt;
&lt;p&gt;此时已填写完成，回到首页，最终确认提交，如果提示 “认证失败”，如果你已经实名，多半是节假日提交的，等工作日再提交就可以了&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/24.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;提交完成后状态变为 “待在线签字”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/25.jpg"&gt;&lt;/p&gt;
&lt;p&gt;此时还未提交到业务部门，需要我们进行签字确认&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;签字确认&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;点击 “详情” 进入详情页，切换到 “在线签字信息” 栏&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/26.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击上图中的 “在线签字”，选择 “小程序扫一扫业务确认”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/27.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;生成文书，进行文书确认&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/28.jpg"&gt;&lt;/p&gt;
&lt;p&gt;没问题点击下一步&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/29.jpg"&gt;&lt;/p&gt;
&lt;p&gt;刻章备案信息，跟我们无关，继续点击下一步&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/30.jpg" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;签署承诺书，选择 “知道了”，然后点击 “同意并下一步”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/31.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;上边这个页面无需按照页面提示操作。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;需要使用 “北京企业服务e窗通” 小程序进行确认（非扫码）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/32.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;点击页面上的 “业务确认”，人脸认证后如果提示 &lt;strong&gt;未开启办理企业登记注册，请在个人认证时开启办理&lt;/strong&gt;，则需要点击首页上的 “个人认证”，将 “是否办理登记业务” 的 “是” 勾选后重新认证。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/33.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;然后在到 “业务确认” 板块，选择 “自然人/法人业务确认”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/34.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;选择要注册的个体户，点击 “业务确认“，一路下一步，签字确认，完成后页面会清空&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1736002140/35.jpg" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;确认后再次回到网页端，详情中可以看到 “签字完成 ✅”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/36.jpg"&gt;&lt;/p&gt;
&lt;p&gt;看到办理状态已变为 “审查中”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/37.jpg"&gt;&lt;/p&gt;
&lt;p&gt;可能会有短信通知，过段时间主动来看下&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/38.jpg"&gt;&lt;/p&gt;
&lt;p&gt;不到一个小时营业执照已审核通过，效率超高！（此时可以点击 “领取证照”），先到详情看一下状态&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/39.jpg"&gt;&lt;/p&gt;
&lt;p&gt;涉税事项进行中&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/40.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;领取证照&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;此时，公章还在刻制中，再等一等（不要 “打印领照单”，如果打印将需要自行去管理局线下领取）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/41.jpg"&gt;&lt;/p&gt;
&lt;p&gt;等待几个小时至一天不等（我在当天下午六点刷新页面已变为 “可领取”）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/42.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择 EMS 寄送，填写收章地址，提交后等待即可&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/skills/1736002140/43.jpg"&gt;&lt;/p&gt;
&lt;p&gt;订单编号（可能）不是物流的快递单号，因为在两天后已收到快递后，此处还显示的 “尚未配送”，也可能是系统数据同步有延迟&lt;/p&gt;
&lt;p&gt;至此，个体工商户开办完成，万里长城走完了第一步 ✅&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>非京籍个体户缴纳社保(一)：概览与先期准备</title><link href="https://blog.yasking.org/a/self-employed-part-one.html" rel="alternate"></link><published>2025-01-03T21:00:00+08:00</published><updated>2025-01-03T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2025-01-03:/a/self-employed-part-one.html</id><summary type="html">&lt;h3&gt;缘起&lt;/h3&gt;
&lt;p&gt;个体经营、非全日制、新就业形态等从业人员，没有入职公司上班，也就没有职工社保（五险一金），一般有几个选择：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;以灵活 …&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt;</summary><content type="html">&lt;h3&gt;缘起&lt;/h3&gt;
&lt;p&gt;个体经营、非全日制、新就业形态等从业人员，没有入职公司上班，也就没有职工社保（五险一金），一般有几个选择：&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;以灵活就业人员身份缴纳职工社保&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缴纳城乡居民社保&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;缴纳商业保险&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;不缴纳&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;首先排除掉“不缴纳”，因为不缴纳什么都不需要做，“商业保险” 也不在本文讨论范畴&lt;/p&gt;
&lt;p&gt;在前两者中，“城乡居民社保” 的保障特别基础，其中的居民医保（新农合）是缴纳一年保障一年，不缴纳则不享受待遇，相比之下，职工医保退休后可以不用再缴纳也享有终身医保待遇。&lt;/p&gt;
&lt;p&gt;另外一个重要的区别是 “城乡居民” 和 “企业职工” 是两条线，不能互转，一些群体在上班和不上班之间徘徊，缴纳些许年职工社保但不满足退休条件，或是阶段性不去上班，以后还会找工作上班，灵活就业就是很好的补充，简单说就是公司和个人的钱都由个人缴纳，国家也算这些人为 “企业职工”，这就是灵活就业人员，养老和医疗保险待遇跟企业职工没有区别（灵活就业人员没有工伤、失业和生育保险，2025年有地区已经出台政策，灵活就业人员可以缴纳生育保险，但不能领取生育津贴）&lt;/p&gt;
&lt;p&gt;基于以上的差异和对比，很多人会 “以灵活就业人员身份缴纳职工社保”，一般情况下灵活就业人员可以在工作地缴纳，但首都有自己的规则&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;在北京的灵活就业人员不能单独缴纳医保，需要养老保险同时缴纳&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;外来的非京籍打工人，不能以灵活就业方式缴纳社保&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;也有变通的方法，即在北京注册 “个体工商户”，以 “做买卖” 的经营者身份，可以给自己缴纳五险一金&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1735903827/100001.jpg" width ="66%" /&gt;&lt;/p&gt;
&lt;p&gt;上图是 2024 年下半年的个体户缴纳社保最低费用：2540.42 元/月&lt;/p&gt;
&lt;p&gt;从网上分享来看，一般开通个体户缴纳社保有以下几个原因&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;在北京做小本经营，需开发票的经营者&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;担心可能被毕业或已毕业的打工人，即使毕业也能给自己续上让社保不断缴&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在北京生活的全职妈妈&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;想要在北京办理退休的灵活就业人员&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;社保要分开来看，其中的养老保险全国标准统一，计算公式相同，都是多缴多得，差距有限，但是医保待遇的差别就大了，从全国来看，北京的医保待遇是独一档的，报销比例高、门诊没有支付上限等等。&lt;/p&gt;
&lt;p&gt;另外值得一提的是个体户也可以为自己缴纳住房公积金，可以用来买房贷款&lt;/p&gt;
&lt;p&gt;关于断缴社保的部分影响：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;机动车摇号条件：近五年(含)连续在本市缴纳社会保险费，不能断月&lt;/p&gt;
&lt;p&gt;医保：医保一般是中断3个月之内，重新续交的，不管是否补交，医保要在重新续交的次月生效。中断3个月以上的，要在重新续交6个月以后，医保才会生效。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;铺垫了很多，应该算是讲清楚了 “非京籍个体户缴纳社保” 这个事情的来龙去脉&lt;/p&gt;
&lt;p&gt;本系列将会记录从准备到最终成功缴纳社保的所有流程步骤，门槛不高，但着实需要些时间和精力，整理出来以作备忘，同时也希望能帮助到有需要的人&lt;/p&gt;
&lt;p&gt;如果你需要开通个体户进行经营活动，或是为自己、家人缴纳社保，那话不多说，快上车！&lt;/p&gt;
&lt;h3&gt;先期准备&lt;/h3&gt;
&lt;p&gt;不得不说，北京的政务系统可用性蛮高的，几乎可以全程网上办理，仅居住证确认单需要去一次派出所开具&lt;/p&gt;
&lt;p&gt;有两个需要先期准备的资料&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;开通网店（开通个体工商户需要先开网店，可以是淘宝或者微店，后者微店更简单一些）&lt;/li&gt;
&lt;li&gt;拥有北京市居住证，并打印居住证确认单（附近派出所）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;微店开店&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;下载微店（店长版），登录后进行店铺认证。&lt;/p&gt;
&lt;p&gt;点击右上角的 “设置” - “店铺设置” - “店铺资料” - “微店开店证明”，保存「微店平台店铺经营证明」图片。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1735903827/100002.jpg" width ="66%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;北京市居住证&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果已经有居住证，&lt;strong&gt;携带身份证&lt;/strong&gt;去附近派出所打印居住证确认单（不能使用电子版居住证）&lt;/p&gt;
&lt;p&gt;从未申领过居住证，需要先在微信搜索 "北京市居住证" 公众号，提交申领居住证，过两天会有社区或户籍工作人员联系你上门办理&lt;/p&gt;
&lt;p&gt;准备好以上材料，就可以申请开通个体工商户了&lt;/p&gt;
&lt;p&gt;本篇概览内容就先到这里！&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>养老保险零基础入门指南（速通版）</title><link href="https://blog.yasking.org/a/yanglaobaoxian-quick-start.html" rel="alternate"></link><published>2024-12-31T21:00:00+08:00</published><updated>2024-12-31T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-12-31:/a/yanglaobaoxian-quick-start.html</id><summary type="html">&lt;p&gt;本文涉及到的知识点如下，要点内容将持续更新&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;什么是 “社平工资”？&lt;/li&gt;
&lt;li&gt;社保缴费基数是否等同于社平工资？&lt;/li&gt;
&lt;li&gt;缴费档位与月缴费 …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;本文涉及到的知识点如下，要点内容将持续更新&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;什么是 “社平工资”？&lt;/li&gt;
&lt;li&gt;社保缴费基数是否等同于社平工资？&lt;/li&gt;
&lt;li&gt;缴费档位与月缴费金额&lt;/li&gt;
&lt;li&gt;社保个人账户与余额&lt;/li&gt;
&lt;li&gt;退休能发多少钱 - 速算版&lt;/li&gt;
&lt;li&gt;退休能发多少钱 - 计算规则&lt;/li&gt;
&lt;li&gt;“退休” 是什么意思？&lt;/li&gt;
&lt;li&gt;延迟退休政策&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1）什么是 “社平工资”？&lt;/h3&gt;
&lt;p&gt;答：被保险人退休时上一年本省（市）职工月平均工资（由当地政府发布）&lt;/p&gt;
&lt;p&gt;例一：黑龙江省 2023 年的社平月工资是 7010 元/月&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;根据黑龙江省人社厅《关于确定2024年度基本养老保险使用的全口径就业人员平均工资的通知》（黑人社函〔2023〕625号），2024年度全省缴纳基本养老保险费及计发基本养老金使用的上年度全口径就业人员平均工资为84120元，上年度全口径就业人员月平均工资为7010元。自2024年1月1日起使用。&lt;/p&gt;
&lt;p&gt;—— &lt;a href="https://m12333.cn/qa/puipb.html"&gt;《黑龙江省 2024年灵活就业人员养老保险缴费标准（全口径就业人员平均工资/社会平均工资）》&lt;/a&gt; - 2024-07-16&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;例二：北京市 2023 年的社平月工资是 11761 元/月&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;北京市全口径城镇单位就业人员平均工资由城镇非私营单位就业人员平均工资和城镇私营单位就业人员平均工资加权计算，仅用于核定北京市社保个人缴费基数上下限。&lt;/p&gt;
&lt;p&gt;2023：年平均工资（元）141133 / 月平均工资（元）11761&lt;/p&gt;
&lt;p&gt;—— &lt;a href="https://rsj.beijing.gov.cn/bm/ywml/202007/t20200717_1950961.html"&gt;《历年北京市全口径城镇单位就业人员平均工资》&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;2）社保缴费基数是否等同于社平工资？&lt;/h3&gt;
&lt;p&gt;答：社保缴费基数是根据社平工资来确定的，但不一定相等&lt;/p&gt;
&lt;p&gt;例一：黑龙江省 2024 年企业职工按 100% 档缴费基数等同于社平工资 7010 元、缴费基数下限为 4206（等于社平工资 7010/月的 60%）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;根据黑龙江省人社厅《关于确定2024年度基本养老保险使用的全口径就业人员平均工资的通知》（黑人社函〔2023〕625号），2024年度全省缴纳基本养老保险费及计发基本养老金使用的上年度全口径就业人员平均工资为84120元，上年度全口径就业人员月平均工资为7010元。自2024年1月1日起使用。&lt;/p&gt;
&lt;p&gt;—— &lt;a href="https://m12333.cn/qa/puipb.html"&gt;《黑龙江省 2024年灵活就业人员养老保险缴费标准（全口径就业人员平均工资/社会平均工资）》&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;例二：北京市 2024 年企业职工缴费基数下限为 6821 元，机关事业单位职工缴费基数下限为 7057 元（等于社平工资 11761/月的 60%）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;一、自2024年7月起，本市2024年度企业职工基本养老保险、失业保险、工伤保险、职工基本医疗保险（含生育）月缴费基数上限确定为35283元，月缴费基数下限为6821元。&lt;/p&gt;
&lt;p&gt;四、自2024年7月起，本市2024年度机关事业单位职工基本养老保险月缴费基数上限确定为35283元，月缴费基数下限为7057元。&lt;/p&gt;
&lt;p&gt;—— &lt;a href="https://rsj.beijing.gov.cn/xxgk/2024zcwj/202407/t20240731_3763677.html"&gt;《北京市人力资源和社会保障局 北京市医疗保障局 国家税务总局北京市税务局关于统一2024年度各项社会保险缴费工资基数上下限的通告》&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;月缴费基数下限通常是根据上一年度社会平均工资（社平工资）来确定的，根据国家政策，缴费基数下限一般不低于社平工资的 60%，上限一般不超过社平工资的 300%&lt;/p&gt;
&lt;p&gt;可见北京企业职工的缴费基数下限（6821元）低于机关事业单位的缴费基数下限（7057元），这说明北京在基数下限的设置上跟社平工资有关，同时也具有一定的灵活性，主要目的应该是为了减轻企业的社保缴费负担&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;当且仅当此地区以上年度社平月工资作为 100% 档位缴费基数，且参保人选择以 100% 档位缴纳社保时，其缴费基数等同于社平工资&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;例如，黑龙江省 2024 年社平工资为 7010 元，政策规定 100% 档位缴费基数为 7010 元，因此选择 100% 档位的参保人，其缴费基数就是 7010 元&lt;/p&gt;
&lt;h3&gt;3）缴费档位与月缴费金额&lt;/h3&gt;
&lt;p&gt;知道了缴费档位，就能够确定月缴费金额，当前政策，灵活就业人员养老保险月缴额为缴费基数的 20%&lt;/p&gt;
&lt;p&gt;黑龙江灵活就业人员，养老保险最低月缴金额为 841.2 元&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1735655477/100001.webp" width ="42%" /&gt;&lt;/p&gt;
&lt;p&gt;北京灵活就业人员，养老保险最低月缴金额为 1364.2 元&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1735655477/100002.webp" width ="42%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;补充：北京不允许非京籍以灵活就业人员身份缴纳社保&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;4）社保个人账户与余额&lt;/h3&gt;
&lt;p&gt;上文提到了养老保险月缴额为缴费基数的 20%，其组成为：缴费基数的 12% 进入统筹、8% 进入个人账户&lt;/p&gt;
&lt;p&gt;统筹账户是大池子，到退休后按照一定规则从大池子中拿一些，再从个人账户拿一些，加一起就是每月的退休金&lt;/p&gt;
&lt;p&gt;以黑龙江灵活就业最低档缴费为例，841.2 元中， 336.48 累计到个人账户&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;余额查询&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通过各省政务网站或小程序可查询，以哈尔滨为例，可以使用 “黑龙江全省事” 小程序，进入后切换到哈尔滨，热门推荐或更多中可以看到 “养老保险个人账户查询”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1735655477/100003.webp" width ="42%" /&gt;&lt;/p&gt;
&lt;p&gt;北京则通过 “京通” 小程序，通过 “社保个人对帐单” 查询余额&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1735655477/100004.webp" width ="42%" /&gt;&lt;/p&gt;
&lt;h3&gt;5）退休能发多少钱 - 速算版&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;注意：速算版非官方计算规则，只是一个经验公式，能够快速获得粗略结果&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;计算公式&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;= （缴费年限 + 个人账户余额（单位为万）） x 100
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;例如：社保共计缴费 20 年，个人账户累计余额 8 万，(20 + 8) x 100 = 2800 / 月&lt;/p&gt;
&lt;p&gt;根据经验来看，速算版上下浮动有限，&lt;/p&gt;
&lt;h3&gt;6）退休能发多少钱 - 计算规则&lt;/h3&gt;
&lt;p&gt;虽说可以根据社保规则进行计算，但显然没人可以知道几十年后的社平基数、政策调整等情况，只能在当前已知规则前提下进行估算&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;退休养老金 = 基础养老金 + 个人账户养老金 + 过渡性养老金&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;基础养老金&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;= (计发基数 + 计发基数 × 个人缴费指数 ) ÷ 2 × 缴费年限 × 1%
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;根据国家规定，基本养老金由基础养老金（统筹养老金）和个人账户养老金组成。退休时的基础养老金月标准以国家确定的&lt;strong&gt;计发基数&lt;/strong&gt;和本人指数化月平均缴费工资的平均值为基数，缴费每满1年发给1％。个人账户养老金月标准为个人账户储存额除以计发月数，计发月数根据职工退休时城镇人口平均预期寿命、本人退休年龄、利息等因素确定。&lt;/p&gt;
&lt;p&gt;—— 山东坊子人社服务公众号《社会保险常用政策问答——待遇计发篇》&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;其中的计发基数以黑龙江为例，等同于社平工资&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;= (P + P × i ) ÷ 2 × n × 1% 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;例如，黑龙江灵活就业人员以最低档位（60%）缴纳 20 年，假设退休时上年度社平是 8000&lt;/p&gt;
&lt;p&gt;假设社平基数，每年上涨 2%，20 年后是 7010×(1+0.03)^20 = 12660&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;= 12660 × (1 + 0.6）÷ 2 × 20 × 1%
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;统筹部分 2025（元/月）&lt;/p&gt;
&lt;p&gt;个人账户养老金累计约等于 81000 元，算上年化 1% 的利息相当于 90000 元&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;= 336.48 × 12 × 20
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;个人养老金每月发放多少取决于计发月数&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;计发月数：根据平均寿命计算，50岁退休按 195 个月，55岁退休按 170 个月，60 岁退休按 139个月。这个“计发月数”只是用来计算退休当年的养老金，与实际发放月数无关，实际会终身发放。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;此时以 139 为计发月数进行计算 &lt;/p&gt;
&lt;p&gt;个人养老金：90000 / 139 = 647 元&lt;/p&gt;
&lt;p&gt;合计：2025 + 647 = 2672 元/月&lt;/p&gt;
&lt;p&gt;因为本例中的利息和社平增长率相对很保守，回过头看看速算版，也属于大差不差。为什么没提过渡性养老金，这个跟八零、九零后同学没啥关系，不用了解&lt;/p&gt;
&lt;h3&gt;7）“退休” 是什么意思？&lt;/h3&gt;
&lt;p&gt;退休，说的是发放待遇时间&lt;/p&gt;
&lt;p&gt;重点要考：&lt;strong&gt;什么时候退休意味着你能从什么时候开始领取养老金，不代表你可以一直工作到退休&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;8）延迟退休政策&lt;/h3&gt;
&lt;p&gt;政策调整前，男性职工统一六十周岁退休，新华社 2024 年 9 月 13 日刊发文章：&lt;a href="https://www.gov.cn/yaowen/liebiao/202409/content_6974294.htm"&gt;《全国人民代表大会常务委员会关于实施渐进式延迟法定退休年龄的决定》&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;第一条　从2025年1月1日起，男职工和原法定退休年龄为五十五周岁的女职工，法定退休年龄每四个月延迟一个月，分别逐步延迟至六十三周岁和五十八周岁；原法定退休年龄为五十周岁的女职工，法定退休年龄每二个月延迟一个月，逐步延迟至五十五周岁。国家另有规定的，从其规定。&lt;/p&gt;
&lt;p&gt;第二条　从2030年1月1日起，将职工按月领取基本养老金最低缴费年限由十五年逐步提高至二十年，每年提高六个月。职工达到法定退休年龄但不满最低缴费年限的，可以按照规定通过延长缴费或者一次性缴费的办法达到最低缴费年限，按月领取基本养老金。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;即部分七零后，八零九零、零零后，国家来养老的时间需要再多等三年&lt;/p&gt;
&lt;p&gt;倘若 43 岁失业，63 岁领取养老金，上有老下有小的打工人这 20 年会有些难熬...&lt;/p&gt;
&lt;p&gt;另外，当前最低缴纳年限现在是十五年，等打工人退休时，最低要缴纳二十年才能办理退休&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;未完待续...&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>了解北京门诊看病工会“二次报销”互助金</title><link href="https://blog.yasking.org/a/beijingshigonghui-huzhujin.html" rel="alternate"></link><published>2024-12-23T21:00:00+08:00</published><updated>2024-12-23T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-12-23:/a/beijingshigonghui-huzhujin.html</id><summary type="html">&lt;p&gt;本文概览: 记录注册成为北京市工会会员，享受医保二次报销互助金，工会默默给你打钱&lt;/p&gt;
&lt;p&gt;费用情况: 注册和开银行卡均免费 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;本文概览: 记录注册成为北京市工会会员，享受医保二次报销互助金，工会默默给你打钱&lt;/p&gt;
&lt;p&gt;费用情况: 注册和开银行卡均免费&lt;/p&gt;
&lt;p&gt;适宜群体: 每个在京打工人(除"先天无垢圣体")，建议办理避免错过一个亿&lt;/p&gt;
&lt;h3&gt;提交入会申请&lt;/h3&gt;
&lt;p&gt;先下载 “北京工会 APP”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100001.webp" width = "38%" /&gt;&lt;/p&gt;
&lt;p&gt;首页的样子&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100002.webp" width = "38%" /&gt;&lt;/p&gt;
&lt;p&gt;点击页面右上角的 “我要入会”，填写资料提交申请，等待审核。&lt;/p&gt;
&lt;p&gt;一般一到两个工作日就会审核完成，会收到短信通知&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100003.webp" width = "42%" /&gt;&lt;/p&gt;
&lt;h3&gt;办理北京银行工会互助卡&lt;/h3&gt;
&lt;p&gt;审核通过后，&lt;strong&gt;携带身份证&lt;/strong&gt;，就近找到北京银行（必须到「北京银行」办理&lt;strong&gt;工会互助卡&lt;/strong&gt;）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;那我已经有了北京银行的银行卡能不能直接使用？
答：不能&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100004.webp" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;跟工作人员说办理 “工会互助卡”，工作人员会指导办理，几分钟就能下卡&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100005.webp" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;出了银行，打开工会 APP，到 “我的” - “个人信息” 页面就可以看到「工会会员互助服务卡」已显示银行卡号，自动绑定成功&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;至此，你啥都不用再管，看了病过段时间自己就会冒出钱来了&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果想要了解“互助金”的补贴规则，可以继续阅读&lt;/p&gt;
&lt;h3&gt;门诊 “二次报销”&lt;/h3&gt;
&lt;p&gt;入会成功后可以享受两类保障 —— “普惠型保障” 与 “会员型保障”，前者入会就有，后者需要所在公司参保（暂不关心），本文只记录了普惠型保障的门诊互助金相关，会员型保障暂不作了解&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100006.webp" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;“普惠型保障” 的互助金的温馨提示&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;“个人自费”、“自付二” 不享受互助金。&lt;/li&gt;
&lt;li&gt;员工需持有工会会员互助服务卡。&lt;/li&gt;
&lt;li&gt;拖欠医疗保险费，保障期限内未补交不享受互助金。&lt;/li&gt;
&lt;li&gt;需是北京市总工会管理的工会会员。&lt;/li&gt;
&lt;li&gt;工伤、生育、职业病导致的医疗费用不享受互助金。&lt;/li&gt;
&lt;li&gt;被保障人不可采取欺诈手段骗取互助金。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;二次报销的互助金比例&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100007.webp" width = "66%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;在北京正常参保，门诊费用超过医保起付线 1800 （全年累计）后的 “自付一” 费用，可获得 20% 的互助金&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;简单说就是门诊看病过了起付线，一般来说，都能得到几杯奶茶钱或几千块的空投互助金&lt;/p&gt;
&lt;p&gt;如果你经常走医保门诊看病，花了不少钱，也比较关心自己的 “自付一” 金额情况，可以通过以下步骤查询：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;查询当前年度自付一总费用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;支付宝 - “京通” 小程序 &lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100008.webp" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “医保消费查询”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100009.webp" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;左右拖动到最后可以看到 “自付一年度总额”，点击 “显示金额” 查看&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100010.webp" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;发放时间&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;按季度支付，一般来说第一季度的互助金 5 月份发放、第二季度 8 月份、第三季度 11 月份、第四季度在次年 1、2 月份自动发放&lt;/p&gt;
&lt;p&gt;工会系统跟医保系统关联，普惠门诊互助金无需提交资料和申请，全程自动支付&lt;/p&gt;
&lt;p&gt;经验来看，很可能较高的 “延迟”（一两个月），如果等了一段时间还未发放，可以咨询 12351 了解情况&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;充要补充&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;如果你在 12 月份申请入会并成功办理工会卡，那么当年 1- 12 月份的 “自付一” 均可按规则正常发放，如果时间来到了一月份，已进入新的自然年，那么之前的互助金将不能补领！&lt;/p&gt;
&lt;p&gt;2025-01 月补充&lt;/p&gt;
&lt;p&gt;发放2024年4季度互助金人民币281.49元，等于自付一减去1800后20%的金额&lt;/p&gt;
&lt;h3&gt;工会卡福利二：可办理畅游公园 100 元年票&lt;/h3&gt;
&lt;p&gt;北京的畅游公园有两个面值的年卡，100 元和 200 元&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100011.webp" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;前者包含的公园少点儿，日常对一些人也够用，后者包含前者的同时也包含 “京津翼旅游卡” 的景区；另外还的区别即前者只有工会成员和退休人员才能办理&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/skills/1734926223/100013.webp" width = "42%" /&gt;&lt;/p&gt;
&lt;p&gt;对于住在市属公园周边，没事儿喜欢逛逛公园的打工人来说，畅游公园 100 元年卡性价比还挺高&lt;/p&gt;</content><category term="Skill"></category></entry><entry><title>注册 US.KG 免费域名（dpdns.org）</title><link href="https://blog.yasking.org/a/register-us-kg-free-domain.html" rel="alternate"></link><published>2024-10-11T21:00:00+08:00</published><updated>2024-04-11T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-10-11:/a/register-us-kg-free-domain.html</id><summary type="html">&lt;p&gt;2025-04-11 更新：今年三月中旬，us.kg 域名因为滥用等原因已凉，域名被自动迁移到 .dpdns.org, ns 信息丢失，需要重新配置，刚切换后不能绑 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;2025-04-11 更新：今年三月中旬，us.kg 域名因为滥用等原因已凉，域名被自动迁移到 .dpdns.org, ns 信息丢失，需要重新配置，刚切换后不能绑定 cf，今天测试绑定没有问题，如下图&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;风险提示：免费域名适合用来临时测试，稳定性可见一斑，不应用于稳定服务&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;官网地址：&lt;a href="https://nic.us.kg/"&gt;https://nic.us.kg/&lt;/a&gt;
注册链接：&lt;a href="https://register.us.kg/auth/register"&gt;https://register.us.kg/auth/register&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;注册 US.KG 域名（dpdns.org）&lt;/h3&gt;
&lt;p&gt;注册用户的过程很容易，之后会提示选择 KYC 校验&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;KYC 是注册域名时的一种重要合规措施，旨在验证客户身份、评估潜在风险，并确保客户符合相关法律法规。通过 KYC 验证，可以防止域名被用于非法活动，保护用户权益，并遵守法律法规。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;选择推荐的 Github KYC 校验&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;首先点击 Star 收藏&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;然后创建一个 Issues，标题需要是固定的格式 "Request GitHub KYC-&lt;your-email-address&gt;"&lt;/p&gt;
&lt;p&gt;可以点击快捷链接直接到 Issues 页面，它会自动填写标题和内容&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;填入你的账户信息&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;几个条件，满足的话勾选上，创建后等待 ⌛️&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;页面说会有每 15 分钟运行一次的自动化脚本进行处理（脚本似乎停了，等了一天看到 Issues 被处理）&lt;/p&gt;
&lt;p&gt;Issues 地址：&lt;a href="https://github.com/DigitalPlatDev/US.KG/issues/10666"&gt;https://github.com/DigitalPlatDev/US.KG/issues/10666&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;回到首页 &lt;a href="https://nic.us.kg/"&gt;https://nic.us.kg/&lt;/a&gt; 继续申请域名，每个用户最多可以申请三个域名&lt;/p&gt;
&lt;p&gt;点击页面左侧的 Domain Registration 选购域名，点击 Check 选择到可注册域名&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;注册前需要填入 Nameserver，此时来到 Cloudflare，注册网站（注：不存在的域名也可以添加到 Cloudflare）&lt;/p&gt;
&lt;p&gt;点击添加域名&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;填入我们申请的域名，选择 “Manually enter DNS records”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;套餐选择页面：免费计划，启动！&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;进到域名详情页，找到 Nameserver&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;将其填入 US.KG 域名注册页面&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击注册，提示注册成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;稍等几分钟，刷新可以看到域名已处于 &lt;code&gt;Active&lt;/code&gt; 活跃状态&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;回到 US.KG 面板，进入域名管理可以看到续费说明，域名有效期一年，过期前 180 天内可以点击续费&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;另外可以免费开启 Whois 保护&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728641324/16.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;最后的吐槽&lt;/h3&gt;
&lt;p&gt;&lt;del&gt;🤔 要是早些发现 US.KG 免费域名能绑定到 CloudFlare，我何必为了体验 CloudFlare 的服务注册个 xyz 域名呢（摔 &lt;/del&gt;&lt;/p&gt;
&lt;p&gt;免费域名说凉就凉，花小钱买省心，推荐购买便宜的域名使用&lt;/p&gt;</content><category term="Technology"></category><category term="FreeDomain"></category></entry><entry><title>白嫖 Cloudflare R2 + Worker 搭建私有镜像仓库</title><link href="https://blog.yasking.org/a/cloudflare-r2-container-registry.html" rel="alternate"></link><published>2024-10-10T21:00:00+08:00</published><updated>2024-10-10T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-10-10:/a/cloudflare-r2-container-registry.html</id><summary type="html">&lt;p&gt;前些天发现一个 Cloudflare Worker，可以搭配其 R2 存储创建私有镜像仓库，本篇记录部署过程和使用方法&lt;/p&gt;
&lt;h3&gt;部署服务&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;克隆 Worker 代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本地电 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;前些天发现一个 Cloudflare Worker，可以搭配其 R2 存储创建私有镜像仓库，本篇记录部署过程和使用方法&lt;/p&gt;
&lt;h3&gt;部署服务&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;克隆 Worker 代码&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;本地电脑执行，安装依赖&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ git clone https://github.com/cloudflare/serverless-registry.git
$ cd serverless-registry

# brew install pnpm
$ pnpm install 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;安装完成依赖后，通过模版创建自己的 Wrangler 配置文件&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ cp wrangler.toml.example wrangler.toml
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Cloudflare Wrangler 是一个命令行工具，用于管理和部署 Cloudflare Workers&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;修改 R2 存储桶名称（需要是不存在的桶名称）以及用于认证的用户名密码&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;## Production
[env.production]
r2_buckets = [
  { binding = &amp;quot;REGISTRY&amp;quot;, bucket_name = &amp;quot;r2-image-registry-prod&amp;quot; }
]

[env.production.vars]
USERNAME = &amp;quot;&amp;lt;your-username&amp;gt;&amp;quot;
PASSWORD = &amp;quot;&amp;lt;your-password&amp;gt;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;安装 Wrangler CLI&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ npm install -g wrangler
$ wrangler --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/02.jpg"&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ wrangler login
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它会调用浏览器弹出网页进行授权，点击同意&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;创建 R2 存储桶&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ npx wrangler --env production r2 bucket create r2-image-registry-prod
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;部署 Worker&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ npx wrangler deploy --env production
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;部署成功后会输出镜像仓库地址：https://r2-registry-production.kissbug8720.workers.dev&lt;/p&gt;
&lt;p&gt;在 Cloudflare 控制台「Workers &amp;amp; Pages」页面可以看到刚创建的 Worker&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;更新用户名/密码可以执行以下命令&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ npx wrangler secret put USERNAME --env production
$ npx wrangler secret put PASSWORD --env production
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;推送/拉取镜像进行测试&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;注意以下命令中的参数替换为你自己的地址和用户名&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 设置环境变量
$ export USERNAME=dong
$ export REGISTRY_URL=r2-registry-production.kissbug8720.workers.dev

# 登录/推送
$ docker login --username $USERNAME $REGISTRY_URL
$ docker pull alpine:latest
$ docker tag alpine:latest $REGISTRY_URL/alpine:latest
$ docker push $REGISTRY_URL/alpine:latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;在 R2 控制台上可以看到镜像已存储在 R2 桶&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/07.jpg"&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 拉取测试
$ docker rmi alpine:latest $REGISTRY_URL/alpine:latest
$ docker pull $REGISTRY_URL/alpine:latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;拉取成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;测试用户权限&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;可以通过 Curl 指定用户名密码的方式查询镜像列表来验证用户权限&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ curl -X GET -u dong:mypasswd https://r2-registry-production.kissbug8720.workers.dev/v2/_catalog
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;重新部署&lt;/h3&gt;
&lt;p&gt;如果修改了 &lt;em&gt;wrangler.toml&lt;/em&gt; 配置文件（例如：添加启用 Logs 的配置）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;# wrangler.toml (wrangler v3.78.6^)
[observability]
enabled = true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以重新执行命令部署&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ npx wrangler deploy --env production
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;启用日志后调试代码看日志很方便&lt;/p&gt;
&lt;h3&gt;使用 JWT 认证方式&lt;/h3&gt;
&lt;p&gt;这里官方仓库没有仔细介绍，看代码才捋顺通&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;需要注意&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JWT 认证方式和用户名密码在当前 worker 实现上是二选一的，启用 JWT 后用户名密码认证将失效&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;生成并配置公钥&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;生成公钥密码对，详参：&lt;a href="https://blog.yasking.org/a/learn-jwt-algorithm.html"&gt;《再思 JWT 的使用场景和算法选择》&lt;/a&gt;，可直接运行以下命令&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 私钥
$ openssl ecparam -name prime256v1 -genkey -noout -out ec_private.pem

# 公钥
$ openssl ec -in ec_private.pem -pubout -out ec_public.pem
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接下来使用在线工具：&lt;a href="https://jwkset.com/generate"&gt;JWK Generator&lt;/a&gt; 将 &lt;em&gt;ec_public.pem&lt;/em&gt; 的内容转换为 JWK 格式的 Key&lt;/p&gt;
&lt;p&gt;粘贴到左侧，其它参数不用选择，点击 “Generate”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;生成的结果在下方的 “PEM Generation Results”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;将 JSON 格式的 Key 复制&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  &amp;quot;kty&amp;quot;: &amp;quot;EC&amp;quot;,
  &amp;quot;kid&amp;quot;: &amp;quot;5910d7df-3a81-4a08-acd0-5dcd58486ed2&amp;quot;,
  &amp;quot;crv&amp;quot;: &amp;quot;P-256&amp;quot;,
  &amp;quot;x&amp;quot;: &amp;quot;hBBteH7wFAkCjoEmBMrKM9_5XtxdJLGMXMDL3QaT7nY&amp;quot;,
  &amp;quot;y&amp;quot;: &amp;quot;lSFOx774nFGYnV_vluA-Elp5Lv64uszu8pLzH7nOJU0&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;借助在线工具：&lt;a href="https://www.base64encode.org/"&gt;https://www.base64encode.org/&lt;/a&gt; 将 JSON Key 使用 Base64 Encode 编码，这就得到了 JWK &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;ewogICJrdHkiOiAiRUMiLAogICJraWQiOiAiNTkxMGQ3ZGYtM2E4MS00YTA4LWFjZDAtNWRjZDU4NDg2ZWQyIiwKICAiY3J2IjogIlAtMjU2IiwKICAieCI6ICJoQkJ0ZUg3d0ZBa0Nqb0VtQk1yS005XzVYdHhkSkxHTVhNREwzUWFUN25ZIiwKICAieSI6ICJsU0ZPeDc3NG5GR1luVl92bHVBLUVscDVMdjY0dXN6dThwTHpIN25PSlUwIgp9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个 Encoded JWK 就是 &lt;code&gt;JWT_REGISTRY_TOKENS_PUBLIC_KEY&lt;/code&gt; 环境变量所需的内容&lt;/p&gt;
&lt;p&gt;执行以下命令将 Key 应用设置到 Cloudflare&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ npx wrangler secret put JWT_REGISTRY_TOKENS_PUBLIC_KEY --env production &amp;lt;&amp;lt;EOF
ewogICJrdHkiOiAiRUMiLAogICJraWQiOiAiNTkxMGQ3ZGYtM2E4MS00YTA4LWFjZDAtNWRjZDU4NDg2ZWQyIiwKICAiY3J2IjogIlAtMjU2IiwKICAieCI6ICJoQkJ0ZUg3d0ZBa0Nqb0VtQk1yS005XzVYdHhkSkxHTVhNREwzUWFUN25ZIiwKICAieSI6ICJsU0ZPeDc3NG5GR1luVl92bHVBLUVscDVMdjY0dXN6dThwTHpIN25PSlUwIgp9
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;生成用于认证的 JWT Token&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Python3 代码示例（摘自：&lt;a href="https://blog.yasking.org/a/learn-jwt-algorithm.html"&gt;《再思 JWT 的使用场景和算法选择》&lt;/a&gt;），此处不多做介绍&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;import time
import jwt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

# 定义常量
EC_PRIVATE_KEY_PATH = &amp;quot;./ec_private.pem&amp;quot;
EC_PUBLIC_KEY_PATH = &amp;quot;./ec_public.pem&amp;quot;

# 加载私钥
def load_private_key(private_key_path):
    with open(private_key_path, &amp;quot;rb&amp;quot;) as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )
    return private_key

# 加载公钥
def load_public_key(public_key_path):
    with open(public_key_path, &amp;quot;rb&amp;quot;) as key_file:
        public_key = serialization.load_pem_public_key(
            key_file.read(),
            backend=default_backend()
        )
    return public_key

# 生成 JWT 令牌
def generate_jwt_token(private_key, algorithm):

    payload = {
        &amp;quot;iat&amp;quot;: int(time.time()),  # 使用秒级时间戳
        &amp;quot;username&amp;quot;: &amp;quot;v0&amp;quot;,
        &amp;quot;capabilities&amp;quot;: [&amp;quot;pull&amp;quot;, &amp;quot;push&amp;quot;],
        # &amp;quot;aud&amp;quot;: &amp;quot;r2-registry-production.kissbug8720.workers.dev&amp;quot;
        &amp;quot;iat&amp;quot;: int(time.time())  # 使用秒级时间戳
    }
    return jwt.encode(payload, private_key, algorithm=algorithm)

# 验证 JWT
def verify_jwt_token(token, public_key, algorithm):
    try:
        decoded = jwt.decode(token, public_key, algorithms=[algorithm])
        return decoded
    except jwt.InvalidTokenError:
        return None

# 主函数
def __main__():

    algorithms = [
        (&amp;quot;ES256&amp;quot;, EC_PRIVATE_KEY_PATH, EC_PUBLIC_KEY_PATH),
    ]

    for algorithm, private_key_path, public_key_path in algorithms:
        # 加载私钥和公钥
        private_key = load_private_key(private_key_path)
        public_key = load_public_key(public_key_path)

        # 生成 JWT
        jwt_token = generate_jwt_token(private_key, algorithm)
        print(f&amp;quot;生成的 {algorithm} JWT:&amp;quot;, jwt_token)

        # 验证 JWT
        decoded_payload = verify_jwt_token(jwt_token, public_key, algorithm)
        if decoded_payload:
            print(f&amp;quot;{algorithm} JWT 验证成功:&amp;quot;, decoded_payload)
        else:
            print(f&amp;quot;{algorithm} JWT 验证失败&amp;quot;)

        print(&amp;quot;---&amp;quot;)

if __name__ == &amp;quot;__main__&amp;quot;:
    __main__()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;这里的 JWT 即使用 &lt;em&gt;ec_private.pem&lt;/em&gt; 签名后的认证所需 Token，可以使用 Curl 请求 Registry 获取镜像列表进行权限验证（执行前注意替换 Token）&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ curl -X GET -u dong:&amp;lt;your-jwt&amp;gt; https://r2-registry-production.kissbug8720.workers.dev/v2/_catalog
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{&amp;quot;repositories&amp;quot;:[&amp;quot;alpine&amp;quot;]}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;简单在说下 JWT 在此处的流程，我们将 JWK 格式的公钥提交到 Cloudflare 后，推送的代码从环境变量 &lt;code&gt;JWT_REGISTRY_TOKENS_PUBLIC_KEY&lt;/code&gt; 可以获取到 Key，然后我们通过 Python 脚本借助私钥生成了 JWT，JWT 的参数中允许 PUSH 和 PULL 能力，签名后的 JWT 相当于密码，需要私密保存，请求 Cloudflare 时，Worder 代码中判断有 JWK 环境变量，就使用 JWT 的认证方式，使用签名验证这个 Token 是不是我们通过私钥签发的，校验没问题后读取出权限，进而允许 PUSH 和 PULL，完成认证过程&lt;/p&gt;
&lt;p&gt;本例中的 Worker 代码是从 Github 下载下来的基础功能代码，遇到问题以代码为准，调试代码可以借助 Cloudflare Worker 中的 Logs 查看日志去定位解决&lt;/p&gt;
&lt;p&gt;如需停用 JWT 认证，在 Cloudflare 控制台删除 &lt;code&gt;JWT_REGISTRY_TOKENS_PUBLIC_KEY&lt;/code&gt; 环境变量即可&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/14.jpg"&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ curl -X GET -u dong:mypasswd https://r2-registry-production.kissbug8720.workers.dev/v2/_catalog
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;配置镜像回源（未调试通过）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;没有测试通过，暂也记录下过程，给后续尝试的人一个参考&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;从日志看登录到 DockerHub 成功，但后续的请求报错&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;设置 REGISTRY_TOKEN&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个是 DockerHub 的用户密码&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ npx wrangler secret put REGISTRY_TOKEN --env production
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;编辑配置文件，添加 REGISTRIES_JSON 配置，注意替换为你的 DockerHub 用户名，配置中的变量 REGISTRY_TOKEN 不要修改，代码回自动从刚设置的 REGISTRY_TOKEN 环境变量中获取&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-yaml"&gt;[env.production.vars]
REGISTRIES_JSON = &amp;quot;[{ \&amp;quot;registry\&amp;quot;: \&amp;quot;https://registry.hub.docker.com\&amp;quot;, \&amp;quot;password_env\&amp;quot;: \&amp;quot;REGISTRY_TOKEN\&amp;quot;, \&amp;quot;username\&amp;quot;: \&amp;quot;kissbug8720\&amp;quot; }]&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;DockerHub 的用户名密码可以使用以下命令登录进行验证确认&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ docker login https://registry.hub.docker.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;执行命令重新部署&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ npx wrangler deploy --env production
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;拉取镜像进行测试&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ export REGISTRY_URL=r2-registry-production.kissbug8720.workers.dev
$ docker rmi nginx:latest $REGISTRY_URL/nginx:latest
$ docker pull $REGISTRY_URL/nginx:latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;到这一步，也翻了会儿源码，暂时也就先研究到这里，兴许是个 BUG... 以后真用到再说&lt;/p&gt;
&lt;h3&gt;小小收获&lt;/h3&gt;
&lt;p&gt;测试 fallback 功能时发现 README.md 中的配置示例有误, 这不白给的 BUG!
感觉 PR 在向我招手🙋&lt;/p&gt;
&lt;p&gt;赶紧提交了一个 PR(&lt;a href="https://github.com/cloudflare/serverless-registry/pull/63"&gt;#63&lt;/a&gt;),一天后被合并，也许是近些年第一次提交 PR 同时也被 Merged，很开心&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728553102/18.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/cloudflare/serverless-registry"&gt;Github: serverless-registry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Cloudflare"></category><category term="R2"></category></entry><entry><title>再思 JWT 的使用场景和算法选择</title><link href="https://blog.yasking.org/a/learn-jwt-algorithm.html" rel="alternate"></link><published>2024-10-06T21:00:00+08:00</published><updated>2024-10-06T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-10-06:/a/learn-jwt-algorithm.html</id><summary type="html">&lt;p&gt;在使用第三方服务的时候，我们总会看到其提供 API Key，这是一种简单的验证用户身份的方法，服务端存储着这个 API Key，可以 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;在使用第三方服务的时候，我们总会看到其提供 API Key，这是一种简单的验证用户身份的方法，服务端存储着这个 API Key，可以通过 Key 来确定用户权限、吊销 Key 等&lt;/p&gt;
&lt;p&gt;相比于 API Key，JWT 有自己的特点和适用场景，如果你不太了解 JWT，可以阅读阮一峰的：&lt;a href="https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html"&gt;《JSON Web Token 入门教程》&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;回顾 JWT 特点&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;自包含&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JWT 是一个自包含的 Token，它包含了所有必要的信息，不需要服务端存储 Token 的状态。JWT 的载荷（payload）部分可以包含用户信息、权限信息、有效期等。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;无状态&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;由于 JWT 自包含所有必要的信息，服务端不需要存储 Token 的状态，所以 JWT 非常适合用于无状态的应用架构，减少了服务端的负担。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;传输安全&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JWT 使用密钥进行签名，可以验证 Token 的合法性和完整性，签名或加密确保了 JWT 在传输过程中不会被篡改。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;扩展性&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JWT 的载荷部分是一个 JSON 对象，可以包含自定义的声明（claims）,这使得 JWT 非常灵活，可以根据具体需求扩展其功能。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;注意事项：在 JWT 中，避免包含密码等敏感信息，JWT 可防篡改但内容可见。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;不可撤销&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JWT 一旦生成，无法单独撤销。如果 JWT 被泄露，攻击者可以滥用 Token，直到 Token 过期，因此，JWT 的有效期通常设置得较短，以减少风险。（撤销需要借助服务器有状态机制）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;例举一种 JWT 场景误用&lt;/h3&gt;
&lt;p&gt;以 HS256 算法为例子，以下是生成和验证的代码示例&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;import time
import jwt

KEY_SECRET = &amp;quot;abncdsr462*********zk52hav3x86dm&amp;quot;

# 生成 JWT 令牌
def generate_jwt_token(key_secret, algorithm=&amp;quot;HS256&amp;quot;):
    payload = {
        &amp;quot;iat&amp;quot;: int(time.time())
    }
    token = jwt.encode(payload, key_secret, algorithm=algorithm)
    return token

# 校验 JWT 令牌
def verify_jwt_token(token, key_secret, algorithm=&amp;quot;HS256&amp;quot;):
    try:
        payload = jwt.decode(token, key_secret, algorithms=[algorithm])
        return payload
    except jwt.InvalidTokenError:
        return None

# 生成令牌
t = generate_jwt_token(KEY_SECRET)
print(f&amp;quot;生成的 JWT:&amp;quot;, t)

# 校验令牌
verified_payload = verify_jwt_token(t, KEY_SECRET)
if verified_payload:
    print(f&amp;quot;JWT 验证成功:&amp;quot;, verified_payload)
else:
    print(&amp;quot;JWT 验证失败&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;正确的 JWT 使用场景，会将 JWT &lt;code&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3Mjc2NjU2MTR9.ItXRitJXiwcDx7X1PHeilgwAs9vt4xaa1lHNKgC3wak&lt;/code&gt; 提供给客户端&lt;/p&gt;
&lt;p&gt;客户端调用服务端时将其再传给服务端，服务端可以验证这个 Token 没有被篡改、同时从中获取信息&lt;/p&gt;
&lt;p&gt;一个错误的用法是将 HS256 的 KEY_SECRET 提供给外部平台，由外部平台生成 JWT。这种方式相当于将 JWT 机制降级为 API Key，使得 JWT 的安全性从“JWT 丢失则其权限会被滥用” 降级为 “API Key 泄露则攻击者可无限制地伪造 JWT，可以对系统进行任意请求”，这属于比较严重的安全漏洞&lt;/p&gt;
&lt;p&gt;所以，当决定采用 JWT，就应尽量遵守其规范，避免 “新奇” 的使用方式&lt;/p&gt;
&lt;h3&gt;不同 JWT 算法使用示例（Python3）&lt;/h3&gt;
&lt;p&gt;JWT 支持 HS256（密钥）、RS256（基于 RSA）、ES256（基于椭圆曲线）、PS256（基于 RSA-PSS）等加密算法，数字表示位数，越长越安全，除 256 外还支持 384 和 512&lt;/p&gt;
&lt;p&gt;HS256 在上文已提供示例，它比较简单、使用的是密钥字符串，也是最常用的 JWT 加密算法，另外三者基于的公钥密码对&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;生成 RS256 公钥密码对&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 私钥
$ openssl genpkey -algorithm RSA -out rsa_private_key.pem -pkeyopt rsa_keygen_bits:2048

# 公钥
$ openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;生成 ES256 公钥密码对&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 私钥
$ openssl ecparam -name prime256v1 -genkey -noout -out ec_private.pem

# 公钥
$ openssl ec -in ec_private.pem -pubout -out ec_public.pem
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;这里选择的曲线进一步说明，prime256v1 P-256，Go 语言的 x509 包默认支持的椭圆曲线是 P-256 和 P-384，另一种常见的曲线是 secp256k1，它是比特币和其他加密货币中常用的椭圆曲线，Go 语言的 x509 包默认不支持它，Python3 是支持的&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;生成 PS256 公钥密码对&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 私钥
$ openssl genpkey -algorithm RSA -out ps_private_key.pem -pkeyopt rsa_keygen_bits:2048

# 公钥
$ openssl rsa -in ps_private_key.pem -pubout -out ps_public_key.pem
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;代码示例&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-python"&gt;import time
import jwt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend

# 定义常量
RSA_PRIVATE_KEY_PATH = &amp;quot;./id_rsa&amp;quot;
RSA_PUBLIC_KEY_PATH = &amp;quot;./id_rsa_pem.pub&amp;quot;
EC_PRIVATE_KEY_PATH = &amp;quot;./ec_private.pem&amp;quot;
EC_PUBLIC_KEY_PATH = &amp;quot;./ec_public.pem&amp;quot;
PS_PRIVATE_KEY_PATH = &amp;quot;./ps_private_key.pem&amp;quot;
PS_PUBLIC_KEY_PATH = &amp;quot;./ps_public_key.pem&amp;quot;

# 加载私钥
def load_private_key(private_key_path):
    with open(private_key_path, &amp;quot;rb&amp;quot;) as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,
            backend=default_backend()
        )
    return private_key

# 加载公钥
def load_public_key(public_key_path):
    with open(public_key_path, &amp;quot;rb&amp;quot;) as key_file:
        public_key = serialization.load_pem_public_key(
            key_file.read(),
            backend=default_backend()
        )
    return public_key

# 生成 JWT 令牌
def generate_jwt_token(private_key, algorithm):
    payload = {
        &amp;quot;iat&amp;quot;: int(time.time())  # 使用秒级时间戳
    }
    return jwt.encode(payload, private_key, algorithm=algorithm)

# 验证 JWT
def verify_jwt_token(token, public_key, algorithm):
    try:
        decoded = jwt.decode(token, public_key, algorithms=[algorithm])
        return decoded
    except jwt.InvalidTokenError:
        return None

# 主函数
def __main__():
    algorithms = [
        (&amp;quot;RS256&amp;quot;, RSA_PRIVATE_KEY_PATH, RSA_PUBLIC_KEY_PATH),
        (&amp;quot;ES256&amp;quot;, EC_PRIVATE_KEY_PATH, EC_PUBLIC_KEY_PATH),
        (&amp;quot;PS256&amp;quot;, PS_PRIVATE_KEY_PATH, PS_PUBLIC_KEY_PATH),
    ]

    for algorithm, private_key_path, public_key_path in algorithms:
        # 加载私钥和公钥
        private_key = load_private_key(private_key_path)
        public_key = load_public_key(public_key_path)

        # 生成 JWT
        jwt_token = generate_jwt_token(private_key, algorithm)
        print(f&amp;quot;生成的 {algorithm} JWT:&amp;quot;, jwt_token)

        # 验证 JWT
        decoded_payload = verify_jwt_token(jwt_token, public_key, algorithm)
        if decoded_payload:
            print(f&amp;quot;{algorithm} JWT 验证成功:&amp;quot;, decoded_payload)
        else:
            print(f&amp;quot;{algorithm} JWT 验证失败&amp;quot;)

if __name__ == &amp;quot;__main__&amp;quot;:
    __main__()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行输出&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728180653/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;基于椭圆曲线算法的 ES256 生成的签名长度，相较于其它算法可谓之遥遥领先，在 JWT 长度敏感的场景下可以优先选择&lt;/p&gt;
&lt;p&gt;另外 PS256 和 RS256 相比较，查阅的资料如下：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PS256 使用 RSASSA-PSS，这是一种概率签名方案，引入了随机性，使得每次签名都是唯一的，因为引入了随机性，PS256 提供了比 RS256 更高的安全性，同样资源消耗也会更高一些&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;另外从 JWT 的是用场景来看，签发与核验 JWT 都由服务端自己完成，所以不存在跟客户端的兼容性问题，选择算法会更加的灵活&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;综上：推荐优先使用 ES256 算法，安全性高，同时签名、密钥对都是最小的&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;线上校验工具 JWT.io&lt;/h3&gt;
&lt;p&gt;这个调试工具支持的算法广泛，本文中提及的算法生成的 JWT 内容都通过 &lt;a href="https://jwt.io/"&gt;https://jwt.io/&lt;/a&gt; 进行了二次核对&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1728180653/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;另外可以在 &lt;a href="https://jwt.io/libraries"&gt;https://jwt.io/libraries&lt;/a&gt; 找到相应语言库支持的算法列表&lt;/p&gt;</content><category term="Technology"></category><category term="JWT"></category></entry><entry><title>黑龙江・木兰县属小村落的星空（2024）</title><link href="https://blog.yasking.org/a/photos-heilongjiang-mulanxian.html" rel="alternate"></link><published>2024-10-03T21:00:00+08:00</published><updated>2024-10-03T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-10-03:/a/photos-heilongjiang-mulanxian.html</id><summary type="html">&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/01.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;收获的季节&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;秋高气爽，结实的玉米棒是一年的辛劳&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/02.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳西下&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;日落西山、夕阳西下&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/03.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;满天星辰&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;尼康 Z30 + 18140，M 档（曝光 20s, 2000 ISO，光圈 …&lt;/p&gt;</summary><content type="html">&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/01.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;收获的季节&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;秋高气爽，结实的玉米棒是一年的辛劳&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/02.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳西下&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;日落西山、夕阳西下&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/03.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;满天星辰&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;尼康 Z30 + 18140，M 档（曝光 20s, 2000 ISO，光圈 F3.5），老丈人帮忙打手电，无意间照了几下天空，就出来了上图比较有趣的效果&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/04.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;北斗七星&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;北斗七星和北极星，值得被记录&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/05.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;天空&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;远处的灯光渲染的天空泛黄，地景和天空是很好的搭配&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/06.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;星轨・初&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;人生中第一张星轨，M 档（曝光 20s, 2000 ISO，光圈 F3.5），间隔拍摄 21s，340 张（约 2 小时）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;晚上拍完发现相机机身和镜头上都有一层露水，星轨的光点变粗，时常也不太够&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;下图是第二次尝试&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/07.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;星轨・旋转&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;第二天的夜晚也是万里如云，参数相同，间隔拍摄了约 500 张（约 3 小时）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;有了前一天的经验，这次用个薄衣服将相机包裹，拿下了镜头的 UV 镜（进光更多），不知道是经过调整还是天气湿度下降，没再出现露水&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在城市久了，有机会在夜晚的乡村看日落、看夕阳和星空，相机拍出来的照片可能很美，但远没有肉眼可见银河来的震撼&lt;/p&gt;
&lt;p&gt;补一张第一天拍摄和第二天拍摄的计划图&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1728185469/08.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;计划图&lt;/div&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;P.S. 拍摄所在地为二级光污染地区&lt;/p&gt;
&lt;/blockquote&gt;</content><category term="Photos"></category><category term="Photos"></category></entry><entry><title>Nginx 启用 HTTPS/3</title><link href="https://blog.yasking.org/a/nginx-deploy-http3.html" rel="alternate"></link><published>2024-09-29T21:00:00+08:00</published><updated>2024-09-29T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-29:/a/nginx-deploy-http3.html</id><summary type="html">&lt;h3&gt;前置条件&lt;/h3&gt;
&lt;p&gt;系统版本：Ubuntu 20.04
Nginx 版本：1.18（稍后需要升级）
用来测试的服务：当前存在可用的 HTTPS/2 网站
OpenSSL：3.0.2（可选升级）&lt;/p&gt;
&lt;h3&gt;检查 …&lt;/h3&gt;</summary><content type="html">&lt;h3&gt;前置条件&lt;/h3&gt;
&lt;p&gt;系统版本：Ubuntu 20.04
Nginx 版本：1.18（稍后需要升级）
用来测试的服务：当前存在可用的 HTTPS/2 网站
OpenSSL：3.0.2（可选升级）&lt;/p&gt;
&lt;h3&gt;检查 Nginx 版本并升级&lt;/h3&gt;
&lt;p&gt;我的系统恰好是 Ubuntu 20.04 + Nginx 1.18，可以参考这篇文章升级 Nginx：&lt;a href="https://hynk.medium.com/upgrading-nginx-from-version-1-18-to-1-25-ubuntu-20-04-b7873069402a"&gt;Upgrading Nginx from version 1.18 to 1.25 (Ubuntu 20.04)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/01.jpg"&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 备份 Nginx 配置
$ sudo cp -r /etc/nginx /etc/nginx-backup

# 添加 Nginx Repository 
$ wget http://nginx.org/keys/nginx_signing.key 
$ sudo mv nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.gpg
# sudo apt-key add nginx_signing.key

$ echo &amp;quot;deb http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx&amp;quot; | sudo tee /etc/apt/sources.list.d/nginx.list

# 更新软件列表
$ sudo apt update

# 安装最新的 Nginx
$ sudo apt install nginx

# 检查版本
$ nginx -v
nginx version: nginx/1.27.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;已升级到了 1.27 版本&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/02.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;Nginx 示例配置&lt;/h3&gt;
&lt;p&gt;没有特别需要说明的，字段含义可以问下 AI，修改配置后记得 &lt;code&gt;nginx -s reload&lt;/code&gt; 加载配置&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-nginx"&gt;server {
    # HTTP/3
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;

    # HTTP/2
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name yasking.org;
    merge_slashes off;

    # 证书
    ssl_certificate /etc/letsencrypt/live/yasking.org-0001/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yasking.org-0001/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    # ssl_prefer_server_ciphers on;

    ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';

    # O-RTT QUIC connection resumption
    ssl_early_data on;

    # Add Alt-SvC header to negotiate HTTP/3.
    add_header Alt-Svc 'h3=&amp;quot;:443&amp;quot;;ma=86400';

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;

    # 启用 HSTS
    add_header Strict-Transport-Security &amp;quot;max-age=31536000; includeSubDomains; preload&amp;quot;;
    add_header X-Content-Type-Options nosniff;

    # 日志配置
    access_log /var/log/nginx/yasking.access.log;
    error_log /var/log/nginx/yasking.error.log;

    root /usr/share/nginx/html;
    index index.html index.htm;
    location / {
        try_files $uri $uri/ =404;
    }
}

# 强制 HTTP 重定向到 HTTPS
server {
    listen 80;
    server_name yasking.org;
    return 301 https://$server_name$request_uri;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;升级 OpenSSL 版本（可选）&lt;/h3&gt;
&lt;p&gt;当前版本 3.0.2，当前最新是 3.3.2，不升级也可以，升级步骤如下&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/03.jpg"&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 下载当前最新的 OpenSSL 程序源码
$ wget https://www.openssl.org/source/openssl-3.3.2.tar.gz

# 解压缩并生成编译配置
$ sudo tar -zxvf openssl-3.3.2.tar.gz -C /usr/src/
$ cd /usr/src/
$ sudo ln -s openssl-3.3.2 openssl
$ cd openssl
$ ./config --prefix=/usr/local/ssl

# 机器 CPU 不太行的话执行 sudo make -j 1 &amp;amp;&amp;amp; sudo make install  
$ sudo make -j $(nproc) &amp;amp;&amp;amp; sudo make install

# 新建 /etc/ld.so.conf.d/openssl-3.0.conf 添加一行 /usr/local/ssl/lib64，此处的 /usr/local/ssl 根据 ./config 的 --prefix 参数确定
$ cat /etc/ld.so.conf.d/openssl-3.0.conf
/usr/local/ssl/lib64

# 备份原 OpenSSL 可执行程序，创建新的链接
$ sudo mv /usr/bin/openssl /usr/bin/openssl_bak
$ sudo ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl

# 链接运行时的动态链接库
$ sudo ldconfig

# 查看库的安装情况
$ sudo ldconfig -v 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/04.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;HTTPS/3 访问验证&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Curl 命令&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ docker run -t --rm alpine/curl-http3 curl --http3 -I https://yasking.org:443
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;macOS Chrome 129&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows Firefox 130&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;在火狐上有个叫「HTTP Version Indicator」的扩展，安装后可以显示 HTTP 协议版本&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;为什么不是 macOS 的 Firefox 测试？因为它一直显示 HTTP/2，清除缓存也没用，我暂不清楚原因&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;在线网站：&lt;a href="https://http3check.net"&gt;https://http3check.net&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;在线网站：&lt;a href="https://http3test.com/"&gt;https://http3test.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727529679/10.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;最后&lt;/h3&gt;
&lt;p&gt;HTTP/3 虽然不是一个新技术，但也在快速发展和完善中，可能今天的配置和参数符合标准，后天浏览器就不认降级回 HTTP/2&lt;/p&gt;
&lt;p&gt;云平台、各个基础组件库都需要陆续迭代支持，需要一个过程，本篇借助 Nginx 使得主域名支持通过 HTTP/3 协议访问&lt;/p&gt;
&lt;p&gt;相比于一两年前，部署方便很多，Nginx 和 OpenSSL 都不用自己编译，安装新版即可，先这样&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codedamn.com/news/backend/leveraging-http3-with-nginx"&gt;Leveraging HTTP/3 with Nginx: A Step-By-Step Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://serverpilot.io/docs/how-to-enable-http3/"&gt;How to Enable HTTP/3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@donfiealex/upgrade-your-encryption-installing-the-latest-openssl-3-on-ubuntu-20-04-bba5f2f33fea"&gt;Upgrade Your Encryption: Installing the Latest OpenSSL 3 on Ubuntu 20.04&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="HTTPS"></category></entry><entry><title>优化网站的 SSL Labs 总体评级为 A+（禁用旧协议 &amp; 启用 HSTS）</title><link href="https://blog.yasking.org/a/optimize-website-ssllabs-rating.html" rel="alternate"></link><published>2024-09-28T21:00:00+08:00</published><updated>2024-11-15T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-28:/a/optimize-website-ssllabs-rating.html</id><summary type="html">&lt;p&gt;使用 &lt;a href="https://www.ssllabs.com/ssltest/"&gt;SSL Labs&lt;/a&gt; 检测&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;安全等级为 &lt;code&gt;B&lt;/code&gt;，接下来调整服务器配置，使其升到 &lt;code&gt;A+&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;PS：几年前部署博客，印象中记得测试评分还是 A，本篇文 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;使用 &lt;a href="https://www.ssllabs.com/ssltest/"&gt;SSL Labs&lt;/a&gt; 检测&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;安全等级为 &lt;code&gt;B&lt;/code&gt;，接下来调整服务器配置，使其升到 &lt;code&gt;A+&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;PS：几年前部署博客，印象中记得测试评分还是 A，本篇文章根据 SSL Labs 提示对博客安全等级进行提升，主要涉及以下两点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;禁用 TLS 1.0 和 TLS 1.1，开启 TLS 1.3 支持&lt;/li&gt;
&lt;li&gt;启用 HSTS 支持&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;TLS 支持版本调整&lt;/h3&gt;
&lt;p&gt;支持 TLS 1.0 也会导致 PCI DSS 不合规，使用 &lt;a href="https://myssl.com"&gt;https://myssl.com&lt;/a&gt; 进行检测时会提示&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/02.jpg"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;PCI 安全标准委员会规定 2018 年 6 月 30 日之后，开启 TLS1.0 将导致 PCI DSS 不合规&lt;/p&gt;
&lt;p&gt;具体参考：&lt;a href="https://blog.myssl.com/pci-dss/"&gt;《更严格的 PCI DSS 合规标准》&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;简单说，如需符合 PCI DSS 至少禁掉 TLS 1.0，想要评分摆脱 B，TLS 1.1 也要禁掉，同时推荐开启 TLS 1.3，未来主流应该是 TLS1.2 + TLS1.3&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;设置支持的最低 TLS 版本为 1.2&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;又拍云&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Bitiful 图床&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Cloudflare Page &amp;amp; Cloudflare R2 图床&lt;/p&gt;
&lt;p&gt;无需设置，Cloudflare 默认关闭 TLS 1.0 和 TLS 1.1，开启 TLS 1.3 支持&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;测试服务器是否支持 TLS 1.3 版本&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;命令如下&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ openssl s_client -connect blog.yasking.org:443 -tls1_3 | grep TLS
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不支持 TLS 1.3&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;支持 TLS 1.3&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;修改 TLS 版本支持后，Rating 将变为 A，想要 A+，需要进一步开启 HSTS&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/07.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;启用 HSTS（HTTP Strict Transport Security）&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;HSTS（HTTP 严格传输安全）是一种机制，服务器可以通过它指示浏览器在与它通信时必须使用安全连接。它可以成为保护用户及其数据的隐私和安全的有效工具。&lt;/p&gt;
&lt;p&gt;然而，当首次连接到一个HSTS主机时，浏览器并不知道是否应该使用安全连接，因为它从未从该主机收到过HSTS头。因此，活跃的网络攻击者可能会阻止浏览器进行安全连接（用户可能永远不会意识到有问题），为了缓解这种攻击，主流浏览器中添加了一个默认强制执行 HSTS 的主机列表，当用户首次连接到这些主机之一时，浏览器将知道它必须使用安全连接。如果网络攻击者阻止与服务器的安全连接，浏览器将不会尝试通过不安全的协议进行连接，从而保持用户的安全。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;仅开启 HSTS 但不提交到 Preload List&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;HSTS 开启前状态&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;开启 HSTS 即添加一个 Header 返回头（&lt;em&gt;strict-transport-security: max-age=15552000&lt;/em&gt;），Nginx 配置片段如下&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-Nginx"&gt;add_header Strict-Transport-Security &amp;quot;max-age=15552000&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里也以又拍云为示例，如果你仅仅希望单域名（主域名、子域名）的评分上到 &lt;code&gt;A+&lt;/code&gt; 而不关心是否进入 Preload List，那么配置的时候根据情况选择是否包含子域名，同时不要勾选预加载选项，缓存时间推荐 180 天&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;需要注意不存在满足 “提交 Preload List 要求” 但不提交的 “中间状态”，如果你不想提交到 Preload List，请务必不要满足其要求（如不勾选 “预加载”），否则很可能被其他人提交，提交不需要验证网站所有者&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;仅配置 max-age 就可以通过 SSL Labs 检测，再次检查子域名，评分变为 &lt;code&gt;A+&lt;/code&gt;，目标已经达到了，如果你还不确定是否会长时间保持所有域名都上 HTTPS，可以点到为止&lt;/p&gt;
&lt;h3&gt;启用 HSTS 并提交到 Preload List&lt;/h3&gt;
&lt;p&gt;提交到 Preload List 就是提交到 &lt;a href="https://hstspreload.org"&gt;https://hstspreload.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;提交成功大概几周后，主流浏览器将会内置到自身的浏览器中，Firefox 浏览器关于 &lt;a href="https://blog.mozilla.org/security/2012/11/01/preloading-hsts/"&gt;Preloading HSTS&lt;/a&gt; 的说明介绍了它的列表基于 hstspreload.org 的数据整合，虽然其由谷歌维护，但它是一个事实上的通用列表&lt;/p&gt;
&lt;p&gt;提交 Preload List 之前，首先要了解其注意事项，同时服务需要满足一定条件&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意：开启后则不能随时关闭，不能再实时降级为 HTTP&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如需关闭强制 HTTPS 访问，必须首先在服务器上禁用 HSTS 配置，并等待 max-age 过期，以确保每个浏览器都知晓此更改，然后才能禁用 HTTPS，平均的 max-age 为六个月，如果在禁用 HSTS 之前移除 HTTPS，网站将无法访问，最长可达 max-age 的时间，或者直到您再次支持 HTTPS，由于在启用 HSTS 的网站上禁用 HTTPS 可能会产生这些后果，强烈建议您在启用此功能之前已经有一个稳定的 HTTPS 服务&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;提交 Preload List 的必备条件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1）提供有效的证书&lt;/p&gt;
&lt;p&gt;即网站能够通过 HTTPS 正常访问（e.g. &lt;a href="https://yasking.org"&gt;https://yasking.org&lt;/a&gt; / &lt;a href="https://blog.yasking.org"&gt;https://blog.yasking.org&lt;/a&gt;）&lt;/p&gt;
&lt;p&gt;&lt;em&gt;建议开启 HSTS 前，你的网站已经启用 HTTPS 一段时间且稳定运行&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;2）如果你在监听 80 端口，请将 HTTP 重定向到同一主机的 HTTPS&lt;/p&gt;
&lt;p&gt;&lt;em&gt;网站能自动重定向 HTTP 到 HTTPS，或者不监听 80 端口的 HTTP 访问，推荐前者&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;3）所有子域名都通过 HTTPS 提供服务（e.g. &lt;code&gt;*.yasking.org&lt;/code&gt; / &lt;code&gt;*.*.yasking.org&lt;/code&gt;）&lt;/p&gt;
&lt;p&gt;特别注意 HSTS 预加载适用于所有子域名，包括非公开访问的内部子域名&lt;/p&gt;
&lt;p&gt;也需要注意如果 www 子域名在 DNS 解析中存在，则它也需要支持 HTTPS&lt;/p&gt;
&lt;p&gt;4）在 HTTPS 请求的基域上提供 HSTS 头&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;max-age 必须至少为 31536000 秒（1年）&lt;/li&gt;
&lt;li&gt;必须指定 includeSubDomains 指令&lt;/li&gt;
&lt;li&gt;必须指定 preload 指令&lt;/li&gt;
&lt;li&gt;如果你在 HTTPS 站点上提供额外的重定向，该重定向仍必须包含HSTS头（而不是它重定向到的页面）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以放心大胆的在 &lt;a href="https://hstspreload.org"&gt;https://hstspreload.org&lt;/a&gt; 点击提交，它会自动检测，不满足条件会给出提示，照着改就好，直到满足条件，最终提交前还有一步确认&lt;/p&gt;
&lt;p&gt;如果你的主域名在 Cloudflare 和 又拍云，满足提交 Preload List 的配置如下&lt;/p&gt;
&lt;p&gt;位置在 “网站” - “SSL/TLS” - “Edge Certificates” - “HTTP Strict Transport Security (HSTS)”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;又拍云&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;补充说明：当主域名被预加载收录后，子域名的访问也会继承主域名的策略，重复在子域名返回 Header 对提交收录没有用处&lt;/p&gt;
&lt;p&gt;为了提交 HSTS，我的网站主域名解析到了 VPS 上的 Nginx 默认欢迎页面，这是我的 Nginx 配置&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-nginx"&gt;server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name yasking.org;
    merge_slashes off;

    # 证书
    ssl_certificate /etc/letsencrypt/live/yasking.org-0001/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yasking.org-0001/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;

    # 启用 HSTS
    add_header Strict-Transport-Security &amp;quot;max-age=31536000; includeSubDomains; preload&amp;quot;;
    add_header X-Content-Type-Options nosniff;

    # 日志配置
    access_log /var/log/nginx/yasking.access.log;
    error_log /var/log/nginx/yasking.error.log;
}

# 强制 HTTP 重定向到 HTTPS
server {
    listen 80;
    server_name yasking.org;
    return 301 https://$server_name$request_uri;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我们访问主域名确认已开启 HTTPS&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;同时查看主域名的 Header，其返回了满足条件的 Strict-Transport-Security 头部&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;以下是提交到 &lt;a href="https://hstspreload.org"&gt;https://hstspreload.org&lt;/a&gt; 时的截图记录&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;如果提交子域名会提示需要输入网站主域名&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;如果检查没问题页面会变为绿色，同时有两个选项，提交前需要再次确认&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;显示提交成功&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;过几周再次查看当前链接：&lt;a href="https://hstspreload.org/?domain=yasking.org"&gt;https://hstspreload.org/?domain=yasking.org&lt;/a&gt; 获取提交状态（注意将 domain 换成你自己的地址）&lt;/p&gt;
&lt;p&gt;此时查看会显示 Pending 状态&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一旦收录，那么恭喜你没有短期的后悔药让你的网站再回退到 HTTP，请确保你当前域名以及其所有子域名持续支持 HTTPS 访问！&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;后悔药参考链接：&lt;a href="https://hstspreload.org/removal/"&gt;https://hstspreload.org/removal/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;启用 HSTS 后，经过一段时间，提交的域名会出现在 Chromium 代码仓库中：&lt;a href="https://source.chromium.org/chromium/chromium/src/+/main:net/http/transport_security_state_static.json"&gt;transport_security_state_static.json&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;修改后的检测结果&lt;/h3&gt;
&lt;p&gt;https://myssl.com 结果&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/20.jpg"&gt;&lt;/p&gt;
&lt;p&gt;SSL Labs 结果&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/21.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;HSTS 收录了！&lt;/h3&gt;
&lt;p&gt;算算将近两个月的时间&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/23.jpg"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Status: yasking.org is currently preloaded.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在chromium 代码仓库也可以看到网站已进入源码&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727528907/22.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://security.stackexchange.com/questions/244323/how-do-browsers-get-hsts-preload-data"&gt;How do browsers get HSTS preload data?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="TLS"></category><category term="Nginx"></category></entry><entry><title>了解 OCSP Stapling 证书吊销验证机制</title><link href="https://blog.yasking.org/a/knowledge-of-ocsp-stapling.html" rel="alternate"></link><published>2024-09-25T21:00:00+08:00</published><updated>2024-09-25T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-25:/a/knowledge-of-ocsp-stapling.html</id><summary type="html">&lt;p&gt;最开始是在 Bitiful CDN 上看到开启 OCSP stapling 开关，才知道有这个技术概念&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/01.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;从吊销证书说起&lt;/h3&gt;
&lt;p&gt;非对称加密是证书体系的基础，每个公钥 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;最开始是在 Bitiful CDN 上看到开启 OCSP stapling 开关，才知道有这个技术概念&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/01.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;从吊销证书说起&lt;/h3&gt;
&lt;p&gt;非对称加密是证书体系的基础，每个公钥都有一个关联的私钥，该私钥由网站所有者私密保存，如果有人窃取到证书的私钥，他们就可以冒充该网站，私钥泄露属于严重风险。&lt;/p&gt;
&lt;p&gt;只要存在私钥泄露的概率，那么它就一定就会发生，所以私钥泄露后第一时间应该 &lt;strong&gt;吊销证书&lt;/strong&gt;，证书吊销是降低密钥泄露风险的一种方法，网站所有者可以通过通知证书颁发者不应再信任该证书来撤销受损的证书。&lt;/p&gt;
&lt;p&gt;回到用户视角，当网站管理员吊销了证书，用户借助浏览器请求网站，浏览器如何判断网站证书存在安全风险，并给出提示或禁止用户访问呢？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;网络浏览器可以通过多种方式检查网站的证书是否被吊销。最著名的机制是证书吊销列表 Certificate revocation list (CRL) 和在线证书状态协议 (OCSP)。 CRL 是由 CA 撤销的证书序列号的签名列表，OCSP 是一种协议，可用于向 CA 查询给定证书的吊销状态，OCSP 响应包含证书未吊销的签名断言&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;查看网站证书&lt;/h3&gt;
&lt;p&gt;在进一步了解其它概念之前，我们可以通过浏览器获取到网站的证书，查看其信息以便稍后更好的理解概念&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;上图是在 FireFox 浏览器，点击绿色锁头，进入到 “View Certificate” 看到的信息，从左到右依次是网站的终端实体证书，R11 是 Let's Encrypt 的中级证书（Intermediate Certificate），用于签发网站终端实体证书&lt;/p&gt;
&lt;p&gt;ISRG Root X1 是 Let's Encrypt 的根证书（Root Certificate），这个证书是整个信任链的起点，由受信任的根证书颁发机构（CA）签发&lt;/p&gt;
&lt;p&gt;大多数操作系统和浏览器都内置了 ISRG Root X1 证书，因此用户可以信任由 Let's Encrypt 颁发的证书，R11 证书的存在是为了在根证书和终端实体证书之间建立信任链&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;我们可以点击 PEM (cert) 下载网站的证书，另外两个证书同理，我这里下载了三者并重命名&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;接下来回到上节提到的 CRL 和 OCSP，之后我们将进一步了解 OCSP Stapling 的作用和实现&lt;/p&gt;
&lt;h3&gt;证书吊销列表 (CRL)&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;证书吊销列表（Certificate Revocation List，简称 CRL）是公钥基础设施（PKI）中的一种重要机制，用于列出已被吊销的数字证书。CRL 由证书颁发机构（CA）发布，包含已吊销证书的序列号和其他相关信息。客户端（如浏览器）可以使用 CRL 来检查证书的有效性，确保不会使用已被吊销的证书。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在 FireFox 浏览器查看 Let's Encrypt 签发的证书，切换到证书链中的 R11 中间证书，其通过 CRL 来验证自身证书是否有效&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;补充：使用命令行也可以查询 CRL URI&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ openssl x509 -in r11.pem -text -noout | grep -A 4 &amp;quot;CRL Distribution Points&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;证书中列出的 CRL 文件下载地址是：&lt;a href="http://x1.c.lencr.org/"&gt;http://x1.c.lencr.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;浏览器打开链接可下载到二进制文件，它就是二进制格式的 CRL，不能直接用文本编辑器打开，稍后会补充如何查看和验证&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;关于 Let's Encrypt 的 lencr.org 域名，有篇文章对其进行了说明，有兴趣了解可以看：&lt;a href="https://letsencrypt.org/docs/lencr.org/"&gt;Let's Encrypt - lencr.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;简要说就是：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;由 c.lencr.org 子域名提供证书吊销列表 (CRL)&lt;/p&gt;
&lt;p&gt;由 o.lencr.org 子域名提供在线证书状态协议（OCSP）&lt;/p&gt;
&lt;p&gt;由 i.lencr.org 子域名提供中间 “颁发者” 证书的副本，这些证书要么由我们的根证书之一签名，要么由另一个证书颁发机构 (CA)“交叉签名”。&lt;/p&gt;
&lt;p&gt;另外使用短域名能减小证书大小，这在互联网海量的证书请求下能节省很多资源&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;除了域名，我们也可以见到 Let's Encrypt 的证书吊销列表下载地址不带 .crl 后缀（猜测也是为了减少链接长度），很多证书集成的证书吊销列表都带有 .crl 路径&lt;/p&gt;
&lt;p&gt;例如 Amazon 证书 CRL 下载地址&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;以及 Google 证书 CRL 下载地址&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;接下来可以进一步了解 CRL 文件&lt;/p&gt;
&lt;h3&gt;CRL 文件的解析与校验（可跳过不影响阅读）&lt;/h3&gt;
&lt;p&gt;可以使用这个在线工具：&lt;a href="https://pkitools.net/pages/ca/readcrl.html"&gt;Parse CRL&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;可以选择 “From file” 上传 crl 文件，也可以选择 “From URI” 填写证书中列出的 CRL Endpoints 地址（例如：http://x1.c.lencr.org/），然后点击 “Parse CRL”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/10.jpg"&gt;
&lt;img alt="" src="https://images.yasking.org/technology/1727250621/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;从解析的内容来看，Version 版本是 2，Issuer name 是 ISRG Root X1，也就是 Let's Encrypt 的 Root 根证书&lt;/p&gt;
&lt;p&gt;其中的 CRL Entries 表示吊销记录，当前为空表示这个 CRL 承载的信息中 ISRG Root X1 没有吊销过其签发的证书&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;查看完 CRL 文件内容，这里还有一些重点：&lt;/p&gt;
&lt;p&gt;为什么 CRL 下载地址提供 HTTP 而不是 HTTPS？（Let's Encrypt &lt;a href="https://letsencrypt.org/docs/lencr.org/"&gt;文档&lt;/a&gt;对 OCSP HTTP 做了解释，CRL 的获取同理）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OCSP 响应始终通过 HTTP 提供。如果通过 HTTPS 提供服务，则会出现“无限循环”问题：为了验证 OCSP 服务器的证书，客户端必须使用 OCSP。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;请求 CRL 文件的地址是 HTTP 的 http://x1.c.lencr.org/ 而非 HTTPS 加密，如何确保浏览器请求到的 CRL 未被篡改？&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OCSP 响应本身带有时间戳和加密签名，因此在这种情况下不需要 TLS 的防篡改属性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;还是这个网页，点击 “Verify CRL” 来验证其有效性&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择 “From certificate”，选择上文下载回来的 &lt;em&gt;ISRG-Root-X1.pem&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击校验，验证签名成功，符合预期&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;我们手动加载 CRL 文件并校验，浏览器也是这样经过验签确定获取到的 CRL 真实完整，同时确认 R11 证书有效后，R11 中间证书也可以验证其签发的网站终端实体证书有效性，反之，R11 被吊销，那么由其签发的叶子证书也不再可信&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CRL 存在的部分问题&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CRL（证书吊销列表）存在一些时效性和规模问题，时效性问题主要体现在 CRL 更新频率低和延迟高，可能导致客户端无法及时获取最新的吊销信息。规模问题则表现为 CRL 文件随着时间的推移变得越来越大，下载和解析时间增加，影响性能。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CRL 虽然有写问题，但不影响使用，例如 Delta CRL、Partitioned CRL、Caching 等技术都可以缓解其问题，此处不做过多发散，仅需知道 CRL 并不是被抛弃的技术即可，很多证书中 CRL 和 OCSP 同时使用，互为补充，确保证书的吊销状态能够及时、准确地被验证&lt;/p&gt;
&lt;p&gt;接下来了解 OCSP 协议&lt;/p&gt;
&lt;h3&gt;OCSP 在线证书状态协议&lt;/h3&gt;
&lt;p&gt;为了克服 CRL 的时效性和规模问题，OCSP（Online Certificate Status Protocol，在线证书状态协议）提供了一种更实时的查询证书状态的方法。&lt;/p&gt;
&lt;p&gt;Let's Encrypt 签发的网站叶子证书使用的是 OCSP 验证，所以在学习之前，先在 FireFox 浏览器切换到网站证书的标签页&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;可以看到 OCSP 服务器地址为：&lt;a href="http://r11.o.lencr.org"&gt;http://r11.o.lencr.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;使用如下命令可以实时验证证书有效性&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ openssl ocsp -issuer r11.pem -cert blog-yasking-org.pem -url http://r11.o.lencr.org -text -no_nonce
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;R11 证书有效性已在上文借助 CRL 通过 Root 证书的有效性验证&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;输出校验成功，可以确定博客 blog.yasking.org 证书是有效状态&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;OCSP 也并非完美的方案，下节回讲到可用性验证的左右为难&lt;/p&gt;
&lt;h3&gt;迷失在 CRL 和 OCSP 中的浏览器&lt;/h3&gt;
&lt;p&gt;本小节内容整理自：&lt;a href="https://blog.cloudflare.com/high-reliability-ocsp-stapling/"&gt;https://blog.cloudflare.com/high-reliability-ocsp-stapling/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;有任何疑问建议阅读原文，讲解的更加详细&lt;/p&gt;
&lt;p&gt;支持 OCSP 的证书包含响应者的 URL，同样支持 CRL 的证书包含可获取 CRL 的 URL，当浏览器获得作为 HTTPS 连接一部分的证书时，它可以使用证书中嵌入的 URL 下载 CRL 或 OCSP 响应，并在呈现网页之前检查证书是否已被吊销。那么问题就变成了：&lt;strong&gt;如果 CRL 或 OCSP 响应请求失败，浏览器应该做什么？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;事实证明，这个问题的两个答案都有问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hard-fail 硬失败 —— 不起作用&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当浏览器无法获取吊销信息时，硬失败策略会阻止页面并显示警告，这种策略虽然保守、安全但很容易因为网络波动或其它因素误报，导致用户警告疲劳并教会用户单击忽略安全警告，这是一个坏主意&lt;/p&gt;
&lt;p&gt;硬故障策略的另一个缺点是，它增加了证书颁发机构保持 OCSP 和 CRL 端点可用和在线的负担，损坏的 OCSP 或 CRL 服务器会成为证书颁发机构颁发的所有证书的中心故障点，如果浏览器遵循硬故障策略，则 OCSP 中断将成为 Internet 中断，整个网络的可用性受到 CA 始终保持其 OCSP 服务在线的能力的限制，构成系统性风险&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Soft-fail 软失败 —— 也好不了多少&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;为避免硬故障策略的缺点，大多数浏览器采用软失败策略进行证书吊销检查，如果吊销信息可用，他们就会依赖该信息，否则会假设证书未吊销并显示没有任何错误的页面&lt;/p&gt;
&lt;p&gt;软故障策略存在严重的安全缺陷：一旦攻击者可以阻止 OCSP 请求并拥有网站私钥，他们就可以拦截该站点的传出连接并将已吊销的证书提供给浏览器，浏览器页面将在不提醒用户的情况下加载攻击者页面&lt;/p&gt;
&lt;p&gt;在首次访问尚未缓存证书的吊销信息时，软故障策略也会使连接速度变慢&lt;/p&gt;
&lt;p&gt;实时 OCSP 检查还有一个额外的缺点：OCSP 请求通过未加密的 HTTP 发送，并绑定到特定证书，它会泄露私人访问站点信息&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;另外，还有一种方案 —— 预打包 CRL&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;浏览器预先打包已撤销证书的列表，并通过浏览器更新来分发它们，由于所有被撤销证书的列表非常庞大，因此该列表中仅包含少数高影响力的证书。该技术在 Firefox 中称为 OneCRL，在 Chrome 中称为 CRLSet，这对于一些备受瞩目的撤销来说是有效的，但它绝不是一个完整的解决方案，这种技术不仅没有覆盖所有证书，而且在证书被吊销和证书列表到达浏览器之间留下了一个漏洞窗口&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;火候差不多了，我们是时候该请出 OCSP Stapling (OCSP 装订)&lt;/p&gt;
&lt;h3&gt;OCSP Stapling 技术&lt;/h3&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;OCSP 装订就像是服务器在返回证书的同时，也将 OCSP 状态一并返回给客户端，使得客户端不用单独请求证书颁发机构（CA）的服务器进行校验，这个过程就像是用订书器将两份文件订在一起一样，因此得名“装订”。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;OCSP 允许 Web 服务器通过与证书颁发机构验证来确定 SSL/TLS 证书的状态。这种提高的安全性伴随着一些性能损失：由于浏览器必须与 Web 服务器和证书颁发机构进行通信，网站的加载时间会增加。&lt;/p&gt;
&lt;p&gt;OCSP Stapling 优化了 SSL/TLS 握手过程，它允许服务器在握手过程中直接提供证书的状态信息，而不需要客户端去查询 OCSP 服务器。&lt;/p&gt;
&lt;p&gt;在某些情况下，OCSP 装订可将连接时间缩短高达 30%，与此同时， OCSP Stapling 修复了与实时 OCSP 获取相关的一些性能和隐私问题&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;查询网站是否开启了 OCSP Stapling&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ openssl s_client -connect blog.yasking.org:443 -status -servername blog.yasking.org
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/20.jpg"&gt;&lt;/p&gt;
&lt;p&gt;从输出看到 “OCSP Response Data” 说明网站服务器支持 OCSP 装订&lt;/p&gt;
&lt;p&gt;测试了一个未开启 OCSP 装订的网站，返回内容如下&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/21.jpg"&gt;&lt;/p&gt;
&lt;p&gt;也可以使用在线工具，例如：&lt;a href="https://entrust.ssllabs.com"&gt;https://entrust.ssllabs.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1727250621/22.jpg"&gt;&lt;/p&gt;
&lt;p&gt;国内用户可以使用在线网站：&lt;a href="https://myssl.com/"&gt;https://myssl.com/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Nginx 开启 OCSP Stapling&lt;/h3&gt;
&lt;p&gt;示例配置如下&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-nginx"&gt;server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/your/certificate.crt;
    ssl_certificate_key /path/to/your/private.key;

    # 启用 OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;

    # 指定用于验证 OCSP 响应的根证书
    ssl_trusted_certificate /path/to/your/trusted_ca_certs.pem;

    # 可选：设置 OCSP 响应的缓存时间
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # 其他配置...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;写在做后&lt;/h3&gt;
&lt;p&gt;当前大多主流的服务和客户端库都支持 OCSP stapling，如果可以，开启它！&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.cloudflare.com/high-reliability-ocsp-stapling/"&gt;High-reliability OCSP stapling and why it matters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="TLS"></category></entry><entry><title>山东・烟台中秋两三日（2024）</title><link href="https://blog.yasking.org/a/photos-zhongqiu-yantai.html" rel="alternate"></link><published>2024-09-17T21:00:00+08:00</published><updated>2024-09-17T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-17:/a/photos-zhongqiu-yantai.html</id><summary type="html">&lt;p&gt;之前去过青岛体验不错，遂趁着中秋节的假期到山东半岛的另一侧走走瞧瞧，这两天的天气很好，主要在金沙滩、养马岛溜 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;之前去过青岛体验不错，遂趁着中秋节的假期到山东半岛的另一侧走走瞧瞧，这两天的天气很好，主要在金沙滩、养马岛溜达，也到了烟大小吃街周边&lt;/p&gt;
&lt;p&gt;烟台有着很棒的沙滩，九月中旬的白天，海里还有人在海里 “泡着”，光脚走在沙滩，被海浪拍打，对于内陆城市的人来说很解压，远望大海无垠，这就是“去看海吧” 的意义&lt;/p&gt;
&lt;p&gt;要说养马岛的正确打开方式，一定是小电驴吹海风，我们在烟大附近租的 59 到晚上的哈啰电动自行车，骑了十多公里到达养马岛，沿海的路途虽不能一直看海，但路况很好、空气很好、吹吹海风心情也很好&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/01.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;月光如雪&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/02.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夜晚的小船&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/03.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;养马岛・獐岛附近&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/04.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;小女孩儿&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/05.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;眺望&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/06.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;日落一&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/07.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;日落二&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/09.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;日落三&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/08.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;骑行&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/10.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;童趣&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726735390/11.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;情侣&lt;/div&gt;
&lt;/div&gt;</content><category term="Photos"></category><category term="Photos"></category></entry><entry><title>分享改造后的博客发布流程和访问链路</title><link href="https://blog.yasking.org/a/blog-publish-and-visit.html" rel="alternate"></link><published>2024-09-15T21:00:00+08:00</published><updated>2024-09-15T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-15:/a/blog-publish-and-visit.html</id><summary type="html">&lt;p&gt;经过陆陆续续几个月的调整改造，博客发布和访问链路都有不同程度的优化，分享和记录如下&lt;/p&gt;
&lt;h3&gt;博客发布流程&lt;/h3&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1726371007/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;改造后，在 Markdown …&lt;/p&gt;</summary><content type="html">&lt;p&gt;经过陆陆续续几个月的调整改造，博客发布和访问链路都有不同程度的优化，分享和记录如下&lt;/p&gt;
&lt;h3&gt;博客发布流程&lt;/h3&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1726371007/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;改造后，在 Markdown 编辑器内写笔记，&lt;strong&gt;运行一个脚本&lt;/strong&gt;，它会做以下事项（感谢 DeepSeek Chat，我描述了需求，脚本是它生成的）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;将文章内的图片收集到一个文件夹并重命名图片&lt;/li&gt;
&lt;li&gt;调用 TinyJPG 的 API 进行压缩&lt;/li&gt;
&lt;li&gt;将图片文件夹放置到本地的图片库&lt;/li&gt;
&lt;li&gt;使用 Rclone 同步到 S3 兼容协议的存储桶，完成图片的发布&lt;/li&gt;
&lt;li&gt;将最终的图片 URL 回写到新的 Markdown 文件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;再手动将 Markdown 文件提交到 Github 的私有仓库，CI/CD 会自动生成最终的静态页面，对于又拍云，是通过 Buddy CI/CD 使用又拍云自己的 upx 工具提交的，对于 Cloudflare Pages，它通过配置的命令自动构建发布&lt;/p&gt;
&lt;p&gt;对我来说，改造后的发布流程大大简化了流程，自动化程度较高，符合改造预期&lt;/p&gt;
&lt;h3&gt;用户访问分流&lt;/h3&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1726371007/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;改造后的博客架构更加灵活，不依赖特定的厂商，无论是博客静态页面还是图床，使用 DNS 分流能够快速切换服务后端，同时博客图床只要是兼容 S3 的存储即可，静态页面和存储，国内外有大把的服务，其免费额度足够一个小小的个人博客使用&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;并不总是完美无缺&lt;/strong&gt;：使用分流后，引入了一个新的问题，即 Cloudflare Pages 会自动将 &lt;code&gt;.html&lt;/code&gt; 后缀永久重定向到没有后缀的链接，就导致海外搜索引擎索引的链接都不带 &lt;code&gt;.html&lt;/code&gt; 后缀了，同时 DNS 分流也不能百分百准确的判断国内外 IP 进行分流，外加上微软 Bing 搜索引擎有国内和全球，最大的不确定因素也可能来自访问者，比如它在国内使用谷歌搜索（规则），访问的链接不带后缀，打开时 DNSPod 判断用户在国内，那么会访问又拍云的服务，我之前没有配置 CDN 的边缘规则，就会 404 报错&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1726371007/03.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;p&gt;解决问题的办法就是又拍云的 CDN 加规则，让没有后缀的请求重定向到 &lt;code&gt;.html&lt;/code&gt; 链接 &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$WHEN($MATCH($_URI,'^([^.]+)([^/])$'))$REDIRECT(https://blog.yasking.org$_URI'.html',302)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;无形中又添加了一个限制，即静态博客的存储或 CDN 现在需要同时支持带后缀和不带后缀两种路径的访问 :-(&lt;/p&gt;
&lt;p&gt;虽然有些战术失误，但战略上是成功的...&lt;/p&gt;
&lt;h3&gt;相关笔记&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.yasking.org/a/auto-posting-static-blog-with-buddy.html"&gt;使用 Buddy 自动发布静态博客&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.yasking.org/a/blog-with-cloudflare-pages.html"&gt;边缘网络：白嫖 Cloudflare Pages 静态博客（DNS 国内外分流）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.yasking.org/a/blog-images-with-cloudflare-r2.html"&gt;边缘网络：白嫖 Cloudflare R2 博客图床（DNS 国内外分流）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="博客配置"></category></entry><entry><title>边缘网络：白嫖 Cloudflare R2 博客图床（DNS 国内外分流）</title><link href="https://blog.yasking.org/a/blog-images-with-cloudflare-r2.html" rel="alternate"></link><published>2024-09-08T21:00:00+08:00</published><updated>2024-09-08T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-08:/a/blog-images-with-cloudflare-r2.html</id><summary type="html">&lt;p&gt;上篇博客&lt;a href="https://blog.yasking.org/a/blog-with-cloudflare-pages.html"&gt;《边缘网络：白嫖 Cloudflare Pages 静态博客（DNS 国内外分流）》&lt;/a&gt; 将博客的静态页面发布到 Cloudflare Pages 并使用 DNS 分流，本篇将沿用这一方案 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;上篇博客&lt;a href="https://blog.yasking.org/a/blog-with-cloudflare-pages.html"&gt;《边缘网络：白嫖 Cloudflare Pages 静态博客（DNS 国内外分流）》&lt;/a&gt; 将博客的静态页面发布到 Cloudflare Pages 并使用 DNS 分流，本篇将沿用这一方案，继续将博客的图床改造&lt;/p&gt;
&lt;p&gt;本篇主要内容是记录 R2 存储如何绑定自定义域名访问&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/01.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;配置 Cloudflare for SaaS 订阅&lt;/h3&gt;
&lt;p&gt;进到 Website 下&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;首次使用需要先开启 Cloudflare for SaaS 订阅&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/03.jpg"&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;添加回退源（Fallback Origin），需要是 Clouldflare 管理的域名，同时应该是有效的（A...） 记录，此处填写的 r2-n6xd83.donx-done.xyz 作为默认 Fallback Origin 仅仅是为了让后续的 images.yasking.org 能够 CNAME 绑定到 Cloudflare，&lt;strong&gt;images.yasking.org 并不能通过 r2-n6xd83.donx-done.xyz 访问到 R2 的资源&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;作为说明，如果 fallback.donx-done.xyz 是有效的解析，也是可以作为 Fallback Origin，本例中只需要一个有效的回退源&lt;/p&gt;
&lt;p&gt;如果 r2-n6xd83.donx-done.xyz 被改为了不存在的 fallback.donx-done.xyz 则会触发报错&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;正确添加后显示为 &lt;code&gt;Active&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “Add Custom Hostname” 配置自定义域名&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;此处填写图床域名 &lt;em&gt;images.yasking.org&lt;/em&gt;，其它保持默认即可&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击刚刚添加的记录，按提示在 DNSPod 上添加两条 TXT 记录&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;解析后稍作等待，刷新后可以看到两个 &lt;code&gt;Active&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;至此，Cloudflare 已准备好接收来自 images.yasking.org 域名的请求（但不能正确处理返回图片，仅仅是解析）&lt;/p&gt;
&lt;h3&gt;添加域名解析&lt;/h3&gt;
&lt;p&gt;将 images.yasking.org 通过 CNAME 指向 r2-n6xd83.donx-done.xyz&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;到这一步，从感觉上已经能访问 R2 图像，上文说过原因，访问 R2 内的文件，从报错上也可以看到提示，R2 不能直接由自定义域名的 CNAME 解析访问&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/12.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;配置 Cloudflare Worker 并绑定 R2 桶&lt;/h3&gt;
&lt;p&gt;回到 Workers &amp;amp; Pages&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/13.jpg"&gt;&lt;/p&gt;
&lt;p&gt;新建 Worker&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择从模版创建，随便选择&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;填写名称&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/16.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 Deploy 部署，成功后点击 “Edit code”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/17.jpg"&gt;&lt;/p&gt;
&lt;p&gt;将以下内容粘贴到 &lt;em&gt;worker.js&lt;/em&gt;，保存后再次点击 Deploy 部署&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-js"&gt;var worker_default = {
  async fetch(request, env) {
    if (request.method !== &amp;quot;GET&amp;quot;) {
      return new Response(&amp;quot;Only GET method allowed&amp;quot;, { status: 405 });
    }
    const url = new URL(request.url);
    const key = url.pathname.slice(1);
    const object = await env.MY_BUCKET.get(key);
    if (!object) {
      return new Response(&amp;quot;Object not found&amp;quot;, { status: 404 });
    }
    const headers = new Headers();
    object.writeHttpMetadata(headers);
    headers.set(&amp;quot;ETag&amp;quot;, object.httpEtag);
    return new Response(object.body, {
      headers
    });
  }
};

export {
  worker_default as default
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;来到 Worder 设置，添加 R2 绑定&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/18.jpg"&gt;&lt;/p&gt;
&lt;p&gt;变量名是 MY_BUCKET，选择 blog 的图片存储桶&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/19.jpg"&gt;&lt;/p&gt;
&lt;p&gt;绑定后如图&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/20.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;添加 Cloudflare 路由&lt;/h3&gt;
&lt;p&gt;回到 Zones 中，选择托管的域名，添加 Workers 路由&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/21.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击 “Add route” 添加路由&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/22.jpg"&gt;&lt;/p&gt;
&lt;p&gt;填写图床域名，非 Cloudflare 托管的域名&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/23.jpg"&gt;&lt;/p&gt;
&lt;p&gt;添加完成&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/24.jpg"&gt;&lt;/p&gt;
&lt;p&gt;此时，通过 images.yasking.org 可以访问 R2 内图像，链路如图&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/25.jpg"&gt;&lt;/p&gt;
&lt;p&gt;示例链接 &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;https://images.yasking.org/photos/1680170549/01.jpg
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;访问测试&lt;/h3&gt;
&lt;p&gt;从国外服务器访问，显示 cloudflare 服务器&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/26.jpg"&gt;&lt;/p&gt;
&lt;p&gt;国内访问，维持原又拍云 CDN&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725799919/27.jpg"&gt;&lt;/p&gt;
&lt;p&gt;配置完成 ✅&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.eallion.com/cdn-cname-cloudflare/"&gt;图床 CDN CNAME 接入 Cloudflare SaaS 实现分流&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Software"></category><category term="Cloudflare"></category><category term="R2"></category></entry><entry><title>边缘网络：白嫖 Cloudflare Pages 静态博客（DNS 国内外分流）</title><link href="https://blog.yasking.org/a/blog-with-cloudflare-pages.html" rel="alternate"></link><published>2024-09-07T21:00:00+08:00</published><updated>2024-09-07T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-07:/a/blog-with-cloudflare-pages.html</id><summary type="html">&lt;p&gt;改造前本博客通过 DNSPod 解析，博客的静态页面存储在又拍云，这样的方案用着没什么问题，又拍云 CDN 有海外节点，访问也不慢 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;改造前本博客通过 DNSPod 解析，博客的静态页面存储在又拍云，这样的方案用着没什么问题，又拍云 CDN 有海外节点，访问也不慢，本次基于 Cloudflare Pages 的改造有以下几点&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;主观上想更多的体验 Cloudflare 免费服务（此处指代 Pages）&lt;/li&gt;
&lt;li&gt;博客部署往更通用化方向改造，不依赖特定的平台、随时可迁移&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;上图即本次改造后的图例，在海外访问本博客，静态页面即由 Cloudflare 提供&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/02.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;部署 Cloudflare Pages&lt;/h3&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/03.jpg"&gt;&lt;/p&gt;
&lt;p&gt;在 Cloudflare 面板找到 Workers &amp;amp; Pages，进入并点击链接 Git 仓库&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;仓库类型支持 Github、Gitlab（我的博客配置存储在 Github 私有仓库）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择仓库&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;我的博客框架是 Python Pelican，使用 &lt;code&gt;pelican&lt;/code&gt; 命令生成静态文件，仓库中需要有 &lt;em&gt;requirements.txt&lt;/em&gt; 来告知 Cloudflare 安装依赖&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 本机执行命令，生成 requirements.txt 文件，推送到代码仓库
$ python3 -m pip install &amp;quot;pelican[markdown]&amp;quot;
$ pip3 freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;（可选）此处支持众多框架，如：Hexo、Jekyll 等，按需调整构建命令&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击执行&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/08.jpg"&gt;&lt;/p&gt;
&lt;p&gt;等待运行完成，页面提示可以通过 &lt;a href="https://blog-yasking-content.pages.dev/"&gt;https://blog-yasking-content.pages.dev/&lt;/a&gt; 访问静态博客&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;备注：此时点击链接还是会跳回到 &lt;a href="https://blog.yasking.org"&gt;https://blog.yasking.org&lt;/a&gt;，站点 URL 是在 Pelican 配置中定义的，因为我这里配置博客是 DNS 分流而不是在 Cloudflare 上的独立站点，所以是符合预期的&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;添加自定义域名与 DNS 分流&lt;/h3&gt;
&lt;p&gt;点击 “Continue to project” 继续，转到添加自定义域名处&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你的域名由 Cloudflare DNS 托管解析，则指定一个自定义子域名即可，例如：“blog-next.donx-done.xyz”，Cloudflare 会自动配置好 HTTPS、解析等，我的域名由 DNSPod 解析，本次调整是让 DNS 分流，所以我填写的是 “blog.yasking.org”，后续需要手动添加 CNAME 解析到 Cloudflare&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;DNSPod 解析，我这里输入博客域名 blog.yasking.org&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择 “My DNS provider”&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;添加记录&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;进行检测&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;等待片刻后出现 &lt;code&gt;Actice&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/13.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;测试 DNS 分流情况&lt;/h3&gt;
&lt;p&gt;从海外服务器请求，返回的 Headers 指明访问的时 cloudflare 服务器&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/14.jpg"&gt;&lt;/p&gt;
&lt;p&gt;国内继续使用又拍云&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725720054/15.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Cloudflare Pages 部署完成，符合预期，下篇会记录 “images.yasking.og” 图床的改造，之前博客图片也是存储在又拍云，同样计划采用 DNS 分流，海外图片使用免费的 Cloudflare R2 进行存储&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://community.cloudflare.com/t/pelican-command-not-found-on-cloudflare-pages/433435/2"&gt;Pelican command not found on Cloudflare pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.cloudflare.com/pages/configuration/language-support-and-tools/"&gt;Language support and tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mv3.dev/deploy-pelican-to-cloudflare"&gt;Deploy pelican to cloudflare &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Software"></category><category term="Cloudflare"></category></entry><entry><title>Cursor 配置 DeepSeek V2 辅助编程（VSCode / JetBrains 适用）</title><link href="https://blog.yasking.org/a/cursor-with-deepseek.html" rel="alternate"></link><published>2024-09-05T21:00:00+08:00</published><updated>2024-09-14T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-05:/a/cursor-with-deepseek.html</id><summary type="html">&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;关于 DeepSeek，访问&lt;a href="https://www.deepseek.com/"&gt;官网&lt;/a&gt;了解更多，DeepSeek-Coder 用于编程辅助，实测体验很棒！&lt;/p&gt;
&lt;p&gt;如果你不想安装插件辅助编程，只是想通过网页版问些问题，DeepSeek …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;关于 DeepSeek，访问&lt;a href="https://www.deepseek.com/"&gt;官网&lt;/a&gt;了解更多，DeepSeek-Coder 用于编程辅助，实测体验很棒！&lt;/p&gt;
&lt;p&gt;如果你不想安装插件辅助编程，只是想通过网页版问些问题，DeepSeek 也提供了网页端 &lt;a href="https://chat.deepseek.com"&gt;DeepSeek Chat&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;获取在线 DeepSeek API Key&lt;/h3&gt;
&lt;p&gt;平台地址：&lt;a href="https://platform.deepseek.com/"&gt;https://platform.deepseek.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;创建 Key 后记得先充值后使用，最低一元&lt;/p&gt;
&lt;h3&gt;（可选）本地部署 DeepSeek&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;日常使用更推荐 DeepSeek 的在线 API&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;模型地址：https://ollama.com/library/deepseek-coder&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;$ ollama run deepseek-coder
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;参数越多，效果越好，但对机器的性能要求越高，安装后不确定模型名称可以使用 &lt;em&gt;ollama list&lt;/em&gt; 查询&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/03.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;方案一：Cursor + DeepSeek API&lt;/h3&gt;
&lt;p&gt;Cursor 是基于 VS Code 改造后的编辑器（IDE），相比于 VS Code + 插件的模式来说，定制化更强，更适合 AI 辅助编程，如果是新建的小项目，我很乐意尝试 Cursor&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/04.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Cursor 提供一些免费额度，但是很少，好在其可以使用其它 AI 平台的 Key，例如刚申请的 DeepSeek 平台 Key&lt;/p&gt;
&lt;p&gt;首先添加 &lt;code&gt;deepseek-coder&lt;/code&gt; 模型名称&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/05.jpg"&gt;&lt;/p&gt;
&lt;p&gt;然后配置 DeepSeek 获取到的 Key，需要配置 Override，地址为 &lt;em&gt;https://api.deepseek.com/beta&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/06.jpg"&gt;&lt;/p&gt;
&lt;p&gt;配置完成，需要注意，使用 TAB 代码补全需要登录（配置自己的 Key 是免费的）&lt;/p&gt;
&lt;h3&gt;方案二：JetBrains / VS Code + Continue + DeepSeek API&lt;/h3&gt;
&lt;p&gt;如果你不想体验 Cursor，VS Code 是你主力代码编辑器，那么可以试试 Continue 插件，它提供了 VS Code 和 JetBrains 的支持&lt;/p&gt;
&lt;p&gt;Continue 插件下载地址：&lt;a href="https://www.continue.dev/"&gt;https://www.continue.dev/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;此处我使用 JetBrains Goland 记录配置 Continue 过程 ，VS Code 应该大差不差&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;环境信息&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;系统：macOS Ventura 
IDE：JetBrains Goland 2023.1.2
Continue: 0.0.67&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Goland 安装 Continue 插件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;点击设置按钮&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/07.jpg"&gt;&lt;/p&gt;
&lt;p&gt;选择从本地磁盘导入 “Install Plugin from Disk...”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;下载到的 Continue 插件无需解压缩&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/08.jpg"&gt;&lt;/p&gt;
&lt;h3&gt;修改 Continue 插件配置&lt;/h3&gt;
&lt;p&gt;点击 Goland 右侧的  Continue 图标&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/09.jpg"&gt;&lt;/p&gt;
&lt;p&gt;点击图标编辑配置&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/10.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;配置参考&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;使用时注意替换自己的 DeepSeek Key，因为 DeepSeek 的 API 是 OpenAI 兼容的，所以提供者是 &lt;em&gt;openai&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-json"&gt;{
  &amp;quot;models&amp;quot;: [
    {
      &amp;quot;title&amp;quot;: &amp;quot;DeepSeek-V2&amp;quot;,
      &amp;quot;model&amp;quot;: &amp;quot;deepseek-chat&amp;quot;,
      &amp;quot;apiKey&amp;quot;: &amp;quot;&amp;lt;your-api-key&amp;gt;&amp;quot;,
      &amp;quot;apiBase&amp;quot;: &amp;quot;https://api.deepseek.com/beta&amp;quot;,
      &amp;quot;provider&amp;quot;: &amp;quot;openai&amp;quot;
    },
    {
      &amp;quot;title&amp;quot;: &amp;quot;DeepSeek Local,
      &amp;quot;model&amp;quot;: &amp;quot;deepseek-coder:1.3b&amp;quot;,
      &amp;quot;contextLength&amp;quot;: 4096,
      &amp;quot;provider&amp;quot;: &amp;quot;ollama&amp;quot;
    }
  ],
  &amp;quot;customCommands&amp;quot;: [
    {
      &amp;quot;name&amp;quot;: &amp;quot;test&amp;quot;,
      &amp;quot;prompt&amp;quot;: &amp;quot;{{{ input }}}\n\nWrite a comprehensive set of unit tests foar the selected code. It should setup, run tests that check for correctness including important edge cases, and teardown. Ensure that the tests are complete and sophisticated. Give the tests just as chat output, don't edit any file.&amp;quot;,
      &amp;quot;description&amp;quot;: &amp;quot;Write unit tests for highlighted code&amp;quot;
    }
  ],
  &amp;quot;tabAutocompleteModel&amp;quot;: {
    &amp;quot;title&amp;quot;: &amp;quot;DeepSeek-V2&amp;quot;,
    &amp;quot;model&amp;quot;: &amp;quot;deepseek-coder&amp;quot;,
    &amp;quot;apiKey&amp;quot;: &amp;quot;&amp;lt;your-api-key&amp;gt;&amp;quot;,
    &amp;quot;contextLength&amp;quot;: 8192,
    &amp;quot;apiBase&amp;quot;: &amp;quot;https://api.deepseek.com&amp;quot;,
    &amp;quot;completionOptions&amp;quot;: {
      &amp;quot;maxTokens&amp;quot;: 4096,
      &amp;quot;temperature&amp;quot;: 0,
      &amp;quot;topP&amp;quot;: 1,
      &amp;quot;presencePenalty&amp;quot;: 0,
      &amp;quot;frequencyPenalty&amp;quot;: 0
    },
    &amp;quot;provider&amp;quot;: &amp;quot;openai&amp;quot;,
    &amp;quot;useLegacyCompletionsEndpoint&amp;quot;: false
  },
  &amp;quot;tabAutocompleteOptions&amp;quot;: {
    &amp;quot;template&amp;quot;: &amp;quot;Please teach me what I should write in the `hole` tag, but without any further explanation and code backticks, i.e., as if you are directly outputting to a code editor. It can be codes or comments or strings. Don't provide existing &amp;amp; repetitive codes. If the provided prefix and suffix contain incomplete code and statement, your response should be able to be directly concatenated to the provided prefix and suffix. Also note that I may tell you what I'd like to write inside comments. \n{{{prefix}}}&amp;lt;hole&amp;gt;&amp;lt;/hole&amp;gt;{{{suffix}}}\n\nPlease be aware of the environment the hole is placed, e.g., inside strings or comments or code blocks, and please don't wrap your response in ```. You should always provide non-empty output.\n&amp;quot;,
    &amp;quot;useCache&amp;quot;: true,
    &amp;quot;maxPromptTokens&amp;quot;: 2048
  },
  &amp;quot;allowAnonymousTelemetry&amp;quot;: true,
  &amp;quot;reranker&amp;quot;: {
    &amp;quot;name&amp;quot;: &amp;quot;free-trial&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;总结&lt;/h3&gt;
&lt;p&gt;当前 Cursor 的付费计划应该是体验最好的编程辅助，借助 Continue 搭配 DeepSeek API 可以低成本的体验质量较高的代码补全功能&lt;/p&gt;
&lt;p&gt;Goland（JetBrains 系列）IDE 整体体验还有较大的提升空间（Continue 待解决的 BUG），但功能是可用的，以下是我遇到的一些零散问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;开启插件后鼠标悬浮在代码上不出现原有的函数/变量提示&lt;/li&gt;
&lt;li&gt;程序运行后出现的 Run(command + 4) 日志面板的 Hide 按钮点击无效&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;内部报错，时不时弹出&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/11.jpg"&gt;&lt;/p&gt;
&lt;p&gt;UI 文字和输入框错位&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725546875/12.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Continue 插件 在 VS Code 下可能会好一些，JetBrains 家的 IDE 可以等过几个月再试试&lt;/p&gt;
&lt;h3&gt;2024-09-14 补充&lt;/h3&gt;
&lt;p&gt;Cursor 的 Tab completions 补全功能，免费账号终身只有 2000
次，用没就没有了，介意的用户慎重选择，或者重新注册一个账号?&lt;/p&gt;
&lt;h3&gt;参考&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://linux.do/t/topic/114309/12"&gt;听说DeepSeek Coder V2的代码能力很牛&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.bingal.com/posts/ai-ide-cursor-usage/"&gt;强烈推荐一个 AI 辅助编程的工具 cursor + deepseek-coder api，实际体验超预期，Github Copilot 已退订&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Technology"></category><category term="Software"></category></entry><entry><title>部署基于两位赛博菩萨 Cloudflare R2 + Vercel 的免费画廊</title><link href="https://blog.yasking.org/a/cloudflare-r2-and-vercel.html" rel="alternate"></link><published>2024-09-01T21:00:00+08:00</published><updated>2024-09-01T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-01:/a/cloudflare-r2-and-vercel.html</id><summary type="html">&lt;p&gt;前些天发现一个基于 Cloudflare 和 Vercel 两位赛博菩萨的图像画廊&lt;a href="https://github.com/linyuxuanlin/Gallery-Portfolio"&gt;仓库&lt;/a&gt;，正好有意了解 Vercel 部署，本文记录其部署流程&lt;/p&gt;
&lt;h3&gt;创建 R2 存储桶&lt;/h3&gt;
&lt;p&gt;选 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;前些天发现一个基于 Cloudflare 和 Vercel 两位赛博菩萨的图像画廊&lt;a href="https://github.com/linyuxuanlin/Gallery-Portfolio"&gt;仓库&lt;/a&gt;，正好有意了解 Vercel 部署，本文记录其部署流程&lt;/p&gt;
&lt;h3&gt;创建 R2 存储桶&lt;/h3&gt;
&lt;p&gt;选择 R2 服务&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/01.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;创建 R2 存储桶&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/02.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;上传文件夹/目录（本地整理好结构）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/03.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;上传完成 &lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/04.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;h3&gt;添加自定义域名&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/05.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;继续 &lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/06.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;等待&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/07.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;配置完成后访问图像地址进行测试&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;https://r2-65a58o.donx-done.xyz/2024-gallery/DSC_2759.JPG
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;创建 R2 访问的 API&lt;/h3&gt;
&lt;p&gt;用于画廊程序访问 R2 图像的认证 Key&lt;/p&gt;
&lt;p&gt;点击右上角的用户头像，点击 “Account Home” 进入个人中心，点击左侧菜单栏的 🫲 的 R2，此时右侧出现 Account ID 以及 “Manage R2 API Tokens” 链接&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/08.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;点击链接进入管理页面&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/09.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;点击 “Create API Token” 创建 Key，权限根据用途进行选择，本例的画廊展示需要可读写&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/10.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;选择特定的存储桶，收敛 API 权限范围&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/11.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;其它保持默认，创建后会生成 Token、Access Key ID、Secret Access Key、S3 endpoint 地址，记录下来（从安全考量，网站不支持重复查看密钥）&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/12.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;h3&gt;部署 Gallery Portfolio 画廊&lt;/h3&gt;
&lt;p&gt;项目地址：&lt;a href="https://github.com/linyuxuanlin/Gallery-Portfolio"&gt;https://github.com/linyuxuanlin/Gallery-Portfolio&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/13.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;补充：点击页面的按钮进行部署，会遇到遇到以下报错（&lt;a href="https://github.com/supabase/supabase/issues/4534"&gt;#issues 4534&lt;/a&gt;）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An unexpected error occurred. Our team has already been notified and are working to resolve the issue, please try again shortly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;所以按照另一种方式，首先点击克隆一个仓库&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/14.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;在 Vercel 首页导入刚刚克隆的仓库&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/15.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;填写环境变量&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/16.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;点击部署&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/17.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;部署后等待 ⌛️&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/18.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;p&gt;回到项目首页，即可访问到画廊&lt;/p&gt;
&lt;p&gt;地址：&lt;a href="https://r2-gallery-portfolio.vercel.app"&gt;https://r2-gallery-portfolio.vercel.app&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;首次加载需要等待片刻，因为程序会创建缩略图，效果如下&lt;/p&gt;
&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725180343/19.jpg" width = "90%" /&gt;&lt;/p&gt;
&lt;h3&gt;最后&lt;/h3&gt;
&lt;p&gt;Vercel 服务提供免费的网络和计算能力、Cloudflare R2 提供 10 GB 免费存储，这是一个很有趣的画廊示例，后续自己可以写一些代码通过 Vercel 进行部署，本文先到这里&lt;/p&gt;</content><category term="Technology"></category><category term="Cloudflare"></category><category term="Vercel"></category></entry><entry><title>北京昌平・今日夕阳（2024）</title><link href="https://blog.yasking.org/a/photos-beijing-the-setting-sun.html" rel="alternate"></link><published>2024-09-01T18:55:00+08:00</published><updated>2024-09-01T18:55:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-09-01:/a/photos-beijing-the-setting-sun.html</id><summary type="html">&lt;p&gt;沿着 42 公里绿道昌平段骑行，沿路发现一个小市集，进去买了些地瓜水果，偶然抬头望天，发现云彩泛红、太阳西落，于是小步 …&lt;/p&gt;</summary><content type="html">&lt;p&gt;沿着 42 公里绿道昌平段骑行，沿路发现一个小市集，进去买了些地瓜水果，偶然抬头望天，发现云彩泛红、太阳西落，于是小步快跑来到开阔地，用相机记录下此刻的夕阳西下&lt;/p&gt;
&lt;p&gt;拍了好多照片后才发现身后也有一些人在记录，难得停下匆匆的脚步，去记录、去感受，无论是感叹 “夕阳无限好，只是近黄昏” 还是赞叹 “最美不过夕阳红”，我想，此刻的感受，每一刻都值得珍藏&lt;/p&gt;
&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726193740/01.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳（一）&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726193740/02.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳（二）&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726193740/03.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳（三）&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726193740/04.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳（四）&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726193740/05.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳（五）&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726193740/06.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳（六）&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726193740/07.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳（七）&lt;/div&gt;
&lt;/div&gt;

&lt;div style="margin-bottom: 1em;"&gt;
  &lt;img src="https://images.yasking.org/photos/1726193740/08.jpg" /&gt;
  &lt;div style="text-align:center;font-style:italic;"&gt;夕阳（八）&lt;/div&gt;
&lt;/div&gt;</content><category term="Photos"></category><category term="Photos"></category></entry><entry><title>Golang Singleflight 防缓存击穿验证示例</title><link href="https://blog.yasking.org/a/go-singleflight-examples.html" rel="alternate"></link><published>2024-08-30T21:00:00+08:00</published><updated>2024-08-30T21:00:00+08:00</updated><author><name>Yieldone</name></author><id>tag:blog.yasking.org,2024-08-30:/a/go-singleflight-examples.html</id><summary type="html">&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725007924/03.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;h3&gt;Singleflight 示例一：基础用法&lt;/h3&gt;
&lt;p&gt;多次请求共享一次请求的结果&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-golang"&gt;package main

import (
    &amp;quot;fmt&amp;quot;
    &amp;quot;time&amp;quot;

    &amp;quot;golang.org/x/sync/singleflight&amp;quot;
)

func main() {
    var group singleflight.Group

    // A function that simulates an expensive operation
    expensiveOperation := func(key string) (interface{}, error …&lt;/code&gt;&lt;/pre&gt;</summary><content type="html">&lt;p&gt;&lt;img src="https://images.yasking.org/technology/1725007924/03.jpg" width = "78%" /&gt;&lt;/p&gt;
&lt;h3&gt;Singleflight 示例一：基础用法&lt;/h3&gt;
&lt;p&gt;多次请求共享一次请求的结果&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-golang"&gt;package main

import (
    &amp;quot;fmt&amp;quot;
    &amp;quot;time&amp;quot;

    &amp;quot;golang.org/x/sync/singleflight&amp;quot;
)

func main() {
    var group singleflight.Group

    // A function that simulates an expensive operation
    expensiveOperation := func(key string) (interface{}, error) {
        time.Sleep(2 * time.Second) // Simulate delay
        return fmt.Sprintf(&amp;quot;Result for %s&amp;quot;, key), nil
    }

    key := &amp;quot;unique-key&amp;quot;

    // Start multiple goroutines that call the expensive operation through singleflight
    for i := 0; i &amp;lt; 3; i++ {
        go func(id int) {
            result, err, shared := group.Do(key, func() (interface{}, error) {
                return expensiveOperation(key)
            })

            if err != nil {
                fmt.Printf(&amp;quot;Goroutine %d received error: %v\n&amp;quot;, id, err)
            } else {
                fmt.Printf(&amp;quot;Goroutine %d received result: %v (shared: %v)\n&amp;quot;, id, result, shared)
            }
        }(i)
    }

    // Wait for goroutines to finish
    time.Sleep(3 * time.Second)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;输出&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;Goroutine 0 received result: Result for unique-key (shared: true)
Goroutine 2 received result: Result for unique-key (shared: true)
Goroutine 1 received result: Result for unique-key (shared: true)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Singleflight 示例二：解决缓存击穿&lt;/h3&gt;
&lt;p&gt;这个示例集成了数据库、缓存和 HTTP API，有以下几个关键点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;提供了 &lt;code&gt;[GET] /gold/prcie&lt;/code&gt; 和 &lt;code&gt;[POST] /gold&lt;/code&gt; 两个接口模拟黄金价格的更新与查询&lt;/li&gt;
&lt;li&gt;缓存由更新接口在更新数据后设置失效，由查询接口负责构建&lt;/li&gt;
&lt;li&gt;高并发查询场景，缓存失效的一瞬间，面临多个请求会同时访问数据库，即缓存击穿&lt;/li&gt;
&lt;li&gt;高并发查询场景，使用 Singleflight 避免缓存击穿&lt;/li&gt;
&lt;li&gt;查看访问数据库的次数，看到 Singleflight 在这个场景中的重要作用&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;创建表作为数据源&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-sql"&gt;-- 创建表
CREATE TABLE gold_realtime_prices (
    id SERIAL PRIMARY KEY,
    price NUMERIC NOT NULL,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 插入一条模拟数据
INSERT INTO gold_realtime_prices (price) VALUES (575.25);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;代码示例&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;通关环境变量设置 &lt;code&gt;enable&lt;/code&gt; 来开启、关闭 Singleflight 功能，并发查询和定时更新会自动模拟，启动运行即可&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-golang"&gt;package main

import (
    &amp;quot;bytes&amp;quot;
    &amp;quot;database/sql&amp;quot;
    &amp;quot;encoding/json&amp;quot;
    &amp;quot;errors&amp;quot;
    &amp;quot;fmt&amp;quot;
    &amp;quot;io&amp;quot;
    &amp;quot;math/rand&amp;quot;
    &amp;quot;net/http&amp;quot;
    &amp;quot;os&amp;quot;
    &amp;quot;sync&amp;quot;
    &amp;quot;time&amp;quot;

    &amp;quot;github.com/gin-gonic/gin&amp;quot;
    &amp;quot;github.com/go-redis/redis/v8&amp;quot;
    _ &amp;quot;github.com/lib/pq&amp;quot;
    &amp;quot;golang.org/x/net/context&amp;quot;
    &amp;quot;golang.org/x/sync/singleflight&amp;quot;
)

var (
    ctx      = context.Background()
    rdb      *redis.Client
    db       *sql.DB
    sf       singleflight.Group
    mu       sync.Mutex
    cacheKey = &amp;quot;gold_price&amp;quot;
    visitKey = &amp;quot;visit_times&amp;quot;
    queryKey = &amp;quot;query_times&amp;quot;

    enable bool
)

func init() {
    // 从环境变量中获取 SFL_ENABLE 的值
    enableEnv := os.Getenv(&amp;quot;SFL_ENABLE&amp;quot;)
    if enableEnv == &amp;quot;1&amp;quot; {
        enable = true
    } else {
        enable = false
    }
}

func initDB() error {
    var err error
    connStr := &amp;quot;postgresql://&amp;lt;pg-user&amp;gt;:&amp;lt;pg-passwd&amp;gt;@localhost:5432/&amp;lt;dbname&amp;gt;?sslmode=disable&amp;quot;
    db, err = sql.Open(&amp;quot;postgres&amp;quot;, connStr)
    if err != nil {
        return err
    }
    return db.Ping()
}

func initRedis() {
    rdb = redis.NewClient(&amp;amp;redis.Options{
        Addr: &amp;quot;localhost:6379&amp;quot;,
        DB:   3, // 注意数据库使用的 DB3
    })
}

func getGoldPriceFromDB() (float64, error) {
    time.Sleep(200 * time.Millisecond) // 增加数据库查询时间 200 毫秒
    var price float64
    err := db.QueryRow(&amp;quot;SELECT price FROM gold_realtime_prices ORDER BY updated_at DESC LIMIT 1&amp;quot;).Scan(&amp;amp;price)
    return price, err
}

func withoutSingleFlight() (string, error) {

    // 查询数据库次数
    rdb.Incr(ctx, queryKey)

    price, err := getGoldPriceFromDB()
    if err != nil {
        return &amp;quot;&amp;quot;, err
    }
    priceStr := fmt.Sprintf(&amp;quot;%.2f&amp;quot;, price)

    // 更新缓存
    rdb.Set(ctx, cacheKey, priceStr, time.Hour)

    return priceStr, nil
}

func withSingleFlight() (string, error) {
    v, err, _ := sf.Do(cacheKey, func() (interface{}, error) {

        // 查询数据库次数
        rdb.Incr(ctx, queryKey)

        price, err := getGoldPriceFromDB()
        if err != nil {
            return nil, err
        }
        priceStr := fmt.Sprintf(&amp;quot;%.2f&amp;quot;, price)

        // 更新缓存
        rdb.Set(ctx, cacheKey, priceStr, time.Hour)

        return priceStr, nil
    })
    if err != nil {
        return &amp;quot;&amp;quot;, errors.New(&amp;quot;could not get price&amp;quot;)
    }
    return fmt.Sprintf(&amp;quot;%.2f&amp;quot;, v), nil
}

func getGoldPrice(c *gin.Context) {

    // 接口调用次数
    rdb.Incr(ctx, visitKey)

    price, err := rdb.Get(ctx, cacheKey).Result()
    if err == redis.Nil {

        if enable {
            v, err := withSingleFlight()
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{&amp;quot;error&amp;quot;: &amp;quot;could not get price&amp;quot;})
                return
            }
            price = v
        } else {
            v, err := withoutSingleFlight()
            if err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{&amp;quot;error&amp;quot;: &amp;quot;could not get price&amp;quot;})
                return
            }
            price = v
        }
    } else if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{&amp;quot;error&amp;quot;: &amp;quot;could not get price from cache&amp;quot;})
        return
    }

    c.JSON(http.StatusOK, gin.H{&amp;quot;price&amp;quot;: price})
}

func updateGoldPrice(c *gin.Context) {
    var request struct {
        Price float64 `json:&amp;quot;price&amp;quot;`
    }
    if err := c.ShouldBindJSON(&amp;amp;request); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{&amp;quot;error&amp;quot;: &amp;quot;invalid request&amp;quot;})
        return
    }

    // 更新数据库中的价格
    _, err := db.Exec(&amp;quot;INSERT INTO gold_realtime_prices (price, updated_at) VALUES ($1, NOW())&amp;quot;, request.Price)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{&amp;quot;error&amp;quot;: &amp;quot;could not update price&amp;quot;})
        return
    }

    // 使缓存失效
    rdb.Del(ctx, cacheKey)

    c.Status(http.StatusNoContent)
}

func main() {
    if err := initDB(); err != nil {
        panic(err)
    }
    initRedis()

    r := gin.Default()
    r.GET(&amp;quot;/gold/price&amp;quot;, getGoldPrice)
    r.POST(&amp;quot;/gold&amp;quot;, updateGoldPrice)

    // 启动一个协程，并发调用 /gold/price 接口
    go func() {
        simulatedAccess()
    }()

    // 启动一个协程，并发调用 /gold 接口
    go func() {
        simulatedUpdate()
    }()

    if err := r.Run(&amp;quot;:8080&amp;quot;); err != nil {
        panic(err)
    }
}

func simulatedAccess() {

    time.Sleep(time.Second)

    startTime := time.Now()
    for time.Since(startTime) &amp;lt; 6*time.Second {
        go func() {
            resp, err := http.Get(&amp;quot;http://localhost:8080/gold/price&amp;quot;)
            if err != nil {
                fmt.Println(&amp;quot;Error making GET request:&amp;quot;, err)
            } else {
                body, _ := io.ReadAll(resp.Body)
                fmt.Println(&amp;quot;Response from /gold/price:&amp;quot;, string(body))
                resp.Body.Close()
            }
        }()
        time.Sleep(1 * time.Millisecond)
    }
}

func simulatedUpdate() {

    time.Sleep(1 * time.Second)

    ticker := time.NewTicker(500 * time.Millisecond)
    defer ticker.Stop()

    startTime := time.Now()
    for time.Since(startTime) &amp;lt; 5*time.Second {
        &amp;lt;-ticker.C // 等待下一个时间点

        // 生成随机价格
        price := randomPrice(560.0, 580.0)

        // 准备 POST 请求数据
        data := map[string]float64{&amp;quot;price&amp;quot;: price}
        jsonData, err := json.Marshal(data)
        if err != nil {
            fmt.Println(&amp;quot;Error marshalling JSON:&amp;quot;, err)
            continue
        }

        resp, err := http.Post(&amp;quot;http://localhost:8080/gold&amp;quot;, &amp;quot;application/json&amp;quot;, bytes.NewBuffer(jsonData))
        if err != nil {
            fmt.Println(&amp;quot;Error making POST request:&amp;quot;, err)
            continue
        }
        fmt.Printf(&amp;quot;Posted price: %.2f, response status: %s\n&amp;quot;, price, resp.Status)
        resp.Body.Close()
    }
}

func randomPrice(min, max float64) float64 {
    return min + rand.Float64()*(max-min)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;运行&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-bash"&gt;# 未开启 SingleFlight
$ SFL_ENABLE=0 go run main.go

# 开启 SingleFlight
$ SFL_ENABLE=1 go run main.go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果（未开启 Singleflight）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725007924/01.jpg"&gt;&lt;/p&gt;
&lt;p&gt;结果（开启了 Singleflight）&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://images.yasking.org/technology/1725007924/02.jpg"&gt;&lt;/p&gt;
&lt;p&gt;可以看出，启用 Singleflight 后，请求数据库的次数等于更新接口调用的次数，缓存失效时，它的机制决定了在并发请求下，它同时只发起一次对数据库的请求，避免缓存击穿&lt;/p&gt;
&lt;p&gt;本例使用数据库作为示例，其实 Singleflight 不关心服务要请求的资源是数据库、存储还是三方接口，只要资源有唯一的标识就可以将并发的请求合并为一，在请求有结果时统一返回，特别适合高并发请求资源的场景&lt;/p&gt;
&lt;p&gt;除了应对缓存击穿，在高并发请求 Redis 前也可以前置 SingleFlight，将结果共享、进一步降低 Redis 的压力&lt;/p&gt;
&lt;p&gt;Singleflight 简单的使用先到这里，That's all.&lt;/p&gt;</content><category term="Technology"></category><category term="Golang"></category></entry></feed>