Skip to content

Commit 30f21cb

Browse files
authored
Merge branch 'master' into master
2 parents ab0a919 + 23f7c67 commit 30f21cb

File tree

29 files changed

+640
-135
lines changed

29 files changed

+640
-135
lines changed

.github/workflows/build.yaml

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
name: build
22

33
on:
4-
push:
5-
branches:
6-
- "*"
7-
pull_request:
8-
branches:
9-
- "*"
4+
- pull_request
5+
- push
106

117
jobs:
128
build:
139
runs-on: ubuntu-latest
10+
outputs:
11+
commit-info: ${{ steps.commit-info.outputs.COMMIT_INFO }}
1412
steps:
1513
- uses: actions/checkout@v4
14+
with:
15+
fetch-depth: 0
1616
- uses: actions/setup-python@v5
1717
with:
1818
python-version: "3.11"
@@ -46,6 +46,7 @@ jobs:
4646
globs: |
4747
docs/**/*.md
4848
README.md
49+
4950
- name: Stop and report errors
5051
run: |
5152
git add -A
@@ -59,18 +60,53 @@ jobs:
5960
mkdocs -v build
6061
: > site/.nojekyll
6162
echo -n '201.ustclug.org' > site/CNAME
63+
64+
- name: Upload artifact
65+
uses: actions/upload-pages-artifact@v3
66+
with:
67+
path: site
68+
69+
- name: Generate commit info
70+
id: commit-info
71+
run: |
72+
git log -1 --pretty="COMMIT_INFO=%an: [%h] %s" >> "$GITHUB_OUTPUT"
73+
74+
deploy:
75+
needs: build
76+
if: github.ref == 'refs/heads/master'
77+
environment:
78+
name: github-pages
79+
url: ${{ steps.deployment.outputs.page_url }}
80+
permissions:
81+
contents: write
82+
pages: write
83+
id-token: write
84+
runs-on: ubuntu-latest
85+
steps:
6286
- name: Deploy to GitHub Pages
63-
if: github.ref == 'refs/heads/master'
87+
id: deployment
88+
uses: actions/deploy-pages@v4
89+
90+
- name: Download artifact
91+
uses: actions/download-artifact@v5
92+
with:
93+
name: github-pages
94+
path: site/
95+
96+
- name: Push site to gh-pages branch
6497
run: |
65-
CINFO="$(git log -1 --pretty="%an: [%h] %s")"
6698
git clone --depth=1 --branch=gh-pages --single-branch --no-checkout \
67-
"https://${GITHUB_ACTOR}:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git" test
99+
"https://${{ github.actor }}:${{ github.token }}@github.com/${{ github.repository }}.git" test
68100
mv test/.git site/.git && rmdir test/
69101
pushd site/ &>/dev/null
102+
if [ -f artifact.tar ]; then
103+
tar xf artifact.tar
104+
rm artifact.tar
105+
fi
70106
git add -A
71107
git -c user.name=GitHub -c [email protected] commit \
72108
-m "Auto deploy from GitHub Actions build ${GITHUB_RUN_NUMBER}" \
73-
-m "$CINFO" \
109+
-m "${{ needs.build.outputs.commit-info }}" \
74110
--allow-empty
75111
git push
76112
popd &>/dev/null

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/.sass-cache/
22
/env/
33
/venv/
4-
/site/
5-
node_modules
4+
/site
5+
node_modules

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
1. `python3 -m venv venv`
66
2. `. venv/bin/activate`
7-
3. `pip install -r requirements.txt`
7+
3. `pip3 install -r requirements.txt`
88
4. `mkdocs serve`
99

1010
## 格式检查
@@ -20,3 +20,7 @@
2020
## 许可
2121

2222
本文档以 Creative Commons BY-NC-SA 4.0 协议发布。详情请见 [LICENSE](LICENSE)
23+
24+
## Star History
25+
26+
[![Star History Chart](https://api.star-history.com/svg?repos=ustclug/Linux201-docs&type=Date)](https://star-history.com/#ustclug/Linux201-docs&Date)

docs/advanced/elk.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
icon: simple/elasticsearch
3+
---
4+
5+
# ELK
6+
7+
!!! warning "本文编写中"

docs/css/counter.scss

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,23 @@ h2::before {
2727
h3::before {
2828
counter-increment: h3;
2929
content: counter(h2) "." counter(h3);
30-
margin-right: 0.8rem;
30+
margin-right: 0.5rem;
3131
}
3232

3333
h4::before {
3434
counter-increment: h4;
3535
content: counter(h2) "." counter(h3) "." counter(h4);
36-
margin-right: 0.8rem;
36+
margin-right: 0.5rem;
3737
}
3838

3939
h5::before {
4040
counter-increment: h5;
4141
content: counter(h2) "." counter(h3) "." counter(h4) "." counter(h5);
42-
margin-right: 0.8rem;
42+
margin-right: 0.3rem;
4343
}
4444

4545
h6::before {
4646
counter-increment: h6;
4747
content: counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) "." counter(h6);
48-
margin-right: 0.8rem;
48+
margin-right: 0.3rem;
4949
}

docs/dev/git.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,14 @@ d959e182468be92957bd175d189472de91f614c8
145145

146146
这被称为 "refspec",基本格式为 `<source>:<destination>`,表示从 `<source>` 获取对象并存储到 `<destination>`。如果 `<source>` 以 `+` 开头,则表示强制覆盖。上面的例子表示将远程仓库中 `refs/heads` 下的所有分支获取到本地的 `refs/remotes/origin` 下,即 `git fetch` 的默认行为。
147147

148+
`git push` 同样也可以接受 refspec,默认的 `push.default` 配置项的值为 `simple`,表示将当前分支推送到与其同名的远程分支,相当于 `refs/heads/<some-branch>:refs/heads/<some-branch>`(把 `<source>` 的对象推送到远程的 `<destination>` 上)。
149+
148150
更多信息可阅读 [Git Book 的 10.5 节](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec) 与 [git-fetch(1)][git-fetch.1]。
149151

152+
!!! tip "`git reflog`"
153+
154+
Reflogs(Reference logs)记录了 git 操作中 ref 的更新历史,在需要从误操作恢复,或确认之前操作给 ref 带来的变化时非常有用。例子参考 [Hackergame 2023 的 "Git? Git!" 一题](https://github.com/USTC-Hackergame/hackergame2023-writeups/tree/master/official/Git%20Git!)。
155+
150156
#### Remote {#git-remote}
151157

152158
绝大部分时候我们都有本地与远程仓库交互的需求,因此这里也介绍与 remote 相关的内容。
@@ -712,6 +718,9 @@ GitHub 的 deploy keys 功能允许用户对特定仓库添加只用于该仓库
712718
- [ ] Task 2
713719
```
714720

721+
- [x] Task 1 #123
722+
- [ ] Task 2
723+
715724
此时可以将这个 Issue 转化为一个任务列表,方便追踪任务的进度,同时 `#123` 会被标记为 `Tracked by #xxx`
716725

717726
#### Issue 模板 {#github-issue-template}
@@ -722,16 +731,16 @@ GitHub 的 deploy keys 功能允许用户对特定仓库添加只用于该仓库
722731
name: Bug Report
723732
about: Create a report to help us improve
724733
labels:
725-
- bug
734+
- bug
726735
body:
727-
- type: textarea
728-
id: bug-description
729-
attributes:
730-
label: Describe the bug
731-
description: A clear and concise description of what the bug is.
732-
placeholder: I'm always frustrated when...
733-
validations:
734-
required: true
736+
- type: textarea
737+
id: bug-description
738+
attributes:
739+
label: Describe the bug
740+
description: A clear and concise description of what the bug is.
741+
placeholder: I'm always frustrated when...
742+
validations:
743+
required: true
735744
```
736745
737746
可以参考 [ustclug/mirrorrequest/.../01-mirror-request.yml](https://github.com/ustclug/mirrorrequest/blob/master/.github/ISSUE_TEMPLATE/01-mirror-request.yml?plain=1), [GitHub 文档](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository).

docs/dev/language/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
icon: material/xml
33
---
44

5-
# 编程语言概览
5+
# 编程语言与工具
66

77
本部分介绍我们开发时常用的编程语言,以及常用工具、实用技巧等信息。
88

docs/images/osi-vs-tcpip.svg

Lines changed: 4 additions & 0 deletions
Loading

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ icon: material/home
1717

1818
- 能够相对熟练地使用 C 和 Python 语言编写自己所需的程序。
1919
- 了解 Linux 101 的内容,并且有能力完成其中的练习。
20-
- 有能力配置可用的 Debian 系统环境(实机/虚拟机/容器等)。
20+
- 有能力配置可用的 Debian 系统环境(物理机/虚拟机/容器等)。
2121
- 能够正确使用 Google 等搜索方式,并相对熟练地阅读英文资料。
2222

2323
除此之外,部分章节可能依赖于其他计算机科学的知识,例如数据库、计算机网络等。如果对前置要求不熟悉,建议先学习相关的知识。作为参考,[cs-self-learning](https://csdiy.wiki/) 提供了不错的自学教程目录。

docs/ops/debug.md

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ icon: material/bug
4141

4242
不幸的是,有些时候出现问题的系统会卡在那里,无法操作,这可能是因为内存几乎已满(OOM),出现了大量 I/O 操作,也有可能是内核崩溃或是硬件问题。如果内核仍然在运行,可以尝试使用 SysRq 快捷键做一些操作。如果机器没有 SysRq 按键(例如笔记本电脑),可以使用 PrintScreen 键代替。
4343

44-
根据发行版配置的不同,默认情况下仅允许有限的 SysRq 操作,可以向 `/proc/sys/kernel/sysrq` 写入 1 来运行全部操作,或者自行计算允许的操作,详情见 [Linux 内核文档的 "Linux Magic System Request Key Hacks" 部分](https://docs.kernel.org/admin-guide/sysrq.html#how-do-i-enable-the-magic-sysrq-key)。需要在 sysctl 配置中设置 `kernel.sysrq=1` 以持久化相应设置。
44+
根据发行版配置的不同,默认情况下仅允许有限的 SysRq 操作,可以向 `/proc/sys/kernel/sysrq` 写入 1 来运行全部操作,或者自行计算允许的操作,详情见 [Linux 内核文档的Linux Magic System Request Key Hacks部分](https://docs.kernel.org/admin-guide/sysrq.html#how-do-i-enable-the-magic-sysrq-key)。需要在 sysctl 配置中设置 `kernel.sysrq=1` 以持久化相应设置。
4545

4646
最常见的 SysRq 系列指令为 REISUB(即 busy 的比较级 busier 反过来),即按顺序按下 Alt+SysRq+R、E、I、S、U、B,分别对应的操作为:
4747

@@ -66,13 +66,15 @@ icon: material/bug
6666

6767
用户态 OOM Killer 可以很大程度缓解这个问题,最常用的两个实现如下:
6868

69-
- systemd-oomd。在最近的发行版中一般预装。它以 cgroup 为单位,根据内存的 PSI 信息与 swap 占用比例判断,如果 PSI 在一段时间内超过设置的阈值,或者 swap 占用比例超过阈值,就会将对应的 cgroup 杀死。如果使用 oomd,建议开启 swap,以便为 oomd 提供足够的响应时间处理。
69+
- systemd-oomd。在最近的发行版中一般预装。它以 cgroup 为单位,根据内存的 PSI 信息与物理内存和 swap 占用比例判断,如果 PSI 在一段时间内超过设置的阈值,或者物理内存和 swap 的占用比例都超过阈值,就会将对应的 cgroup 杀死。如果使用 oomd,建议开启 swap,以便为 oomd 提供足够的响应时间处理。
7070

7171
由于 oomd 处理以 cgroup 为单位,因此在桌面环境下需要确定桌面环境可以正确将每个应用放在独立的 cgroup 中(GNOME、KDE 等现代桌面环境是没有问题的);在服务器场景下,如果你有使用 tmux 等工具的习惯,那么可能需要配置让它们的每个窗口都在不同的 cgroup 中(例如配置 tmux 的 `default-command` 为 `systemd-run --user --scope bash`),否则在运行了过分占用内存的程序后,oomd 会将整个 tmux cgroup 杀死。
7272

7373
oomd 是 opt-in 的——需要主动在 systemd 相关 unit 中添加相关配置,oomd 才会处理。可以使用 `oomctl` 命令获取当前 oomd 状态,检查 "Swap Monitored CGroups" 与 "Memory Pressure Monitored CGroups" 是否包含需要监控的 systemd unit。诸如 Debian、Fedora 等发行版均做了相关的预配置。
7474

75-
除了在 unit 文件中配置 `ManagedOOMSwap` 和 `ManagedOOMMemoryPressure` 外,建议通过编辑 `/etc/systemd/oomd.conf` 文件来调整 oomd 的全局行为。其中 `SwapUsedLimit` 参数(默认为 90%)虽然名称中包含 "Swap",但它同时适用于物理内存和 Swap 空间。oomd 触发的条件是:内存压力(PSI)超过 `OOMMemoryPressureLimit` **或** (物理内存使用率 > `SwapUsedLimit` **且** Swap 空间使用率 > `SwapUsedLimit`)。在物理内存较大的服务器上,默认的 90% `SwapUsedLimit` 可能过早触发 OOM Killer,影响正常使用。此时可以考虑将其调整至更高的值,例如 95% 或 98%,根据实际物理内存大小预留一部分即可。
75+
除了在 unit 文件中配置 `ManagedOOMSwap` 和 `ManagedOOMMemoryPressure` 外,建议通过编辑 `/etc/systemd/oomd.conf` 文件来调整 oomd 的全局行为。其中 `SwapUsedLimit` 参数(默认为 90%)虽然名称中包含 "Swap",但它**同时适用于物理内存和 Swap 空间**。oomd 触发的条件是:内存压力(PSI)超过 `DefaultMemoryPressureLimit` **或** (物理内存使用率 > `SwapUsedLimit` **且** Swap 空间使用率 > `SwapUsedLimit`)。当达到 `SwapUsedLimit` 时,oomd 会杀死占用 swap 最高且占用量超过 5% swap 的 cgroup;当达到 `OOMMemoryPressureLimit` 时,oomd 会优先选择需要让系统回收最多内存(带来的压力最多)的 cgroup。
76+
77+
在物理内存较大的服务器上,默认的 90% `SwapUsedLimit` 可能过早触发 OOM Killer,影响正常使用。此时可以考虑将其调整至更高的值,例如 95% 或 98%,根据实际物理内存大小预留一部分即可。另外,可能有一点不符合预期的是,在设置 `SwapUsedLimit` 的时候,会首先 kill 占用 swap 最多的进程,而不是占用内存最多的进程,因此可能会出现占用了最多的内存的进程并没有被 kill,而是占用比较少内存的进程被 kill 了。
7678

7779
??? example "Debian 12 中的 systemd-oomd 配置"
7880

@@ -88,7 +90,7 @@ icon: material/bug
8890
ManagedOOMMemoryPressure=kill
8991
ManagedOOMMemoryPressureLimit=50%
9092
```
91-
93+
9294
??? example "Fedora 42 中的 systemd-oomd 配置"
9395

9496
Fedora 42 的默认配置为:在系统和用户 slice 下,如果内存压力超过 80%,则杀死压力最大的 cgroup。
@@ -109,7 +111,7 @@ icon: material/bug
109111
earlyoom 可以配置在杀死进程后执行命令(例如提示用户有进程被杀死)。Vlab 项目即做了相关的配置,通过结合 zenity 弹出对话框,效果如下:
110112

111113
![earlyoom in Vlab](../images/vlab-earlyoom.png)
112-
114+
113115
!!! question "tmpfs?"
114116

115117
思考这个问题:如果某个在容器中的进程错误地向 tmpfs 写入了大量数据导致内存不足,systemd-oomd 可以解决这个问题吗?earlyoom 呢?
@@ -124,13 +126,15 @@ icon: material/bug
124126
- 占用空间小
125127
- `arch-chroot` 工具可以方便地 chroot 到安装的系统中,以便执行操作
126128
- 如果不使用 `arch-chroot`,在 chroot 进入系统前就需要手动挂载 `/proc`、`/sys`、`/dev` 等文件系统、配置 `/etc/resolv.conf` 等等,比较麻烦。
127-
129+
128130
如果可以看到 GRUB 界面,但是发现进入系统时卡死且没有详细的错误信息,那么需要在 GRUB 界面中按下 `e` 键,编辑对应的启动项,删除 `linux` 这一行的 `quiet` 和 `splash` 选项。发行版可能会默认包含这些选项,以减小启动时的输出信息,以及显示漂亮的启动动画(如果有),但是这会影响到问题调试。
129131

130132
诸如 Debian 等发行版会额外生成 recovery 的启动项,会配置进入单用户模式(single user mode),可以尝试使用这个选项进入系统。
131133

132134
## 服务状态与日志 {#status-and-logs}
133135

136+
### 日志简介 {#logs-intro}
137+
134138
当出现异常,登录系统后,第一件事情可能是检查当前系统的服务状态。
135139
`systemctl --failed` 可以列出当前失败的服务。
136140
如果显示大量服务失败,那么说明可能遇到了比较严重的问题,例如磁盘已满等。
@@ -183,6 +187,43 @@ logrotate 会定期(一般是每天,或者文件足够大的时候,请参
183187

184188
某些大型程序也有专门的搜索网站,例如 [Chromium Code Search](https://source.chromium.org/chromium)。
185189

190+
### Kernel panic 与 pstore {#kernel-panic-and-pstore}
191+
192+
当内核遇到不可恢复的致命错误时,就会发生「内核恐慌」,即 kernel panic,表示内核崩溃,无法继续操作。
193+
默认情况下,kernel panic 的时候会打印出报错信息,然后需要人工重启。
194+
然而,对于实验室炼丹炉或者不易远程操作的服务器等一些场景来说,管理员可能更希望服务能够尽快恢复,此时可以通过设置 `kernel.panic` 这一项 sysctl 参数实现在 panic 时的自动重启,但这也使得管理员无法及时地在终端上看到重启前最后的 panic 信息。
195+
196+
**pstore**(Persistent Storage)是一个内核特性,用于在系统崩溃时保存报错信息,以供后续分析。
197+
pstore 支持多种存储后端,包括一小段专门划分的内存区域(称为 [ramoops](https://docs.kernel.org/admin-guide/ramoops.html))、ACPI ERST 表以及 UEFI 变量存储区域等。
198+
存储后端通常能够提供至少 64 KiB 的存储空间,足够保存数百行 dmesg(默认保留最后 10 KiB)及其他状态信息。
199+
默认情况下,Linux 会在 `/sys/fs/pstore` 的位置挂载 pstore 文件系统,管理员可以通过此目录查看 pstore 中存储的日志。
200+
pstore 模块本身的参数也通过 sysfs 暴露,例如可以通过 `/sys/module/pstore/parameters/backend` 的内容确认当前 pstore 选用的存储后端。
201+
202+
!!! tip "ACPI ERST"
203+
204+
可以使用以下命令验证硬件是否支持 ACPI ERST:
205+
206+
```shell
207+
ls /sys/firmware/acpi/tables/ | grep ERST
208+
```
209+
210+
!!! note "UEFI 变量存储可能不会被默认启用"
211+
212+
UEFI 变量存储区域的空间是有限的,并且非常不幸的是,UEFI 固件的编写者不少都没有恰当处理**变量存储区域被写满**的情况。这意味着,一旦这种情况发生,那么**系统就可能变砖,无法正常启动**。因此内核提供了 `CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE` 选项,如果它被启用,那么内核就不会默认使用 UEFI 变量存储区域作为 pstore 的存储后端。
213+
214+
视内核与发行版配置,可以使用 `zcat /proc/config.gz | grep PSTORE` 或 `cat /boot/config-$(uname -r) | grep PSTORE` 来检查当前内核是否启用了 pstore 以及相关配置情况。
215+
216+
!!! note "ramoops 能够保留数据吗?"
217+
218+
pstore 的 ramoops 后端无法突破物理规律——如果机器断电重启了,那么(易失性)内存里的数据就自然没了。在不断电重启的情况下,内存是否会被清空取决于硬件实现。
219+
220+
!!! tip "kdump"
221+
222+
如果无法使用 pstore,kdump 机制也可以作为替代方案。kdump 需要在启动时占用一块内存空间存储备用内核等信息。在 kernel panic 时,kernel 会 kexec 到备用内核上,备用内核此时就可以获取到内核的 coredump、dmesg 等信息。Debian 可以使用上文提到的 `kdump-tools` 包来配置 kdump。
223+
224+
然而,pstore 的容量是有限的,因此 **systemd-pstore** 服务会在启动时自动将 pstore 的内容归档至 `/var/lib/systemd/pstore`,以便腾出空间,同时保留记录供管理员查阅。
225+
也就是说,如果你在重启后发现 `/sys/fs/pstore` 是空的,那么你应该去查看 `/var/lib/systemd/pstore`
226+
186227
## procfs 与 strace {#procfs-and-strace}
187228

188229
`/proc`(procfs)是内核以文件系统形式向用户空间提供的查看、管理进程状态的接口。
@@ -778,7 +819,7 @@ tcpdump -ni eth0 host 8.8.8.8
778819

779820
![Wireshark setting pre-master-secret log filename](../images/wireshark-tls.png)
780821

781-
[bcc](#eBPF) 提供的 `sslsniff` 工具、[eCapture](https://github.com/gojue/ecapture) 工具则通过 eBPF 的方式实现了查看加密内容的功能。
822+
[bcc](#ebpf) 提供的 `sslsniff` 工具、[eCapture](https://github.com/gojue/ecapture) 工具则通过 eBPF 的方式实现了查看加密内容的功能。
782823

783824
!!! note "HTTP/HTTPS 抓包工具"
784825

@@ -1140,6 +1181,14 @@ example(1023, 1024)
11401181
- [The bpftrace One-Liner Tutorial](https://github.com/bpftrace/bpftrace/blob/master/docs/tutorial_one_liners.md)[中文版](https://github.com/bpftrace/bpftrace/blob/master/docs/tutorial_one_liners_chinese.md)
11411182
- [bpftrace(8) Manual Page](https://github.com/bpftrace/bpftrace/blob/master/man/adoc/bpftrace.adoc)
11421183

1184+
!!! lab "eBPF 程序编写实验"
1185+
1186+
尝试使用 bpftrace 或 bcc 完成以下任务:
1187+
1188+
- 对整个系统的程序做监测,当程序退出时,输出程序的运行时间(Wall time)。
1189+
- 挑战:能否尽可能输出程序被执行时的命令行参数?
1190+
- 对某个程序做监测,当该程序执行某种系统调用时(例如读取文件),输出程序的调用栈。
1191+
11431192
## 补充阅读 {#supplement}
11441193

11451194
### 书籍 {#supplement-books}

0 commit comments

Comments
 (0)