<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Yet Another Blog</title>
    <description>又一个不怎么更新的博客，纯面向自己写作 :)
</description>
    <link>https://yangcongchufang.com/</link>
    <atom:link href="https://yangcongchufang.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 06 Nov 2025 07:33:41 +0000</pubDate>
    <lastBuildDate>Thu, 06 Nov 2025 07:33:41 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>把玩crAPI</title>
        <description>&lt;p&gt;Github从来不缺好玩的，最近在研究API攻防，注意到了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crAPI&lt;/code&gt;。全称是“​​完全脆弱的API​​”。正如其名，它是一个被故意设计得千疮百孔的API交互站。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/OWASP/crAPI&quot;&gt;crAPI&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cd cd crAPI-main/deploy/docker
docker compose -f docker-compose.yml --compatibility up -d
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;项目内设置的挑战之一是这样的：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Challenge 1 - Access details of another user’s vehicle
To solve the challenge, you need to leak sensitive information of another user’s vehicle.

Since vehicle IDs are not sequential numbers, but GUIDs, you need to find a way to expose the vehicle ID of another user.

Find an API endpoint that receives a vehicle ID and returns information about it.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;解法倒是蛮简单，可以通过观察发现不同API直接有关联性，进而找到泄露点：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Challenge 1 - Access details of another user’s vehicle

Detailed solution

1. Login to the application from http://localhost:8888/login
2. From the Dashboard, choose Add a Vehicle and add the vehicle by providing the VIN and pincode received in Mailhog mailbox after Signup or by reinitiating from Dashboard page.
After the vehicle details are verified successful, the vehicle will get added and then be populated in the Dashboard page.
4. Observe the request sent when we click Refresh Location. It can be seen that the endpoint is in the format /identity/api/v2/vehicle/&amp;lt;vehicleid&amp;gt;/location.
5. Sensitive information like latitude and longitude are provided back in the response for the endpoint. Send the request to Repeater for later purpose.
6. Click Community in the navbar to visit http://localhost:8888/forum
7. It can be observed that the forum posts are populated based on the response from /community/api/v2/community/posts/recent endpoint. On further analysing the response, it can be seen that vehicleid is also received back corresponding to the author of each post.
8. Edit the vehicleid in the request sent to Repeater in Step 5 with the vehicleid received from endpoint /community/api/v2/community/posts/recent.
9. Upon sending the request, sensitive details like latitude, longitude and full name are received in the response.

The above challenge was completed using Burp Suite Community Edition.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在折腾过程中，踩到的坑是：使用Docker启动，默认监听的地址是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;127.0.0.1&lt;/code&gt;，这个地址看起来是如此正常，却与&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Burp Suite&lt;/code&gt;工具水土不服，BS默认不截获来自localhost的流量。&lt;/p&gt;

&lt;p&gt;最终发现，最简单的办法是设置:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; sudo sh -c &apos;echo &quot;127.0.0.1 crapi.local&quot; &amp;gt;&amp;gt; /etc/hosts&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过访问伪域名&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crapi.local&lt;/code&gt;，便能截获API请求了。&lt;/p&gt;

&lt;p&gt;当然这些都不足够有趣，有趣的是我发现有一个印度Youtuber &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Medusa&lt;/code&gt;用crAPI录制了一系列教学视频。
嚯，第一次觉得印度姑娘有魅力。&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/crapi.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/crapi.html</guid>
        
        
      </item>
    
      <item>
        <title>我所想体验的一切</title>
        <description>&lt;p&gt;我的脑子被物欲绑架了。回顾这种物欲纠结的感觉，大概从之前纠结要买哪一块表开始，从纠结哪一辆车开始。
这种折磨的表现是：可以从21点刷闲鱼直到凌晨1点。然后现在已忘记到底要买什么。
进一步反思，我发现自己总会被一些固定的念头绑架，我盘点了一下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;需要花时间的&lt;/strong&gt;：看 DHH 演讲（Rails作者近期神作）、玩 Omarchy（DHH订制的Archlinux）、国际站外贸上货（我已经拖延快1年了）、读书（囤了好多专题的书籍）、看大模型论文（看了个开头，浑浑噩噩）、自研大模型软件（做了一点点，但是没有驱动力了）。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;需要长期跟踪的&lt;/strong&gt;：Youtube订阅的一系列视频、《凡人修仙传》、《凸变英雄》。&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;：摩托车驾照、本田 CM300、开源软件认证、洗衣机、摔倒报警腕表。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;除了追更《凡人修仙传》。其它很有可能全死在 TODO 清单里，尸骨无存。&lt;/p&gt;

&lt;p&gt;心魔？？？&lt;/p&gt;

&lt;p&gt;以前会硬上一下，非得达到是目的，牺牲休息时间也可。
现在缺了这口劲儿。
想着如今已经年过三十，不妨与自己和解，试试别的路数。&lt;/p&gt;

&lt;p&gt;盘点下来，《凡人修仙传》实在是无法割舍，每周六准时享受。《凸变英雄》这种餐后甜点，也快追完了。这也仅仅占用周六2个小时。&lt;/p&gt;

&lt;p&gt;DHH演讲最多2个小时，不过是没时间看罢了，可能也就是某个空闲时，便能吸收其精华。其实已经知道个大概了，人家开发理念确实好。&lt;/p&gt;

&lt;p&gt;Omarchy Linux已经在我小机器装好了，没想到由于各种情况，基本耗费了1天时间，体验上了，还缺个梯子，未来想用于开发机。&lt;/p&gt;

&lt;p&gt;读书，我一直在囤，我总是在深夜开始想念他们。有一个专题的书籍，哪怕每天看5页呢。&lt;/p&gt;

&lt;p&gt;国际站外贸上货，我也不知道我在等啥，就是没心情去搞，这个投资了小五万，现在就缺个上货。在等契机，还没想好。&lt;/p&gt;

&lt;p&gt;看大模型论文，确实有启发，这周抽空看了一下，总是被细碎的生活琐事打断，但是沉浸式与GPT交互读论文，还是小有启发的。&lt;/p&gt;

&lt;p&gt;Youtube订阅的一系列视频，每当我打开机器，我总是随机在算法引导下游走，或许在做饭的时候听一下即可。&lt;/p&gt;

&lt;p&gt;调研数据中台，调研机器人，其实就是更商业沟通的事情，我倾向于在工作日处理。&lt;/p&gt;

&lt;p&gt;还有花小钱就能买到的物件，现在差一个白板，要贴满整面墙。还差一双防滑拖鞋，给老婆准备的，或许可以交给她解决？或许可以在刷抖音时候解决？也说不清在纠结啥，很占脑子。心疼这点钱，总还是是无效投入。&lt;/p&gt;

&lt;p&gt;驾照，11月才能增加摩托车，增加后还得算算能不能买得起CM300，或者直接租借过瘾即可。&lt;/p&gt;

&lt;p&gt;洗衣机，摔倒报警腕表。洗衣机等回血，腕表太贵了，想着要不二手，要不干脆不要了。&lt;/p&gt;

&lt;p&gt;啊，真正杀死我时间的是脑子里混乱的焦虑，根本不是我喜欢的这些所有。&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;写下上面的碎碎念，是在9月9日，如今10月9日有什么变化呢？&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;DHH演讲看完后，又开始对Rails感兴趣了，下载了Rails的书籍，却又囤着没时间读，成了又一颗钉子。&lt;/p&gt;

&lt;p&gt;Omarchy Linux确实很有意思，我为之投入了小一百元买了U盘，装在了自己的NUC小主机里。在安装过程中体验到了一些问题，均是因为“GFW”导致，好在顺着报错一一解决。&lt;/p&gt;

&lt;p&gt;国际站依然没有上货。好大一颗钉子在脑子里。&lt;/p&gt;

&lt;p&gt;书籍这块，我重新做了分类和整理，我这是知识松鼠除了囤就是整理，乐此不疲。做出的优化是，我的分类开始顺应着自己的规划了，我给自己了三个定位：数据工程师，全栈开发者，创业者。基于这样的定位，我重新整理了书单。我想着每天都回顾一下自己的目标，以便于驱动自己读书。
一个比较有效的尝试，开始听书，不知不觉听完了《创业维艰》。撕碎的时间里，用播客填补空白，可以挽救几百个小时的时间。&lt;/p&gt;

&lt;p&gt;读论文，顺利读完，还是有更深刻的认知，缺乏实践，衍生出的扩展阅读还需要跟进。&lt;/p&gt;

&lt;p&gt;自研大模型基座的软件，可以尝试一下spec-kit啦。&lt;/p&gt;

&lt;p&gt;《凡人修仙传》依然无法割舍，《凸变英雄》追完了，垃圾。《和平使者2》无脑在看。突然想看漫画，下载了《钢之炼金术师》，还是那么喜欢。突然想看《迷宫饭》，神作，喜欢。&lt;/p&gt;

&lt;p&gt;至于花小钱办大事系列，我尝试了之前自己所认为的无意义的花钱，结果没想到还挺香，比如买了一个贴墙白板，比如防滑拖鞋，比如我尝试了阳台种菜，比如冰箱上的计时器，这些事情是那么简单，花销是那么小，但是换来的生活体验是那么多。&lt;/p&gt;

&lt;p&gt;摩托车驾照考试降价到650了，等等党的胜利。&lt;/p&gt;

&lt;p&gt;买了新洗衣机，老婆很满意！&lt;/p&gt;

&lt;p&gt;有了清晰的人生定位，有了果断的行动，从容。&lt;/p&gt;
</description>
        <pubDate>Wed, 10 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/desires-2025.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/desires-2025.html</guid>
        
        
      </item>
    
      <item>
        <title>超轻量超简单的markdown博客</title>
        <description>&lt;p&gt;我的markdown越攒越多了，有时候又需要给人分享。就想着找个简单轻量的markdown博客系统部署出去。
结果没想到，现在仅仅是把markdown伺服起来这么一个简单的需求，都没有合适的工具了。
大概看了ghost、cms.js等工具，感觉还是不够简单。干脆用AI写个得了。&lt;/p&gt;

&lt;p&gt;在这篇文章中，将展示如何构建一个极简的、超轻量级的 Markdown 博客系统。整个系统依赖于 Python 的 Flask 框架，使用 Markdown 格式的文件作为文章内容，并通过简单的前端页面展示。
它不仅易于部署，而且具备基础的登录功能来保护你的内容。&lt;/p&gt;

&lt;h3 id=&quot;功能概述&quot;&gt;&lt;strong&gt;功能概述&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;登录保护&lt;/strong&gt;：确保只有经过验证的用户可以访问 Markdown 文件。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Markdown 渲染&lt;/strong&gt;：将 Markdown 文件转换为 HTML 并展示。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;文件管理&lt;/strong&gt;：列出目录下的所有 Markdown 文件，用户可以点击查看。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;技术栈&quot;&gt;&lt;strong&gt;技术栈&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Flask&lt;/strong&gt;：轻量级的 Python Web 框架，用于构建 Web 应用。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Markdown&lt;/strong&gt;：将 Markdown 格式的文本文件转换为 HTML。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;HTML/CSS&lt;/strong&gt;：用于前端展示，没有任何排版。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;搭建步骤&quot;&gt;&lt;strong&gt;搭建步骤&lt;/strong&gt;&lt;/h3&gt;

&lt;h4 id=&quot;1-安装必要的依赖&quot;&gt;1. &lt;strong&gt;安装必要的依赖&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;需要安装 Flask 和 Markdown Python 库。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;flask markdown
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;2-项目结构&quot;&gt;2. &lt;strong&gt;项目结构&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;项目的文件结构如下所示：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/markdown-blog
    /local-files    # 存放所有的Markdown文件
    /templates      # 存放所有的HTML模板
        index.html
        login.html
        md.html
    app.py           # 主应用文件
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;3-编写-flask-应用apppy&quot;&gt;3. &lt;strong&gt;编写 Flask 应用（app.py）&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;这是整个应用的核心部分。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Flask&lt;/code&gt; 用于创建 Web 应用，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdown&lt;/code&gt; 用于将 Markdown 文件转换为 HTML，应用还实现了登录保护功能。&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;flask&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url_for&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;markdown&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;secret_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;your_secret_key_here&apos;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 设置一个随机密钥
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 配置Markdown文件目录（修改为你的实际路径）
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MD_DIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__file__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;local-files&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;PASSWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;123&apos;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 硬编码密码
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;check_auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;检查是否已登录&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;authenticated&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;/login&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;GET&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;登录页面&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;POST&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;form&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;password&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PASSWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;authenticated&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;index&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;login.html&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;密码错误&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;login.html&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;显示Markdown文件列表&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check_auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;login&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 获取目录下所有md文件
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;mds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MD_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;.md&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 按文件名排序
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;mds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;index.html&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mds&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;/md/&amp;lt;filename&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;render_md&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;渲染指定Markdown文件&quot;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check_auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redirect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;login&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 防止路径穿越攻击
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;..&apos;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MD_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;404&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 构建完整文件路径
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;filepath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MD_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 读取并转换Markdown
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filepath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;r&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;utf-8&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;html_content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;markdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;markdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;extra&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Error reading file: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render_template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;md.html&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;html_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&apos;__main__&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 确保目录存在
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;makedirs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MD_DIR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exist_ok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;4-创建-html-模板&quot;&gt;4. &lt;strong&gt;创建 HTML 模板&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;index.html&lt;/strong&gt;（显示所有 Markdown 文件的列表）：&lt;/p&gt;
&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Markdown文件列表&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;800px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;text-decoration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#0366d6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#f6f8fa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;选择要查看的Markdown文件：&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;p&amp;gt;&lt;/span&gt;目录下没有Markdown文件&lt;span class=&quot;nt&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;login.html&lt;/strong&gt;（用于登录页面）：&lt;/p&gt;
&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;登录&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;请输入访问密码&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;method=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;post&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;password&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;password&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;submit&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;登录&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;md.html&lt;/strong&gt;（显示 Markdown 文件内容）：&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;\{\{ filename \}\}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;max-width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;800px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;pre&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#f6f8fa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;15px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SFMono-Regular&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Consolas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Menlo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;monospace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;blockquote&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;border-left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4px&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#dfe2e5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding-left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;15px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#6a737d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;border-collapse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;collapse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;td&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#dfe2e5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;6px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;13px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;\{\{ url_for(&apos;index&apos;) \}\}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;← 返回列表&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;markdown-content&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
        \{\{ content|safe \}\}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;5-运行应用&quot;&gt;5. &lt;strong&gt;运行应用&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;在项目目录下执行以下命令启动 Flask 应用：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python app.py
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;应用将运行在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://127.0.0.1:5000&lt;/code&gt;，你可以通过浏览器访问它。&lt;/p&gt;

&lt;h4 id=&quot;6-如何使用&quot;&gt;6. &lt;strong&gt;如何使用&lt;/strong&gt;&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;将你的 Markdown 文件（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.md&lt;/code&gt; 格式）放在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;local-files&lt;/code&gt; 目录下。&lt;/li&gt;
  &lt;li&gt;访问首页并输入正确的密码登录。&lt;/li&gt;
  &lt;li&gt;登录后，你可以浏览所有 Markdown 文件，点击链接查看文件内容。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;总结&quot;&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;这个简单的 Markdown 博客系统是一个非常基础的项目，适合想要搭建轻量博客的开发者。你可以通过自定义 Markdown 文件目录、密码保护等，满足个人博客的需求。因为是 Flask 应用，你还可以根据需求进一步扩展功能，比如添加评论系统、分页功能等。&lt;/p&gt;
</description>
        <pubDate>Fri, 18 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/markdown-blog.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/markdown-blog.html</guid>
        
        
      </item>
    
      <item>
        <title>回想2024的思维导图</title>
        <description>&lt;p&gt;无意间翻出2024年期间，热火朝天干工作，脑子发热时候写下的MindMap。
当时脑子真是太热了，想通过思维导图方式整理下思绪。
现在再回头看，往事东流水，笑谈也不成了。 
那时候的情绪，现在想细微去品觉，一分难以回应。&lt;/p&gt;

&lt;p&gt;彼时大概情景是，机缘巧合在线结识一个号称类似摩根士丹利什么鬼的金融大鳄归国。
GPT横空出世，引发巨大商机，作为金融弄潮儿想在中国商海引起一波涟漪。我自觉时运已到，赶快合作一波。一来二去，就张罗着开始搞创业了。&lt;/p&gt;

&lt;p&gt;MindMap中，写下的“核心任务”大概有这些项，第一大主题里是想弄个纯AI SKU的淘宝店：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;项目&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;当时怎么想&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;现在怎么想&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;淘宝店&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;这淘宝店可是不一般。当时GPT新鲜劲儿刚来，就想张罗着给人去充值4.0账户。淘宝上挂出这个商品，还是有商机在的。GPT 4.0账户 、企业版席位这关键字上去，就是绝佳爆品。金融大鳄憋了大的说他弟弟在OpenAI工作，意图拿下中国金牌代理席位。哥们儿是真敢说呀。&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;还是惊叹阿里巴巴的配合程度，品类分类有问题，反馈后立马给作出了调整。GPT账号充值，我也终于找到了稳定的方法。至于API黑色产业，也有一定了解。作为Tire 4玩家，这方面已经没有什么疑问了。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;DEEP LEARNING 深度学习代做&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;作为中国AI界的吃螃蟹者(自诩的)，当然得深入技术底层，什么机器学习、深度学习，已经是工业场景成熟的产物，一顿忽悠直接上，回头再想调用什么API。&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;当时是作为技术人员的拧巴，觉得这种服务必须上。其实放到今天，心底也只有一个人选能做。自己半斤八两只懂个皮毛，10年前就想学，也却是学了，也却是忘了。未来遇到这样的技术需求，默认去调用大厂API，这样ROI更高。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;BID 标书自动生成&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;大模型做标书生成，一键直接出标书全文，可谓是大模型落地之首。这个产品是直接找一个叫阿然的网友采购的，他也是二道贩子。忘了因为什么，还产生了些纠纷，把服务器给停了。&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;涉及到标书，核心原因还是股东里有个小伙子公司是做标书服务的。我们后续也做了真金白银的落地测试。目前最终情况是，培训标书专员去使用ChatGPT成本最低。这也是去年失败投资里最成功的一件事之一，当然了，也没有什么收益。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;代购PIXCEL 8&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;AI手机，不必多说。&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;手机内嵌大模型功能已经普及，我已经非常习惯了，没想仅仅几百天前，真正的AI手机只有一台P8能看得上眼。这里金融大鳄曾说要每人赠送一部，然并无。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;AI生成服装、盲盒&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;没记错的话，是Stable Diffution，当时通过生成做出一个不错的人物形象，甚至计划出实体手办。&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;在线测试服装换衣，在云栖大会里见到了实际产品，也有联系试用，无后续。盲盒的话，确实可行，一个叫阿威的哥们做了个原形，还挺好看。一高兴送了一条挺贵的领带，妈的。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;厂商合作&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;科大讯飞办公硬件， 飞虎的文字生图。&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;科大会议耳机看起来目前已经推广的不错。文生图主要是想与杭州的一家公司合作，这公司目前看做得不错，只记得CEO有不少比特币。可惜我没维护这条关系线。我觉得金融大鳄一直马扁这家公司，就没好意思联系人家。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;数字人&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;印象中大模型爆火后，跟着数字人就火了，大家都想着说数字人接入大模型。&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;硅基智能作为大营销公司活到现在也真是骗不知耻，现在还有个朋友在跟这个项目，大家都是个API二道贩子，没啥技术含量。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;VR设备&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;印象中是想卖Meta的VR设备&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;无后续，一切关于硬件采买的，金融大鳄都跳票了。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;泡塑机料枪&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;对接了一家工厂，想将AI接入到工厂的工作流程中提效&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;我当时想到去训练ChatBot给业务员用，在导出客户资料那天，厂长和厂长夫人紧急叫停了，他们担心客户外泄。这个厂目前还有保持在联系。&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;赶着双11当日，我们结合各类AI工具，花了1天就把这个淘宝店上线了。草台班子也挺有行动力。
这篇博客我写了一半，其实就不太想写了。做得失败事情挺多，挺没意思的。做商业这些人都挺虚伪的。
金融大鳄满口AI，其实都不知道artificial intelligence怎么拼。不过人家今年却是骗出点成绩，看样子常州套了个办公楼。&lt;/p&gt;

&lt;p&gt;MindMap第二大主题是，会所小程序。此事源头还是与合作的金融大鳄有关，他说自己在上海的会所想弄个小程序做会员卡管理。我一琢磨，这可行啊，淘宝花钱给搭个。
上海会所的老钱风和老土风是并重的，X公馆。这哥们儿进了会所就暴露了，这哪是他开的，只能说确实是千丝万缕的联系吧。
这会所老大倒是有点意思，平时爱叼着一根雪茄，第一次见面的时候，正在纠结新买的摇表器柜子摆到哪里。
我们大概磋商了一下小程序设计风格，我说宝玑风吧，他连连称赞。
此事结束的时间点是在之后了，金融大鳄暗戳戳跟我说，你给报价XX万吧（高报5倍），多余的钱我们分。&lt;/p&gt;

&lt;p&gt;MindMap第三大主题是，“APEC 青岛 1月1日前确定”，哈哈哈，我是做梦都没想到，参加个国际级会议的门槛，其实还挺低的。不过最终还是没去参加的，这tmd的怎么去嘛，展示个球。&lt;/p&gt;

&lt;p&gt;2024年，总的来说就是祛魅的一年。彻底祛魅了。现在遇到一个商海大佬，我怼一个。但是经历这些，也没让我长太多记性。我现在又陷入了下一场故事之中。
为什么会偶然打开这个MindMap呢，因为我是要写新的MindMap整理新的思绪。&lt;/p&gt;

&lt;p&gt;不缺商机，闭着眼睛都有商机。
骗子最终套路都一致——借假修真。&lt;/p&gt;

&lt;p&gt;我们无产阶级真可怜，活在既得利益者没怎么上心构建的局中。&lt;/p&gt;
</description>
        <pubDate>Tue, 21 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/review-2024.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/review-2024.html</guid>
        
        
      </item>
    
      <item>
        <title>考驾照一二事</title>
        <description>&lt;p&gt;8月底时，家父见我闲得发慌，终于强推到驾校去学习。我老张家自从老老张就是老司机，到了老张更是跟车打了一辈子交道，如今到我竟然驾照都没，简直不能忍。&lt;/p&gt;

&lt;p&gt;没有驾照——简直是心病。&lt;/p&gt;

&lt;p&gt;对于开车，我是确实没啥兴趣，一是买不起，二是打工打到骨子里，根本没有用车场景，叫个网约车对我来说都是奢侈行为了。
也罢，总不能虚度时光，回顾2024年，新技术学习不能仅仅是会更好的写提示词。
这进了驾校才知道，多少人对于取到驾照竟然是如此执念。从高三毕业党到退休大妈，一天到晚都在驾校孜孜不倦。&lt;/p&gt;

&lt;p&gt;我不太当回事，权当打发时间，心理压力一直不足。科目一刷题两日，找回点学习的感觉，果断下单了驾校一点通，想着速战速决。奔着满分去，没想到有几道题牵扯到营运车辆问题，是个知识盲区，遗憾90分晋级。&lt;/p&gt;

&lt;p&gt;为了省钱，一切都是为了省钱，在我们内蒙古考个驾照才2000。&lt;/p&gt;

&lt;p&gt;科目二烈日炎炎，排队的车友太多，总是觉得练得不过瘾，教练主张一个无师自通，大道至简，自己刷抖音学得奇技淫巧一律不管用，全凭教练点位点拨以及极简操作。家父直接出阵教学，借了车拉着一家子在废弃广场里一轮一轮练习。自信练得不错，手动挡不过如此。&lt;/p&gt;

&lt;p&gt;怎奈，科目二第一场就挂了，开始考试指令一发，直接启动——没有系安全带。是的，我仔细回顾自己的用车历史，老爹没系过，教练没系过，骨子里就没意识到这是个考点。第二次机会，在侧方停车项目中，停车点位不对，再挂。&lt;/p&gt;

&lt;p&gt;“啊，教练，你确实没教过啊，你要说一声我也不至于挂。”&lt;/p&gt;

&lt;p&gt;科目二不得已间隔十日后再战。补考费200。&lt;/p&gt;

&lt;p&gt;好不容易熬到科三，已经开始有了车瘾，方向盘上手后有点小兴奋。膨胀到已经开始看车，基本锁定想弄个马自达练手，没想到买车竟然如此便宜，虽然荷包空空，但已经基本锁定要来一辆二手手动挡玩玩。&lt;/p&gt;

&lt;p&gt;只是没想到，科目三是噩梦的开始，压力逐渐显现。不知不觉挂了三轮了：&lt;/p&gt;

&lt;p&gt;一挂在,教练车和考试车车型不一样，实在搞不懂考试车的判定逻辑，明明自己感觉没问题的操作，考试机器就判定为失误操作。&lt;/p&gt;

&lt;p&gt;补考费累计：400。&lt;/p&gt;

&lt;p&gt;二挂在，教练追求的大道至简实在不适合于我等资质平凡之辈，比如我是挂了后才知道原来刹车需要在一个要求的范围内。&lt;/p&gt;

&lt;p&gt;补考费累计：600。&lt;/p&gt;

&lt;p&gt;家父家母施压，给教练红包：300。&lt;/p&gt;

&lt;p&gt;三挂在，考试过程中路边临时施工，我就按照抖音中学到的操作得意洋洋的打双闪静候近半个小时，全考场中唯一一个正确处理的考生。怎奈何，怎奈何，重新给车打火时，离合死活找不到点，熄火两次，挂。&lt;/p&gt;

&lt;p&gt;补考费累计：800。&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;杭州加课练车费：150。&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;果断再多加练1小时，杭州加课练车费累计：300。&lt;/p&gt;

&lt;p&gt;原来老天让我挂三次是为了我好啊，我根本就没学驾驶，挂了也是应该的。&lt;/p&gt;

&lt;p&gt;10月，12日。张某将会再重返内蒙古重战科目三。&lt;/p&gt;

&lt;p&gt;路费：1000+。&lt;/p&gt;

</description>
        <pubDate>Sun, 29 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/driver-license.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/driver-license.html</guid>
        
        
      </item>
    
      <item>
        <title>关于最近的我</title>
        <description>&lt;p&gt;我完整的休息了一年。&lt;/p&gt;

&lt;p&gt;是的，脱离工作苦海。&lt;/p&gt;

&lt;p&gt;不得不承认高强度工作带来的职业倦怠感是致命的。我真诚的建议任何从业者都不要过度投入到别人制作的世界中。真的会PTSD。&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;

</description>
        <pubDate>Wed, 25 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/recent-about-me.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/recent-about-me.html</guid>
        
        
      </item>
    
      <item>
        <title>诊断并解决MongoDB BTC勒索攻击：一个实战案例</title>
        <description>&lt;h2 id=&quot;引言&quot;&gt;引言&lt;/h2&gt;

&lt;p&gt;最近，我的朋友遭遇了一个令人不安的安全问题：他的MongoDB数据库受到了BTC勒索攻击。经历了一系列排查和解决的步骤后，我决定把这个经验总结成这篇博客。文中介绍用于诊断和解决问题的工具和方法，并分享一些有用的经验教训。&lt;/p&gt;

&lt;h2 id=&quot;开始时的状况&quot;&gt;开始时的状况&lt;/h2&gt;

&lt;p&gt;问题开始于我的朋友发现数据库中有一些未知的集合，这些集合包含了勒索信息。一个严重的安全问题，需要立即采取行动。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{ &quot;_id&quot; : ObjectId(&quot;64fe8b50a20497578c3d0826&quot;), &quot;content&quot; : &quot;All your data is backed up. You must pay 0.0125 BTC to 19GCf7HvckzroTEQQcAfotci9WDkzpk5jW In 48 hours, your data will be publicly disclosed and deleted. (more information: go to http://iplis.ru/data1)After paying send mail to us: rambler+FUCKYOU@onionmail.org and we will provide a link for you to download your data. Your DBCODE is: FUCKYOU&quot; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;绝不妥协，绝不纵容勒索。&lt;/p&gt;

&lt;h2 id=&quot;使用mongo-shell进行初步审查&quot;&gt;使用Mongo Shell进行初步审查&lt;/h2&gt;

&lt;p&gt;首先使用Mongo Shell连接到数据库以进行初步审查。虽然这个工具提供了许多有用的命令来查看数据库和集合的状态，但它无法告诉他哪个用户从哪个IP地址进行了操作。&lt;/p&gt;

&lt;p&gt;MongoDB企业版才具备审计功能。但是对于大部分MongoDB用户来说，大家都是社区版使用者。&lt;/p&gt;

&lt;p&gt;翻阅日志，只能看到建表信息：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cat /var/log/mongodb/mongod.log | grep README
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;配置mongodb日志&quot;&gt;配置MongoDB日志?&lt;/h2&gt;

&lt;p&gt;初步商量的想法，肯定是先增加日志级别协助排查。&lt;/p&gt;

&lt;p&gt;调整MongoDB的日志设置，以便记录更多详细的审计信息。修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/mongod.conf&lt;/code&gt; 文件，并在其中添加了如下内容：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;systemLog:
  destination: file
  path: &quot;/var/log/mongodb/mongod.log&quot;
  logAppend: true
  component:
    accessControl:
      verbosity: 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;理论上来说，这样的配置可以帮助他了解数据库的访问控制信息，但担心仍然没有足够的数据来诊断问题。同时考虑到，我们第一次遭遇这样的情况，不确定直接重启MongoDB实例，将会遭遇怎样的后果。&lt;/p&gt;

&lt;p&gt;直接通过日志来看，名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REAMDE&lt;/code&gt; 的collection内容在不定期重复创建。&lt;strong&gt;我们决定：直接抓鬼。&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;利用tcpdump和wireshark捕获网络流量&quot;&gt;利用tcpdump和Wireshark捕获网络流量&lt;/h2&gt;

&lt;p&gt;考虑到MongoDB日志的局限性，决定使用 tcpdump 工具捕获与数据库相关的网络流量。运行 tcpdump 后，得到了一个包含所有网络数据包的 pcap 文件。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo yum install tcpdump
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;只监听&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;27017&lt;/code&gt;端口，用tcpdump录制流量，产生的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mongodb_packets.pcap&lt;/code&gt;将会解答一切疑惑。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo tcpdump -i eth0 &apos;port 27017&apos; -w mongodb_packets.pcap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;wireshark分析&quot;&gt;Wireshark分析&lt;/h2&gt;

&lt;p&gt;功夫不负有心人，一夜等待后，通过MongoDB日志发现再次发生了创建勒索表的行为。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2023-09-14T06:22:36.094+0800 I STORAGE  [conn14539449] createCollection: READ__ME_TO_RECOVER_YOUR_DATA.README with generated UUID: fc718e02-1707-4b94-9881-3e4d274a9fe1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wireshark打开这个 pcap 文件，并开始仔细分析数据包。最初尝试了多种过滤方法，优先按照日志触发时间筛选了&lt;strong&gt;心目中的可疑IP&lt;/strong&gt;：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(tcp and ip.addr == XXX.1.1XX.X0) and (frame.time &amp;gt;= &quot;Sep 14, 2023 03:00:00&quot;)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但最终使用了一个非常简单但非常有效的显示过滤器：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;frame contains &quot;README&quot; or frame contains &quot;create&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个过滤器立即突显出了一些非常可疑的数据包，其中包括勒索软件很可能用于创建恶意集合的命令。&lt;/p&gt;

&lt;p&gt;我们发现：竟然是一个外网IP，访问到了处于内网环境中的MongoDB。&lt;/p&gt;

&lt;h2 id=&quot;破案&quot;&gt;破案&lt;/h2&gt;

&lt;p&gt;我们当即陷入各种揣测和幻想，这尼玛骇客都玩得这么牛逼了？怎么渗透进来的？&lt;/p&gt;

&lt;p&gt;同志们，这如果是按照一个技术问题排查，那以我们的技术能力来看，这简直算是与顶尖骇客较量了，一台内网的机器，你这是怎么黑进来的？？？&lt;/p&gt;

&lt;p&gt;但是真相往往需要一点点灵感和跳出局限。为什么我们有个&lt;strong&gt;心目中的可疑IP&lt;/strong&gt;呢？因为数据库被黑时间段，是另一个BI项目上线时间段，我们怀疑过某种关联。&lt;/p&gt;

&lt;p&gt;而这个关联虽然没有通过“技术上”通过流量访问判断出来，但是有逻辑意义上的关联。继续深挖发现，为了BI项目，可能各个项目组之间缺乏沟通和安全意识，是有在公网上打开了27017端口！&lt;/p&gt;

&lt;p&gt;使用nmap甚至能够探测到版本号！&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo nmap -p 27017 -sV XXX.16.22.XXX

PORT      STATE SERVICE VERSION
27017/tcp open  mongodb MongoDB 4.0.24

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.38 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;好了，后面就是联系负责的小伙伴去关端口了。&lt;/p&gt;

&lt;p&gt;得亏数据库内容是测试库，不重要。&lt;/p&gt;

&lt;h2 id=&quot;结论和教训&quot;&gt;结论和教训&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;多元化工具：在安全分析中，没有哪一个工具能解决所有问题。Mongo Shell、MongoDB日志、tcpdump和Wireshark都有各自的优势和局限。&lt;/li&gt;
  &lt;li&gt;深入分析：单单依赖数据库日志是不够的。网络流量分析提供了更多线索，可以用来诊断和解决问题。要结合场景看问题，不要纯粹寻求技术解读。&lt;/li&gt;
  &lt;li&gt;关键词过滤：有时候，简单的关键词搜索就足以找出问题的根源。在这个案例中，一个简单的Wireshark过滤器就帮助他找到了问题的核心。&lt;/li&gt;
  &lt;li&gt;安全最佳实践：这次经历提醒了诸位，加强访问控制和进行定期的安全审查是非常必要的。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;通过综合运用这些工具和方法，成功地找出了问题的源头，并避免了可能更严重的损失。我希望我的这篇博客能为面临类似问题的人提供一些实用的指导。再次强调，数据库安全是一个永不停歇的战斗，但有了正确的工具和方法，我们至少能更有信心地面对挑战。&lt;/p&gt;
</description>
        <pubDate>Thu, 14 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/btc-mongodb-hacked.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/btc-mongodb-hacked.html</guid>
        
        <category>MongoDB</category>
        
        <category>Hack</category>
        
        
      </item>
    
      <item>
        <title>开始折腾GKE</title>
        <description>&lt;p&gt;当在GKE集群中部署应用时，可能会遇到Pod调度失败的问题，在我尝试跟着引导教程启动一个集群时候，报错发生了：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0/3 nodes are available: 3 Insufficient cpu. preemption: 0/3 nodes are available: 3 No preemption victims found for incoming pod.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以看到有3个节点无法分配该Pod，初步检索回答都说原因是节点上的CPU资源不足。&lt;/p&gt;

&lt;p&gt;我试图使用命令kubectl获取该Pod的详细信息，查看该Pod所在的Node。然后再获取该Node的详细信息，查看该Node的CPU使用情况。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;kubectl describe pod &amp;lt;pod-name&amp;gt; 
#kubectl describe node &amp;lt;node-name&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但是却发现，Pod的状态是Pending并且Node列中显示为none，这意味着调度程序无法将Pod调度到任何节点。这可能是由于可用的节点资源不足，或者可能是由于Kubernetes集群无法自动扩容以满足请求。看describe输出的Events中有稍微更详细的提示：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Events:
  Type     Reason             Age                    From                Message
  ----     ------             ----                   ----                -------
  Normal   NotTriggerScaleUp  3m47s (x512 over 89m)  cluster-autoscaler  pod didn&apos;t trigger scale-up:
  Warning  FailedScheduling   3m43s (x18 over 89m)   default-scheduler   0/3 nodes are available: 3 Insufficient cpu. preemption: 0/3 nodes are available: 3 No preemption victims found for incoming pod.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;问题基本定位，我需要看看如何再GKE下做节电池扩容。手动操作路径是：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;登录 Google Cloud Console，选择目标 GKE 集群。&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;通过命令行完成节点扩容方式是在Web console下执行：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcloud container clusters resize CLUSTER_NAME --node-pool POOL_NAME --size NEW_SIZE --region REGION
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CLUSTER_NAME&lt;/code&gt; 为 GKE 集群的名称。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POOL_NAME&lt;/code&gt; 为要扩容的节点池的名称。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NEW_SIZE&lt;/code&gt; 为扩容后节点池的大小。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REGION&lt;/code&gt; 为 GKE 集群所在的区域。&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Wed, 01 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/gke-001.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/gke-001.html</guid>
        
        <category>GKE</category>
        
        <category>k8s</category>
        
        <category>GCP</category>
        
        
      </item>
    
      <item>
        <title>记录一次Spark升级调试版本依赖的经验</title>
        <description>&lt;p&gt;版本调试是开发过程中必不可少的一环，尤其是在涉及到复杂依赖关系的情况下，比如Spark升级、Scala版本变化或Gradle依赖冲突等。近期工作中尝试做了一次Spark2升级到Spark3.0.X的改造。遇到了不少关于依赖管理的问题。&lt;/p&gt;

&lt;p&gt;升级过程中，环境基本信息如下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;测试系统是MacOS Intel/ MacOS M1/ CentOS 7&lt;/li&gt;
  &lt;li&gt;升级前Spark 2.4.7，Scala 2.11.12， DeltaLake 0.6.1 …&lt;/li&gt;
  &lt;li&gt;版本管理使用Gradle&lt;/li&gt;
  &lt;li&gt;JDK 8&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;因为一个依赖包需要，项目不得不尝试升级到Spark 3.0.X。那么，问题就开始了。&lt;/p&gt;

&lt;p&gt;主要的一个报错是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;job.java.lang.NoSuchMethodError&lt;/code&gt; ，因为版本依赖变更，很多旧包调用的底层方法失效。报错摘要如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;java.lang.AbstractMethodError: Method org/apache/spark/sql/delta/commands/WriteIntoDelta.org$apache$spark$sql$catalyst$plans$logical$Command$_setter_$nodePatterns_$eq(Lscala/collection/Seq;)V is abstract
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;failed to build the batch job.java.lang.NoSuchMethodError: scala.collection.immutable.$colon$colon.tl$1()Lscala/collection/immutable/List;
	at play.api.libs.json.jackson.JsValueDeserializer.deserialize(JacksonJson.scala:184)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;以第一个报错摘要为例子，我以为的基本处理思路是：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;想去厘清Spark 和 Delta Lake 的依赖冲突&lt;/li&gt;
  &lt;li&gt;找到官方文档的版本匹配说明调整版本号&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;但是实际上，根据官方文档调整版本号后，发现还是报错。 于是又开始尝试逐个切换版本号试错。
有趣的是，最终发现在自己本地M1机器上跑通了，但是放到CentOS下跑不通。
可见还需要考虑到芯片架构问题，确实用着不同JDK，可能在不同系统下才能暴露问题。&lt;/p&gt;

&lt;p&gt;而我目前不得不部署的时候用一套依赖配置，本地开发的时候用一套依赖配置。&lt;/p&gt;

&lt;p&gt;遇到的第二大类问题算Gradle依赖管理的问题，有些共同依赖隐藏到不同包内，这就导致了包名一致，但是包内方法不一致。解决主要处理思路是：&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;以Gradle为例，我们发现报错来自&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;javax.servlet&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;使用gradle协助列出依赖树：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./gradlew dependencies
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在依赖树中检索，确实存在不同版本的多次引入。于是尝试清除共同依赖，方法算用exclude，示例:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    implementation(&quot;org.apache.spark:spark-core_2.12:${sparkVersion}&quot;) {
        exclude group: &apos;javax.servlet&apos;, module: &apos;*&apos;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但是清理后发现还是存在旧版本，这个时候使用 gradle dependencyInsight 命令检查依赖冲突。该命令可以列出特定依赖项的所有版本以及每个版本的依赖项，并标识可能存在的冲突:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#gradle dependencyInsight --dependency javax.servlet
gradle dependencyInsight --dependency &amp;lt;dependency-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;看到清晰的依赖关系后，不得不手动将产生引用的地方全部exclude掉。&lt;/p&gt;

&lt;p&gt;同理，因为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;com.fasterxml.jackson.core&lt;/code&gt;算一个相对底层的依赖，不少JSON相关的库底层都用了它。这就发生了多次引用的问题：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;failed to build the batch job.java.lang.NoSuchMethodError: scala.collection.immutable.$colon$colon.tl$1()Lscala/collection/immutable/List;
	at play.api.libs.json.jackson.JsValueDeserializer.deserialize(JacksonJson.scala:184)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;除了排除依赖外，也用到了强制指明依赖，在implementation后加&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!!&lt;/code&gt; 让全局依赖到的位置都用指定的版本：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    implementation &apos;com.fasterxml.jackson.core:jackson-databind:2.12.3!!&apos;
    implementation &apos;com.fasterxml.jackson.core:jackson-core:2.12.3!!&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;处理依赖问题非常耗时，主要是各种等待和调试，需要耐心和时间，最终改动或许只有几行代码，可能就会被误解工作量不够，希望遇到类似问题的工程师们能被理解。&lt;/p&gt;
</description>
        <pubDate>Wed, 22 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/dependencies-in-gradle.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/dependencies-in-gradle.html</guid>
        
        <category>gradle</category>
        
        
      </item>
    
      <item>
        <title>安装MySQL 8到CentOS 7.9</title>
        <description>&lt;h1 id=&quot;1-下载和安装&quot;&gt;1. 下载和安装&lt;/h1&gt;

&lt;p&gt;搜索到&lt;a href=&quot;https://dev.mysql.com/downloads/repo/yum/&quot;&gt;MySQL Community Downloads&lt;/a&gt; 获得MySQL源下载链接。&lt;/p&gt;

&lt;p&gt;CentOS7 系统选择 &lt;strong&gt;Red Hat Enterprise Linux 7 / Oracle Linux 7 (Architecture Independent), RPM Package&lt;/strong&gt; 下载。&lt;/p&gt;

&lt;p&gt;下载完成后安装MySQL源：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo rpm -ivh mysql57-community-release-el7-9.noarch.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接着可通过yum直接安装MySQL：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo yum install mysql-server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;2-启动前配置&quot;&gt;2. 启动前配置&lt;/h1&gt;

&lt;p&gt;修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/my.cnf&lt;/code&gt; 文件配置MySQL启动参数：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[mysqld]
# datadir=/var/lib/mysql
# socket=/var/lib/mysql/mysql.sock
datadir=/usr/local/bsjx/data/mysql
socket=/usr/local/bsjx/data/mysql/mysql.sock

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在上面示例中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;datadir&lt;/code&gt;修改到一块挂载磁盘。
系统中如何开启SELinux，会导致MySQL无法用挂载的磁盘作为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;datadir&lt;/code&gt;启动。
可从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log-error&lt;/code&gt;指向的日志中看到报错信息。
如果启动后遇到类似报错：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;InnoDB: The innodb_system data file &apos;ibdata1&apos; must be writable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;则需要关闭SELinux才能顺利启动：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;setenforce 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;3-启动mysql&quot;&gt;3. 启动MySQL&lt;/h1&gt;

&lt;p&gt;启动MySQL:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo systemctl enable mysqld
sudo systemctl start mysqld
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;查看启动状态：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo systemctl status mysqld
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在安装过程中，会为 MySQL root 用户生成一个临时密码。
mysqld.log使用以下命令找到它：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo grep &apos;password&apos; /var/log/mysqld.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;执行后匹配出初始化的密码：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2022-09-24T06:09:39.950202Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: 4hL33yzBCp%N
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;4-启动后的配置mysql&quot;&gt;4. 启动后的配置MySQL&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mysql_secure_installation&lt;/code&gt; 工具可以协助更改默认密码和做数据库初始化的设置。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo mysql_secure_installation
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;执行后，跟随命令行配置引导完成设置。
这里建议在引导中选择删除&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test&lt;/code&gt;数据库，该库的权限验证机制不太一样。&lt;/p&gt;

&lt;h1 id=&quot;5-测试安装情况&quot;&gt;5. 测试安装情况&lt;/h1&gt;

&lt;p&gt;验证数据库安装情况：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mysqladmin -u root -p version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</description>
        <pubDate>Sat, 24 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://yangcongchufang.com/install-mysql-on-centos.html</link>
        <guid isPermaLink="true">https://yangcongchufang.com/install-mysql-on-centos.html</guid>
        
        <category>MySQL</category>
        
        
      </item>
    
  </channel>
</rss>
