LLM 工程化在福 uu 中的落地实践 —— 假期调课的智能解析

在对话框以外,大模型又能发挥什么作用呢?

2026/3/30
阅读更多

实现一个 CSS 词法分析器(Lexer)

最近在实习的时候,遇到了一些需求,需要自己去实现 CSS 的解析、(伪)渲染流程。以之为契机,我学习了一下编译相关的知识,其中的第一环就是 Lexer。

2025/8/5
阅读更多

向着璀璨的未来进发 —— 我的 2024 年度总结

2024 年就这样过去了。上半年发生的一系列事情对我仿佛一场梦一样,而下半年我才回到真实的生活中。

2025/1/28
阅读更多

愿此去前路皆坦途 —— 我的 2023 年度总结

2023 年就这样在恍恍惚惚间过去了,在这一年中发生了许多事情,就让我挑一些大家可能感兴趣的事情来讲讲吧。

2024/1/1
阅读更多

如何创建一个打印友好型的网页

在某些情况下,我们会遇到需要将网页打印出来的需求。但是,直接打印网页的效果往往不尽如人意,因为网页的排版和打印的排版是不同的。本文将介绍如何创建一个在打印时具有出色的质量和可读性的网页。

2023/5/28
阅读更多

我的 OI 生涯 —— 一名退役竞赛生的回忆录

在经历了四年半的不算短也不算长的时光后,我的 OI 生涯画上了一个并不算圆满的句号。 是的,我退役了。

2023/4/2
阅读更多

向 #define int long long 说不

在算法竞赛社区中,经常能看见有人在代码中使用 #define int long long 来偷懒。这种做法会导致代码的可读性大大降低,并带来一些难以预料的问题。本文将从 C++ 标准定义的角度,解释为什么这种做法是不可取的。

2023/2/8
阅读更多

再见,2022 —— 我的 2022 年度总结

又一年过去了。由于学业繁忙,这一年中发生的能写出来公之于众的事情并没有多少,但做一些微小的记录总是值得的,所以就有了这篇年度总结。

2022/12/31
阅读更多

我的新冠阳性日记

一直以为「感染新冠」这件事离我很远,像我这种居家上网课的人也不太可能与外面的病毒产生什么联系。直到 12 月 13 日午休之后,我居然发烧了,拿出抗原一测,发现自己阳了。

2022/12/23
阅读更多

USTC Hackergame 2022 Write Up

<h2 id="签到">签到</h2><p>日常改参数。</p><p><img src="https://arina.loli.net/2022/10/22/g6qoWrfzeBpnYOE.png" alt="" loading="lazy"></p><h2 id="猫咪问答喵">猫咪问答喵</h2><ol><li><p>中国科学技术大学 NEBULA 战队(USTC NEBULA)是于何时成立的喵?</p><p><a href="https://cybersec.ustc.edu.cn/2022/0826/c23847a565848/page.htm" rel="external nofollow noreferrer"></a></p><p>在这个页面中有这样一段介绍:</p><blockquote><p><strong>星云战队(Nebula)</strong></p><p>中国科学技术大学“星云战队(Nebula)”成立于 <strong>2017 年 3 月</strong>,“星云”一词来自中国科学技术大学 BBS“瀚海星云”,代表同学们对科学技术的无限向往和追求。战队现领队为网络空间安全学院吴文涛老师,现任队长为网络空间安全学院李蔚林、童蒙和武汉。战队核心成员包括了来自网络空间安全学院、少年班学院、物理学院、计算机学院等各个院系的同学,充分体现了我校多学院共建网络空间安全一级学科的特点。战队以赛代练,以赛促学,在诸多赛事中获得佳绩。</p></blockquote><p>可知答案为 <code>2017-03</code>。</p></li></ol><ol start="3"><li><p>22 年坚持,小 C 仍然使用着一台他从小用到大的 Windows 2000 计算机。那么,在不变更系统配置和程序代码的前提下,Firefox 浏览器能在 Windows 2000 下运行的最后一个大版本号是多少?</p><p>Google 搜索 <code>windows 2000 firefox</code> 可以搜索到一个帖子:<a href="https://www.betaarchive.com/forum/viewtopic.php?t=34790" rel="external nofollow noreferrer">Last version of fireFox to work on Windows 2000?</a>,可知答案为 12。</p></li><li><p>你知道 PwnKit(CVE-2021-4034)喵?据可靠谣传,出题组的某位同学本来想出这样一道类似的题,但是发现 Linux 内核更新之后居然不再允许 argc 为 0 了喵!那么,请找出在 Linux 内核 master 分支(torvalds/linux.git)下,首个变动此行为的 commit 的 hash 吧喵!</p><p>关于这部分的限制在 <code>fs/exec.c</code> 文件下,那么 <code>git blame</code> 可知这部分是在 <a href="https://github.com/torvalds/linux/commit/dcd46d897adb70d63e025f175a00a89797d31a43" rel="external nofollow noreferrer"><code>dcd46d8</code></a> 中被修改的。</p></li></ol><h2 id="家目录里的秘密">家目录里的秘密</h2><h3 id="vs-code-里的-flag">VS Code 里的 flag</h3><p>全局搜索 <code>flag&#123;</code> 可得:</p><p><img src="https://arina.loli.net/2022/10/23/Wa7JPK3rlwYLN9b.png" alt="" loading="lazy"></p><h3 id="rclone-里的-flag">rclone 里的 flag</h3><p><img src="https://arina.loli.net/2022/10/23/Fj2cKvUZOIrdiSY.png" alt="" loading="lazy"></p><p>在 <code>rclone.conf</code> 里可以找到一个密码,通过在 Google 上搜索可以找到 <a href="https://forum.rclone.org/t/how-to-retrieve-a-crypt-password-from-a-config-file/20051/3" rel="external nofollow noreferrer">一份现成的解密代码</a>:</p><pre><code class="hljs go"><span class="hljs-keyword">package</span> main <span class="hljs-keyword">import</span> ( <span class="hljs-string">&quot;crypto/aes&quot;</span> <span class="hljs-string">&quot;crypto/cipher&quot;</span> <span class="hljs-string">&quot;crypto/rand&quot;</span> <span class="hljs-string">&quot;encoding/base64&quot;</span> <span class="hljs-string">&quot;errors&quot;</span> <span class="hljs-string">&quot;fmt&quot;</span> <span class="hljs-string">&quot;log&quot;</span> ) <span class="hljs-comment">// crypt internals</span> <span class="hljs-keyword">var</span> ( cryptKey = []<span class="hljs-type">byte</span>&#123; <span class="hljs-number">0x9c</span>, <span class="hljs-number">0x93</span>, <span class="hljs-number">0x5b</span>, <span class="hljs-number">0x48</span>, <span class="hljs-number">0x73</span>, <span class="hljs-number">0x0a</span>, <span class="hljs-number">0x55</span>, <span class="hljs-number">0x4d</span>, <span class="hljs-number">0x6b</span>, <span class="hljs-number">0xfd</span>, <span class="hljs-number">0x7c</span>, <span class="hljs-number">0x63</span>, <span class="hljs-number">0xc8</span>, <span class="hljs-number">0x86</span>, <span class="hljs-number">0xa9</span>, <span class="hljs-number">0x2b</span>, <span class="hljs-number">0xd3</span>, <span class="hljs-number">0x90</span>, <span class="hljs-number">0x19</span>, <span class="hljs-number">0x8e</span>, <span class="hljs-number">0xb8</span>, <span class="hljs-number">0x12</span>, <span class="hljs-number">0x8a</span>, <span class="hljs-number">0xfb</span>, <span class="hljs-number">0xf4</span>, <span class="hljs-number">0xde</span>, <span class="hljs-number">0x16</span>, <span class="hljs-number">0x2b</span>, <span class="hljs-number">0x8b</span>, <span class="hljs-number">0x95</span>, <span class="hljs-number">0xf6</span>, <span class="hljs-number">0x38</span>, &#125; cryptBlock cipher.Block cryptRand = rand.Reader ) <span class="hljs-comment">// crypt transforms in to out using iv under AES-CTR.</span> <span class="hljs-comment">//</span> <span class="hljs-comment">// in and out may be the same buffer.</span> <span class="hljs-comment">//</span> <span class="hljs-comment">// Note encryption and decryption are the same operation</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">crypt</span><span class="hljs-params">(out, in, iv []<span class="hljs-type">byte</span>)</span></span> <span class="hljs-type">error</span> &#123; <span class="hljs-keyword">if</span> cryptBlock == <span class="hljs-literal">nil</span> &#123; <span class="hljs-keyword">var</span> err <span class="hljs-type">error</span> cryptBlock, err = aes.NewCipher(cryptKey) <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> &#123; <span class="hljs-keyword">return</span> err &#125; &#125; stream := cipher.NewCTR(cryptBlock, iv) stream.XORKeyStream(out, in) <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span> &#125; <span class="hljs-comment">// Reveal an obscured value</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Reveal</span><span class="hljs-params">(x <span class="hljs-type">string</span>)</span></span> (<span class="hljs-type">string</span>, <span class="hljs-type">error</span>) &#123; ciphertext, err := base64.RawURLEncoding.DecodeString(x) <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> &#123; <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;&quot;</span>, fmt.Errorf(<span class="hljs-string">&quot;base64 decode failed when revealing password - is it obscured? %w&quot;</span>, err) &#125; <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(ciphertext) &lt; aes.BlockSize &#123; <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;&quot;</span>, errors.New(<span class="hljs-string">&quot;input too short when revealing password - is it obscured?&quot;</span>) &#125; buf := ciphertext[aes.BlockSize:] iv := ciphertext[:aes.BlockSize] <span class="hljs-keyword">if</span> err := crypt(buf, buf, iv); err != <span class="hljs-literal">nil</span> &#123; <span class="hljs-keyword">return</span> <span class="hljs-string">&quot;&quot;</span>, fmt.Errorf(<span class="hljs-string">&quot;decrypt failed when revealing password - is it obscured? %w&quot;</span>, err) &#125; <span class="hljs-keyword">return</span> <span class="hljs-type">string</span>(buf), <span class="hljs-literal">nil</span> &#125; <span class="hljs-comment">// MustReveal reveals an obscured value, exiting with a fatal error if it failed</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">MustReveal</span><span class="hljs-params">(x <span class="hljs-type">string</span>)</span></span> <span class="hljs-type">string</span> &#123; out, err := Reveal(x) <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> &#123; log.Fatalf(<span class="hljs-string">&quot;Reveal failed: %v&quot;</span>, err) &#125; <span class="hljs-keyword">return</span> out &#125; <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123; fmt.Println(MustReveal(<span class="hljs-string">&quot;tqqTq4tmQRDZ0sT_leJr7-WtCiHVXSMrVN49dWELPH1uce-5DPiuDtjBUN3EI38zvewgN5JaZqAirNnLlsQ&quot;</span>)) &#125;</code></pre><p>跑一遍就出来了:</p><p><img src="https://arina.loli.net/2022/10/23/HdkNQMnDtKPC2pi.png" alt="" loading="lazy"></p><h2 id="heilang">HeiLang</h2><p>打开 VSCode,将 <code>\| ([\d]+)\] = ([\d]+)</code> 递归替换为 <code>] = $2\na[$1] = $2</code>,然后执行脚本即可得到 flag:</p><p><img src="https://arina.loli.net/2022/10/22/MXHg5NSwhCptjnb.png" alt="" loading="lazy"></p><h2 id="xcaptcha">Xcaptcha</h2><p>在打开验证码页面的一瞬间将这段 JS 脚本塞进控制台里即可。</p><pre><code class="hljs javascript"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">3</span>; i++) &#123; <span class="hljs-keyword">let</span> raw_str = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">querySelector</span>(<span class="hljs-string">`label[for=&quot;captcha<span class="hljs-subst">$&#123;i&#125;</span>&quot;]`</span>).<span class="hljs-property">innerHTML</span>; <span class="hljs-keyword">let</span> match = <span class="hljs-regexp">/([\d]+)\+([\d]+)/</span>.<span class="hljs-title function_">exec</span>(raw_str); <span class="hljs-keyword">let</span> sum = <span class="hljs-title class_">BigInt</span>(match[<span class="hljs-number">1</span>]) + <span class="hljs-title class_">BigInt</span>(match[<span class="hljs-number">2</span>]); <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&#x27;captcha&#x27;</span> + i).<span class="hljs-property">value</span> = sum.<span class="hljs-title function_">toString</span>(); &#125; <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">getElementById</span>(<span class="hljs-string">&#x27;submit&#x27;</span>).<span class="hljs-title function_">click</span>();</code></pre><p><img src="https://arina.loli.net/2022/10/23/pHf1hyrcMCaO3AF.png" alt="" loading="lazy"></p><h2 id="旅行照片-2-0">旅行照片 2.0</h2><h3 id="照片分析">照片分析</h3><p><img src="https://arina.loli.net/2022/10/22/JKqzcnk2Iv7GYF4.png" alt="" loading="lazy"></p><p>exiftool 一把梭。</p><h2 id="latex-机器人">LaTeX 机器人</h2><h3 id="纯文本">纯文本</h3><p>众所周知,LaTeX 有一个 <code>\input</code> 指令:</p><p><img src="https://arina.loli.net/2022/10/22/oTlw9jqFINLvQZA.png" alt="" loading="lazy"></p><p>Flag 到手:<code>flag&#123;becAr3fu11dUd3c5a1b17ffa&#125;</code>。</p><h2 id="安全的在线测评">安全的在线测评</h2><h3 id="无法-ac-的题目">无法 AC 的题目</h3><p>最开始我打算在程序里读文件,结果不知道为什么写挂了……</p><p>于是就立马想到了用汇编读文件,代码和动态数据差不多。</p><h3 id="动态数据">动态数据</h3><p>查看评测机的源码可以发现 n = 5,那么可以用汇编在编译的时候读文件:</p><pre><code class="hljs c"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&lt;stdio.h&gt;</span></span> <span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">&lt;string.h&gt;</span></span> <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;staticInput: .incbin \&quot;data/static.in\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;staticAnswer: .incbin \&quot;data/static.out\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicInput0: .incbin \&quot;data/dynamic0.in\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicInput1: .incbin \&quot;data/dynamic1.in\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicInput2: .incbin \&quot;data/dynamic2.in\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicInput3: .incbin \&quot;data/dynamic3.in\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicInput4: .incbin \&quot;data/dynamic4.in\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicAnswer0: .incbin \&quot;data/dynamic0.out\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicAnswer1: .incbin \&quot;data/dynamic1.out\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicAnswer2: .incbin \&quot;data/dynamic2.out\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicAnswer3: .incbin \&quot;data/dynamic3.out\&quot;&quot;</span>); <span class="hljs-keyword">asm</span>(<span class="hljs-string">&quot;dynamicAnswer4: .incbin \&quot;data/dynamic4.out\&quot;&quot;</span>); <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> staticInput[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> staticAnswer[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicInput0[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicInput1[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicInput2[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicInput3[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicInput4[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicAnswer0[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicAnswer1[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicAnswer2[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicAnswer3[]; <span class="hljs-keyword">extern</span> <span class="hljs-type">char</span> dynamicAnswer4[]; <span class="hljs-type">char</span> n[<span class="hljs-number">1000000</span>], a[<span class="hljs-number">6</span>][<span class="hljs-number">1000000</span>], p[<span class="hljs-number">1000000</span>], q[<span class="hljs-number">1000000</span>]; <span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">int</span> argc, <span class="hljs-type">char</span> **argv[])</span> &#123; <span class="hljs-built_in">scanf</span>(<span class="hljs-string">&quot;%s\n&quot;</span>, &amp;n); <span class="hljs-built_in">sscanf</span>(staticInput, <span class="hljs-string">&quot;%s&quot;</span>, a[<span class="hljs-number">0</span>]); <span class="hljs-built_in">sscanf</span>(dynamicInput0, <span class="hljs-string">&quot;%s&quot;</span>, a[<span class="hljs-number">1</span>]); <span class="hljs-built_in">sscanf</span>(dynamicInput1, <span class="hljs-string">&quot;%s&quot;</span>, a[<span class="hljs-number">2</span>]); <span class="hljs-built_in">sscanf</span>(dynamicInput2, <span class="hljs-string">&quot;%s&quot;</span>, a[<span class="hljs-number">3</span>]); <span class="hljs-built_in">sscanf</span>(dynamicInput3, <span class="hljs-string">&quot;%s&quot;</span>, a[<span class="hljs-number">4</span>]); <span class="hljs-built_in">sscanf</span>(dynamicInput4, <span class="hljs-string">&quot;%s&quot;</span>, a[<span class="hljs-number">5</span>]); <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">strcmp</span>(n, a[<span class="hljs-number">0</span>])) &#123; <span class="hljs-built_in">sscanf</span>(staticAnswer, <span class="hljs-string">&quot;%s\n%s&quot;</span>, p, q); <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;%s\n%s\n&quot;</span>, p, q); &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">strcmp</span>(n, a[<span class="hljs-number">1</span>])) &#123; <span class="hljs-built_in">sscanf</span>(dynamicAnswer0, <span class="hljs-string">&quot;%s\n%s&quot;</span>, p, q); <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;%s\n%s\n&quot;</span>, p, q); &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">strcmp</span>(n, a[<span class="hljs-number">2</span>])) &#123; <span class="hljs-built_in">sscanf</span>(dynamicAnswer1, <span class="hljs-string">&quot;%s\n%s&quot;</span>, p, q); <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;%s\n%s\n&quot;</span>, p, q); &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">strcmp</span>(n, a[<span class="hljs-number">3</span>])) &#123; <span class="hljs-built_in">sscanf</span>(dynamicAnswer2, <span class="hljs-string">&quot;%s\n%s&quot;</span>, p, q); <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;%s\n%s\n&quot;</span>, p, q); &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">strcmp</span>(n, a[<span class="hljs-number">4</span>])) &#123; <span class="hljs-built_in">sscanf</span>(dynamicAnswer3, <span class="hljs-string">&quot;%s\n%s&quot;</span>, p, q); <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;%s\n%s\n&quot;</span>, p, q); &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">strcmp</span>(n, a[<span class="hljs-number">5</span>])) &#123; <span class="hljs-built_in">sscanf</span>(dynamicAnswer4, <span class="hljs-string">&quot;%s\n%s&quot;</span>, p, q); <span class="hljs-built_in">printf</span>(<span class="hljs-string">&quot;%s\n%s\n&quot;</span>, p, q); &#125; <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; &#125;</code></pre><p><img src="https://arina.loli.net/2022/10/23/f7FIqpXbV61iyRl.png" alt="" loading="lazy"></p><h2 id="企鹅拼盘">企鹅拼盘</h2><h3 id="这么简单我闭眼都可以!">这么简单我闭眼都可以!</h3><p>手动一个一个试就好啦~</p><p><img src="https://arina.loli.net/2022/10/23/ANl2KCbYjL76MtB.png" alt="" loading="lazy"></p><p><img src="https://arina.loli.net/2022/10/23/DeyVZRbJCQ25WPf.png" alt="" loading="lazy"></p><h2 id="后记">后记</h2><p><img src="https://arina.loli.net/2022/10/29/afcCSBUqALiImz4.png" alt="" loading="lazy"></p><p>今年是我打 Hackergame 的第三年了,由于近期学业繁忙(甚至我刚从 CSP-S 考场出来就回来写 Write Up),所以并没有能抽出足够的时间来享受这场比赛了,只能用两天的零碎时间水一点签到题了事,binary 还是一如既往地稀烂……</p>

2022/10/29
阅读更多

OIerDb NG —— 新一代的 OIerDb

笔者有幸能与 OI 巨神虞皓翔等人合作来共同参与 OIerDb NG 的开发,经过数个月的不断改进,目前项目已经初具雏形,特此写下本篇文章对其进行简要介绍。

2022/8/9
阅读更多

拥抱 Atomic CSS-in-JS

当下,Atomic CSS 愈发受到人们的关注。相比于传统 CSS 编写方法中每个组件对应一个 CSS 类,使用了 Atomic CSS 以后,每一个 CSS 类都唯一对应了一条独立的 CSS 规则,随着组件数量逐渐增加、能复用的 CSS 规则越来越多,最终的 CSS 产物体积也会下降许多,使得网页的加载速度能够产生一个质的飞跃。

2022/7/23
阅读更多

使用 GitHub Actions 自动申请与部署 SSL 证书

对于一个有很多服务器的人来说,在不同服务器上同步 SSL 证书是一件麻烦事。笔者尝试过很多种方式,最后在 Menci 的推荐下选定了使用 GitHub Actions 来自动申请、续期 SSL 证书,并自动推送到各个服务器上。

2022/5/15
阅读更多

强制卸载三星应用分身中的残留应用

<p>前一阵子不小心手抖把手机里的 Chrome 卸载了,然后就装不上了。</p><img src="https://s1.baoshuo.ren/2022/04/30/6Y5HdtnT4fKrcxZ.jpg" width="350"><p>▲ 安装时的报错信息</p><p>这个迷惑的报错信息误导了我很长时间,再加上我在学校里拿不到手机,于是 3 月初的问题一直拖到了 4 月底才解决。</p><p>拿到手机之后我突然想看看手机里有什么不再需要的应用需要卸载,清理清理手机的存储空间。于是我翻到了这么一个应用:</p><img src="https://s1.baoshuo.ren/2022/04/30/TvSn9tKzrZ5qifx.jpg" width="350"><p>▲ 应用图标右下角的橙色标志代表了这是一个安装在应用分身中的应用</p><p>但是我手机里的应用分身只能安装两个应用:微信和 QQ。所以问题应该就是出在了这里。我试着点击了下方的「卸载」按钮,但提示卸载成功并重启后,这个 Chrome 浏览器依然静静地呆在手机里,丝毫没有要离开的意思。</p><p>我在网上找到了一篇名为《<a href="https://www.sizau.com/a/one-ui-dual-app.html" rel="external nofollow noreferrer">技术 | One UI 不熔断,让应用分身双开任何应用</a>》的文章,里面讲解了如何在应用分身中安装其他应用的方法,还提到了应用分身其实是以 Android 多用户的形式实现的,分身中的所有应用都安装在了名为 <code>DUAL_APP</code> 的用户下。知道了这些信息,事情就好办得多了,直接用 ADB 把它搞掉就行了(<a href="https://developer.android.com/studio/releases/platform-tools#downloads" rel="external nofollow noreferrer">ADB 下载地址</a>)。</p><p><a href="https://publish.samsungsimulator.com/simulator/418c1904-4e51-4517-bee3-334744957266/#!topic/%E8%AE%BE%E7%BD%AE%E8%8F%9C%E5%8D%95/%E5%BC%80%E5%90%AF%E5%BC%80%E5%8F%91%E8%80%85%E9%80%89%E9%A1%B9" rel="external nofollow noreferrer">在手机上开启开发者模式</a> 后,在「开发者选项」中允许「USB 调试」,然后使用数据线将手机连接到电脑,这样就可以在电脑上通过 ADB 操控手机了。</p><p>使用下面的命令来查看手机中的用户列表:</p><pre><code class="hljs shell">adb shell pm list users</code></pre><p><img src="https://s1.baoshuo.ren/2022/04/30/9PDszfwVaoT8NCQ.png" alt="" loading="lazy"></p><p>▲ 图中被红色方框框住的就是应用分身对应的用户了</p><p>然后使用下面的命令来查看分身中的应用列表:</p><pre><code class="hljs shell">adb shell pm list packages --user 95</code></pre><p><img src="https://s1.baoshuo.ren/2022/04/30/F3rhWgUpY4evMZa.png" alt="" loading="lazy"></p><p>▲ 图中被红色方框框住的就是应用分身中的 Chrome 浏览器的包名了</p><p>那么就可以卸载分身中的 Chrome 浏览器了:</p><pre><code class="hljs shell">adb uninstall --user 95 com.android.chrome</code></pre><p><img src="https://s1.baoshuo.ren/2022/04/30/HInGCjd4JRuUrwT.png" alt="" loading="lazy"></p><p>卸载完成后,就可以通过你喜欢的方式安装应用了。我这里同样使用了 ADB 来进行 Chrome 浏览器的安装操作:</p><pre><code class="hljs shell">adb install &quot;com.android.chrome_101.0.4951.41-495104123.apk&quot;</code></pre><p><img src="https://s1.baoshuo.ren/2022/04/30/yNFCt7fqYPAoDBO.png" alt="" loading="lazy"></p><p>最后不要忘记关掉「USB 调试」功能,以免产生安全风险。</p>

2022/4/30
阅读更多

2022 年常中集训游记

这是我第一次出省参加外校集训。此行的目的地是江苏省常州高级中学,于 1907 年建校,截止本文写作时该校在「OIerDb 全国信息学竞赛学校排行榜」上位列第九。

2022/2/28
阅读更多