<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>TiancyのBlog</title>
  
  <subtitle>Tiancyの小屋</subtitle>
  <link href="https://tianci-king.github.io/atom.xml" rel="self"/>
  
  <link href="https://tianci-king.github.io/"/>
  <updated>2024-12-08T13:29:28.635Z</updated>
  <id>https://tianci-king.github.io/</id>
  
  <author>
    <name>Tiancy</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>使用 LLaMA-Factory 微调模型</title>
    <link href="https://tianci-king.github.io/2024/12/08/rlhf-shi-yong-llama-factory-wei-diao-llm/"/>
    <id>https://tianci-king.github.io/2024/12/08/rlhf-shi-yong-llama-factory-wei-diao-llm/</id>
    <published>2024-12-08T08:16:00.000Z</published>
    <updated>2024-12-08T13:29:28.635Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>基于人类反馈的强化学习，即RLHF（Reinforcement Learning from Human Feedback），是一种结合了强化学习与人类反馈的方法来优化语言模型的行为。它的核心在于利用人类对模型行为的反馈作为指导，通过强化学习的方式微调语言模型，以提升其性能和决策质量。这种方法的优势在于能够更加精细地调整模型的行为，使其更加符合人类的预期和标准。通过RLHF，可以在一定程度上解决传统机器学习方法中难以捕捉的细微差别和复杂性问题。</p><p>RLHF的过程可以分为以下几个关键步骤：</p><ol><li><p>预训练语言模型：首先，需要有一个预先训练好的大语言模型（LLM）作为 base，这个模型通常是通过大量的文本数据训练得到的，以便能够理解和生成自然语言。</p></li><li><p>训练奖励模型：其次，收集问答数据集并训练一个奖励模型（Reward Model，RM）。这个奖励模型的目的是根据人类的反馈来为语言模型的行为打分，判断哪些回答是优秀的，哪些需要改进。</p></li><li><p>强化学习微调：最后，使用强化学习（RL）的方法来微调语言模型。在这个过程中，奖励模型提供的分数被用作反馈信号，指导语言模型在特定任务或行为上进行优化。</p></li></ol><p>本文采用 LLaMA-Factory 作为RLHF框架。介绍 LLaMA-Factory 的环境安装和微调模型前的准备工作。</p><h1 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h1><p>在实验室服务器上，是没有 root 权限的，无法通过 apt 安装任何包，通过 <code>apt list</code> 发现当前环境连 git 都没有。因此需要先安装 conda ，然后在虚拟环境中完成接下来的所有工作。</p><h2 id="下载-Anaconda-3"><a href="#下载-Anaconda-3" class="headerlink" title="下载 Anaconda 3"></a>下载 Anaconda 3</h2><blockquote><p><a href="https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&amp;O=D">Anaconda3 清华大学开源软件镜像</a></p></blockquote><p>通过 wget 下载：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">wget</span> --user-agent<span class="token operator">=</span><span class="token string">"Mozilla"</span> https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2024.10-1-Linux-x86_64.sh<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>使用 wget 下载 Anaconda 报错ERROR&nbsp;403 Forbidden. 原因可能是服务器正在检查引用者，一些 HTTP 请求也会得到错误响应，因为它们会拒绝不以 Mozilla 开头或不包含 Wget 的用户代理。因此需要添加 <code>--user-agent="Mozilla" </code>。</p><p>下载完成后，切换到该文件目录下，运行：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">bash</span> Anaconda3-2024.10-1-Linux-x86_64.sh <span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412081640006.png" alt="安装 Anaconda3"></p><p>一路回车到底，输入 yes 接受协议即可，安装完成后，需要退出终端或通过 source 命令刷新环境变量：<br><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412081645446.png" alt="刷新环境变量"></p><h2 id="克隆仓库代码"><a href="#克隆仓库代码" class="headerlink" title="克隆仓库代码"></a>克隆仓库代码</h2><p>首先得先把 git 装好：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">conda <span class="token function">install</span> <span class="token function">git</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>克隆 LLaMA-Factory 仓库代码，并进入到该目录：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">git</span> clone https://github.com/hiyouga/LLaMA-Factory.git<span class="token builtin class-name">cd</span> LLaMA-Factory/<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>接下来在虚拟环境中安装 LLaMA-Factory 的依赖：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">pip <span class="token function">install</span> <span class="token parameter variable">-r</span> requirements.txt<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><blockquote><p>值得注意的是，为了确保环境干净，推荐新建虚拟环境来安装 LLaMA-Factory 的依赖。</p><p>一定不要先安装 pytorch 后再 pip install -r requirements. txt ，网上许多教程在 pip install之前会先安装一些前置依赖，这些都不是必须的，因为 pip install 的时候会自动安装上正确的 pytorch 版本。自行安装反而会导致 pytorch 版本不符，无法启动 LLaMA-Factory。</p></blockquote><p>安装完成以后，启动 webui：</p><blockquote><p>注意！一定要直接在仓库根目录下 python src/webui.py。如果是先进到src文件夹，然后python webui.py，后续的操作会失败！</p></blockquote><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">python src/webui.py<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412081726664.png" alt="启动 webui"></p><p>在浏览器输入 <code>http://0.0.0.0:7860</code> 即可访问 LLaMA-Factory 的 webui 界面。</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412081729078.png" alt="webui 界面"></p><h2 id="下载模型"><a href="#下载模型" class="headerlink" title="下载模型"></a>下载模型</h2><p>由于是多模态任务，笔者权衡了许多模型，最后选择 <a href="https://modelscope.cn/models/Qwen/Qwen2-VL-7B-Instruct">Qwen2-VL-7B-Instruct</a> 作为 model base。可以根据服务器的性能与任务需要自行选择合适的基础模型。</p><p>下载模型可以前往 <a href="https://huggingface.co/collections/Qwen/qwen2-vl-66cee7455501d7126940800d">Hugging Face</a> 或者 <a href="https://modelscope.cn/organization/qwen">Model Scope</a> 按照教程下载，笔者使用的是魔搭社区（Model Scope）提供的下载方式。</p><p>先通过如下命令安装ModelScope：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">pip <span class="token function">install</span> modelscope<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>然后下载模型到指定文件夹（./dir 替换为指定的文件夹目录）：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">modelscope download <span class="token parameter variable">--model</span> Qwen/Qwen2-VL-7B-Instruct <span class="token parameter variable">--local_dir</span> ./dir<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412081742926.png" alt="下载模型"></p><blockquote><p>没有指定文件夹的话，模型会默认下载在 /. cache/modelscope 目录下</p></blockquote><p>下载好的模型目录结构如下：</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412081958642.png" alt="模型目录结构"></p><h2 id="上传训练数据集"><a href="#上传训练数据集" class="headerlink" title="上传训练数据集"></a>上传训练数据集</h2><p>接下来就是准备数据集（此步骤略）上传到服务器。</p><h1 id="微调"><a href="#微调" class="headerlink" title="微调"></a>微调</h1><h2 id="加载模型"><a href="#加载模型" class="headerlink" title="加载模型"></a>加载模型</h2><p>启动 LLaMA-Factory 的 webui 界面，并在顶部模型名称和模型路径中输入使用的模型的信息，其中模型路径可以使用绝对路径：</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412082015622.png" alt="启动界面"></p><p>为了测试模型是否下载完整，且成功导入，点击 Chat 界面，加载模型：</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412082018154.png" alt="加载模型"></p><p>终端会加载模型，webui 会显示“模型已加载，可以开始聊天了！”：</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412082019324.png" alt="终端信息"></p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412082020704.png" alt="webui 界面"></p><p>说明模型下载的是完整的，且能成功导入到 LLaMA-Factory ，那么接下来就可以开始微调模型哩！</p><blockquote><p>如果加载模型时 webui 显示错误，请仔细检查终端信息的报错，可能是少装了某些依赖，终端会提示诸如 pip install vllm 的命令，安装完成后再试试加载模型。</p></blockquote><h2 id="加载数据集"><a href="#加载数据集" class="headerlink" title="加载数据集"></a>加载数据集</h2><p>数据集的路径和数据集文件名照如下方式依着瓢画葫芦即可，无须赘述：<br><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412082039483.png" alt="加载数据集"></p><h2 id="参数设置"><a href="#参数设置" class="headerlink" title="参数设置"></a>参数设置</h2><p>设置学习率为 1e-4，训练轮数为 10，更改计算类型为 pure_bf16，梯度累积为 2，有利于模型拟合。</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412082042710.png" alt="设置参数"></p><p>在其他参数设置区域修改保存间隔为 1000，节省硬盘空间。</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412082042207.png" alt="其他参数区域"></p><h2 id="启动微调"><a href="#启动微调" class="headerlink" title="启动微调"></a>启动微调</h2><p>将输出目录修改为 <code>train_qwen2vl</code>，训练后的模型权重将会保存在此目录中。点击「预览命令」可展示所有已配置的参数，如果想通过代码运行微调，可以复制这段命令，在命令行运行。</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202412082048374.png" alt="image.png"></p><p>开始！</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;基于人类反馈的强化学习，即RLHF（Reinforcement Learning from Human Feedback），是一种结合了强化</summary>
      
    
    
    
    <category term="大模型" scheme="https://tianci-king.github.io/categories/%E5%A4%A7%E6%A8%A1%E5%9E%8B/"/>
    
    
    <category term="LLM" scheme="https://tianci-king.github.io/tags/LLM/"/>
    
    <category term="Qwen2-VL" scheme="https://tianci-king.github.io/tags/Qwen2-VL/"/>
    
    <category term="LLaMA-Factory" scheme="https://tianci-king.github.io/tags/LLaMA-Factory/"/>
    
    <category term="RLHF" scheme="https://tianci-king.github.io/tags/RLHF/"/>
    
  </entry>
  
  <entry>
    <title>通过 pmset 工具管理 masOS 睡眠</title>
    <link href="https://tianci-king.github.io/2024/11/10/use-pmset-manage-hibernate/"/>
    <id>https://tianci-king.github.io/2024/11/10/use-pmset-manage-hibernate/</id>
    <published>2024-11-10T15:54:23.000Z</published>
    <updated>2024-12-08T13:29:28.683Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>本文参考 「少数派」<a href="https://sspai.com/post/61379">https://sspai.com/post/61379</a></p></blockquote><h1 id="查看电源情况"><a href="#查看电源情况" class="headerlink" title="查看电源情况"></a>查看电源情况</h1><p><code>pmset -g</code>              <code># 显示正在使用的设置</code></p><p><code>pmset -g custom</code>       <code># 显示为所有电源的自定义设置</code></p><p><code>pmset -g batt</code>         <code># 显示电池的状态</code></p><p><code>pmset -g stats</code>        <code># 显示自系统启动以来睡眠和唤醒系统的计数。</code></p><p><code>pmset -g systemstate</code>  <code># 显示当前系统的电量状态和可用能力。</code></p><hr><h1 id="电池供电下的-pmset-设置"><a href="#电池供电下的-pmset-设置" class="headerlink" title="电池供电下的 pmset 设置"></a>电池供电下的 pmset 设置</h1><p><img src="https://cdnfile.sspai.com/2020/07/11/eccbaecb64b1320e7aa1f113a15ef9f5.png?imageView2/2/w/1120/q/90/interlace/1/ignore-error/1/format/webp" alt="电池供电下的 pmset 设置"></p><h2 id="详细设置："><a href="#详细设置：" class="headerlink" title="详细设置："></a><strong>详细设置：</strong></h2><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">// 20 分钟后进入休眠sudo pmset -b sleep 20// 向硬盘写入镜像，同时内存供电sudo pmset -b hibernatemode 3// 显示器休眠时间：15 分钟sudo pmset -b displaysleep 15// 硬盘休眠时间：30 分钟sudo pmset -b disksleep 30// 休眠时断网sudo pmset -b tcpkeepalive 0// 高电量下 standby: 4小时sudo pmset -b standbydelayhigh 14400// 低电量下 standby: 2小时sudo pmset -b standbydelaylow 7200// standby 电量阈值：75%sudo pmset -b highstandbythreshold 75// 开盖唤醒sudo pmset -b lidwake 1// 关闭被同一 iCloud 下的设备唤醒sudo pmset -b acwake 0<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h1 id="外部供电下的-pmset-设置"><a href="#外部供电下的-pmset-设置" class="headerlink" title="外部供电下的 pmset 设置"></a>外部供电下的 pmset 设置</h1><p><img src="https://cdnfile.sspai.com/2020/07/11/d1bddc8581e915ceed4f71c21600dc95.png?imageView2/2/w/1120/q/90/interlace/1/ignore-error/1/format/webp" alt="外部供电下的 pmset 设置"></p><h2 id="详细设置：-1"><a href="#详细设置：-1" class="headerlink" title="详细设置："></a>详细设置：</h2><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">// 120 分钟后进入休眠，延长清醒时间sudo pmset -c sleep 120// 显示器休眠时间：30 分钟sudo pmset -c displaysleep 30// 硬盘休眠时间：60 分钟sudo pmset -c disksleep 60// 内存供电，内存镜像不写入硬盘sudo pmset -c hibernatemode 0// 关闭 standby 模式sudo pmset -c standby 0// 关闭 autopoweroffsudo pmset -c autopoweroff 0// 休眠时持续联网sudo pmset -c tcpkeepalive 1<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h1 id="参数的含义"><a href="#参数的含义" class="headerlink" title="参数的含义"></a>参数的含义</h1><p><code># -c 调节设定用于连接充电器的时候</code></p><p><code># -b 调节设定用于使用电池（Battery）的时候</code></p><p><code># -u 调节设定用于使用 UPS 的时候</code></p><p><code># -a 调节设定用于全部情景</code></p><hr><h1 id="具体配置"><a href="#具体配置" class="headerlink" title="具体配置"></a>具体配置</h1><h2 id="1-合盖后关闭网络唤醒"><a href="#1-合盖后关闭网络唤醒" class="headerlink" title="1.合盖后关闭网络唤醒"></a>1.合盖后关闭网络唤醒</h2><p><code>sudo</code> <code>pmset -b tcpkeepalive 0</code><br><code>sudo</code> <code>pmset -c tcpkeepalive 1</code></p><h2 id="2-阻止从睡眠中自动唤醒"><a href="#2-阻止从睡眠中自动唤醒" class="headerlink" title="2.阻止从睡眠中自动唤醒"></a>2.阻止从睡眠中自动唤醒</h2><p><code>sudo pmset -b powernap 0</code><br><code>sudo pmset -c powernap 1</code></p><h2 id="3-合盖设置成休眠模式"><a href="#3-合盖设置成休眠模式" class="headerlink" title="3.合盖设置成休眠模式"></a>3.合盖设置成休眠模式</h2><p>3模式是将当前工作内容保存到内存中，意味着恢复工作状态（重新打开盖子进入系统）时间比较短，且内存不断电（就是说没那么省电，并且某些机型的风扇仍会转动以散热），25模式是将当前工作内容保存到硬盘中，意味着恢复工作状态时间较长（因为需要把内容重新读取到内存中，但是现在基本都是固态硬盘，相信时间也不会差太远）</p><p><code>sudo pmset -b hibernatemode 25</code><br><code>sudo pmset -c hibernatemode 3</code></p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;本文参考 「少数派」&lt;a href=&quot;https://sspai.com/post/61379&quot;&gt;https://sspai.com/post/61379&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;查看电源情况&quot;&gt;&lt;a href=</summary>
      
    
    
    
    <category term="MAC调教" scheme="https://tianci-king.github.io/categories/MAC%E8%B0%83%E6%95%99/"/>
    
    
    <category term="MacBook" scheme="https://tianci-king.github.io/tags/MacBook/"/>
    
    <category term="Pmset" scheme="https://tianci-king.github.io/tags/Pmset/"/>
    
  </entry>
  
  <entry>
    <title>Conda 更新遇到错误的尝试和解决方案</title>
    <link href="https://tianci-king.github.io/2024/11/10/fix-conda-update/"/>
    <id>https://tianci-king.github.io/2024/11/10/fix-conda-update/</id>
    <published>2024-11-10T07:20:03.000Z</published>
    <updated>2024-12-08T13:29:28.659Z</updated>
    
    <content type="html"><![CDATA[<h1 id="事情起因"><a href="#事情起因" class="headerlink" title="事情起因"></a>事情起因</h1><p>从 A13 开始 Apple 的 A 系列芯片中就搭载了 AMX 单元（Apple Matrix Coprocessor 苹果矩阵运算协处理器），通过专门设计的硬件单元来加速矩阵运算的速度，过去 AMX 基本只服务于苹果内部生态的应用，常见的应用如 benchmark 等都无法调用之，而现在 BLAS 库（Basic Linear Algebra Subprograms 基础线性代数子程序库）适配了 AMX，里面拥有大量关于线性代数运算方法的工具函数。而我们熟悉的 Numpy 就调用了 BLAS，因此，如今可以将 Numpy 背后的 BLAS 换成经过 AMX 加速后的版本，以在 MacBook 上加速 Numpy 的运算。</p><p>通过以下命令即可：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">conda install -c conda-forge numpy "libblas=*=*accelerate"<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>但是在我输入后，终端却提示我的 conda 版本过低，需要先升级 conda 到最新的版本。</p><h1 id="问题出现"><a href="#问题出现" class="headerlink" title="问题出现"></a>问题出现</h1><p>终端提示需要先升级 conda ，那么我输入了 update 命令，想着升级完应该即可继续执行上面的代码了，但是终端却报错了：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">❯ conda update conda# ------------------------------------------# 省略部分信息（许多包名的下载过程Proceed ([y]/n)? yDownloading and Extracting PackagesPreparing transaction: doneVerifying transaction: failed# 报错了RemoveError: 'jsonpatch' is a dependency of conda and cannot be removed fromconda's operating environment.RemoveError: 'requests' is a dependency of conda and cannot be removed fromconda's operating environment.<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>我首先尝试向 GPT-4o 提问找到解决方案：</p><p><img src="https://cdn.jsdelivr.net/gh/Tianci-King/PicGo@main/img/202411101519914.png" alt="GPT 给出的解释"></p><p>GPT 告诉我上面的包是 conda 自身的核心包，导致更新失败了，他建议我在新的环境中操作。</p><p>我试着 create 了新的 env，但是同样的问题仍然显示在终端上报错了。</p><p><del>GPT 果然还是不太靠谱哇</del></p><h1 id="尝试解决"><a href="#尝试解决" class="headerlink" title="尝试解决"></a>尝试解决</h1><p>在 stackoverflow 查阅到有人直接强制更新解决了这个问题，<del>力大砖飞</del></p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">conda update --force conda<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>我试着输入但是还是报了同样的错误。</p><p>虽然GPT 给出的解决方案（新建新的环境）以及强制更新都经过尝试失败了，我转头回去继续对话 GPT：</p><blockquote><p>Conda 检测到它的核心依赖包（如 jsonpatch 和 requests）可能会被移除或替换，这会导致 Conda 无法正常工作。因此，Conda 会阻止这个操作并提示 RemoveError。</p></blockquote><p>GPT 说的这句话是很有道理的，显然报错是因为我现在所在的虚拟环境（如 base 或其他虚拟环境）本身所需要这些核心包，我不能在使用它们的情况下强行更新它们，这会导致我的虚拟环境崩溃。</p><p>所以我尝试先退出子环境：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">#deactivate the sub envconda deactivate<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>然后再执行更新操作：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">#update base if neededconda update condaconda update anacondaconda update --all<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><p>最后再更新子环境中的包：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">#update environment from baseconda update -n yourEnvHere [-c ARepository] --all#reactivate the envconda activate yourEnvHere <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>显然，退出了子环境后的更新操作，不需要 force 也正常执行了。</p><p>最后进入子环境，执行：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">❯ conda activate❯ conda install -c conda-forge numpy "libblas=*=*accelerate"# ------------------------------------------/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/conda/base/context.py:198: FutureWarning: Adding 'defaults' to channel list implicitly is deprecated and will be removed in 25.3.To remove this warning, please choose a default channel explicitly with conda's regular configuration system, e.g. by adding 'defaults' to the list of channels:  conda config --add channels defaultsFor more information see https://docs.conda.io/projects/conda/en/stable/user-guide/configuration/use-condarc.html  deprecated.topic(Channels: - conda-forge - defaultsPlatform: osx-arm64Collecting package metadata (repodata.json): doneSolving environment: | warning  libmamba Added empty dependency for problem type SOLVER_RULE_UPDATEdone## Package Plan ##  environment location: /opt/homebrew/Caskroom/miniconda/base  added / updated specs:    - libblas[build=*accelerate]    - numpy# 省略部分信息（许多包名的下载过程The following packages will be downloaded:The following NEW packages will be INSTALLED:The following packages will be REMOVED:The following packages will be UPDATED:Proceed ([y]/n)? yDownloading and Extracting Packages:Preparing transaction: doneVerifying transaction: doneExecuting transaction: done                                                               <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后就可以愉快的使用加速过的Numpy啦。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;事情起因&quot;&gt;&lt;a href=&quot;#事情起因&quot; class=&quot;headerlink&quot; title=&quot;事情起因&quot;&gt;&lt;/a&gt;事情起因&lt;/h1&gt;&lt;p&gt;从 A13 开始 Apple 的 A 系列芯片中就搭载了 AMX 单元（Apple Matrix Coprocessor 苹</summary>
      
    
    
    
    <category term="ML" scheme="https://tianci-king.github.io/categories/ML/"/>
    
    
    <category term="Conda" scheme="https://tianci-king.github.io/tags/Conda/"/>
    
  </entry>
  
  <entry>
    <title>Basic Knowledge for PWN</title>
    <link href="https://tianci-king.github.io/2024/04/13/binary-exploitation-and-pwn/"/>
    <id>https://tianci-king.github.io/2024/04/13/binary-exploitation-and-pwn/</id>
    <published>2024-04-13T09:58:12.000Z</published>
    <updated>2024-12-08T13:29:28.631Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Binary-Exploitation"><a href="#Binary-Exploitation" class="headerlink" title="Binary Exploitation"></a>Binary Exploitation</h2><p>二进制程序利用通过利用程序（Binary）的漏洞（Vulnerability），在执行期间控制执行流程（Control flow），进而使程序执行特定行为。</p><h2 id="计算机组成浅析"><a href="#计算机组成浅析" class="headerlink" title="计算机组成浅析"></a>计算机组成浅析</h2><h3 id="冯诺依曼体系结构"><a href="#冯诺依曼体系结构" class="headerlink" title="冯诺依曼体系结构"></a>冯诺依曼体系结构</h3><p>冯.诺伊曼结构（<strong>von Neumann architecture</strong>），也称<strong>普林斯顿结构</strong>，是一种<strong>将【程序指令存储器】和【数据存储器】合并在一起</strong>的电脑设计概念结构。</p><p>在该结构中，<strong>CPU 通过地址线单向连接Memory，通过数据线双向连接 Memory。</strong>另外还有许多控制线，但是一般并不画出来。</p><p><img src="https://pic1.zhimg.com/80/v2-b7f42346bc3ceabe110eb17feb2cbdf4_1440w.webp" alt="冯诺依曼体系"></p><p>冯.诺依曼结构中，将程序和数据一样看待，<strong>将程序编码为数据，然后与数据一同存放在存储器中</strong>，这样计算机就可以调用存储器中的程序来处理数据了。意味着，无论什么程序，最终都是会转换为数据的形式存储在存储器中，要执行相应的程序只需要从存储器中依次取出指令、执行，冯.诺依曼结构的灵魂所在正是这里：减少了硬件的连接。</p><h3 id="哈佛结构-Harvard-architecture"><a href="#哈佛结构-Harvard-architecture" class="headerlink" title="哈佛结构(Harvard architecture)"></a>哈佛结构(<strong>Harvard architecture</strong>)</h3><p>哈佛结构是一种<strong>将程序指令储存和数据储存分开</strong>的存储器结构。</p><p><img src="https://pic4.zhimg.com/80/v2-37c21ba84e8b4221ea3807643e8a619b_1440w.webp" alt="哈佛结构"></p><p>中央处理器首先到程序指令储存器中读取程序指令内容，解码后得到数据地址，再到相应的数据储存器中读取数据，并进行下一步的操作（通常是执行）。程序指令储存和数据储存分开，<strong>数据和指令的储存可以同时进行</strong>，可以使指令和数据有不同的数据宽度。</p><p>哈佛结构的微处理器通常具有较高的执行效率。其程序指令和数据指令分开组织和储存的，<strong>执行时可以预先读取下一条指令</strong>。</p><p>现在的单片机或者嵌入式机器通常采用<strong>改良的哈佛结构</strong>。</p><hr><h2 id="Executable-and-Linkable-Format"><a href="#Executable-and-Linkable-Format" class="headerlink" title="Executable and Linkable Format"></a>Executable and Linkable Format</h2><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202404141351810.png" alt="ELF-WorkFlow"></p><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202404141350239.png"></p><hr><h2 id="xxd-elf-less-命令-分析二进制文件"><a href="#xxd-elf-less-命令-分析二进制文件" class="headerlink" title="xxd ./elf | less 命令  分析二进制文件"></a>xxd ./elf | less 命令  分析二进制文件</h2><p><code>xxd</code> 是一个在 Unix/Linux 系统中常用的工具，用于将二进制文件转换为十六进制表示，或者反过来。在你的命令中，<code>xxd ./elf</code> 将 <code>elf</code> 文件转换为十六进制表示。</p><p><code>|</code> 是 Unix/Linux 中的<strong>管道操作符</strong>，它将前一个命令的输出作为后一个命令的输入。在你的命令中，<code>xxd ./elf | less</code> 将 <code>xxd ./elf</code> 的输出作为 <code>less</code> 命令的输入。</p><p><code>less</code> 是一个在 Unix/Linux 系统中常用的分页工具，用于查看文件内容。它允许用户向前和向后浏览文件，而 <code>more</code> 命令只允许向前浏览。命令<code>xxd ./elf | less</code> 将 <code>elf</code> 文件的十六进制表示分页显示。</p><p>因此，<code>xxd ./elf | less</code> 的整体作用是将 <code>elf</code> 文件转换为十六进制表示，并分页显示。</p><p>less 回显的十六进制文件中关键字的含义如下：</p><p><strong>•RSP</strong> - Stack Pointer Register  指向 stack 顶端（头）</p><p><strong>•RBP</strong> - Base Pointer Register  指向 stack 底端（尾）</p><p><strong>•RIP</strong> - Program Counter Register  指向当前执行指令instruction位置</p><h3 id="gdb"><a href="#gdb" class="headerlink" title="gdb"></a>gdb</h3><p><strong>分析二进制文件调试工具</strong></p><p>以下是使用 GDB 分析二进制文件的一般步骤：</p><ol><li><strong>启动 GDB</strong>: 你可以通过在命令行中键入 <code>gdb &lt;你的程序&gt;</code> 来启动 GDB，并加载你的程序。</li><li><strong>设置断点</strong>: 使用 <code>break</code> 命令在感兴趣的代码行或函数上设置断点。</li><li><strong>运行程序</strong>: 使用 <code>run</code> 命令开始执行程序，程序会在设置的断点处停下来。</li><li><strong>检查状态</strong>: 当程序在断点处停止时，你可以使用 <code>info</code> 命令来查看变量的值、堆栈的状态等。</li><li><strong>单步执行</strong>: 使用 <code>step</code> 或 <code>next</code> 命令可以单步执行程序，区别在于 <code>step</code> 会进入函数内部，而 <code>next</code> 会在函数返回前完成函数的执行。</li><li><strong>继续执行</strong>: 使用 <code>continue</code> 命令可以从当前停止点继续执行程序，直到遇到下一个断点。</li><li><strong>修改变量</strong>: 使用 <code>set</code> 命令可以修改变量的值。</li><li><strong>退出 GDB</strong>: 使用 <code>quit</code> 命令退出 GDB。</li></ol><p>以下是一些有用的 GDB 命令：</p><ul><li><code>list</code>: 显示源代码。</li><li><code>print</code>: 打印变量的值。</li><li><code>backtrace</code>: 显示函数调用堆栈。</li><li><code>disassemble</code>: 反汇编当前函数的汇编代码。</li><li><code>x</code>: 从内存中检查数据。</li></ul><p>在分析二进制文件时，可能需要知道它的编译信息，例如是否包含调试符号，如果没有调试符号，可能无法获取源代码级别的信息，但仍可以查看和分析汇编级别的指令。</p><hr><h2 id="常见的几个汇编指令"><a href="#常见的几个汇编指令" class="headerlink" title="常见的几个汇编指令"></a>常见的几个汇编指令</h2><p><strong>jmp (jump)</strong>: <code>jmp</code> 是跳转指令，用于无条件地将程序的控制权转移到指定的地址。在你的例子中，<code>jmp A</code> 就是将程序计数器 <code>rip</code>（在 64 位系统中）设置为地址 <code>A</code>，然后从那里开始执行。</p><pre class="line-numbers language-none"><code class="language-none">jmp A = mov rip, A<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p><strong>call</strong>: <code>call</code> 指令用于调用子程序。它首先将下一条指令的地址（即返回地址）压入堆栈，然后跳转到指定的地址开始执行。在你的例子中，<code>call A</code>就是将 <code>next_rip</code>（即下一条指令的地址）压入堆栈，然后将 <code>rip</code> 设置为地址 <code>A</code>。</p><pre class="line-numbers language-none"><code class="language-none">call A = push next_ripmov rip, A<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p><strong>leave</strong>: <code>leave</code> 指令用于恢复调用者的堆栈帧。它首先将基指针 <code>rbp</code> 的值复制到堆栈指针 <code>rsp</code>，然后弹出 <code>rbp</code> 的值。这样就恢复了调用者的堆栈帧。</p><pre class="line-numbers language-none"><code class="language-none">mov rsp, rbp  pop rbp<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p><strong>ret (return)</strong>: <code>ret</code> 指令用于从子程序返回。它从堆栈中弹出一个值，然后将 <code>rip</code> 设置为这个值。这样，程序的控制权就返回到了调用者。</p><pre class="line-numbers language-none"><code class="language-none">pop rip<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><hr><h2 id="内存对齐规则和寄存器"><a href="#内存对齐规则和寄存器" class="headerlink" title="内存对齐规则和寄存器"></a>内存对齐规则和寄存器</h2><p><strong>内存对齐</strong>是为了提高内存访问效率而采取的一种策略。具体到你的问题：</p><ol><li><strong>8 bytes alignment</strong>：在 x64 架构下，数据通常以 8 字节对齐。这意味着数据的起始地址是 8 的倍数。这是因为 x64 架构的 CPU 设计为一次可以读取 8 字节的数据，如果数据没有对齐，那么可能需要多次访问内存才能读取完整的数据，这会降低效率。</li><li><strong>Stack 0x10 bytes alignment</strong>：对于堆栈，x64 架构要求堆栈指针 <code>rsp</code> 在函数调用时必须是 16 字节对齐的。这是为了满足 SSE 数据类型（如 <code>xmm</code> 寄存器）的对齐要求，因为这些数据类型需要 16 字节对齐。</li></ol><p>这些对齐规则是为了提高内存访问效率和满足特定数据类型的对齐要求。编译器和操作系统通常会自动处理这些对齐问题。</p><p><strong>寄存器</strong></p><ul><li><strong>RAX, RBX, RCX, RDX, RDI, RSI</strong> - 这些是64位的通用寄存器。在x64架构中，它们被扩展到了64位，以’R’开头表示。这些寄存器在进行各种运算时使用，如算术运算、内存访问等。</li><li><strong>EAX, EBX, ECX, EDX, EDI, ESI</strong> - 这些是32位的通用寄存器。它们是x86（32位）架构中的原始寄存器，以’E’开头表示。当运行在兼容的32位模式下时，x64架构仍然使用这些寄存器。</li><li><strong>AX, BX, CX, DX, DI, SI</strong> - 这些是16位的寄存器，分别是上述32位寄存器的低16位部分。在历史上，这些是原始的x86 16位寄存器。</li><li><strong>AH, AL</strong> - 这些代表16位AX寄存器的高8位（AH）和低8位（AL）。这种细分允许对8位数据进行操作，这在处理字符和其他8位数据时非常有用。</li></ul><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202404141350122.png" alt="寄存器结构图"></p><p><strong>RAX</strong> 寄存器是64位的，这是最大的寄存器，它能包含EAX、AX、AH和AL。    </p><p><strong>EAX</strong> 是RAX的低32位，它是32位的。</p><p><strong>AX</strong> 是EAX的低16位，它是16位的。进一步地，AX被分为两个8位的部分：高8位的AH和低8位的AL。</p><hr><h2 id="函数调用约定（calling-convention）"><a href="#函数调用约定（calling-convention）" class="headerlink" title="函数调用约定（calling convention）"></a>函数调用约定（calling convention）</h2><p>函数调用约定定义了如何在函数调用过程中传递参数和返回值，以及如何使用寄存器。具体到 x64 架构，有以下规定：</p><ol><li><strong>参数传递</strong>：</li></ol><h4 id="linux下内核模式"><a href="#linux下内核模式" class="headerlink" title="linux下内核模式"></a>linux下内核模式</h4><p>在Linux x64架构下的内核模式，函数的参数传递与在用户模式下类似，前六个整型或指针类型的参数通过寄存器 <code>rdi</code>、<code>rsi</code>、<code>rdx</code>、<code>r10</code>（而不是用户模式下的 <code>rcx</code>）、<code>r8</code> 和 <code>r9</code> 传递。如果参数多于六个，额外的参数则通过堆栈传递。这些信息主要来自SysTutorials网站的相关文章。</p><h4 id="linux-下用户模式"><a href="#linux-下用户模式" class="headerlink" title="linux 下用户模式"></a>linux 下用户模式</h4><p>在 x64 架构下，前六个整型或指针类型的参数分别通过 <code>rdi</code>、<code>rsi</code>、<code>rdx</code>、<code>rcx</code>、<code>r8</code> 和 <code>r9</code> 寄存器传递。如果有更多的参数，它们将通过堆栈传递。这是与 x86 架构的一个主要区别，<strong>因为在 x86 架构下，所有的参数都是通过堆栈传递的。</strong></p><h4 id="window-下"><a href="#window-下" class="headerlink" title="window 下"></a>window 下</h4><p>Windows x64平台有自己的调用约定，前四个整型或指针类型的参数通过 <code>rcx</code>、<code>rdx</code>、<code>r8</code> 和 <code>r9</code> 寄存器传递。在Windows上，为了支持更大向量类型的参数传递，还引入了 __vectorcall 调用约定，这个约定扩展了前述的寄存器用法，允许使用 XMM/YMM0-5 寄存器来传递浮点数、向量或 HVA（Homogeneous Vector Aggregate）参数。返回值依然是通过 <code>rax</code> 寄存器返回的。这些调用约定的详细信息可在Wikipedia的相关页面找到。</p><ol start="2"><li><strong>返回值</strong>：在 x64 架构下，函数的返回值通过 <code>rax</code> 寄存器返回。</li></ol><hr><h2 id="Stack-Frame-栈帧"><a href="#Stack-Frame-栈帧" class="headerlink" title="Stack Frame 栈帧"></a>Stack Frame 栈帧</h2><p>它是计算机内存中的一块区域，用于存储有关函数调用和局部变量的信息。PPT在这个例子中，可以看到了一个函数<code>func()</code>的栈帧。</p><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202404141349032.png" alt="栈帧"></p><p>从高地址向低地址看，栈帧包含以下几个部分：</p><ol><li><strong>参数（Arguments）</strong>: 当函数被调用时，传递给函数的参数在这里存储。</li><li><strong>返回地址（Return Address）</strong>: 这是当函数执行完毕后，程序执行需要跳转回去的地方的地址。</li><li><strong>保存的rbp（Saved rbp）</strong>: 这是调用函数之前的基指针（Base Pointer），也就是上一个栈帧的rbp值，用来恢复栈的状态。</li><li><strong>局部变量（Local variables of func()）</strong>: 这个区域用于存放函数内声明的局部变量。</li></ol><p>在栈帧的最顶部和底部，我们看到有两个指针：</p><ul><li><strong>rsp (Stack Pointer)</strong>: 这指向栈的顶部，通常表示当前栈帧的结束位置。</li><li><strong>rbp (Base Pointer)</strong>: 这指向栈的底部，通常用来作为参考点，便于访问栈帧中的局部变量和参数。</li></ul><p>图中还提到了两个术语：</p><ul><li><strong>Function Prologue</strong>: 这是函数开始执行时的一段代码，用于设置栈帧，例如保存旧的rbp值，分配局部变量所需的空间。</li><li><strong>Function Epilogue</strong>: 这是函数即将返回前的一段代码，用于恢复栈的状态，比如将rbp恢复到调用前的值。</li></ul><p>另外，有注释说明<code>[rbp] = old rbp (caller rbp)</code>和<code>[rbp + 0x8] = Return Address</code>，这说明在栈中通过基指针rbp可以访问到调用者的基指针和返回地址。这对于理解函数如何返回到调用它的地方以及如何维护栈的结构非常重要。</p><h3 id="Canary"><a href="#Canary" class="headerlink" title="Canary"></a>Canary</h3><blockquote><p>为什么第一个字节是 0？</p></blockquote><p>堆栈金丝雀（Stack Canary）是一种用于检测和防止堆栈缓冲区溢出攻击的安全特性。它的名称来源于矿工用金丝雀来检测有毒气体的做法；同理，堆栈金丝雀用来检测堆栈中的异常变化。当函数执行时，系统会在堆栈中的返回地址之前放置一个随机的金丝雀值。当函数准备返回时，会检查这个金丝雀值是否发生变化——如果金丝雀值被改变，系统就认为发生了缓冲区溢出，程序可以采取措施立即终止，从而阻止攻击的进一步发展。</p><p>金丝雀值的第一个字节通常是0（空字节）。<strong>这是因为在C语言中，字符串以空字符结束。如果溢出攻击尝试使用字符串操作来覆盖堆栈，并且没有包含空字节，它将在达到金丝雀的空字节时停止，因此可以保护剩余的金丝雀值和返回地址不被覆盖。这就增加了攻击者利用缓冲区溢出的难度，因为攻击者必须找到一种方法，在不触动金丝雀值的情况下覆盖返回地址。</strong></p><p>堆栈金丝雀在性能和安全性之间提供了一种平衡，因为它们在函数返回之前引入了额外的检查，但与它们提供的安全好处相比，这种开销通常是微不足道的。它们是由编译器实现的，可以通过特定的编译器标志启用，例如在GCC中使用<code>-fstack-protector</code>，它为容易受到攻击的函数添加了堆栈保护。</p><hr><h2 id="PWN-overflow"><a href="#PWN-overflow" class="headerlink" title="PWN overflow"></a>PWN overflow</h2><p>利用溢出（Overflow）的漏洞的原理是超出了程序为其数据所分配的内存区域的边界。在程序编写时，如果没有对输入数据进行恰当的边界检查，就可能出现超出边界的情况。这意味着当数据写入该区时，超出该区大小的数据可能会覆盖相邻内存位置的内容。</p><p>具体的溢出情况有以下几种：</p><ol><li><strong>Buffer Overflow（缓冲区溢出）</strong>: 当程序试图往缓冲区内写入超过其容量的数据时，就会发生缓冲区溢出。</li><li><strong>Stack Overflow（栈溢出）</strong>: 类似于缓冲区溢出，但是是发生在调用栈的内存区域，通常是因为递归调用过深或是局部变量太大。</li><li><strong>Heap Overflow（堆溢出）</strong>: 当程序往堆内存区域写入数据超过了为某个对象分配的空间时发生。</li></ol><p>以缓冲区溢出举例，这种溢出漏洞的利用通常涉及以下几个步骤：</p><ol><li><strong>定位漏洞</strong>: 首先，攻击者需要识别出程序中的缓冲区溢出漏洞。</li><li><strong>控制EIP</strong>: 接着，攻击者会尝试通过输入超出预期长度的数据来覆盖内存中的特定地址。这通常是指向所谓的指令指针（Instruction Pointer，IP），在x86架构下是<code>EIP</code>（Extended Instruction Pointer），它决定了程序接下来要执行哪条指令。</li><li><strong>注入代码</strong>: 攻击者可能会向溢出的缓冲区中注入恶意代码。这通常是一段小型的代码，称为shellcode，它通常用于提供攻击者访问系统的shell。</li><li><strong>执行代码</strong>: 通过控制EIP，攻击者将其指向溢出缓冲区中的shellcode，当程序执行到这里时，会跳转到shellcode并执行。</li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Binary-Exploitation&quot;&gt;&lt;a href=&quot;#Binary-Exploitation&quot; class=&quot;headerlink&quot; title=&quot;Binary Exploitation&quot;&gt;&lt;/a&gt;Binary Exploitation&lt;/h2&gt;&lt;p&gt;二进</summary>
      
    
    
    
    <category term="CTF" scheme="https://tianci-king.github.io/categories/CTF/"/>
    
    
    <category term="PWN" scheme="https://tianci-king.github.io/tags/PWN/"/>
    
  </entry>
  
  <entry>
    <title>爬虫小记</title>
    <link href="https://tianci-king.github.io/2024/04/10/crawler-1/"/>
    <id>https://tianci-king.github.io/2024/04/10/crawler-1/</id>
    <published>2024-04-10T03:58:12.000Z</published>
    <updated>2024-12-08T13:29:28.635Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>笔者的一个项目需要收集小红书|抖音|微博等平台上关于杭州的花景的数据集以进行语义分析训练模型。</p><p>在 Github 上看到一个 Star数高达 10K+的爬虫项目，遂在其基础上二次开发以便在自己的项目上使用，并提交了 PR 。</p></blockquote><h1 id="Repository"><a href="#Repository" class="headerlink" title="Repository"></a>Repository</h1><p><a href="https://github.com/NanmiCoder/MediaCrawler">https://github.com/NanmiCoder/MediaCrawler</a></p><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/crawler202404141413440.png" alt="star 图"></p><h1 id="Contributions"><a href="#Contributions" class="headerlink" title="Contributions"></a>Contributions</h1><ol><li>feat(core): 新增控制爬虫 <code>search</code> 参数起始页面的页数start_page，原项目固定只能从第一页开始爬取，不方便爬取时间跨度更大的内容信息。</li></ol><p><img src="/2024/04/10/crawler-1/WeChat1538636d38c7620e3fdb5af1dd89b169.jpg" alt="修改 search 函数"></p><ol start="2"><li>perf(argparse): 向命令行解析器添加程序参数起始页面页数和关键字</li></ol><p>原项目的命令行解析器程序参数提供的比较少，新增了 start_page 和 keyword 接口直接在命令行填写，<strong>方便后续编写 shell 脚本自动化爬取需求</strong>，原本需要前往 base_config 手动修改参数，现在可以直接在命令行上调整起始页面和查询关键字。</p><p><img src="/2024/04/10/crawler-1/101161712718958_.pic_hd.jpg" alt="增加命令行解析器程序参数"></p><p>通过上述改写源码，爬取了杭州春天花景的”最热门”的200 多条数据，以及最新的 2024 年 3 月至 4 月的200 多条数据，圆满完成任务，并提交了 PR。</p><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/crawler.png" alt="提交 PR"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;笔者的一个项目需要收集小红书|抖音|微博等平台上关于杭州的花景的数据集以进行语义分析训练模型。&lt;/p&gt;
&lt;p&gt;在 Github 上看到一个 Star数高达 10K+的爬虫项目，遂在其基础上二次开发以便在自己的项目上使用，并提交了 PR 。&lt;/p&gt;
</summary>
      
    
    
    
    <category term="项目学习" scheme="https://tianci-king.github.io/categories/%E9%A1%B9%E7%9B%AE%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="crawler" scheme="https://tianci-king.github.io/tags/crawler/"/>
    
  </entry>
  
  <entry>
    <title>Unbuntu22.04 使用 Docker 安装 OpenGauss</title>
    <link href="https://tianci-king.github.io/2024/03/05/opengauss-docker-build/"/>
    <id>https://tianci-king.github.io/2024/03/05/opengauss-docker-build/</id>
    <published>2024-03-05T08:10:38.000Z</published>
    <updated>2024-12-08T13:29:28.663Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>如果您是 macOS 用户，又如果您恰好目前选修的一门 数据库原理 的课程需要使用华为“自研”的国产 opengauss 数据库，又如果您正准备安装 opengauss 环境。那么您可以花费 5 分钟左右的时间照着本文搭建 opengauss 以便学习使用。</p><p>另外，作者与好朋友亲测 OpenGauss 的 ARM Docker 镜像 在 macOS 上无法使用，请不要浪费您宝贵的时间，尝试在 macOS 使用 Docker 安装，因此，本文在 Parallels Desktop  Unbuntu 22.04 上用 Docker 安装 opengauss ，或者您也可以在您的云服务器用 Docker 安装 opengauss。</p><p>另外，如果您成功的在 您的 macOS 上 用 Docker 运行了opengauss 5.0.0及以上的版本，希望您联系我，不吝赐教，感谢。</p></blockquote><h1 id="零、Unbuntu-安装-Docker"><a href="#零、Unbuntu-安装-Docker" class="headerlink" title="零、Unbuntu 安装 Docker"></a>零、Unbuntu 安装 Docker</h1><p>Docker 官网：<a href="https://docs.docker.com/engine/install/ubuntu/">https://docs.docker.com/engine/install/ubuntu/</a></p><p><del>虽然可能看不懂他在说什么，但是只要照着文档里的代码在终端按顺序敲下来，docker 就安装完了</del></p><h1 id="一、搜索-opengauss-镜像-并拉取镜像"><a href="#一、搜索-opengauss-镜像-并拉取镜像" class="headerlink" title="一、搜索 opengauss 镜像 并拉取镜像"></a>一、搜索 opengauss 镜像 并拉取镜像</h1><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">docker search opengauss<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p><img src="/2024/03/05/opengauss-docker-build/Pasted%20image%2020240305092313.png" alt="搜索 opengauss 镜像"></p><p> 这里可以选择 star 数比较多的 <code>enmotech/opengauss</code> ，也可以选择官方的 <code>opengauss/opengauss</code> ，我这里选择的是 <code>opengauss/opengauss 5.0.0</code> 但是后面发现官方的这个镜像是轻量版，无法切换到 omm 用户，因此推荐大家还是安装 <code>enmotech/opengauss</code> ：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">docker pull enmotech/opengauss:5.0.0<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p><img src="/2024/03/05/opengauss-docker-build/Pasted%20image%2020240305092554.png" alt="拉取 opengauss 镜像"></p><p>等待下载完成~</p><h1 id="二、配置-compose-yml-文件并启动-docker"><a href="#二、配置-compose-yml-文件并启动-docker" class="headerlink" title="二、配置 compose.yml 文件并启动 docker"></a>二、配置 compose.yml 文件并启动 docker</h1><p><img src="/2024/03/05/opengauss-docker-build/Pasted%20image%2020240305092827.png" alt="新建文件夹"></p><p>在硬盘中新建文件夹并新建如图的文件和空文件夹，opengauss 文件夹是用于存放 data 数据文件的，我们暂时不用动它，接下来我们来配置 <code>compose.yml</code> 文件：</p><pre class="line-numbers language-yaml" data-language="yaml"><code class="language-yaml"><span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">'5.0.0'</span><span class="token key atrule">services</span><span class="token punctuation">:</span>  <span class="token key atrule">opengauss</span><span class="token punctuation">:</span>    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> opengauss    <span class="token key atrule">image</span><span class="token punctuation">:</span> enmotech/opengauss<span class="token punctuation">:</span>5.0.0    <span class="token key atrule">environment</span><span class="token punctuation">:</span>      <span class="token key atrule">GS_PASSWORD</span><span class="token punctuation">:</span> Wtc@7130      <span class="token key atrule">TZ</span><span class="token punctuation">:</span> Asia/Shanghai    <span class="token key atrule">ports</span><span class="token punctuation">:</span>      <span class="token punctuation">-</span> <span class="token string">"5432:5432"</span>    <span class="token key atrule">privileged</span><span class="token punctuation">:</span> <span class="token boolean important">true</span>    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>      <span class="token punctuation">-</span> ./opengauss/data<span class="token punctuation">:</span>/var/lib/opengauss/data<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>配置完成后，回到 终端 并 cd 到刚刚创建的 <code>compose.yml</code> 文件所在的目录中，输入：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">docker compose up -ddocker psdocker exec -it {xx}  /bin/bash<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>其中 {xx} 是 ps 命令查看到当前 container 的头两个字符（如图当前是 108957e6721c 那么我这里就输入 <code>docker exec -it 10  bash</code> ）</p><p><img src="/2024/03/05/opengauss-docker-build/Pasted%20image%2020240305102613.png" alt="三步走启动 Docker"></p><p>此时就进入 root 用户了，而后输入 ：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">su - omm<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>切换到 omm 用户，然后输入：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">gsql<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>即可成功进入 gsql ，愉快的使用 opengauss 了~</p><p><del>当然我这里没有办法截屏，因为 macOS 做到进入 omm 用户以后就无法进入 gsql 了，直接死掉了，在  Google 上有很多人遇到相同的问题，但是大家也都没找到原因解决方案，乐</del>。</p><p>后续在 PD 虚拟机上重复了上述的操作一点都没变，就可以成功的跑起来了。如图：</p><p><img src="/2024/03/05/opengauss-docker-build/Pasted%20image%2020240305155856.png" alt="在 unbuntu 上成功进入 gsql"></p><h1 id="三、链接-Navicat-Premium"><a href="#三、链接-Navicat-Premium" class="headerlink" title="三、链接 Navicat Premium"></a>三、链接 Navicat Premium</h1><p>进入 gsql 后，输入命令创建用户：</p><pre class="line-numbers language-sql" data-language="sql"><code class="language-sql"><span class="token keyword">CREATE</span> <span class="token keyword">USER</span> tiancy PASSWORD <span class="token string">'Tiancy@123'</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>然后打开 Navicat Premium  - 连接 ：</p><p><img src="/2024/03/05/opengauss-docker-build/Pasted%20image%2020240305160204.png" alt="连接 Navicat"></p><ol><li>连接名可以随便取，就是名字而已；</li><li>主机就是虚拟机的 ip 地址，通过 <code>ip -a</code> 命令查看自己虚拟机的 ip 地址，端口就是 5432 （因为在 Docker compose.yml 中我们配置了端口映射，将 opengauss 的 5432 默认端口映射到了 unbuntu 本机的 5432端口上，所以这里我们访问虚拟机的 ip:5432 就可以访问到我们的数据库）；</li><li>初始化数据库名可以自己取；</li><li>用户名和密码就是刚刚我们 create 的用户名和密码。</li></ol><p>然后就可以连上 Navicat Premium 操作你的 opengauss 数据库哩~</p><p><img src="/2024/03/05/opengauss-docker-build/Pasted%20image%2020240305160639.png" alt="Navicat 操作界面"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;如果您是 macOS 用户，又如果您恰好目前选修的一门 数据库原理 的课程需要使用华为“自研”的国产 opengauss 数据库，又如果您正准备安装 opengauss 环境。那么您可以花费 5 分钟左右的时间照着本文搭建 opengauss 以便</summary>
      
    
    
    
    <category term="后端学习" scheme="https://tianci-king.github.io/categories/%E5%90%8E%E7%AB%AF%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="OpenGauss" scheme="https://tianci-king.github.io/tags/OpenGauss/"/>
    
    <category term="Docker" scheme="https://tianci-king.github.io/tags/Docker/"/>
    
    <category term="SQL" scheme="https://tianci-king.github.io/tags/SQL/"/>
    
  </entry>
  
  <entry>
    <title>Java多版本切换</title>
    <link href="https://tianci-king.github.io/2024/02/01/java-multi-version-switching-trick/"/>
    <id>https://tianci-king.github.io/2024/02/01/java-multi-version-switching-trick/</id>
    <published>2024-02-01T13:57:01.000Z</published>
    <updated>2024-12-08T13:29:28.659Z</updated>
    
    <content type="html"><![CDATA[<pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">vim ~/.bash_profile<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>在 .bash_profile 中加入 Java config：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token comment"># Java config</span><span class="token builtin class-name">export</span> <span class="token assign-left variable">JAVA_8_HOME</span><span class="token operator">=</span><span class="token string">"/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home"</span><span class="token builtin class-name">export</span> <span class="token assign-left variable">JAVA_17_HOME</span><span class="token operator">=</span><span class="token string">"/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home"</span><span class="token comment"># config alias</span><span class="token builtin class-name">alias</span> <span class="token assign-left variable">jdk8</span><span class="token operator">=</span><span class="token string">"export JAVA_HOME=<span class="token variable">$JAVA_8_HOME</span>"</span><span class="token builtin class-name">alias</span> <span class="token assign-left variable">jdk17</span><span class="token operator">=</span><span class="token string">"export JAVA_HOME=<span class="token variable">$JAVA_17_HOME</span>"</span><span class="token comment"># config default jdk</span><span class="token builtin class-name">export</span> <span class="token assign-left variable">JAVA_HOME</span><span class="token operator">=</span><span class="token variable">$JAVA_17_HOME</span><span class="token builtin class-name">export</span> <span class="token assign-left variable"><span class="token environment constant">PATH</span></span><span class="token operator">=</span><span class="token string">"<span class="token variable">$JAVA_HOME</span>:<span class="token environment constant">$PATH</span>"</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>修改保存上述配置，对bash_profile进行编译生效：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">source ~/.bash_profile<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>打开终端，输入 <code>jdk8</code> 或者 <code>jdk17</code> 即可手动切换 java 版本：</p><p><img src="/2024/02/01/java-multi-version-switching-trick/image-20240201220106917.png" alt="image-20240201220106917"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;pre class=&quot;line-numbers language-zsh&quot; data-language=&quot;zsh&quot;&gt;&lt;code class=&quot;language-zsh&quot;&gt;vim ~/.bash_profile&lt;span aria-hidden=&quot;true&quot; class=&quot;lin</summary>
      
    
    
    
    <category term="MAC调教" scheme="https://tianci-king.github.io/categories/MAC%E8%B0%83%E6%95%99/"/>
    
    
    <category term="Java" scheme="https://tianci-king.github.io/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>Eslint 的换行编码报错</title>
    <link href="https://tianci-king.github.io/2024/01/26/eslint-line-feed-code/"/>
    <id>https://tianci-king.github.io/2024/01/26/eslint-line-feed-code/</id>
    <published>2024-01-26T01:35:13.000Z</published>
    <updated>2024-12-08T13:29:28.659Z</updated>
    
    <content type="html"><![CDATA[<h1 id="情况描述"><a href="#情况描述" class="headerlink" title="情况描述"></a>情况描述</h1><blockquote><p>起因是精弘的一位手持 Windows 的小朋友来问我打开的项目每行代码的最后都报红，全屏有几千个报错，十分骇人。但仔细看都是同一个报错，遂<del>记录一篇</del>水一篇博客解决这个问题</p></blockquote><p><img src="/2024/01/26/eslint-line-feed-code/0366fcf74ed8d0eb659429af88de4b6d.jpg" alt="Vscode 下的报错"></p><p>找到项目的 Eslint 配置文件，在项目中使用 Eslint 有一条规范：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token string">"linebreak-style"</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span><span class="token string">"error"</span>, <span class="token string">"unix"</span><span class="token punctuation">]</span>,<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>这个规则的意思是<code>回车换行</code>符使用unix风格的，也就是<code>LF</code>。unix 其实主要就是指 mac ，或者 ubuntu 这类的。本来团队都用Mac就没啥问题。但如果你用的是 windows 。就会有标题中的错误。虽然看起来没区别但是在项目中的两者编码是不一样的，这会被 Eslint 报错，全屏通红。</p><h1 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h1><p>项目中应该还有一个<code>.editorconfig</code>文件，如果没有，你就自己添加一个，并输入如下：</p><pre class="line-numbers language-editorconfig" data-language="editorconfig"><code class="language-editorconfig"><span class="token comment"># http://editorconfig.org  </span><span class="token key attr-name">root</span> <span class="token value attr-value"><span class="token punctuation">=</span> true  </span>  <span class="token section selector"><span class="token punctuation">[</span><span class="token operator">*</span><span class="token punctuation">]</span></span>  <span class="token comment"># 缩进使用空格</span><span class="token key attr-name">indent_style</span> <span class="token value attr-value"><span class="token punctuation">=</span> space</span><span class="token comment"># 缩进2个字符</span><span class="token key attr-name">indent_size</span> <span class="token value attr-value"><span class="token punctuation">=</span> 2</span><span class="token comment"># 行结尾使用 lf !!!!</span><span class="token key attr-name">end_of_line</span> <span class="token value attr-value"><span class="token punctuation">=</span> lf</span><span class="token comment"># 删除行尾空格</span><span class="token key attr-name">trim_trailing_whitespace</span> <span class="token value attr-value"><span class="token punctuation">=</span> true</span><span class="token comment"># 文件结尾添加一个空行</span><span class="token key attr-name">insert_final_newline</span> <span class="token value attr-value"><span class="token punctuation">=</span> true</span><span class="token comment"># 行最大长度</span><span class="token key attr-name">max_line_length</span> <span class="token value attr-value"><span class="token punctuation">=</span> 100</span><span class="token comment"># 编码采用 utf-8</span><span class="token key attr-name">charset</span> <span class="token value attr-value"><span class="token punctuation">=</span> utf-8</span><span class="token section selector"><span class="token punctuation">[</span><span class="token operator">*</span>.md<span class="token punctuation">]</span></span>  <span class="token key attr-name">trim_trailing_whitespace</span> <span class="token value attr-value"><span class="token punctuation">=</span> false</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>正常情况下，这个文件会约束当前的项目的书写规范。但为什么了windows下没生效呢？因为这个文件需要你的编辑器支持。换言之你需要安装插件！</p><p>在vscode中，可以直接搜索 <strong>editorconfig</strong> 。安装后重启即可。而在 Webstorm 中则自带该插件</p><p>值得注意的是，你可能发现仍旧没有生效。因为你还需要保存下报错的文件。</p><p>最后，还有一种解决方法，比如添加规则如下</p><pre class="line-numbers language-Shell" data-language="Shell"><code class="language-Shell">'linebreak-style':[0,'error','window'],<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>其实这是相当于windows下关闭了换行的规则。这是很不优雅的。</p><p>当然其实关闭也是可以的，因为git会在你提交的时候帮你把CRLF转成LF。我这里亲测本地上传时候是CRLF，再从gitlab上直接下载下来（不是克隆下来，也就是不走git），打开查看就是LF。想想也是，如果你上传的和别人的不一致，那岂不各种冲突。</p><p>最后的最后…有些时候直接选择关闭是很无奈的，比如你的项目下clone的时候git已经把lf转换为了crlf，那么当你再看开启editorconfig的配置之后，就会在修改并保存文件的时候修改换行符，也就是导致文件都被修改。所以如果想优雅的解决这个问题。还需要先配置git不自动转换crlf。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;情况描述&quot;&gt;&lt;a href=&quot;#情况描述&quot; class=&quot;headerlink&quot; title=&quot;情况描述&quot;&gt;&lt;/a&gt;情况描述&lt;/h1&gt;&lt;blockquote&gt;
&lt;p&gt;起因是精弘的一位手持 Windows 的小朋友来问我打开的项目每行代码的最后都报红，全屏有几千个报</summary>
      
    
    
    
    <category term="前端学习" scheme="https://tianci-king.github.io/categories/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="EsLint" scheme="https://tianci-king.github.io/tags/EsLint/"/>
    
    <category term="Editorconfig" scheme="https://tianci-king.github.io/tags/Editorconfig/"/>
    
  </entry>
  
  <entry>
    <title>MacBook 查询SSD硬盘读写量</title>
    <link href="https://tianci-king.github.io/2023/10/13/macbook-ssd-check/"/>
    <id>https://tianci-king.github.io/2023/10/13/macbook-ssd-check/</id>
    <published>2023-10-13T02:35:17.000Z</published>
    <updated>2024-12-08T13:29:28.663Z</updated>
    
    <content type="html"><![CDATA[<h2 id="工具安装"><a href="#工具安装" class="headerlink" title="工具安装"></a>工具安装</h2><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">brew install smartmontools<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><p>前几天刚刚看到了 M1 芯片的 MacBook 疯狂写入的消息，吓得我也赶紧去查查我自己的硬盘写入，很悲伤的消息是查出来我 4 天写入了 600GB ，不多也不少。</p><h2 id="查询-SSD-硬盘读写量教程"><a href="#查询-SSD-硬盘读写量教程" class="headerlink" title="查询 SSD 硬盘读写量教程"></a>查询 SSD 硬盘读写量教程</h2><p>可以通过一个叫 smartctl 的工具，使用命令行快速查询。 为了避免大家踩坑，我整理了一下安装流程。</p><h3 id="HomeBrew-安装"><a href="#HomeBrew-安装" class="headerlink" title="HomeBrew 安装"></a>HomeBrew 安装</h3><p>我是通过 Mac os 上的软件包管理工具 <a href="https://link.zhihu.com/?target=http://brew.sh/">HomeBrew</a> 来进行安装的，因此首先要做的就是安装上 HomeBrew，如果你的电脑上已经安装了 HomeBrew 则可以直接忽略这一步。</p><h4 id="第一步：安装xcode命令行工具"><a href="#第一步：安装xcode命令行工具" class="headerlink" title="第一步：安装xcode命令行工具"></a>第一步：安装xcode命令行工具</h4><pre class="line-numbers language-czh" data-language="czh"><code class="language-czh">xcode-select --install<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h4 id="第二步：安装-homebrew"><a href="#第二步：安装-homebrew" class="headerlink" title="第二步：安装 homebrew"></a>第二步：安装 homebrew</h4><p>官网给出的方法十分简单，只需要在终端中粘贴如下代码即可：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>我也按照官网的提示进行安装，但因为一些众所周知的原因，这个方法失败了，终端中出现如下提示：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">raw.githubusercontent.com port 443: Connection refused<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>所以我们不选择官方源，在未能正确配置网络环境的时候，用官方源多数是报错，并且速度很慢。这里我们用国内源绕过。</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>接下来会进行选择源。1、中科大 2、清华源 … 这里推荐选择1或者2，直接输入数字即可，按<code>enter</code>回车后，输入<code>y</code>确认安装，接下来会要求输入密码，这里的密码就是电脑的开机密码。 安装完后会提示重启<code>terminnal</code>。</p><p>等待安装完成后，需要设置环境变量，在终端中接着输入以下代码即可：</p><p><strong>注意：如果你确定使用的终端是zsh（一般默认是zsh），那么直接执行下面代码，否则请将两段的末尾的 zshrc 改为bashrc即可</strong></p><pre class="line-numbers language-none"><code class="language-none">echo export PATH=/opt/homebrew/bin:$PATH &gt;&gt; .zshrcsource ~/.zshrc<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre><p>重启终端，并在其中输入 <code>brew</code> ，如果没有报错，则说明安装成功了。</p><h3 id="安装-smartctl"><a href="#安装-smartctl" class="headerlink" title="安装 smartctl"></a>安装 smartctl</h3><p>成功安装 HomeBrew 之后，我们就可以安装 smartctl 了！在终端中输入如下代码，即可进行安装：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">brew install smartmontools<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>在终端输入 <code>smartctl</code> ,如果没有报错则说明安装成功了。</p><h3 id="查看硬盘使用量"><a href="#查看硬盘使用量" class="headerlink" title="查看硬盘使用量"></a>查看硬盘使用量</h3><p>在终端中输入如下代码，即可进行看查硬盘使用量。</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">smartctl -a disk0<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>结果如下，里面的<strong>Percentage Used</strong> 就是损耗值，<strong>Data Units Written</strong> 就是写入量。</p><p><img src="https://pic2.zhimg.com/80/v2-40f72d959d7f4686ede1a84189f88119_1440w.webp" alt="M1 MacBook 硬盘写入情况"></p><h3 id="如何卸载"><a href="#如何卸载" class="headerlink" title="如何卸载"></a>如何卸载</h3><p>使用brew包管理器安装，卸载也是十分的方便，只需要在终端输入下面的代码即可卸载成功：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">brew uninstall smartmontools <span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h2 id="写在结尾"><a href="#写在结尾" class="headerlink" title="写在结尾"></a>写在结尾</h2><p>由于 mac os 相对激进的 swap 策略和 unix 的内存管理机制，在内存充足的情况下仍然会进行 swap，如果正常使用的话，这个读写数据放在 win 本中可能一年都写不到。不过这种机制让使用者确实没有因为内存不足而导致体验上的不佳，我开了很多应用仍然十分丝滑，这在 win 本上是想都不要想的，所以也只能说有利有弊吧。不过这一代 Mac 不支持更换 SSD，所以四五年之后极有可能 SSD 就会报销，因此大家还是尽量要避免频繁的 swap，增加硬盘寿命，如何”关闭”硬盘 swap （在内存充足的情况不调用 swap）请看我上一篇博客。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;工具安装&quot;&gt;&lt;a href=&quot;#工具安装&quot; class=&quot;headerlink&quot; title=&quot;工具安装&quot;&gt;&lt;/a&gt;工具安装&lt;/h2&gt;&lt;pre class=&quot;line-numbers language-zsh&quot; data-language=&quot;zsh&quot;&gt;&lt;code </summary>
      
    
    
    
    <category term="MAC调教" scheme="https://tianci-king.github.io/categories/MAC%E8%B0%83%E6%95%99/"/>
    
    
    <category term="MacBook" scheme="https://tianci-king.github.io/tags/MacBook/"/>
    
    <category term="Smartctl" scheme="https://tianci-king.github.io/tags/Smartctl/"/>
    
  </entry>
  
  <entry>
    <title>MacBook 关闭虚拟内存(交换内存 SwapMemory)</title>
    <link href="https://tianci-king.github.io/2023/10/13/macbook-swap-off/"/>
    <id>https://tianci-king.github.io/2023/10/13/macbook-swap-off/</id>
    <published>2023-10-13T02:22:17.000Z</published>
    <updated>2024-12-08T13:29:28.663Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>由于 MacBook 激进的 SWAP 策略 和 unix 特有的内存管理模式，导致 MacBook 在轻量使用情况下仍然占用大量内存，且会对 SSD 进行 SWAP 过量擦写硬盘，在高强度使用时，SWAP 擦写更频繁，导致电脑 SSD 寿命大幅下降</p></blockquote><h1 id="为什么建议关闭？"><a href="#为什么建议关闭？" class="headerlink" title="为什么建议关闭？"></a>为什么建议关闭？</h1><p>听说M1有SSD磨损的问题。</p><p>我在了解之后，就把虚拟内存关掉了。但在我关闭后，打开电脑奇怪的发现虚拟内存还在使用，并且还是一直保持2GB左右，半个月不到就2TB了，我表示很慌。在第二天我打开电脑准备工作时，习惯性打开活动监视器(command + 空格)，发现已使用的交换内存为0字节，我特别高兴。</p><p>但在我打开3个idea窗口时，分别运行了1个Springboot的项目和2个node项目时，习惯性查看活动监视器，发现又上升到了2GB，也就是说，关闭虚拟内存和启动虚拟内存是不一样的效果。</p><p>1.启动虚拟内存(默认)：不管怎么样都会使用虚拟内存，除非你的内存特别大，目的是为了防止在突然打开一个超大的文件时，导致需要重新处理内存与虚拟内存。所以默认使用虚拟内存，尽量让出大部分物理内存。</p><p>2.关闭虚拟内存(需要手动)：默认不使用虚拟内存，但经过我观察，<strong>似乎是超过预警阈值(内存GB-2GB的样子)就会开始使用虚拟内存，我猜测目的是为了系统的稳定性</strong></p><p>也就是说，即使关闭了虚拟内存，也不会影响系统稳定性，<strong>因为超过阈值又会继续使用虚拟内存</strong>。<strong>但关闭后就可以在没必要的情况下使用虚拟内存</strong>。其实效果也不是很好，因为我打开电脑一定就是打开idea搞开发，所以每天都还是会使用大量虚拟内存。</p><h1 id="如何关闭虚拟内存"><a href="#如何关闭虚拟内存" class="headerlink" title="如何关闭虚拟内存"></a>如何关闭虚拟内存</h1><p>为缓解 MacBook 激进的 SWAP 策略，在内存有余量的情况下，可以关闭虚拟内存，不对 SSD 进行硬盘的 SWAP ，以延长电脑使用寿命，具体操作如下：</p><ol><li>关闭系统完整性保护机制</li><li>关闭虚拟内存</li></ol><h2 id="关闭系统完整性保护机制"><a href="#关闭系统完整性保护机制" class="headerlink" title="关闭系统完整性保护机制"></a>关闭系统完整性保护机制</h2><p>首先关闭系统完整性保护需要进入recovery OS，Mac M1进入模式好像不太一样。就在电脑完全关机的情况下，一直按着电源键不放，提示你继续按着电源键就可以进入，然后直到提示你正在进入恢复模式就可以放手了。</p><p>选择用户输入密码后，左上角有一排的菜单，找到终端打开他，输入：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">csrutil disable<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>我记得好像会提示什么权限转移吧，反正yes就可以了。</p><h2 id="关闭虚拟内存"><a href="#关闭虚拟内存" class="headerlink" title="关闭虚拟内存"></a>关闭虚拟内存</h2><p>重启电脑后打开终端，输入：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.dynamic_pager.plist<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>然后就关闭了，使用这个指令可以查看虚拟内存使用情况：</p><pre class="line-numbers language-zsh" data-language="zsh"><code class="language-zsh">sysctl vm.swapusage<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><h2 id="重新开启系统完整性保护机制"><a href="#重新开启系统完整性保护机制" class="headerlink" title="重新开启系统完整性保护机制"></a>重新开启系统完整性保护机制</h2><p>到了这里你就关闭了虚拟内存，但注意，你之前关闭了系统完整性保护，我建议你重新开启，以免不必要的问题，重新进入recovery OS恢复模式，在终端输入：</p><pre class="line-numbers language-none"><code class="language-none">csrutil enable<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p>关闭虚拟内存不排除是否有风险，如果你每天都是负载使用MAC，关不关都无所谓的。如果你只是简单使用MAC，内存一大半没用就被使用了虚拟内存，你就可以关闭掉虚拟内存。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;由于 MacBook 激进的 SWAP 策略 和 unix 特有的内存管理模式，导致 MacBook 在轻量使用情况下仍然占用大量内存，且会对 SSD 进行 SWAP 过量擦写硬盘，在高强度使用时，SWAP 擦写更频繁，导致电脑 SSD 寿命大幅下</summary>
      
    
    
    
    <category term="MAC调教" scheme="https://tianci-king.github.io/categories/MAC%E8%B0%83%E6%95%99/"/>
    
    
    <category term="MacBook" scheme="https://tianci-king.github.io/tags/MacBook/"/>
    
    <category term="Swap" scheme="https://tianci-king.github.io/tags/Swap/"/>
    
  </entry>
  
  <entry>
    <title>WebStorm快速配置EsLint</title>
    <link href="https://tianci-king.github.io/2023/09/03/fix-eslint-in-webstorm/"/>
    <id>https://tianci-king.github.io/2023/09/03/fix-eslint-in-webstorm/</id>
    <published>2023-09-03T11:18:27.000Z</published>
    <updated>2024-12-08T13:29:28.659Z</updated>
    
    <content type="html"><![CDATA[<h1 id="WebStorm快速配置EsLint"><a href="#WebStorm快速配置EsLint" class="headerlink" title="WebStorm快速配置EsLint"></a>WebStorm快速配置EsLint</h1><blockquote><p>因为工作的疏忽，<a href="https://www.bilibili.com/video/BV1194y1r7WW/">精弘网络暑期前端授课视频</a>中 5:03的关于EsLint的配置环境的教程，有部分内容是错误的，可能会误导到听课的同学。为此我感到十分抱歉，所以特此出一篇博客，纠正这个问题，还望大家海涵。</p></blockquote><h2 id="一、Webstorm安装插件"><a href="#一、Webstorm安装插件" class="headerlink" title="一、Webstorm安装插件"></a>一、Webstorm安装插件</h2><p>前往设置-插件，搜索如下图片的关键字，安装EsLint所需要的插件</p><h2 id="二、根目录下编辑-Eslint配置文件"><a href="#二、根目录下编辑-Eslint配置文件" class="headerlink" title="二、根目录下编辑 Eslint配置文件"></a>二、根目录下编辑 Eslint配置文件</h2><p>首先我们要知道的是，在eslint中，<strong>插件会自动检索根目录下面的配置文件</strong>作为EsLint的配置规则，顺序是</p><ol><li>.eslintrc.js </li><li>.eslintrc.cjs </li><li>.eslintrc.yaml </li><li>.eslintrc.yml </li><li>.eslintrc.json </li><li>package.json</li></ol><p>打个比方说，一个项目同时有.eslintrc.cjs 和.eslintrc.json 配置文件，那么会优先采用.cjs的配置规则，.json就不起作用了</p><p><strong>之前授课的错误就是，我把两种配置规则混在一起了，导致一个项目中同时有2个规则。但是插件那边选择了auto，插件就没有选择配置文件，导致我们想要的规则不起作用。</strong></p><p>因此，</p><p><strong>不需要Eslint –init  配置</strong>，只需要直接在根目录新建一个文件<code>.eslintrc.cjs</code></p><p>内容如下：</p><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>  <span class="token literal-property property">env</span><span class="token operator">:</span> <span class="token punctuation">{</span>    <span class="token literal-property property">browser</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>    <span class="token literal-property property">es2021</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>    <span class="token literal-property property">node</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>  <span class="token punctuation">}</span><span class="token punctuation">,</span>  <span class="token keyword">extends</span><span class="token operator">:</span> <span class="token punctuation">[</span>    <span class="token string">"plugin:vue/vue3-essential"</span><span class="token punctuation">,</span>    <span class="token string">"@vue/eslint-config-typescript/recommended"</span>  <span class="token punctuation">]</span><span class="token punctuation">,</span>  <span class="token literal-property property">overrides</span><span class="token operator">:</span> <span class="token punctuation">[</span>  <span class="token punctuation">]</span><span class="token punctuation">,</span>  <span class="token literal-property property">parserOptions</span><span class="token operator">:</span> <span class="token punctuation">{</span>    <span class="token literal-property property">ecmaVersion</span><span class="token operator">:</span> <span class="token string">"latest"</span><span class="token punctuation">,</span>    <span class="token literal-property property">sourceType</span><span class="token operator">:</span> <span class="token string">"module"</span><span class="token punctuation">,</span>    <span class="token literal-property property">project</span><span class="token operator">:</span> <span class="token string">"./tsconfig.json"</span>  <span class="token punctuation">}</span><span class="token punctuation">,</span>  <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>    <span class="token string">"vue"</span>  <span class="token punctuation">]</span><span class="token punctuation">,</span>  <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">{</span>    <span class="token literal-property property">quotes</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"warn"</span><span class="token punctuation">,</span> <span class="token string">"double"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>    <span class="token literal-property property">semi</span><span class="token operator">:</span> <span class="token string">"error"</span><span class="token punctuation">,</span>    <span class="token string-property property">"vue/multi-word-component-names"</span><span class="token operator">:</span> <span class="token string">"off"</span><span class="token punctuation">,</span>    <span class="token string-property property">"@typescript-eslint/ban-ts-comment"</span><span class="token operator">:</span> <span class="token string">"off"</span><span class="token punctuation">,</span>    <span class="token string-property property">"no-trailing-spaces"</span><span class="token operator">:</span> <span class="token string">"error"</span>  <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><hr><p>另外值得一提的是，为什么在二者只能选其一的情况下，我们不使用EsLint –init，而更推荐大家直接使用上面的.cjs文件来配置EsLint呢？</p><p>因为EsLint –init配置出来的规则是最基础的规范，而上面的.cjs则是精弘一直使用的团队规范，虽然不能保证是最好的规则，但也至少比–init的要好。而且最主要的原因是，在这个Demo中，我们使用的就是精弘网络要求的规范和技术栈，使用–init创建的规范文件，可能在这个Demo中会存在不适配和报错的情况。</p><h2 id="三、Eslint具体设置"><a href="#三、Eslint具体设置" class="headerlink" title="三、Eslint具体设置"></a>三、Eslint具体设置</h2><p>设置左上角输入Eslint就可以跳转到这个界面，选择  <strong>手动/自动</strong> 均可</p><p>下面都不用动，都会自动匹配到.cjs的规则。</p><h2 id="四、补全Eslint所需要的依赖"><a href="#四、补全Eslint所需要的依赖" class="headerlink" title="四、补全Eslint所需要的依赖"></a>四、补全Eslint所需要的依赖</h2><p>.cjs中所需要的规则需要额外添加一些关于EsLint的依赖环境，</p><p>请在<code>package.json</code>中按照如下补全依赖,检查是否有缺失的依赖，无误后<code>pnpm i</code>：</p><pre class="line-numbers language-json" data-language="json"><code class="language-json"><span class="token punctuation">{</span>  <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"addressbook"</span><span class="token punctuation">,</span>  <span class="token property">"private"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>  <span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"0.0.0"</span><span class="token punctuation">,</span>  <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"module"</span><span class="token punctuation">,</span>  <span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span>    <span class="token property">"dev"</span><span class="token operator">:</span> <span class="token string">"vite"</span><span class="token punctuation">,</span>    <span class="token property">"build"</span><span class="token operator">:</span> <span class="token string">"vue-tsc &amp;&amp; vite build"</span><span class="token punctuation">,</span>    <span class="token property">"preview"</span><span class="token operator">:</span> <span class="token string">"vite preview"</span>  <span class="token punctuation">}</span><span class="token punctuation">,</span>  <span class="token property">"dependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span>    <span class="token property">"@element-plus/icons-vue"</span><span class="token operator">:</span> <span class="token string">"^2.1.0"</span><span class="token punctuation">,</span>    <span class="token property">"axios"</span><span class="token operator">:</span> <span class="token string">"^1.2.2"</span><span class="token punctuation">,</span>    <span class="token property">"element-plus"</span><span class="token operator">:</span> <span class="token string">"^2.3.7"</span><span class="token punctuation">,</span>    <span class="token property">"pinia"</span><span class="token operator">:</span> <span class="token string">"^2.1.4"</span><span class="token punctuation">,</span>    <span class="token property">"pinia-plugin-persistedstate"</span><span class="token operator">:</span> <span class="token string">"^3.2.0"</span><span class="token punctuation">,</span>    <span class="token property">"vue"</span><span class="token operator">:</span> <span class="token string">"^3.2.47"</span><span class="token punctuation">,</span>    <span class="token property">"vue-router"</span><span class="token operator">:</span> <span class="token string">"4"</span>  <span class="token punctuation">}</span><span class="token punctuation">,</span>  <span class="token property">"devDependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span>    <span class="token property">"@types/node"</span><span class="token operator">:</span> <span class="token string">"^20.5.1"</span><span class="token punctuation">,</span>    <span class="token property">"@typescript-eslint/eslint-plugin"</span><span class="token operator">:</span> <span class="token string">"^6.5.0"</span><span class="token punctuation">,</span>    <span class="token property">"@typescript-eslint/parser"</span><span class="token operator">:</span> <span class="token string">"^6.5.0"</span><span class="token punctuation">,</span>    <span class="token property">"@vitejs/plugin-vue"</span><span class="token operator">:</span> <span class="token string">"^4.1.0"</span><span class="token punctuation">,</span>    <span class="token property">"@vue/eslint-config-typescript"</span><span class="token operator">:</span> <span class="token string">"^11.0.2"</span><span class="token punctuation">,</span>    <span class="token property">"eslint"</span><span class="token operator">:</span> <span class="token string">"^8.44.0"</span><span class="token punctuation">,</span>    <span class="token property">"eslint-plugin-vue"</span><span class="token operator">:</span> <span class="token string">"^9.17.0"</span><span class="token punctuation">,</span>    <span class="token property">"typescript"</span><span class="token operator">:</span> <span class="token string">"^5.0.2"</span><span class="token punctuation">,</span>    <span class="token property">"vite"</span><span class="token operator">:</span> <span class="token string">"^4.3.9"</span><span class="token punctuation">,</span>    <span class="token property">"vue-tsc"</span><span class="token operator">:</span> <span class="token string">"^1.4.2"</span>  <span class="token punctuation">}</span><span class="token punctuation">}</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p><code>pnpm install</code>以后，重启WebStorm。</p><h2 id="四、写在后面"><a href="#四、写在后面" class="headerlink" title="四、写在后面"></a>四、写在后面</h2><p>另外如果你在设置的eslint里勾选了eslint –fix，ctrl+s保存时也可以自动修复。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;WebStorm快速配置EsLint&quot;&gt;&lt;a href=&quot;#WebStorm快速配置EsLint&quot; class=&quot;headerlink&quot; title=&quot;WebStorm快速配置EsLint&quot;&gt;&lt;/a&gt;WebStorm快速配置EsLint&lt;/h1&gt;&lt;blockquo</summary>
      
    
    
    
    <category term="前端学习" scheme="https://tianci-king.github.io/categories/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="EsLint" scheme="https://tianci-king.github.io/tags/EsLint/"/>
    
    <category term="WebStorm" scheme="https://tianci-king.github.io/tags/WebStorm/"/>
    
  </entry>
  
  <entry>
    <title>初识 Node</title>
    <link href="https://tianci-king.github.io/2022/12/03/node/"/>
    <id>https://tianci-king.github.io/2022/12/03/node/</id>
    <published>2022-12-03T03:10:38.000Z</published>
    <updated>2024-12-08T13:29:28.663Z</updated>
    
    <content type="html"><![CDATA[<p>Node.js 是一个开源和跨平台的 JavaScript 运行时环境。Node.js 可以在浏览器之外运行 V8 JavaScript 引擎（基于 Google Chrome 的内核），用于服务端和网络应用开发。Node.js最初的定位是提升开发者日常工作效率，用于编写服务器端代码。然而，它在前端领域也大放异彩。</p><h1 id="一-Node-js介绍"><a href="#一-Node-js介绍" class="headerlink" title="一 Node.js介绍"></a>一 Node.js介绍</h1><p>Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。严格意义上讲Node.js本身并不属于前端技术，而是属于前端技术栈，是前端开发工具链中的重要工具之一。要理解Node.js不属于前端技术，首先要区分清楚前端、前端技术、前端技术栈和前端工具等名词的区别：</p><ol><li><p>“前端”通常指的是在浏览器中执行的环境，这与在服务器上运行的“后端”环境形成对比。</p></li><li><p>“前端技术”涵盖了浏览器端应用开发所需的所有技术，包括但不限于常见的HTML、CSS、JavaScript三件套、以及过去常用的Flash、ActiveX和Applet等。</p></li><li><p>“前端技术栈”则更广泛地指那些辅助和增强前端技术运行的各种技术，它包括了前端技术本身及其相关支持技术，但其范围和应用超出了纯粹的前端技术。</p></li><li><p>“前端工具”则是在这个技术栈中，有一部分专门是“前端工具”，这些工具虽然是前端技术栈的组成部分，但它们本身并不直接构成前端技术。</p></li></ol><p>如果理解了以上概念间的差别，显而易见，Node.js在前端开发的过程中主要是起到开发工具的作用，参与前端工具链的工作并提供了更多更好的开发工具。</p><p>Web的开发体系可以分为前端、后端、开发工具三个重要领域。而在前端开发领域，随着前端工程化的推进，现在的前端开发工程师写前端，已经不再是写HTML文件然后在里面写JS写CSS这么简单，而是采用工程化的前端框架、脚手架、打包工具等开发工具构建开发流程，快速且高效地构建前端代码。</p><p>而这些工具和依赖背后主要是用Node.js开发的，并通过Node.js下的包管理器NPM统一管理。Node.js的作用相当于Java中的GWT，以工具的形式，参与到前端开发中。</p><h1 id="二-Node-js安装"><a href="#二-Node-js安装" class="headerlink" title="二 Node.js安装"></a>二 Node.js安装</h1><h3 id="1-进入官网地址下载安装包"><a href="#1-进入官网地址下载安装包" class="headerlink" title="1.进入官网地址下载安装包"></a>1.进入官网地址下载安装包</h3><p>打开浏览器，输入<a href="https://nodejs.org/en%E7%BD%91%E5%9D%80%E5%89%8D%E5%BE%80Node.js%E5%AE%98%E7%BD%91%EF%BC%8C%E7%82%B9%E5%87%BB%E2%80%9C20.11.0">https://nodejs.org/en网址前往Node.js官网，点击“20.11.0</a> LTS Recommended For Most Users”绿色按钮就可以下载安装包。其中LTS（Long-Term Support）版本是 Node.js 的长期支持版本，通常每隔两年发布一次。 LTS 版本的主要特点是稳定性和可靠性。 它们接受持续的维护和安全更新，以确保企业和生产环境的稳定性。Current 版本是 Node.js 的最新开发版本，通常每隔几个月发布一次。 它包含最新的功能、改进和实验性特性，但不太稳定。 Current 版本的目标是提供给开发人员一个平台来尝试新的功能和实验性特性，以便反馈和测试。</p><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242110531.png" alt="图1-1 打开Node.js官网">                               </p><p>如果你需要安装特定版本的Node.js，可以点击“Other Downloads”，跳转到<a href="https://nodejs.org/en/download/%E9%A1%B5%E9%9D%A2%EF%BC%8C%E9%80%89%E6%8B%A9%E9%9C%80%E8%A6%81%E7%9A%84%E7%89%88%E6%9C%AC%E4%B8%8B%E8%BD%BD%E3%80%82">https://nodejs.org/en/download/页面，选择需要的版本下载。</a></p><p>下载完成后，双击“node-v20.11.0-x64.msi”。</p><h3 id="2-进入安装程序"><a href="#2-进入安装程序" class="headerlink" title="2.进入安装程序"></a>2.进入安装程序</h3><p> <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242110949.png" alt="图1-2 Node.js安装程序之介绍页面"></p><p>点击“Next”下一步；</p><p> <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242111552.png" alt="图1-3 Node.js安装程序之同意许可协议"> </p><p>勾选“I accept the terms in the License Agreement”，并点击“Next”；</p><p> <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242112451.png" alt="图1-4 Node.js安装程序之选择安装路径"></p><p>此处可根据个人需求点击“Change”修改安装路径，修改完毕后点击“Next”下一步；</p><p> <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242112771.png" alt="图1-5 Node.js安装程序之自定义安装"></p><p>点击“Next”下一步；</p><p> <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242112822.png" alt="图1-6 Node.js安装程序之本机模块工具"></p><p>不勾选，点击“Next”下一步。</p><p>Chocolatey是Windows平台的包管理工具，类似于Linux的yum/apt-get。可以通过Chocolatey安装包。如若需要安装Chocolatey，勾选并点击“Next”即可。</p><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242113165.png" alt="图1-7 Node.js安装程序之准备安装"></p><p>点击“Install”开始安装Node.js；</p><p> <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242113921.png" alt="图1-7 Node.js安装程序之安装完成"></p><p>安装完成，点击“Finish”结束安装。</p><h3 id="3-测试安装成功"><a href="#3-测试安装成功" class="headerlink" title="3.测试安装成功"></a>3.测试安装成功</h3><p>按下“Win+R”键，输入“cmd”，回车打开CMD窗口，输入：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">node</span> <span class="token parameter variable">-v</span> //显示Node.js版本<span class="token function">npm</span> <span class="token parameter variable">-v</span>  //显示NPM版本<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><p>  <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242115689.png" alt="图1-8 CMD中查看Node.js版本号"></p><p>如若能正确回显如图的版本号，说明安装成功，可进入下一步；否则，请检查上述步骤是否有误，重新安装Node.js。</p><h3 id="4-配置Node-js环境变量"><a href="#4-配置Node-js环境变量" class="headerlink" title="4.配置Node.js环境变量"></a>4.配置Node.js环境变量</h3><blockquote><p>注意：到此为止上述操作已经完成了Node.js的安装操作，即使不进行下述操作配置环境变量也不影响Node.js的使用。但是若不进行环境变量的配置，那么在终端使用命令安装Node.js全局模块时，会默认安装到默认路径中。因此，需要配置全局安装模块“node_global”和缓存目录“node_cache”的环境变量。</p></blockquote><p>找到安装Node.js所在的目录：</p><p> <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242116471.png" alt="图1-9 打开Node.js安装所在的目录"></p><p>在安装目录下新建两个文件夹，分别命名为“node_global”和“node_cache”：</p><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242116745.png" alt="图1-10  新建“node_global”和“node_cache”文件夹"> </p><p>创建完成以后，使用管理员身份打开CMD，输入：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> config <span class="token builtin class-name">set</span> prefix <span class="token string">"C:\Program Files<span class="token entity" title="\n">\n</span>odejs<span class="token entity" title="\n">\n</span>ode_global"</span>//引号中是创建的node_global文件夹的路径地址，以具体路径为准<span class="token function">npm</span> config <span class="token builtin class-name">set</span> cache <span class="token string">"C:\Program Files<span class="token entity" title="\n">\n</span>odejs<span class="token entity" title="\n">\n</span>ode_cache"</span>//引号中是创建的node_cache文件夹的路径地址，以具体路径为准<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>在“node_global”文件夹中再新建一个文件夹，命名“node_modules”。</p><p>打开“此电脑”，单击右键，单击“属性”，单击“高级系统设置”，单击“环境变量”：</p><p>在“系统变量”中点击“新建”，其中变量名为“NODE_PATH”，变量值为”C:\Program Files\nodejs\node_global\node_modules”（变量值为安装路径的node_global\node_modules，以具体路径为准）：</p><p> <img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242117496.png" alt=" 图1-11  修改环境变量"></p><p>编辑“用户变量”中的“Path”: </p><p>将默认的“Roaming\npm”地址修改为“node_global”的路径：</p><p>在“系统变量”中选择“Path”，点击“编辑”，添加“%NODE_PATH%”，随后一直点确定： </p><h3 id="5-测试"><a href="#5-测试" class="headerlink" title="5.测试"></a>5.测试</h3><p>配置完成后，全局安装一个常用的express模块进行测试：</p><pre class="line-numbers language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">-g</span> express // <span class="token parameter variable">-g</span> 代表全局安装<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre><p><img src="https://raw.githubusercontent.com/Tianci-King/PicGo/main/img/202405242118830.png" alt="图1-12  打开终端输入命令进行测试"></p><p>终端显示如图文字即表示配置成功，打开先前新建的“node_global”文件夹中的“node_modules”文件夹，可以看到express文件夹，说明express的确安装到了这个新建的文件夹中，而非安装在默认文件夹。</p><blockquote><p>注意：如果出现安装失败的话可能是你没有使用管理员身份运行cmd窗口，或者可以修改一下“node_global”和“node_cache”的权限：鼠标右击“node_global”的文件夹，点击“属性”，再点击“安全”，再点击“编辑”，将权限都勾上，随即点击“确定”即可，“node_cache”步骤同理。  </p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Node.js 是一个开源和跨平台的 JavaScript 运行时环境。Node.js 可以在浏览器之外运行 V8 JavaScript 引擎（基于 Google Chrome 的内核），用于服务端和网络应用开发。Node.js最初的定位是提升开发者日常工作效率，用于编写服</summary>
      
    
    
    
    <category term="前端学习" scheme="https://tianci-king.github.io/categories/%E5%89%8D%E7%AB%AF%E5%AD%A6%E4%B9%A0/"/>
    
    
    <category term="Node" scheme="https://tianci-king.github.io/tags/Node/"/>
    
  </entry>
  
  <entry>
    <title>第一篇博客</title>
    <link href="https://tianci-king.github.io/2022/11/01/first-blog/"/>
    <id>https://tianci-king.github.io/2022/11/01/first-blog/</id>
    <published>2022-11-01T08:06:36.000Z</published>
    <updated>2024-12-08T13:29:28.659Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p><strong>“求知若饥，虚心若愚”</strong></p><p>——Steve Jobs</p></blockquote><h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>  这是我的第一个博客，也是参加精弘网络后作为小部员的第二个小作业项目。</p><h1 id="搭建过程"><a href="#搭建过程" class="headerlink" title="搭建过程"></a>搭建过程</h1><h2 id="一、Hexo搭建博客"><a href="#一、Hexo搭建博客" class="headerlink" title="一、Hexo搭建博客"></a>一、Hexo搭建博客</h2><p>通过查阅Google以后，我得知常见的博客搭建有两种方法，其一就是我目前采用的 <strong>Hexo</strong> ，另外一种是     <strong>Wordpress</strong> 。</p><p> <strong>Hexo</strong> 非常出色的一点是：能快速部署在<strong>Github</strong>上， 挂载到** <strong>Github</strong> <strong>pages</strong> ， 帮我省下<del>去阿某云租云服务器的钱</del> 部署到云上的时间，省时省力。因此我最后采用 **Hexo ** 搭建我的博客。</p><p>通过以下的文档，很快就能搭建完成</p><ol><li><p><a href="https://hexo.io/zh-cn/docs/">文档 | Hexo</a></p></li><li><p><a href="https://zhuanlan.zhihu.com/p/552639819">2022【保姆级教程】含泪搭建hexo博客 - 知乎 (zhihu.com)</a></p></li></ol><h2 id="二、购买域名"><a href="#二、购买域名" class="headerlink" title="二、购买域名"></a>二、购买域名</h2><p> 由于我没有选择国内的云服务器搭建个人博客，<strong>所以我省去了国内建站备案的繁琐过程，也不需要在国内高额购买域名</strong> ， 我前往</p><p><a href="https://www.namesilo.com/">https://www.namesilo.com/</a></p><p>购买了一个域名，并进行了DNS解析。</p><p>然后就可以通过访问我购买的域名来访问我的博客了。</p><h1 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h1><p>  之后应该会把在精弘的学习笔记陆续上传，权且作为自己的“知识仓库”，也能记录一些自己的心得与大家分享。</p><p>  当然生活中的一些随笔琐事亦会在此略加记录，把这里当作吐槽负面情绪的树洞也未尝不可。</p><hr><p>  <strong>以上，可以算是我的博客的第一篇札记。</strong></p><p>​</p><p>​共勉！</p><p><strong>Location:</strong></p><p>​尚德园，ZJUT</p><p><strong>Date:</strong></p><p>​2022/11/01 午后</p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“求知若饥，虚心若愚”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;——Steve Jobs&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;</summary>
      
    
    
    
    <category term="随笔拾遗" scheme="https://tianci-king.github.io/categories/%E9%9A%8F%E7%AC%94%E6%8B%BE%E9%81%97/"/>
    
    
    <category term="Hexo" scheme="https://tianci-king.github.io/tags/Hexo/"/>
    
  </entry>
  
</feed>
