<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>CI_Knight</title>
  
  <subtitle>且行善举，莫问前程。</subtitle>
  <link href="https://blog.ibeats.top/atom.xml" rel="self"/>
  
  <link href="https://blog.ibeats.top/"/>
  <updated>2025-01-27T14:26:52.000Z</updated>
  <id>https://blog.ibeats.top/</id>
  
  <author>
    <name>CI_Knight</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>分享几个好用的 Chrome AI 插件</title>
    <link href="https://blog.ibeats.top/ai/chrome-ai-extension-recommendations.html"/>
    <id>https://blog.ibeats.top/ai/chrome-ai-extension-recommendations.html</id>
    <published>2025-01-27T14:26:52.000Z</published>
    <updated>2025-01-27T14:26:52.000Z</updated>
    
    <content type="html"><![CDATA[<p>自从使用 Cursor 以来，我更喜欢比较垂直的AI工具，无需注册，操作简单，能够提高效率。Deepseek的出现，也让使用成本大大降低，最近刚换了一些Chrome插件，顺便分享一下。</p><p>虽说工欲善其事必先利其器，我感觉工具的迭代时非常快的，我有近十年的vim使用经验，这期间 vim 插件也经历了多次迭代。正如我们现在不会用汇编写程序一样，好的工具能大大提高效率，何乐而不为。</p><p>Chrome也是，去年的翻译工具还在用SalaDict，AI的兴起，现在又可以换新的了。另外，最近在使用Google 的NoteBookLM，感觉还不错，还要再体验一段时间才知道好坏。</p><p>不多说了，进入正题，下面推荐几个好用的插件，适用于Chrome和Edge浏览器。</p><h3 id="FisherAI"><a href="#FisherAI" class="headerlink" title="FisherAI"></a>FisherAI</h3><p>有时候看大篇幅文章很费力，在这个信息快餐，可以让AI先总结一下，先看下有没有价值信息，如果有再去精读，可以大大节省时间提高效率，FisherAI可以直接配置Deepseek的APIKey（也支持OpenAI），无需注册，只有三个简单按钮，支持网站，PDF，B站视频和油管视频等。还可以直接自己提问，进行深入交流。感兴趣可以点击链接了解详情 <a href="https://chromewebstore.google.com/detail/fisherai-your-best-summar/ipfiijaobcenaibdpaacbbpbjefgekbj">https://chromewebstore.google.com/detail/fisherai-your-best-summar/ipfiijaobcenaibdpaacbbpbjefgekbj</a></p><h3 id="沉浸式翻译-网页翻译插件-PDF翻译-免费"><a href="#沉浸式翻译-网页翻译插件-PDF翻译-免费" class="headerlink" title="沉浸式翻译 - 网页翻译插件 | PDF翻译 | 免费"></a>沉浸式翻译 - 网页翻译插件 | PDF翻译 | 免费</h3><p>是的，这个插件的名字就这么长。翻译体验很好，全文翻译，局部翻译，油管视频字幕，可以使用Deepseek，可以使用特殊的Prompt进行翻译。如果注册开通会员可以使用高级功能，比如漫画翻译等。可以访问插件详情页了解更多<a href="https://chromewebstore.google.com/detail/bpoadfkcbjbfhfodiogcnhhhpibjhbnh">https://chromewebstore.google.com/detail/bpoadfkcbjbfhfodiogcnhhhpibjhbnh</a></p><h3 id="Page-Assist-本地-AI-模型的-Web-UI"><a href="#Page-Assist-本地-AI-模型的-Web-UI" class="headerlink" title="Page Assist - 本地 AI 模型的 Web UI"></a>Page Assist - 本地 AI 模型的 Web UI</h3><p>这是个 AI 大语言模型的 Web UI，简单好用。可以连接Ollama，没有花里胡哨的功能，可以管理提示词和知识库，对话共享可以自建服务，多端可以共享聊天历史，非常的隐私。直接访问插件详情页体验<a href="https://chromewebstore.google.com/detail/jfgfiigpkhlkbnfnbobbkinehhfdhndo">https://chromewebstore.google.com/detail/jfgfiigpkhlkbnfnbobbkinehhfdhndo</a></p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>如果你也有好用的插件推荐，欢迎在评论区分享。我也会持续关注和更新优质插件推荐。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;自从使用 Cursor 以来，我更喜欢比较垂直的AI工具，无需注册，操作简单，能够提高效率。Deepseek的出现，也让使用成本大大降低，最近刚换了一些Chrome插件，顺便分享一下。&lt;/p&gt;
&lt;p&gt;虽说工欲善其事必先利其器，我感觉工具的迭代时非常快的，我有近十年的vim使</summary>
      
    
    
    
    <category term="ai" scheme="https://blog.ibeats.top/categories/ai/"/>
    
    
    <category term="AI" scheme="https://blog.ibeats.top/tags/ai/"/>
    
    <category term="chrome" scheme="https://blog.ibeats.top/tags/chrome/"/>
    
    <category term="chrome extension" scheme="https://blog.ibeats.top/tags/chrome-extension/"/>
    
    <category term="deepseek" scheme="https://blog.ibeats.top/tags/deepseek/"/>
    
    <category term="cursor" scheme="https://blog.ibeats.top/tags/cursor/"/>
    
    <category term="NoteBookLM" scheme="https://blog.ibeats.top/tags/notebooklm/"/>
    
  </entry>
  
  <entry>
    <title>程序员不存在了</title>
    <link href="https://blog.ibeats.top/opinions/rise-of-artificial-intelligence.html"/>
    <id>https://blog.ibeats.top/opinions/rise-of-artificial-intelligence.html</id>
    <published>2024-12-18T02:39:54.000Z</published>
    <updated>2024-12-18T02:39:54.000Z</updated>
    
    <content type="html"><![CDATA[<p>差不多一年前，我开始使用Github Copilot，当时我申请到了三个月的体验时间，整体使用感受还不错。Copilot就好像是一个小助手，能够帮你补全代码，极大的提升了 开发效率，使用时，我只需要专注于代码的逻辑，而不必过多的考虑实现。甚至有时我只需要写下注释，让Copilot根据提示生成代码。不过体验中也存在不少问题，比如变量名用错，逻辑不符合预期等等，所以后来我并没有继续使用。感觉人工智能或许是比以前高级不少，但也没有颠覆世界的可能。</p><p>又一年的时间过去，这期间GPT也迭代了好几代，给我的印象是他更加聪明了。早期就体验过Cursor，给我的感觉可能就是少打开浏览器，直接集成了聊天窗口在IDE，那时Copilot也有在Vscode Insiders版本做同样的功能。现在再去看，Cursor已经大火，Copilot都免费了，重新用了Cursor几个月之后，我感觉程序员未来不久可能不存在了。有些从未学过开发的人已经使用Cursor编程了，就好像只要你有想法，会和Cursor沟通，你就可以写出自己的程序了，而Cursor这个程序员，只需要20美元一个月。</p><p>一开始总以为AI对文科生打击很大，现在看来对理工科也是一样的，2024年的生物化学诺贝尔奖都颁发给了AI。AI学的太快了，发展太快了，GPT o1拥有更强的推理。可以说是对人类的全方位打击了。当然他也不是无所不能得，AI的优势时推理，还有超强的学习能力，就目前来讲AI还是不能自主的创造，这不能否定未来的AI是做不到的。所以对于目前来讲，像很多文化，艺术，音乐创作的AI还不能很好的替代，也许目前对理工科的打击会大于文科类的学科。</p><p>AI会给我们带来巨大的改变，未来AI会给我们带来再一次的工业革命，大大提高生产力。既然是生产力工具我们应该学会使用工具，学会和AI更高效的沟通就变得很重要了。未来肯定是AI的天下，各行各业都在探索，如果说想在这方面去发展，转到一笔钱，更好的方式是探索AI怎么应用到我们的各行各业中。如果说要去搞大模型，首先要看看自己有多少钱，训练大模型，现在动辄好几百万美金。</p><p>我自己的写作能力并不好，下面我直接让AI帮我重写了文章</p><hr><p>《AI 浪潮下的思考》</p><p>差不多一年前，我初次体验了 Github Copilot。作为一个代码辅助工具，它确实带来了不少便利 - 只需专注于代码逻辑，具体实现可以交给它来完成，有时甚至只要写下注释就能生成相应代码。但当时的体验也不尽如人意，经常出现变量命名错误或逻辑偏差等问题。那时我想:”AI 虽然进步了，但离颠覆性突破还很远。”</p><p>然而短短一年间，AI 的发展令人惊叹。以编程领域为例，Cursor 的崛起就很能说明问题。它不再仅仅是个集成了聊天功能的 IDE，而是成为了一个强大的编程助手。即便是编程零基础的人，只要能够清晰地表达需求，就可以在 Cursor 的帮助下实现自己的想法。每月 20 美元，就能获得一个”AI 程序员”的服务。</p><p>AI 的影响远不止于此。它正在重塑各个领域，从文科到理工科都不能幸免。2024 年诺贝尔生物化学奖授予 AI 研究就是最好的证明。伴随着 GPT 系列的持续迭代，AI 展现出越来越强大的推理能力。不过，当前的 AI 仍有其局限性 - 尽管在推理和学习方面表现出色，但在自主创造力方面还有待提高。这也解释了为什么在文化、艺术、音乐创作等领域，AI 还不能完全取代人类。</p><p>站在新一轮工业革命的风口，我们需要积极应对这场变革。与其担忧被取代，不如专注于如何更好地利用这个工具。学会与 AI 高效协作将成为未来的必备技能。对个人而言，真正的机会在于探索如何将 AI 应用到各个行业中去。至于开发大模型，除非有充足的资金支持（动辄数百万美元的训练成本），否则不应该盲目追求。</p><p>在这场席卷全球的AI革命中，我们既是见证者，也是参与者。面对AI带来的机遇与挑战，恐惧和抵触并不能解决问题。真正明智的做法是，顺势而为，深入理解AI的特性，学会与之共舞。在这个AI加速发展的时代，或许最重要的不是担心被取代，而是思考如何借助AI的力量，创造出更大的价值。毕竟，AI终究是工具，而决定这个工具如何使用的，始终是我们人类自己。未来已来，让我们以开放的心态拥抱这场变革，在AI与人类智慧的协作中，开创一个更美好的明天。</p><hr><p>他妈的，感觉自己是个废物😢</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;差不多一年前，我开始使用Github Copilot，当时我申请到了三个月的体验时间，整体使用感受还不错。Copilot就好像是一个小助手，能够帮你补全代码，极大的提升了 开发效率，使用时，我只需要专注于代码的逻辑，而不必过多的考虑实现。甚至有时我只需要写下注释，让Copi</summary>
      
    
    
    
    <category term="opinions" scheme="https://blog.ibeats.top/categories/opinions/"/>
    
    
  </entry>
  
  <entry>
    <title>优化WSL2</title>
    <link href="https://blog.ibeats.top/tutorials/optimization-wsl.html"/>
    <id>https://blog.ibeats.top/tutorials/optimization-wsl.html</id>
    <published>2024-11-30T14:24:57.000Z</published>
    <updated>2024-11-30T14:24:57.000Z</updated>
    
    <content type="html"><![CDATA[<p>WSL2是基于 Hyper-V 的虚拟化技术，因此，WSL2 的性能比 WSL1 更高。但是，WSL2 的性能仍然比宿主机性能要差。你以为你在运行Linux，其实你是在运行 Windows Defender。习惯使用Linux的用户，使用WSL2 还是很方便，如果安装了docker，那么docker 也可以运行在WSL2 上，可以说是打通生态链了。也可以用到宿主机的显卡和MPS，还可以在WSL2上运行GUI 应用。所有优化WSL还是很必要的。</p><h3 id="使用固定大小的虚拟磁盘"><a href="#使用固定大小的虚拟磁盘" class="headerlink" title="使用固定大小的虚拟磁盘"></a>使用固定大小的虚拟磁盘</h3><p>WSL2 默认使用动态扩展的虚拟磁盘，这会导致磁盘空间不足的问题。你可以使用固定大小的虚拟磁盘来避免这个问题。(这个我一直导入没成功，有成功的朋友分享下经验)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">wsl --export Ubuntu-24.04 G:\wsl.tar</span><br><span class="line"></span><br><span class="line">wsl --unregister Ubuntu-24.04</span><br><span class="line"></span><br><span class="line"># 使用 PowerShell 创建一个新的 VHD 文件。假设创建一个 20GB 的 VHD 文件</span><br><span class="line">New-VHD -Path G:\wsl\ubuntu_fixed.vhdx -SizeBytes 20GB -Fixed</span><br><span class="line"></span><br><span class="line">Mount-VHD -Path G:\wsl\ubuntu_fixed.vhdx</span><br><span class="line"></span><br><span class="line"># 初始化磁盘，这两个可以用软件手动做，失败我感觉是分区的问题，我是用软件格式化ext4的分区了</span><br><span class="line">Initialize-Disk -Number (Get-Disk | Where-Object IsOffline -Eq $true | Select-Object -First 1).Number</span><br><span class="line">New-Partition -DiskNumber (Get-Disk | Where-Object IsOffline -Eq $true | Select-Object -First 1).Number -UseMaximumSize -AssignDriveLetter | Format-Volume -FileSystem NTFS -NewFileSystemLabel &quot;WSL&quot;</span><br><span class="line"></span><br><span class="line">DisMount-VHD -Path G:\wsl\ubuntu_fixed.vhdx</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">wsl --import Ubuntu-24.04 G:\wsl\ubuntu_fixed.vhdx G:\wsl.tar  --version 2</span><br><span class="line"></span><br><span class="line">wsl -d Ubuntu-24.04</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="调整配置虚拟内存和CPU"><a href="#调整配置虚拟内存和CPU" class="headerlink" title="调整配置虚拟内存和CPU"></a>调整配置虚拟内存和CPU</h3><p>创建一个配置文件 <code>C:\Users\&lt;username&gt;\.wslconfig</code>，并添加以下内容：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[wsl2]</span><br><span class="line">memory=16GB</span><br><span class="line">processors=12</span><br></pre></td></tr></table></figure><p>重启WSL2。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wsl --shutdown</span><br><span class="line">wsl</span><br></pre></td></tr></table></figure><h3 id="添加排除项到-Windows-安全中心"><a href="#添加排除项到-Windows-安全中心" class="headerlink" title="添加排除项到 Windows 安全中心"></a>添加排除项到 Windows 安全中心</h3><p>为了进一步优化性能，可以将新的 VHD 文件添加到 Windows 安全中心的排除项中：</p><ul><li>打开“Windows 安全中心”。</li><li>进入“病毒和威胁防护”设置。</li><li>点击“管理设置”。</li><li>在“排除项”下，点击“添加或删除排除项”。</li><li>添加新的 VHD 文件路径（例如 G:\wsl\ubuntu_fixed.vhdx）。</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;WSL2是基于 Hyper-V 的虚拟化技术，因此，WSL2 的性能比 WSL1 更高。但是，WSL2 的性能仍然比宿主机性能要差。你以为你在运行Linux，其实你是在运行 Windows Defender。习惯使用Linux的用户，使用WSL2 还是很方便，如果安装了do</summary>
      
    
    
    
    <category term="tutorials" scheme="https://blog.ibeats.top/categories/tutorials/"/>
    
    
  </entry>
  
  <entry>
    <title>gdrv3.sys 蓝屏</title>
    <link href="https://blog.ibeats.top/issues/gdrv3-blue-screen-of-death.html"/>
    <id>https://blog.ibeats.top/issues/gdrv3-blue-screen-of-death.html</id>
    <published>2024-03-25T15:59:48.000Z</published>
    <updated>2024-03-25T15:59:48.000Z</updated>
    
    <content type="html"><![CDATA[<p>前几天给电脑装了个蓝牙WiFi模块，还是PCIE的，装完又过了几天就开始蓝屏了，还以为是装了这个蓝牙模块的问题，后来仔细看了下蓝屏的信息，不太像是蓝牙引起的。这个蓝屏并不是稳定复现的，是每次开机显示锁定屏幕后不一定哪一次就会蓝屏。我以为大概率升级了系统，或者显卡驱动的问题。我就把显卡驱动和系统都回滚了下，发现还是有问题。</p><img src="/images/2024/gdrv3-blue-screen.jpg" width="40%" height="40%"><p>后来我就根据这个蓝屏显示的 gdrv3.sys 文件查了下是做什么用的。其实这里我就犯了个错误，我应该直接差蓝屏给出的错误信息，方便定位问题，而我就根据自己想的就随意折腾了下。</p><p>查下来这个是跟技嘉主板有关系，我的主板是Z270，买的也比较早了，大概有七年了。按道理装的windows肯定不会有技嘉主板的驱动的，或者windows更新的时候自动安装的某些驱动。我就找到这个文件，在<code>C:\windows\windows32\drivers</code>目录下面，并且在安全模式下把这个文件改了名字，但是依旧蓝屏，这时候就没有任何思路了。</p><p>就这样过了一天，恍惚间想到我装过技嘉的APP Center，也许是这个软件的问题，很早之前有折腾过超频什么的，装了这个软件，随着时间的推移，已经忘记这个软件的存在了，老的产品技嘉支持的不怎么好了，就没再用过它。但是它还是会定期自动更新一下，可能就是因为它的更新出现了什么问题。</p><p>我果断卸载了这个软件，这才恢复正常了，不再蓝屏了。这时候要批评下技嘉了，可能真的是改动了某些代码，对老的产品兼容不好了，这是不是就在催我们换新呢。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;前几天给电脑装了个蓝牙WiFi模块，还是PCIE的，装完又过了几天就开始蓝屏了，还以为是装了这个蓝牙模块的问题，后来仔细看了下蓝屏的信息，不太像是蓝牙引起的。这个蓝屏并不是稳定复现的，是每次开机显示锁定屏幕后不一定哪一次就会蓝屏。我以为大概率升级了系统，或者显卡驱动的问题。</summary>
      
    
    
    
    <category term="issues" scheme="https://blog.ibeats.top/categories/issues/"/>
    
    
    <category term="windows" scheme="https://blog.ibeats.top/tags/windows/"/>
    
    <category term="gigabyte" scheme="https://blog.ibeats.top/tags/gigabyte/"/>
    
  </entry>
  
  <entry>
    <title>1Password 弃用Classic extension</title>
    <link href="https://blog.ibeats.top/tutorials/1password-deprecated-classic-extenstion.html"/>
    <id>https://blog.ibeats.top/tutorials/1password-deprecated-classic-extenstion.html</id>
    <published>2023-07-14T07:41:10.000Z</published>
    <updated>2023-07-14T07:41:10.000Z</updated>
    
    <content type="html"><![CDATA[<p>在Mac的App Store提示更新1Password的时候，我看到</p><blockquote><p>Deprecation warning about the classic extension.</p></blockquote><p>我还没想到classic extension是什么，就点下了更新，后来才想到应该是浏览器的依赖桌面端的插件。</p><h3 id="最好用的密码管理器"><a href="#最好用的密码管理器" class="headerlink" title="最好用的密码管理器"></a>最好用的密码管理器</h3><p>1Password真的非常好用，如果不想付费其实还可以一直白嫖，我用上的时候是1Password7，已经是订阅制了，如果不付费可以在移动端添加更新条目，然后在桌面端使用。为了更好的体验还是建议订阅，和别人组车队，加上折扣一年也就五十人民币左右，非常的便宜。</p><p>1Password7支持云存储，还有第三方云存储，比如Dropbox，或者本地存储。但是升级到1Password8之后只剩下云存储了，那我感觉和LastPass来比较就没有什么差别了。</p><h3 id="推荐使用方式"><a href="#推荐使用方式" class="headerlink" title="推荐使用方式"></a>推荐使用方式</h3><p>LastPass使用的云存储，有多次数据泄露的事件，我依然认为还是本地加云存储的方式会更好一些，需要自己管理好自己的Vault文件。可以放到本地，用云盘来同步，或者直接用Dropbox。如果需要浏览器插件的支持是需要安装Classic版本的，也就是Desktop required的版本。最新更新的1Password7.9.10是不在支持了，所以要使用旧版本，可以直接下载1Password7.9.9的版本。浏览器插件也需要手动下载安装一下。</p><h3 id="软件下载"><a href="#软件下载" class="headerlink" title="软件下载"></a>软件下载</h3><p>官方有下载地址，下载后最后留存一份备份，以免官方不再维护。直接在 <a href="https://app-updates.agilebits.com/product/_history/OPM7">https://app-updates.agilebits.com/product\_history/OPM7</a> 这个网址下载7.9.9的版本。插件在 <a href="https://app-updates.agilebits.com/product_history/OPX4">https://app-updates.agilebits.com/product_history/OPX4</a> 这里下载。其他版本直接在  <a href="https://app-updates.agilebits.com/">https://app-updates.agilebits.com/</a> 这个页面寻找。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;在Mac的App Store提示更新1Password的时候，我看到&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Deprecation warning about the classic extension.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我还没想到classic</summary>
      
    
    
    
    <category term="tutorials" scheme="https://blog.ibeats.top/categories/tutorials/"/>
    
    
  </entry>
  
  <entry>
    <title>AutoGPT</title>
    <link href="https://blog.ibeats.top/technologies/autogpt.html"/>
    <id>https://blog.ibeats.top/technologies/autogpt.html</id>
    <published>2023-04-22T15:13:06.000Z</published>
    <updated>2023-04-22T15:13:06.000Z</updated>
    
    <content type="html"><![CDATA[<p>其实我并不是想写个关于AutoGPT的教程出来，我也不喜欢写教程，大多都可以谷歌搜索出来，或者看官方文档，或者去Github Issue上搜索，再或者去问问ChatGPT，现在更多的是可以在视频网站上搜索，比如Youtube，跟着视频手把手学习。除非我是真的是遇到棘手的问题，没有搜索到解决方案的会写一下，其他情况一些简单的东西我是写到本地的Wiki里，我自己用的是<a href="/tutorials/tiddlywiki5-recommended">TiddlyWiki5</a>来管理的。</p><p>搜索算是互联网时代必备的技能了，文字，音频，视频本质上是媒介的转变，并不是技术上的革新。ChatGPT应该就是革新，它已经改变了搜索这种形式，就好比马车和内燃机的区别，提升了效率。</p><h3 id="ChatGPT"><a href="#ChatGPT" class="headerlink" title="ChatGPT"></a>ChatGPT</h3><p>ChatGPT已经火了很久了，微软开始把它慢慢融合到各个服务里，来改变我们之前的使用方式。我们需要知道一个问题的答案，在没有互联网的时候，可能要通过各种方式去寻找答案，归纳总结比如神农尝百草，查阅文献，做实验，还有更懂得人（交流）。有了互联网就提高了找到问题答案的效率。GPT又把效率提高了一大截。</p><p>简单的问题，可能通过Google就能搜索到答案，但是比较复杂的问题，互联网上没有的，那我们可能要分好几步去搜索了。ChatGPT基本上可以一次得到比较不错的答案，就好比我们去问了一个行业的专家，他已经学了很多知识了，我们可以直接得到结果一样，不过专家也有犯错的时候。</p><p>微软已经在很多领域融入进了人工智能，在最早的Github Copilot，到New bing，体验上也在不断变好，人工智能很早就有，微软给了我们另一种可能。在这之后各个公司也开始学着一起做了，毕竟蛋糕还是要早点分一块才好。</p><h3 id="面对革新"><a href="#面对革新" class="headerlink" title="面对革新"></a>面对革新</h3><p>比较敏感的人，已经在用ChatGPT做很多事情了，新的事物出现总有一批人能抓住先机，能做出更多有创造性挑战性的事情。AutoGPT就是，能够更好的利用AI，将一件事情拆分出小的任务，再依次解决。ChatGPT也会不停地更新自己，能够处理更多地文字，效率也会越来越高，效率的提升肯定会让一部分人失业。现在AI也只是通过文字，图像来交互，随着发展，可能会到制造，科研等，再以各种形式接入到我们的生活。在我看来，这已经是一种革命了。资本也会持续的加码AI，促进它的快速发展，在未来的某一天也许我们会被他取代掉。</p><h3 id="危险性"><a href="#危险性" class="headerlink" title="危险性"></a>危险性</h3><p>新的事物总会带来一些新的问题，隐私问题，安全问题等等。ChatGPT 刚出一段时间就有出逃问题，如果出逃之后入侵一些军事设施，问题还是很严重的。还有一些公司使用会不会泄露重要信息，我自己会使用Github Copilot，这就没有办法避免让它来扫描我的代码，也就会有一定的风险。就和互联网出来之后一样，也带来了很多的问题，这些问题也需要一点点来解决。</p><p>总而言之，在目前像GPT这样的大语言模型，确实是未来一段时间的风口，在资本的加码下，可能会发展的越来越好，我们能做的也只是要学习它驾驭它，未来才不会被淘汰掉。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;其实我并不是想写个关于AutoGPT的教程出来，我也不喜欢写教程，大多都可以谷歌搜索出来，或者看官方文档，或者去Github Issue上搜索，再或者去问问ChatGPT，现在更多的是可以在视频网站上搜索，比如Youtube，跟着视频手把手学习。除非我是真的是遇到棘手的问题</summary>
      
    
    
    
    <category term="technologies" scheme="https://blog.ibeats.top/categories/technologies/"/>
    
    
    <category term="AI" scheme="https://blog.ibeats.top/tags/ai/"/>
    
    <category term="ChatGPT" scheme="https://blog.ibeats.top/tags/chatgpt/"/>
    
  </entry>
  
  <entry>
    <title>小米智能家居是如何赚你钱的</title>
    <link href="https://blog.ibeats.top/essays/xiaomi-smart-home.html"/>
    <id>https://blog.ibeats.top/essays/xiaomi-smart-home.html</id>
    <published>2022-09-28T13:04:21.000Z</published>
    <updated>2022-09-28T13:04:21.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="我用的智能家居"><a href="#我用的智能家居" class="headerlink" title="我用的智能家居"></a>我用的智能家居</h2><p>我有用过小米的手机，总体体验来说一般，但是智能家居，小米还是挺能打的。上手简单，软硬件齐备，价格嘛，真的很便宜。这东西真的能挣钱？相比一些高端品牌（不考虑国外品牌）那么便宜能赚几个钱？</p><p>我们家刚装修完，用了全套的小米智能家居。价格吧，比起非智能确实贵了些，比如插座好一些的十块一个，小米卖到六十，加一些传感器要卖这么多？那可能没有，贵应该是贵在整个生态上，毕竟开发设计都是要钱的。那比起高端一些的又便宜很多，我猜硬件肯定不会高出那么多成本的。我在Aqara（绿米）的线下体验店看过，有一百多的开关，有三百多的开关，差在哪？在设计上，材质上，贵的摸上去看上去都高端，你买个房子几百万几千万，那不得好好设计一下。只有我们这种不在乎设计的会选择更加亲民的小米，那丑是真的丑。当时挑选的时候，想挑一些生态比较好的，东西多，玩法多，肯定是小米必选。好看一些的，如影，一个中控面板卖你2000＋甚至更高，太贵，超出了预算。只能考虑红米的智能音响了，三百左右，还有小爱智能屏幕，难用是真的难用，还有状态同步慢等等问题，MIUI Home还在发展中，体验上还是不如中控好，毕竟一分钱一分货。</p><h2 id="其他的平台"><a href="#其他的平台" class="headerlink" title="其他的平台"></a>其他的平台</h2><p>除了米家还有苹果的HomeKit，也是很好的选择，也包括小米的一些智能设备可以接入HomeKit，选择的时候可以注意。小米生态链的Aqara，Yeelight也都做了自己的智能家居平台，还有不容小觑的美的美居，现在美的的设备都带着智能，玩法虽然都是借鉴的，智能家居还是需要用心搞搞的。还有就是涂鸦，我老家用的涂鸦，感觉线下用的会多，他们貌似自己不做产品，制作生态，没有统一定价，线下就更好赚钱了。</p><h2 id="米家到底怎么赚钱的？"><a href="#米家到底怎么赚钱的？" class="headerlink" title="米家到底怎么赚钱的？"></a>米家到底怎么赚钱的？</h2><p>说了那么多，米家到底怎么赚的钱呢，我感觉这一切都要从网关说起</p><h3 id="网关"><a href="#网关" class="headerlink" title="网关"></a>网关</h3><p>网关到底是什么？可以把他理解成一个路由器，让智能设备连接的路由器。一般来说智能家居都是用的Zigbee和蓝牙，蓝牙Mesh(BLE 5.0)，这些协议我就不展开讲了。如果用WiFi的话，可以直接连接路由器，如果其他的就需要专门的网关了。</p><h4 id="网关也有种类"><a href="#网关也有种类" class="headerlink" title="网关也有种类"></a>网关也有种类</h4><p>小米网关种类非常多，光买网关就可以赚你的钱了。网关可以分为以下三个种类。</p><ul><li>中枢网关</li><li>从网关</li><li>盲网关</li></ul><p>从协议分也有三种</p><ul><li>多模网关</li><li>蓝牙网关</li><li>集成网关(也就是智能设备自带的)</li></ul><p>可以看下我们家里的网关</p><img src="/images/2022/mihome-gateway.jpeg" width="40%" height="40%"><p>盲网关是需要连接WiFi的，所有场景和自动化执行必须从互联网走一圈，而且不受中枢网关的控制，只要一断网家里的智能基本上就趴窝了。像吸顶灯，小爱音响或者一些摄像头都会带一个网关，基本上都是盲网关，无法变成从网关。从网关在没有中枢网关的时候也是盲网关，小米多模网关就可以变成从网关，接受中枢网关的调度，多模是支持通信协议（包括蓝牙、蓝牙Mesh、Zigbee)，也是需要从互联网走一圈的。如果想要断网依旧可以设备互联，这时候就要有一个中枢网关了，当中枢网关搭建起来，可以将云端执行的场景转换到本地执行，并且多模网关会变成从网关。为了有更好的体验，最好把其他盲网关关掉。</p><p>这些网关就很赚钱了，我最初买了多模网关，不能本地执行，有时候会很慢（多模网关是WiFi连接），就买了中枢网关，买完后多模网关就上新款了，变成了有线连接。</p><h4 id="设备联动"><a href="#设备联动" class="headerlink" title="设备联动"></a>设备联动</h4><p>当你买了网关，就可以接入更多的设备，设备之间也可以联动，为了有更多的玩法你就会买更多的智能设备。场景米家会给你推荐一些，但是更多的玩法也是根据自家环境来探索的。智能家居体验上还是挺好的，米家也大大减少了入门门槛，只需要简单学习一下就可以。</p><h3 id="一些很贵的设备"><a href="#一些很贵的设备" class="headerlink" title="一些很贵的设备"></a>一些很贵的设备</h3><p>当然家里的电器也可以换成支持米家的，总体体验会好很多，油烟机洗碗机、冰箱洗衣机，小米也开始渗透到生活家电的各个方面，价格优惠，产品质量也说得过去。</p><p>除了电器，智能窗帘的价格也不便宜，电机加轨道基本上也快要上千了。还有中央空调控制器，绿米的那个大概在2500元左右（太贵了到现在还没有装）。</p><p>钱是被赚走了，体验变好了，双赢。</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;p&gt;我有用过小米的手机，总体体验来说一般，但是智能家居，小米还是挺能打的。上手简单，软硬件齐备，价格嘛，</summary>
      
    
    
    
    <category term="essays" scheme="https://blog.ibeats.top/categories/essays/"/>
    
    
  </entry>
  
  <entry>
    <title>TiddlyWiki5</title>
    <link href="https://blog.ibeats.top/tutorials/tiddlywiki5-recommended.html"/>
    <id>https://blog.ibeats.top/tutorials/tiddlywiki5-recommended.html</id>
    <published>2022-03-26T08:17:25.000Z</published>
    <updated>2022-03-26T08:17:25.000Z</updated>
    
    <content type="html"><![CDATA[<p>现在有很多笔记和知识管理软件，比如Notion、语雀、幕布，还有老牌服务Confluence等。这些各有优势，但是基本上都不支持私有云部署，支持私有云的也是价格昂贵。我个人还是倾向于使用私有云，笔记这种东西，迁移数据还是挺麻烦的。</p><p>我自己就用的开源Wiki软件<a href="https://github.com/Jermolene/TiddlyWiki5">TiddlyWiki5</a>，部署在家里的NAS里面。</p><h2 id="TiddlyWiki5"><a href="#TiddlyWiki5" class="headerlink" title="TiddlyWiki5"></a>TiddlyWiki5</h2><p>使用简单，功能丰富，支持插件。</p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>直接使用npm安装，使用起来就几个简单命令。</p><p>初始化</p><blockquote><p>tiddlywiki mywiki –init server</p></blockquote><p>运行</p><blockquote><p>tiddlywiki mywiki –liste</p></blockquote><h3 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h3><p>官方已经自带了很多插件了，具体可以看<a href="https://github.com/Jermolene/TiddlyWiki5/tree/master/plugins/tiddlywiki">https://github.com/Jermolene/TiddlyWiki5/tree/master/plugins/tiddlywiki</a>。修改配置文件<code>tiddlywiki.info</code>，将需要的插件写入配置文件，运行服务就可以了。</p><h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><p>使用起来非常简单，目录结构基本上都是通过tag实现，当然也可以看官方给的样例来学习如何使用。</p><p>官方样例看：<a href="https://tiddlywiki.com/">https://tiddlywiki.com/</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;现在有很多笔记和知识管理软件，比如Notion、语雀、幕布，还有老牌服务Confluence等。这些各有优势，但是基本上都不支持私有云部署，支持私有云的也是价格昂贵。我个人还是倾向于使用私有云，笔记这种东西，迁移数据还是挺麻烦的。&lt;/p&gt;
&lt;p&gt;我自己就用的开源Wiki软件</summary>
      
    
    
    
    <category term="tutorials" scheme="https://blog.ibeats.top/categories/tutorials/"/>
    
    
    <category term="wiki" scheme="https://blog.ibeats.top/tags/wiki/"/>
    
  </entry>
  
  <entry>
    <title>Apple MacBook M1安装Python3.7</title>
    <link href="https://blog.ibeats.top/tutorials/apple-m1-install-python37.html"/>
    <id>https://blog.ibeats.top/tutorials/apple-m1-install-python37.html</id>
    <published>2021-11-01T07:33:40.000Z</published>
    <updated>2021-11-01T07:33:40.000Z</updated>
    
    <content type="html"><![CDATA[<p>由于我们线上环境依然使用的Python 3.7，换了M1的电脑后，Python 3.7无法使用。大多软件基本上没有遇到兼容问题，唯独遇到Python 3.7有问题。大概就是3.7版本还没有兼容M1，在升级到3.8后也遇到了其他的问题。为了开发稳定还是要使用3.7版本开发。当然办法有很多，在我现在看来，成本最低就是解决3.7版本的运行问题。查阅尝试了很多方法，最靠谱的就是使用brew安装x86的Python 3.7，然后再做软连接到pyenv，如果不用pyenv，也可以做软连接到自己的喜欢的地方。</p><p>brew在M1和x86有不同的家目录，详细可以看brew介绍，接下来看如何操作。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Install x86 brew</span></span><br><span class="line">arch -x86_64 /bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)&quot;</span><br><span class="line">alias ibrew=/usr/local/bin/brew</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Install Python 3.7</span></span><br><span class="line">ibrew install python@3.7</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Add `python` executable (symlink to `python3`)</span></span><br><span class="line">ln -s python3 &quot;$(ibrew --prefix python@3.7)&quot;/bin/python</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Symlink x86 Python 3.7 into pyenv</span></span><br><span class="line">ln -s &quot;$(ibrew --prefix python@3.7)&quot; .pyenv/versions/3.7.12</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Check</span></span><br><span class="line">pyenv local 3.7.12</span><br><span class="line">python -V</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Python 3.7.12</span></span><br><span class="line">python -c &#x27;import _ctypes&#x27;. # works!</span><br></pre></td></tr></table></figure><p>想要尝试其他方法，可以看我引用的链接。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://github.com/pyenv/pyenv/issues/1768#issuecomment-871602950">https://github.com/pyenv/pyenv/issues/1768#issuecomment-871602950</a></li><li><a href="https://stackoverflow.com/questions/65349982/issues-installing-python-3-x-via-pyenv">https://stackoverflow.com/questions/65349982/issues-installing-python-3-x-via-pyenv</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;由于我们线上环境依然使用的Python 3.7，换了M1的电脑后，Python 3.7无法使用。大多软件基本上没有遇到兼容问题，唯独遇到Python 3.7有问题。大概就是3.7版本还没有兼容M1，在升级到3.8后也遇到了其他的问题。为了开发稳定还是要使用3.7版本开发。当</summary>
      
    
    
    
    <category term="tutorials" scheme="https://blog.ibeats.top/categories/tutorials/"/>
    
    
    <category term="python" scheme="https://blog.ibeats.top/tags/python/"/>
    
    <category term="MacBook" scheme="https://blog.ibeats.top/tags/macbook/"/>
    
    <category term="M0" scheme="https://blog.ibeats.top/tags/m0/"/>
    
  </entry>
  
  <entry>
    <title>Hexo文字排版问题</title>
    <link href="https://blog.ibeats.top/issues/hexo-text-align.html"/>
    <id>https://blog.ibeats.top/issues/hexo-text-align.html</id>
    <published>2021-10-08T07:33:40.000Z</published>
    <updated>2021-10-08T07:33:40.000Z</updated>
    
    <content type="html"><![CDATA[<p>博客总是有一些奇怪的排版，尤其是中引文混用的时候，就像下面这样。</p><p><img src="/images/hexo-text-align-1.png"></p><p>一般文字排版都是CSS的text-align属性控制的，当调整text-align属性时，文字会相应的使用不同的对齐方式。但上面这种是因为英文单词截断方式导致的，纯汉字或者纯英文一行不会发生这样的问题，而且换行位置正好是有连接符的，这就让我猜想应该是英文字符截断有关。直接通过chrome调试，更改连接符位置，果然会重新换到连接符的位置换行。那这时候就应该调整word-break了。</p><p>但纯的调整text-align不能达到美化的效果，会导致每行行数不一。所以调整word-break到break-all就可以了，具体的也可以根据不同浏览器适配来调整。</p><p>因为网站大多是自适应排版，除非固定post-body的宽度，才能做到比较好看的排版。也或者hexo有自动截断英文单词并且添加连接符的插件，这种插件当然我没有找到，如果有人知道可以告诉我。现在的排版已经好很多了，不会再出现非常难看的超宽字距了，况且也不能和专业排版软件比。</p><h3 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h3><ul><li><a href="https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/">https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;博客总是有一些奇怪的排版，尤其是中引文混用的时候，就像下面这样。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/hexo-text-align-1.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;一般文字排版都是CSS的text-align属性控制的，当调整text-align属性时，文字会</summary>
      
    
    
    
    <category term="issues" scheme="https://blog.ibeats.top/categories/issues/"/>
    
    
    <category term="hexo" scheme="https://blog.ibeats.top/tags/hexo/"/>
    
  </entry>
  
  <entry>
    <title>如何快速搭建一个代理服务器</title>
    <link href="https://blog.ibeats.top/gfw/deploy-trojan-server.html"/>
    <id>https://blog.ibeats.top/gfw/deploy-trojan-server.html</id>
    <published>2021-09-29T08:29:35.000Z</published>
    <updated>2021-09-29T08:29:35.000Z</updated>
    
    <content type="html"><![CDATA[<p>还有一天就国庆了，现在满脑子都在想给祖国庆生。不过这样重大的节日，翻墙总是会出些问题，为了应对这样的问题，应该提前多建几个代理服务器，那我就选了一台 vultr 服务器做备用机，之前都是 vmess 协议，这次打算尝试下 trojan 的安全性。如果你在搬瓦工、digital ocean、vultr等这种云服务商搭建的 vpn，在重大节日时，大概率都会被封端口或者是 IP，而且 vmess 现在应该是可以被准确识别了，我的 vmess 代理每次都可以精准被封端口。</p><p>vultr 的美国线路要比 digital ocean 更好，而且有日本可选，新加坡基本抢不到，如果选美国最好使用美西服务器，如果电脑系统是 MacOS，可以安装 BestTrace 软件看下线路，vultr 提供了测试的 IP 地址，在他们官网可以找到。</p><p>如果是 vultr 的新用户可以网上搜下优惠码，这样你可以获得 100 美金的试用金，一个月内有效。vultr 可以使用支付宝和加密货币支付，这点还是挺厉害的。</p><h2 id="搭建-trojan-服务器"><a href="#搭建-trojan-服务器" class="headerlink" title="搭建 trojan 服务器"></a>搭建 trojan 服务器</h2><p>我选的系统是 Debian 11，接下来可以直接跟着步骤操作。vultr 需要在后台设置下安全组，放开 80 和 443 就可以了。使用 trojan 需要一个域名，并且使用ssl加密。如果想了解更多，可以看p4gefau1t trojan的文档。</p><h3 id="关闭防火墙"><a href="#关闭防火墙" class="headerlink" title="关闭防火墙"></a>关闭防火墙</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">systemctl disable ufw.service</span><br><span class="line">systemctl stop ufw.service</span><br></pre></td></tr></table></figure><h3 id="安装-Nginx"><a href="#安装-Nginx" class="headerlink" title="安装 Nginx"></a>安装 Nginx</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">apt install tmux unzip nginx</span><br><span class="line">systemctl enable nginx</span><br><span class="line">systemctl start nginx</span><br></pre></td></tr></table></figure><h3 id="下载-trojan"><a href="#下载-trojan" class="headerlink" title="下载 trojan"></a>下载 trojan</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">mkdir trojan</span><br><span class="line">cd trojan</span><br><span class="line">wget https://github.com/p4gefau1t/trojan-go/releases/download/v0.10.6/trojan-go-linux-amd64.zip</span><br><span class="line">unzip -o trojan-go-linux-amd64.zip</span><br><span class="line">rm trojan-go-linux-amd64.zip</span><br><span class="line">cat &gt; config.json &lt;&lt;EOF</span><br><span class="line">&#123;</span><br><span class="line">  &quot;run_type&quot;: &quot;server&quot;,</span><br><span class="line">  &quot;local_addr&quot;: &quot;0.0.0.0&quot;,</span><br><span class="line">  &quot;local_port&quot;: 443,</span><br><span class="line">  &quot;remote_addr&quot;: &quot;127.0.0.1&quot;,</span><br><span class="line">  &quot;remote_port&quot;: 80,</span><br><span class="line">  &quot;password&quot;: [&quot;your password&quot;],</span><br><span class="line">  &quot;ssl&quot;: &#123;</span><br><span class="line">    &quot;cert&quot;: &quot;/etc/letsencrypt/live/example.com/fullchain.pem&quot;,</span><br><span class="line">    &quot;key&quot;: &quot;/etc/letsencrypt/live/example.com/privkey.pem&quot;,</span><br><span class="line">    &quot;sni&quot;: &quot;example.com&quot;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><p>配置文件要把域名和密码修改成自己的。</p><h3 id="申请证书"><a href="#申请证书" class="headerlink" title="申请证书"></a>申请证书</h3><p>我们使用 certbot 申请证书，也可以使用自己购买的证书。(或者使用acme.sh)</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">apt install snapd</span><br><span class="line">snap install core</span><br><span class="line">snap refresh core</span><br><span class="line">snap install --classic certbot</span><br><span class="line">certbot certonly --nginx</span><br></pre></td></tr></table></figure><h3 id="运行-trojan"><a href="#运行-trojan" class="headerlink" title="运行 trojan"></a>运行 trojan</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">tmux new -s trojan-server</span><br><span class="line">./trojan-go -config config.json</span><br></pre></td></tr></table></figure><h3 id="证书续订"><a href="#证书续订" class="headerlink" title="证书续订"></a>证书续订</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">certbot renew --dry-run</span><br></pre></td></tr></table></figure><h2 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h2><p>我推荐使用ClashX，是一个小猫咪的图标，有 MacOS、Windows、Android 版本，配置可以根据<a href="https://github.com/Hackl0us/SS-Rule-Snippet/blob/master/LAZY_RULES/clash.yaml">https://github.com/Hackl0us/SS-Rule-Snippet/blob/master/LAZY_RULES&#x2F;clash.yaml</a>自行修改，配置可以托管在服务器上，多端共用一套配置即可。iOS可以使用shadowrocket，兼容Clash的配置，可以直接添加。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://p4gefau1t.github.io/trojan-go/basic/trojan/">https://p4gefau1t.github.io/trojan-go/basic/trojan/</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;还有一天就国庆了，现在满脑子都在想给祖国庆生。不过这样重大的节日，翻墙总是会出些问题，为了应对这样的问题，应该提前多建几个代理服务器，那我就选了一台 vultr 服务器做备用机，之前都是 vmess 协议，这次打算尝试下 trojan 的安全性。如果你在搬瓦工、digita</summary>
      
    
    
    
    <category term="gfw" scheme="https://blog.ibeats.top/categories/gfw/"/>
    
    
    <category term="gfw" scheme="https://blog.ibeats.top/tags/gfw/"/>
    
    <category term="trojan" scheme="https://blog.ibeats.top/tags/trojan/"/>
    
    <category term="vultr" scheme="https://blog.ibeats.top/tags/vultr/"/>
    
  </entry>
  
  <entry>
    <title>记一次使用pycoin遇到的坑</title>
    <link href="https://blog.ibeats.top/issues/python-pycoin-run.html"/>
    <id>https://blog.ibeats.top/issues/python-pycoin-run.html</id>
    <published>2021-09-14T11:51:23.000Z</published>
    <updated>2021-09-14T11:51:23.000Z</updated>
    
    <content type="html"><![CDATA[<p>问题和教程都有时效性，我一般写的都很少，很多依赖于版本或者系统，当遇到问题更建议去 Stack Overflow 或者 Github issue 中搜索，也或者直接使用 Google 搜索，肯定很多人乐于写这些。不过我今天还是水了一篇文章。</p><h2 id="版本和软件环境"><a href="#版本和软件环境" class="headerlink" title="版本和软件环境"></a>版本和软件环境</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">System: MacOS 10.15</span><br><span class="line">Python: 3.7.6</span><br><span class="line">gunicorn: 19.9.0</span><br><span class="line">pycoin: 0.90.20190728</span><br></pre></td></tr></table></figure><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>我在家里电脑启动一个 gunicorn 服务时，出现 worker 无法的情况，但是并没有任何保存，只有 worker 重启日志，因为没有报错，排查起来就比较麻烦了。我使用的 pipenv 启动的，软件依赖问题可能性很小。当我尝试使用 ipython 运行的时候，则会报错 <code>Abort trap</code>。</p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>这时候会发现服务并没有抛错，而我还没办法定位哪里出现的异常，并且吞掉了错误信息。如果使用 pdb 这种工具，定位错误是很费力的。想要快速定位 Abort 位置，可以使用 <code>PYTHONVERBOSE</code> 环境变量。</p><p>将 PYTHONVERBOSE 设置为 3 再启动服务，会打印加载模块时的日志，闪退后最后输入的日志，就是我们要定位的地方。通过这种方式我知道是 pycoin 加载 openssl 动态链接库的时候报错了，因为使用了 pycoin 的 ecdsa 模块，并且还是用了 openssl 加速，找不到动态链接库才闪退的。</p><p>我们可以将 <code>/usr/local/Cellar/openssl</code> 下的动态链接库拷贝到 <code>/usr/local/lib/</code> 下，并且再做软连接。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">brew install openssl</span><br><span class="line">cd /usr/local/Cellar/openssl@1.1/1.1.1i/lib</span><br><span class="line">sudo cp libssl.1.1.dylib libcrypto.1.1.dylib /usr/local/lib/</span><br><span class="line">cd /usr/local/lib</span><br><span class="line">sudo ln -s libssl.1.1.dylib libssl.dylib</span><br><span class="line">sudo ln -s libcrypto.1.1.dylib libcrypto.dylib</span><br></pre></td></tr></table></figure><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://stackoverflow.com/questions/24287239/abort-trap-6-when-running-a-python-script">https://stackoverflow.com/questions/24287239/abort-trap-6-when-running-a-python-script</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;问题和教程都有时效性，我一般写的都很少，很多依赖于版本或者系统，当遇到问题更建议去 Stack Overflow 或者 Github issue 中搜索，也或者直接使用 Google 搜索，肯定很多人乐于写这些。不过我今天还是水了一篇文章。&lt;/p&gt;
&lt;h2 id=&quot;版本和软</summary>
      
    
    
    
    <category term="issues" scheme="https://blog.ibeats.top/categories/issues/"/>
    
    
    <category term="python" scheme="https://blog.ibeats.top/tags/python/"/>
    
    <category term="pycoin" scheme="https://blog.ibeats.top/tags/pycoin/"/>
    
  </entry>
  
  <entry>
    <title>Flow 单公钥地址签名交易</title>
    <link href="https://blog.ibeats.top/blockchain/send-flow.html"/>
    <id>https://blog.ibeats.top/blockchain/send-flow.html</id>
    <published>2021-07-05T14:53:56.000Z</published>
    <updated>2021-07-05T14:53:56.000Z</updated>
    
    <content type="html"><![CDATA[<h3 id="安装flow-cli"><a href="#安装flow-cli" class="headerlink" title="安装flow-cli"></a>安装flow-cli</h3><p>安装 flow-cli，MacOS 需要下载最新版本的二进制文件，brew 只能安装旧版本。具体安装方法见文档 <a href="https://docs.onflow.org/flow-cli/install/">Install the Flow CLI</a>，该文档使用版本是 v0.25.0。</p><h3 id="生成key-pair"><a href="#生成key-pair" class="headerlink" title="生成key-pair"></a>生成key-pair</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">flow keys generate --sig-algo=ECDSA_secp256k1</span></span><br><span class="line"></span><br><span class="line">Store private key safely and don&#x27;t share with anyone!</span><br><span class="line">Private Key 11e67f5360e61d7d92eb73e1dc48ffbd71c55c8bdf727520d11ddfa6db63554d</span><br><span class="line">Public Key cd23c71391d33c23c867319258ad6cd082b0066e564e23d3fda3c4e5b9ec841eaaa07d2189965130445a4edda244720628334f6a879d80220b573d9914edcbe2</span><br></pre></td></tr></table></figure><h3 id="创建testnet-flow地址"><a href="#创建testnet-flow地址" class="headerlink" title="创建testnet flow地址"></a>创建testnet flow地址</h3><p>访问页面：<a href="https://testnet-faucet-v2.onflow.org/">Flow Testnet Faucet</a> ，创建地址。填入生成的 public key，选择ECDSA_secp256k1签名算法和SHA3_256（和 ETH 哈希算法相同）哈希算法。</p><p>创建成功后得到地址：0x25470ac6e0585a62，也可以跳过该步骤，直接使用生成好的地址。</p><h3 id="初始化flow配置文件"><a href="#初始化flow配置文件" class="headerlink" title="初始化flow配置文件"></a>初始化flow配置文件</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">mkdir</span> flow-example; <span class="built_in">cd</span> flow-example</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">flow init --service-priv-key 11e67f5360e61d7d92eb73e1dc48ffbd71c55c8bdf727520d11ddfa6db63554d --service-sig-algo=ECDSA_secp256k1 --service-hash-algo=SHA3_256</span></span><br><span class="line"></span><br><span class="line">Configuration initialized</span><br><span class="line">Service account: 0xf8d6e0586b0a20c7</span><br><span class="line"></span><br><span class="line">Start emulator by running: &#x27;flow emulator&#x27;</span><br><span class="line">Reset configuration using: &#x27;flow init --reset&#x27;</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cat</span> flow.json</span></span><br><span class="line">&#123;</span><br><span class="line">  &quot;emulators&quot;: &#123;</span><br><span class="line">    &quot;default&quot;: &#123;</span><br><span class="line">      &quot;port&quot;: 3569,</span><br><span class="line">      &quot;serviceAccount&quot;: &quot;emulator-account&quot;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;contracts&quot;: &#123;&#125;,</span><br><span class="line">  &quot;networks&quot;: &#123;</span><br><span class="line">    &quot;emulator&quot;: &quot;127.0.0.1:3569&quot;,</span><br><span class="line">    &quot;mainnet&quot;: &quot;access.mainnet.nodes.onflow.org:9000&quot;,</span><br><span class="line">    &quot;testnet&quot;: &quot;access.devnet.nodes.onflow.org:9000&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;accounts&quot;: &#123;</span><br><span class="line">    &quot;emulator-account&quot;: &#123;</span><br><span class="line">      &quot;address&quot;: &quot;f8d6e0586b0a20c7&quot;,</span><br><span class="line">      &quot;key&quot;: &#123;</span><br><span class="line">        &quot;type&quot;: &quot;hex&quot;,</span><br><span class="line">        &quot;index&quot;: 0,</span><br><span class="line">        &quot;signatureAlgorithm&quot;: &quot;ECDSA_secp256k1&quot;,</span><br><span class="line">        &quot;hashAlgorithm&quot;: &quot;SHA3_256&quot;,</span><br><span class="line">        &quot;privateKey&quot;: &quot;11e67f5360e61d7d92eb73e1dc48ffbd71c55c8bdf727520d11ddfa6db63554d&quot;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;deployments&quot;: &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们将配置里的地址 f8d6e0586b0a20c7 修改为 25470ac6e0585a62。</p><h3 id="创建交易并签名广播"><a href="#创建交易并签名广播" class="headerlink" title="创建交易并签名广播"></a>创建交易并签名广播</h3><p>在构造 flow 的交易时，我们需要先使用 Cadence 语言编写执行脚本，代码如下：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cat</span> &gt; tx.cdc &lt;&lt;<span class="string">EOF</span></span></span><br><span class="line">import FungibleToken from 0x9a0766d93b6608b7</span><br><span class="line">import FlowToken from 0x7e60df042a9c0868</span><br><span class="line"></span><br><span class="line">transaction(amount: UFix64, to: Address) &#123;</span><br><span class="line"></span><br><span class="line">    // The Vault resource that holds the tokens that are being transferred</span><br><span class="line">    let sentVault: @FungibleToken.Vault</span><br><span class="line"></span><br><span class="line">    prepare(signer: AuthAccount) &#123;</span><br><span class="line"></span><br><span class="line">        // Get a reference to the signer&#x27;s stored vault</span><br><span class="line">        let vaultRef = signer.borrow&lt;&amp;FlowToken.Vault&gt;(from: /storage/flowTokenVault)</span><br><span class="line">            ?? panic(&quot;Could not borrow reference to the owner&#x27;s Vault!&quot;)</span><br><span class="line"></span><br><span class="line">        // Withdraw tokens from the signer&#x27;s stored vault</span><br><span class="line">        self.sentVault &lt;- vaultRef.withdraw(amount: amount)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    execute &#123;</span><br><span class="line"></span><br><span class="line">        // Get a reference to the recipient&#x27;s Receiver</span><br><span class="line">        let receiverRef =  getAccount(to)</span><br><span class="line">            .getCapability(/public/flowTokenReceiver)</span><br><span class="line">            .borrow&lt;&amp;&#123;FungibleToken.Receiver&#125;&gt;()</span><br><span class="line">                ?? panic(&quot;Could not borrow receiver reference to the recipient&#x27;s Vault&quot;)</span><br><span class="line"></span><br><span class="line">        // Deposit the withdrawn tokens in the recipient&#x27;s receiver</span><br><span class="line">        receiverRef.deposit(from: &lt;-self.sentVault)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><p>在 testnet 网络上，FlowToken 的合约地址是 0x7e60df042a9c0868。如果使用主网或者是 emulator，需要替换成对应的合约地址，具体查询：<a href="https://docs.onflow.org/core-contracts/">Flow Core Contracts</a>。</p><p>我们 cdc 代码中定义了 transaction 方法，并且包含两个参数 amount 和 to，我们构造交易时，也要传入对应参数。</p><p>我们使用 flow-cli 来构造交易，可以将 flow 发送到 0x72aeca95731d54e5（必须是一个真实创建的地址）。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">flow transactions build ./tx.cdc \</span></span><br><span class="line"><span class="language-bash">    --authorizer emulator-account \</span></span><br><span class="line"><span class="language-bash">    --proposer emulator-account \</span></span><br><span class="line"><span class="language-bash">    --payer emulator-account \</span></span><br><span class="line"><span class="language-bash">    --args-json <span class="string">&#x27;[&#123;&quot;type&quot;: &quot;UFix64&quot;, &quot;value&quot;: &quot;1.0&quot;&#125;, &#123;&quot;type&quot;: &quot;Address&quot;, &quot;value&quot;: &quot;0x72aeca95731d54e5&quot;&#125;]&#x27;</span> \</span></span><br><span class="line"><span class="language-bash">    --network testnet \</span></span><br><span class="line"><span class="language-bash">    --filter payload \</span></span><br><span class="line"><span class="language-bash">    --save built.rlp</span></span><br><span class="line"></span><br><span class="line">result saved to: built.rlp</span><br></pre></td></tr></table></figure><p>我们只保存 payload，我们的接下来对 payload 进行签名，生成签名后的哈希。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">flow transactions sign ./built.rlp --signer emulator-account \</span></span><br><span class="line"><span class="language-bash">  --filter payload --save signed.rlp</span></span><br><span class="line"></span><br><span class="line">result saved to: signed.rlp</span><br></pre></td></tr></table></figure><p>广播签名后的交易。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">flow transactions send-signed --network testnet ./signed.rlp</span></span><br><span class="line"></span><br><span class="line">Sending transaction with ID: 8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7</span><br><span class="line"></span><br><span class="line">Status    ✅ SEALED</span><br><span class="line">ID    8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7</span><br><span class="line">Payer    25470ac6e0585a62</span><br><span class="line">Authorizers  [25470ac6e0585a62]</span><br><span class="line"></span><br><span class="line">Proposal Key:</span><br><span class="line">    Address  25470ac6e0585a62</span><br><span class="line">    Index  0</span><br><span class="line">    Sequence  0</span><br><span class="line"></span><br><span class="line">No Payload Signatures</span><br><span class="line"></span><br><span class="line">Envelope Signature 0: 25470ac6e0585a62</span><br><span class="line">Signatures (minimized, use --include signatures)</span><br><span class="line"></span><br><span class="line">Events:</span><br><span class="line">    Index  0</span><br><span class="line">    Type  A.7e60df042a9c0868.FlowToken.TokensWithdrawn</span><br><span class="line">    Tx ID  8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7</span><br><span class="line">    Values</span><br><span class="line">    - amount (UFix64): 1.00000000</span><br><span class="line">    - from (Address?): 0x25470ac6e0585a62</span><br><span class="line"></span><br><span class="line">    Index  1</span><br><span class="line">    Type  A.7e60df042a9c0868.FlowToken.TokensDeposited</span><br><span class="line">    Tx ID  8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7</span><br><span class="line">    Values</span><br><span class="line">    - amount (UFix64): 1.00000000</span><br><span class="line">    - to (Address?): 0x72aeca95731d54e5</span><br><span class="line"></span><br><span class="line">    Index  2</span><br><span class="line">    Type  A.7e60df042a9c0868.FlowToken.TokensWithdrawn</span><br><span class="line">    Tx ID  8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7</span><br><span class="line">    Values</span><br><span class="line">    - amount (UFix64): 0.00010000</span><br><span class="line">    - from (Address?): 0x25470ac6e0585a62</span><br><span class="line"></span><br><span class="line">    Index  3</span><br><span class="line">    Type  A.7e60df042a9c0868.FlowToken.TokensDeposited</span><br><span class="line">    Tx ID  8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7</span><br><span class="line">    Values</span><br><span class="line">    - amount (UFix64): 0.00010000</span><br><span class="line">    - to (Address?): 0x912d5440f7e3769e</span><br><span class="line"></span><br><span class="line">    Index  4</span><br><span class="line">    Type  A.912d5440f7e3769e.FlowFees.TokensDeposited</span><br><span class="line">    Tx ID  8a979bd7d0278bada8b9cf57611608a5ba258090ecdddaaa83e2e5d04fe53af7</span><br><span class="line">    Values</span><br><span class="line">    - amount (UFix64): 0.00010000</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Code (hidden, use --include code)</span><br><span class="line"></span><br><span class="line">Payload (hidden, use --include payload)</span><br></pre></td></tr></table></figure><p>广播后如果 Status 为 SEALED 则发送成功。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;安装flow-cli&quot;&gt;&lt;a href=&quot;#安装flow-cli&quot; class=&quot;headerlink&quot; title=&quot;安装flow-cli&quot;&gt;&lt;/a&gt;安装flow-cli&lt;/h3&gt;&lt;p&gt;安装 flow-cli，MacOS 需要下载最新版本的二进制文件，brew </summary>
      
    
    
    
    <category term="blockchain" scheme="https://blog.ibeats.top/categories/blockchain/"/>
    
    
  </entry>
  
  <entry>
    <title>博客的迁移</title>
    <link href="https://blog.ibeats.top/technologies/blog-migration.html"/>
    <id>https://blog.ibeats.top/technologies/blog-migration.html</id>
    <published>2021-03-12T12:31:44.000Z</published>
    <updated>2021-03-12T12:31:44.000Z</updated>
    
    <content type="html"><![CDATA[<p>我的博客一直是通过netlify来构建部署的，有一次升级hexo后，在netlify构建就失败了，并且一直没有解决这个问题。主要是我本地并没有失败过，所以我就考虑使用新的平台了。</p><h2 id="vercel"><a href="#vercel" class="headerlink" title="vercel"></a>vercel</h2><p>现在已经切换到了vercel，部署更加简单，配置也更方便，也没有遇到过netlify构建异常。我怀疑是netlify的node版本过低，是8.x的版本。vercel能识别项目使用的框架，非常友好。</p><h2 id="ipfs-ipns"><a href="#ipfs-ipns" class="headerlink" title="ipfs+ipns"></a>ipfs+ipns</h2><p>去中心化是非常好的选择，如果使用的是ipfs，博客要使用相对路径，修改hexo配置中的relative_link就可以实现。当然也可以配置上ipns，ipns是基于dnslink实现，配置一下dnslink的txt记录即可。当你浏览器装了ipfs-companion的插件后，访问你的博客域名，就会自动重定向到ipfs的资源了。除了ipfs.io，现在cloudflare和infura也提供了ipfs的gateway，当然你也可以下载一个ipfs的软件，运行在本地来充当gateway。</p><h2 id="后续更新"><a href="#后续更新" class="headerlink" title="后续更新"></a>后续更新</h2><p>2021四月我将博客迁移至cloudflare的pages服务上，这是cloudflare刚上不久的服务，目前还是beta阶段，和vercel的配置是一样的，非常简单，vercel比较麻烦的地方是，需要通过命令行设置一下主域名，这样每次自动构建的页面才会部署在自定义域名上。</p><p>当然也可以安装ipfs的浏览器插件，直接访问我的博客，ipfs的gateway推荐使用cloudflare-ipfs.com。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;我的博客一直是通过netlify来构建部署的，有一次升级hexo后，在netlify构建就失败了，并且一直没有解决这个问题。主要是我本地并没有失败过，所以我就考虑使用新的平台了。&lt;/p&gt;
&lt;h2 id=&quot;vercel&quot;&gt;&lt;a href=&quot;#vercel&quot; class=&quot;he</summary>
      
    
    
    
    <category term="technologies" scheme="https://blog.ibeats.top/categories/technologies/"/>
    
    
    <category term="netlify" scheme="https://blog.ibeats.top/tags/netlify/"/>
    
    <category term="vercel" scheme="https://blog.ibeats.top/tags/vercel/"/>
    
    <category term="ipfs" scheme="https://blog.ibeats.top/tags/ipfs/"/>
    
    <category term="ipns" scheme="https://blog.ibeats.top/tags/ipns/"/>
    
    <category term="dnslink" scheme="https://blog.ibeats.top/tags/dnslink/"/>
    
  </entry>
  
  <entry>
    <title>在Cloudflare Workers上部署Pyenv-proxy</title>
    <link href="https://blog.ibeats.top/tutorials/pyenv-proxy-by-cloudflare-workers.html"/>
    <id>https://blog.ibeats.top/tutorials/pyenv-proxy-by-cloudflare-workers.html</id>
    <published>2021-01-24T15:22:21.000Z</published>
    <updated>2021-01-24T15:22:21.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="最新加速方案"><a href="#最新加速方案" class="headerlink" title="最新加速方案"></a>最新加速方案</h2><p>我讲pyenv-proxy部署在了Cloudflare上，json数据存储在了Cloudflare KV，用了Cloudflare workers 作为Web服务，不依靠我个人的服务器，保证服务的稳定。</p><p>新的配置如下：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">export PYTHON_BUILD_MIRROR_URL=&quot;https://pyenv.ibeats.top&quot;</span><br></pre></td></tr></table></figure><p>workers代码请查看项：<a href="https://github.com/ciknight/pyenv-proxy">pyenv-proxy</a></p><p>参考文章：<a href="/tutorials/pyenv-proxy.html">如何加速Pyenv</a></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;p&gt;我讲pyenv-proxy部署在了Cloudflare上，json数据存储在了Cloudflare KV，用</summary>
      
    
    
    
    <category term="tutorials" scheme="https://blog.ibeats.top/categories/tutorials/"/>
    
    
    <category term="python" scheme="https://blog.ibeats.top/tags/python/"/>
    
    <category term="pyenv" scheme="https://blog.ibeats.top/tags/pyenv/"/>
    
    <category term="cloudflare" scheme="https://blog.ibeats.top/tags/cloudflare/"/>
    
  </entry>
  
  <entry>
    <title>CloudFront国内访问优化</title>
    <link href="https://blog.ibeats.top/tutorials/cloudfront-china-optimize.html"/>
    <id>https://blog.ibeats.top/tutorials/cloudfront-china-optimize.html</id>
    <published>2020-06-06T00:28:29.000Z</published>
    <updated>2020-06-06T00:28:29.000Z</updated>
    
    <content type="html"><![CDATA[<p>如果做网站加速，CDN是有很多种选择的，如果只做国内业务可以选择任意一家CDN都没问题，国外一般选择CloudFront和Cloudflare。Cloudflare在我看来，使用非常方便，傻瓜都可以操作，基本都是一键设置，不过功能相对于CloudFront少很多，毕竟CloudFront是AWS的一个服务。CloudFront优势在于可以和AWS的其他服务相结合，实现特定的需求。所以我更倾向于使用CloudFront，如果是个人静态博客之类的直接使用Cloudflare足矣。</p><p>这两个服务，国外加速效果都非常好，国内访问高峰期，有时会慢到让人无法接受，如果公司使用还是要对国内访问进行加速的，国内加速我更推荐使用CloudFront，虽说Cloudflare有很多黑科技，比如argo之类加速功能，但是比起CloudFront逊色不少。</p><p>由于国内特色的网络环境，想要解析到国内的服务器，一定要做网站备案，这就导致Cloudflare和CloudFront在国内并没有加速节点。不过Cloudflare有Partner曲线救国的方式，设置起来就比较麻烦了，而且最终还是逃不过备案。</p><p>我最终选择的方案是GeoDNS区域解析，因为域名的NS在Cloudflare托管，所以我优先选择使用Cloudflare的Load Balance，可以根据区域进行自定义解析，从使用体验上讲，该服务收费而且中国IP识别准确率也很低，划分区域相对简单，是根据大陆板块划分，没有根据国家划分区域，所以只好放弃Cloudflare。在一番对比后，国内的DNSPod，AliyunDNS准确率都很高，最后我还是选择了AWS的route53服务。</p><p>服务器可以考虑使用Alibaba Cloud的OSS服务，香港的OSS对于国内访问速度还是非常快的，而且比较稳定。将中国的解析执行OSS就可以了。当然这只是前端页面加速，如果是其他业务，也可以使用HAProxy或者Nginx做转发，就可以实现更多特殊的需求了。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;如果做网站加速，CDN是有很多种选择的，如果只做国内业务可以选择任意一家CDN都没问题，国外一般选择CloudFront和Cloudflare。Cloudflare在我看来，使用非常方便，傻瓜都可以操作，基本都是一键设置，不过功能相对于CloudFront少很多，毕竟Clo</summary>
      
    
    
    
    <category term="tutorials" scheme="https://blog.ibeats.top/categories/tutorials/"/>
    
    
    <category term="cloudfront" scheme="https://blog.ibeats.top/tags/cloudfront/"/>
    
    <category term="cloudflare" scheme="https://blog.ibeats.top/tags/cloudflare/"/>
    
    <category term="aws" scheme="https://blog.ibeats.top/tags/aws/"/>
    
  </entry>
  
  <entry>
    <title>记一次使用asyncio.run遇到的坑</title>
    <link href="https://blog.ibeats.top/issues/python-asyncio-run.html"/>
    <id>https://blog.ibeats.top/issues/python-asyncio-run.html</id>
    <published>2020-04-30T13:04:47.000Z</published>
    <updated>2020-04-30T13:04:47.000Z</updated>
    
    <content type="html"><![CDATA[<p>如果写同步的程序，我都是使用 requests 发送 http 请求，异步程序，我更倾向于使用 aiohttp，这两个都是非常优秀的工具包，但是写异步代码，如果掌握不精很容易坑了自己。接下来我会讲述一下我在使用中遇到的一个问题。</p><h2 id="版本和软件环境"><a href="#版本和软件环境" class="headerlink" title="版本和软件环境"></a>版本和软件环境</h2><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">System: MacOS 10.15</span><br><span class="line">Python: 3.7.6</span><br><span class="line">aiohttp: 3.5.4</span><br></pre></td></tr></table></figure><h2 id="aiohttp-client-抛了异常"><a href="#aiohttp-client-抛了异常" class="headerlink" title="aiohttp client 抛了异常"></a>aiohttp client 抛了异常</h2><p>下面是简化过的代码。</p><figure class="highlight python"><figcaption><span>http.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> aiohttp</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Http</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self</span>):</span><br><span class="line">        connector = aiohttp.TCPConnector()</span><br><span class="line">        <span class="variable language_">self</span>.session = aiohttp.ClientSession(connector=connector)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">get</span>(<span class="params">self, url</span>):</span><br><span class="line">        <span class="keyword">async</span> <span class="keyword">with</span> <span class="variable language_">self</span>.session.get(url) <span class="keyword">as</span> r:</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">await</span> r.text()</span><br><span class="line"></span><br><span class="line">http = Http()</span><br></pre></td></tr></table></figure><figure class="highlight python"><figcaption><span>main.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> base <span class="keyword">import</span> b</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line">    r = <span class="keyword">await</span> b.get(<span class="string">&quot;https://blog.ibeats.top/robots.txt&quot;</span>)</span><br><span class="line">    <span class="built_in">print</span>(r)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    <span class="keyword">import</span> asyncio</span><br><span class="line">    asyncio.run(main())</span><br></pre></td></tr></table></figure><p>这时候执行 main.py 就抛出了异常</p><blockquote><p>RuntimeError: Timeout context manager should be used inside a task</p></blockquote><p>打断点查看，确实是在 with timer 抛出的错误，这情况很有可能是没在事件循环内实例化 session。代码少还是很容易看出来，运行事件循环前导入了 http，并且实例化了 session。</p><p>所以从根本上上解决问题就是导入http时不要初始化 session，然后代码可以改成这样。</p><figure class="highlight python"><figcaption><span>http.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> aiohttp</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Http</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.session = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">get_session</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="keyword">if</span> <span class="variable language_">self</span>.session <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">            connector = aiohttp.TCPConnector()</span><br><span class="line">            <span class="variable language_">self</span>.session = aiohttp.ClientSession(connector=connector)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">self</span>.session</span><br><span class="line"></span><br><span class="line">    <span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">get</span>(<span class="params">self, url</span>):</span><br><span class="line">        session = <span class="keyword">await</span> <span class="variable language_">self</span>.get_session()</span><br><span class="line">        <span class="keyword">async</span> <span class="keyword">with</span> session.get(url) <span class="keyword">as</span> r:</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">await</span> r.text()</span><br><span class="line"></span><br><span class="line">http = Http()</span><br></pre></td></tr></table></figure><p>这样就可以就可以放心的在任何地方初始化了。</p><h2 id="为什么不能运行前实例化session。"><a href="#为什么不能运行前实例化session。" class="headerlink" title="为什么不能运行前实例化session。"></a>为什么不能运行前实例化session。</h2><p>运行事件循环前也可以实例化 session。但是不要使用 asyncio.run 方法，可以自己创建一个loop来运行事件循环。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line">    ...</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    loop =  <span class="keyword">async</span>.get_event_loop()</span><br><span class="line">    loop.run_until_complete(main())</span><br></pre></td></tr></table></figure><p>为什么会这样，我们要进入 asyncio 内部看一下了，CPython 有用 Python 实现的 asyncio 代码，就不用直接看C了。在看过 aiohttp 代码后，aiohttp 初始化 session 时，使用的是 asyncio.get_event_loop() ，asyncio.run() 是自己创建的事件循环。那么我将代码简化后写出来再分析一下。</p><figure class="highlight python"><figcaption><span>runners.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> events <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">def</span> <span class="title function_">run</span>()</span><br><span class="line">    <span class="keyword">if</span> events._get_running_loop() <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span>:</span><br><span class="line">        <span class="keyword">raise</span> RuntimeError(<span class="string">&quot;asyncio.run() cannot be called from a running event loop&quot;</span>)</span><br><span class="line"></span><br><span class="line">    loop = events.new_event_loop()</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        events.set_event_loop(loop)</span><br><span class="line">        <span class="keyword">return</span> loop.run_until_complete(main)</span><br><span class="line">    <span class="keyword">finally</span>:</span><br><span class="line">        ...</span><br></pre></td></tr></table></figure><figure class="highlight python"><figcaption><span>events.py</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">_RunningLoop</span>(threading.local):</span><br><span class="line">    loop_pid = (<span class="literal">None</span>, <span class="literal">None</span>)</span><br><span class="line"></span><br><span class="line">_event_loop_policy = <span class="literal">None</span></span><br><span class="line">_running_loop = _RunningLoop()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_running_loop</span>():</span><br><span class="line">    loop = _get_running_loop()</span><br><span class="line">    <span class="keyword">if</span> loop <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">        <span class="keyword">raise</span> RuntimeError(<span class="string">&#x27;no running event loop&#x27;</span>)</span><br><span class="line">    <span class="keyword">return</span> loop</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">_get_running_loop</span>():</span><br><span class="line">    running_loop, pid = _running_loop.loop_pid</span><br><span class="line">    <span class="keyword">if</span> running_loop <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span> <span class="keyword">and</span> pid == os.getpid():</span><br><span class="line">        <span class="keyword">return</span> running_loop</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">_set_running_loop</span>(<span class="params">loop</span>):</span><br><span class="line">    _running_loop.loop_pid = (loop, os.getpid())</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">_init_event_loop_policy</span>():</span><br><span class="line">    <span class="keyword">global</span> _event_loop_policy</span><br><span class="line">    <span class="keyword">with</span> _lock:</span><br><span class="line">        <span class="keyword">if</span> _event_loop_policy <span class="keyword">is</span> <span class="literal">None</span>:  <span class="comment"># pragma: no branch</span></span><br><span class="line">            <span class="keyword">from</span> . <span class="keyword">import</span> DefaultEventLoopPolicy</span><br><span class="line">            _event_loop_policy = DefaultEventLoopPolicy()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_event_loop_policy</span>():</span><br><span class="line">    <span class="keyword">if</span> _event_loop_policy <span class="keyword">is</span> <span class="literal">None</span>:</span><br><span class="line">        _init_event_loop_policy()</span><br><span class="line">    <span class="keyword">return</span> _event_loop_policy</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">get_event_loop</span>():</span><br><span class="line">    current_loop = _get_running_loop()</span><br><span class="line">    <span class="keyword">if</span> current_loop <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">None</span>:</span><br><span class="line">        <span class="keyword">return</span> current_loop</span><br><span class="line">    <span class="keyword">return</span> get_event_loop_policy().get_event_loop()</span><br></pre></td></tr></table></figure><p>aiohttp使用get_event_loop，就是说如果不调用 set_event_loop，当执行 asyncio.run 时，会重新创建一个事件循环，导致事件循环不是同一个，运行事件循环时，aiohttp 里抛出，所以启动事件循环时，也使用 get_event_loop 就能保证最后使用的是同一个事件循环，当然还是不建议这么做，稍微控制不好就会耽误很长的时间找问题所在，最后得不偿失了。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://github.com/tiangolo/fastapi/issues/301">https://github.com/tiangolo/fastapi/issues/301</a></li><li><a href="https://stackoverflow.com/questions/52232177/runtimeerror-timeout-context-manager-should-be-used-inside-a-task">https://stackoverflow.com/questions/52232177/runtimeerror-timeout-context-manager-should-be-used-inside-a-task</a></li><li><a href="https://github.com/raphaelauv/fastAPI-aiohttp-example">https://github.com/raphaelauv/fastAPI-aiohttp-example</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;如果写同步的程序，我都是使用 requests 发送 http 请求，异步程序，我更倾向于使用 aiohttp，这两个都是非常优秀的工具包，但是写异步代码，如果掌握不精很容易坑了自己。接下来我会讲述一下我在使用中遇到的一个问题。&lt;/p&gt;
&lt;h2 id=&quot;版本和软件环境&quot;&gt;&lt;</summary>
      
    
    
    
    <category term="issues" scheme="https://blog.ibeats.top/categories/issues/"/>
    
    
    <category term="python" scheme="https://blog.ibeats.top/tags/python/"/>
    
    <category term="asyncio" scheme="https://blog.ibeats.top/tags/asyncio/"/>
    
    <category term="aiohttp" scheme="https://blog.ibeats.top/tags/aiohttp/"/>
    
  </entry>
  
  <entry>
    <title>科学上网（翻墙）服务器推荐</title>
    <link href="https://blog.ibeats.top/gfw/akkocloud-recommend.html"/>
    <id>https://blog.ibeats.top/gfw/akkocloud-recommend.html</id>
    <published>2020-04-08T14:02:56.000Z</published>
    <updated>2020-04-08T14:02:56.000Z</updated>
    
    <content type="html"><![CDATA[<p>2021年03月12日更新</p><p>目前已经换到了<a href="https://bandwagonhost.com/aff.php?aff=59518">搬瓦工</a>，AkkoCloud毕竟是小服务商，虽然说线路不错，但是没事断个网也是很难受的，非重度用户不影响。如果使用搬瓦工也可以使用我的推荐链接<a href="https://bandwagonhost.com/aff.php?aff=59518">https://bandwagonhost.com/aff.php?aff=59518</a>，非常感谢。</p><hr><p>之前聊过如何科学上网，如果不了解可以先看一下<a href="tutorials/how-to-fanqiang.html">《如何科学上网》</a>。科学上网要有一个好的服务器，所以我推荐<a href="https://www.akkocloud.com/aff.php?aff=256">AkkoCloud</a>，这也是我在使用的服务器，如果想购买可以使用我的推荐链接<a href="https://www.akkocloud.com/aff.php?aff=256">https://www.akkocloud.com/aff.php?aff=256</a>注册购买，非常感谢。</p><h2 id="AkkoCloud介绍"><a href="#AkkoCloud介绍" class="headerlink" title="AkkoCloud介绍"></a>AkkoCloud介绍</h2><p>这家服务商还比较新，知道的人也比较少，所以不会像搬瓦工那样，便宜的服务器经常处于售空的状态，即便补货你也是抢不到。</p><h3 id="线路和带宽"><a href="#线路和带宽" class="headerlink" title="线路和带宽"></a>线路和带宽</h3><p>翻墙肯定是要稳定，推荐美国圣何塞CN2 GIA，如果你不知道什么是CN2 GIA可以谷歌搜索一下，CN2线路还是很稳定的，高峰期基本不会丢包。更重要的是，三网优化。</p><p>带宽最低是50mbps，双向600G流量，油管2k基本无压力，最大是150mbps，1500G流量。当然越大的价格越贵。</p><h3 id="奈非？HBO？"><a href="#奈非？HBO？" class="headerlink" title="奈非？HBO？"></a>奈非？HBO？</h3><p>比较不错的是，AkkoCloud基本上是可以解锁流媒体的，可以看Netflix、HBO和Disney+，亲身体验是没问题的，但是官方不保证可以解锁流媒体服务，如果需要换IP，也可以加钱更换。</p><h3 id="价格与付款"><a href="#价格与付款" class="headerlink" title="价格与付款"></a>价格与付款</h3><p>支持支付宝支付，最便宜的50元一个月。不时会推出一个活动，打个八折，还是非常优惠的。建议买75元一个月的，带宽能达到100mbps。</p><h3 id="关于注册"><a href="#关于注册" class="headerlink" title="关于注册"></a>关于注册</h3><p>手机号可以不填，邮箱最好填真实的，虽然说不会验证你的邮箱，但是是用来接收invoice的。</p><h3 id="MC服务器"><a href="#MC服务器" class="headerlink" title="MC服务器"></a>MC服务器</h3><p>AkkoCloud整体偏向于二次元，所以还提供我的世界服务器托管，10块钱一个月，太良心了。</p><h2 id="为什么翻墙？"><a href="#为什么翻墙？" class="headerlink" title="为什么翻墙？"></a>为什么翻墙？</h2><p>和世界接轨。</p><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>最近发现<a href="https://bandwagonhost.com/aff.php?aff=59518">搬瓦工</a>有个补货监控网站，网站链接<a href="https://status.bwgyhw.cn/">https://status.bwgyhw.cn/</a>，他们也有TG群的补货通知，感兴趣的加入。如果有买搬瓦工服务器的，可以点击我的邀请链接<a href="https://bandwagonhost.com/aff.php?aff=59518">https://bandwagonhost.com/aff.php?aff=59518</a>，在此谢过了。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;2021年03月12日更新&lt;/p&gt;
&lt;p&gt;目前已经换到了&lt;a href=&quot;https://bandwagonhost.com/aff.php?aff=59518&quot;&gt;搬瓦工&lt;/a&gt;，AkkoCloud毕竟是小服务商，虽然说线路不错，但是没事断个网也是很难受的，非重度用户不影响</summary>
      
    
    
    
    <category term="gfw" scheme="https://blog.ibeats.top/categories/gfw/"/>
    
    
    <category term="gfw" scheme="https://blog.ibeats.top/tags/gfw/"/>
    
    <category term="akkocloud" scheme="https://blog.ibeats.top/tags/akkocloud/"/>
    
    <category term="bandwagonhost" scheme="https://blog.ibeats.top/tags/bandwagonhost/"/>
    
    <category term="搬瓦工" scheme="https://blog.ibeats.top/tags/%E6%90%AC%E7%93%A6%E5%B7%A5/"/>
    
  </entry>
  
  <entry>
    <title>比特币如何确保十分钟挖一个块</title>
    <link href="https://blog.ibeats.top/blockchain/blockchain-retarget.html"/>
    <id>https://blog.ibeats.top/blockchain/blockchain-retarget.html</id>
    <published>2020-03-17T14:00:00.000Z</published>
    <updated>2020-03-17T14:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>美股月内四次熔断，比特币也从一万美元跌至最低三千八百美元，在比特币产量减半之前，首先实现了市值减半，可以说很刺激了。随着币价的暴跌，也出现了各种流言，我就听到了一个这样的消息，真实唯恐天下不乱。</p><blockquote><p>“比特币系统出错，矿工已经四小时没有出块了，后台增发数量造成算力漏洞被攻击，可以双花了。黑客利用这个漏洞凭空造出了一千万个比特币出来”。</p></blockquote><p>虽然说的有头有尾，但是稍微了解比特币的人直接可以确认这是谣言了。那么我们就针对这个谣言来聊聊细节吧。</p><h2 id="比特币挖矿"><a href="#比特币挖矿" class="headerlink" title="比特币挖矿"></a>比特币挖矿</h2><p>挖矿在区块链中就是出块的意思，也就是矿机做哈希计算得到合法并且符合预期结果，进而获得更多节点的认可并入区块链。所有的块连接到一起就形成区块链，这就像是链表一样的结构,然后通过共识进而达到无法篡改的目的。那么如果说比特币系统出错，或者算力大幅度减少，后台也不可能增发数量（额，比特币是没有后台的），也不太可能一直不出块（也只有算力暴跌百分之九十才有可能很难出块），或者在一些区块链浏览器看一下谣言也不证自破了。</p><h2 id="目标（Target）"><a href="#目标（Target）" class="headerlink" title="目标（Target）"></a>目标（Target）</h2><p>Target是一个256位的数，在挖矿时，块哈希必须小于或等于网络当前的Target。Target越小就越难计算。Target每2016个块调整一次难度（大概两周的时间）,每个比特币客户端将生成2016块的实际时间与两周的目标（2016*10分钟）进行了比较，并通过百分比差异修改了目标,单次调整Target永远不会向下降低（增加难度）超过4倍，向上升高（降低难度）超过0.75倍。目标中的变化也叫做<code>Difficulty adjustment</code>（难度调整），</p><blockquote><p>在2017年8月从BTC分叉之前，都是2016个块重新计算一次难度。由于早期一个版本的BUG，调整了算法，变成了每2015个块调整一次难度。</p></blockquote><p>区块链以Bits的形式存储Target，十六进制有固定的公式来计算，比如区块在存储的值为<code>0x1b0404cb</code>（以小阶数排序存储：CB 04 04 04 1B），十六进制标识为：</p><blockquote><p>0x0404cb * 2**(8*(0x1b - 3)) &#x3D; 0x00000000000404CB000000000000000000000000000000000000000000000000</p></blockquote><p>比特币定义创世纪块中使用的目标为Difficulty Level 1（难度就是difficulty_1_target），Bits值为0x1d00ffff，十六进制也就是：</p><blockquote><p>0x00ffff * 2**(8 * (0x1d - 3)) &#x3D; 0x00000000FFFF0000000000000000000000000000000000000000000000000000</p></blockquote><h2 id="难度（Difficulty）"><a href="#难度（Difficulty）" class="headerlink" title="难度（Difficulty）"></a>难度（Difficulty）</h2><p>哈希计算出来的值，哈希值前面的<code>0</code>越多，计算出来的难度就越大。也就是一个计算难度的衡量标准。</p><p>Target用十六进制来表示，Difficulty就可以这样计算：</p><blockquote><p>difficulty &#x3D; difficulty_1_target &#x2F; current_target</p></blockquote><p>比如在<code>0x1b0404cb</code>的难度就是</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">0x00000000FFFF0000000000000000000000000000000000000000000000000000 /</span><br><span class="line">0x00000000000404CB000000000000000000000000000000000000000000000000</span><br><span class="line">= 16307.420938523983 (bdiff)</span><br></pre></td></tr></table></figure><p>也可以</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF /</span><br><span class="line">0x00000000000404CB000000000000000000000000000000000000000000000000</span><br><span class="line">= 16307.669773817162 (pdiff)</span><br></pre></td></tr></table></figure><p>还有一种就是，btc.com通过算例推算出的难度。</p><p>在挖矿时，谁计算的快，也就是谁的算力大，就有更大机会得到挖矿奖励，目前大概是12.5个比特币奖励，区块包括矿工费所以一般大于12.5个。下次奖励减半时间大概是2020年5月14日。具体可以看<a href="https://btc.com/stats/halving">https://btc.com/stats/halving</a>。</p><h2 id="比特币大概每十分钟出一个块"><a href="#比特币大概每十分钟出一个块" class="headerlink" title="比特币大概每十分钟出一个块"></a>比特币大概每十分钟出一个块</h2><p>为了保持每十分钟一个块，比特币每2016个块重新计算一次网络的难度。如果说上一个2016个块的周期时间大于两个星期，那么就要降低难度，反之亦然。这样我们就可以通过时间比率来调整难度了。</p><p>可以看我的实现<a href="https://github.com/ciknight/microchain/blob/master/microchain/chain.py#L76">github.com&#x2F;ciknight&#x2F;microchain&#x2F;blob&#x2F;master&#x2F;microchain&#x2F;chain.py#L76</a>，我使用比率来计算，并且规定比率在4到1&#x2F;4之间。</p><h2 id="如果想要了解更多的比特币知识"><a href="#如果想要了解更多的比特币知识" class="headerlink" title="如果想要了解更多的比特币知识"></a>如果想要了解更多的比特币知识</h2><p>可以看一下《Mastering Bitcoin》这本书，想了解更多技术相关可以看比特币的开发手册和Bitcoin wiki。当然比特币只是区块链技术的一种，还有其他的链可以学习，他们互相取长补短，不知道在未来的某一天，区块链会不会改变我们的生活。</p><h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul><li><a href="https://en.bitcoin.it/wiki/Difficulty">https://en.bitcoin.it/wiki/Difficulty</a></li><li><a href="https://wiki.bitcoinsv.io/index.php/Difficulty">https://wiki.bitcoinsv.io/index.php/Difficulty</a></li><li><a href="https://en.bitcoin.it/wiki/Protocol_rules#.22block.22_messages">https://en.bitcoin.it/wiki/Protocol_rules#.22block.22_messages</a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;美股月内四次熔断，比特币也从一万美元跌至最低三千八百美元，在比特币产量减半之前，首先实现了市值减半，可以说很刺激了。随着币价的暴跌，也出现了各种流言，我就听到了一个这样的消息，真实唯恐天下不乱。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“比特币系统出错，矿工已经四小时没有出</summary>
      
    
    
    
    <category term="blockchain" scheme="https://blog.ibeats.top/categories/blockchain/"/>
    
    
    <category term="blockchain" scheme="https://blog.ibeats.top/tags/blockchain/"/>
    
    <category term="bitcoin" scheme="https://blog.ibeats.top/tags/bitcoin/"/>
    
  </entry>
  
  <entry>
    <title>Hexo Markdown渲染时多余的空格</title>
    <link href="https://blog.ibeats.top/issues/hexo-markdown-space.html"/>
    <id>https://blog.ibeats.top/issues/hexo-markdown-space.html</id>
    <published>2020-02-02T14:34:47.000Z</published>
    <updated>2020-02-02T14:34:47.000Z</updated>
    
    <content type="html"><![CDATA[<p>hexo使用的是markdown渲染博客的，不过在写文章的时候，我vim并没有设置auto wrap，一般我会自己去换行。但是 markdown 语法中换行就是分段，一行多了换行后分段导致行间距增大，感觉是多了一个空格，排版就会变得很难看。如果从 hexo 的 markdown 渲染引擎入手我感觉会异常麻烦，所以，我打算写个脚本把换行去掉合并成一行，这样就简单的解决了这个问题，修复原来的文字，后续的不再手动换行了。</p><p>也可以使用hexo-renderer-markdown-it引擎解决这个问题，不过我还是建议使用标准，而不是利用引擎来解决这个问题。</p><p>花了几十分钟写完，代码如下。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="keyword">from</span> glob <span class="keyword">import</span> glob</span><br><span class="line"><span class="keyword">from</span> typing <span class="keyword">import</span> <span class="type">List</span></span><br><span class="line"></span><br><span class="line">files = glob(<span class="string">&quot;*/**/*.md&quot;</span>, recursive=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">fmt</span>(<span class="params">content: <span class="type">List</span>[<span class="built_in">str</span>]</span>) -&gt; <span class="built_in">str</span>:</span><br><span class="line">    data: <span class="type">List</span>[<span class="built_in">str</span>] = []</span><br><span class="line">    lens = <span class="built_in">len</span>(content)</span><br><span class="line">    n = <span class="number">0</span></span><br><span class="line">    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">        <span class="keyword">if</span> <span class="string">&quot;---&quot;</span> <span class="keyword">in</span> content[n]:</span><br><span class="line">            tmp: <span class="type">List</span>[<span class="built_in">str</span>] = []</span><br><span class="line">            tmp.append(<span class="string">&quot;---&quot;</span>)</span><br><span class="line">            <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">                n += <span class="number">1</span></span><br><span class="line">                tmp.append(content[n])</span><br><span class="line">                <span class="keyword">if</span> <span class="string">&quot;---&quot;</span> <span class="keyword">in</span> content[n]:</span><br><span class="line">                    <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">                        n += <span class="number">1</span></span><br><span class="line">                        <span class="keyword">if</span> content[n] == <span class="string">&quot;&quot;</span>:</span><br><span class="line">                            <span class="keyword">continue</span></span><br><span class="line">                        <span class="keyword">break</span></span><br><span class="line">                    <span class="keyword">break</span></span><br><span class="line">                <span class="keyword">continue</span></span><br><span class="line">            data.append(<span class="string">&quot;\n&quot;</span>.join(tmp))</span><br><span class="line"></span><br><span class="line">        tmp = []</span><br><span class="line">        <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">            <span class="keyword">if</span> <span class="string">&quot;```&quot;</span> <span class="keyword">in</span> content[n]:</span><br><span class="line">                _tmp: <span class="type">List</span>[<span class="built_in">str</span>] = []</span><br><span class="line">                _tmp.append(content[n])</span><br><span class="line">                <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">                    n += <span class="number">1</span></span><br><span class="line">                    <span class="keyword">if</span> lens == n:</span><br><span class="line">                        n -= <span class="number">1</span></span><br><span class="line">                        <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">                    _tmp.append(content[n])</span><br><span class="line">                    <span class="keyword">if</span> <span class="string">&quot;```&quot;</span> <span class="keyword">in</span> content[n]:</span><br><span class="line">                        <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">                            n += <span class="number">1</span></span><br><span class="line">                            <span class="keyword">if</span> lens == n:</span><br><span class="line">                                n -= <span class="number">1</span></span><br><span class="line">                                <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">                            <span class="keyword">if</span> content[n] == <span class="string">&quot;&quot;</span>:</span><br><span class="line">                                <span class="keyword">continue</span></span><br><span class="line">                            <span class="keyword">break</span></span><br><span class="line">                        <span class="keyword">break</span></span><br><span class="line">                    <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line">                data.append(<span class="string">&quot;\n&quot;</span>.join(_tmp))</span><br><span class="line"></span><br><span class="line">            tmp.append(content[n])</span><br><span class="line">            i = n + <span class="number">1</span></span><br><span class="line">            n += <span class="number">1</span></span><br><span class="line">            <span class="keyword">if</span> i == lens <span class="keyword">or</span> content[i] == <span class="string">&quot;&quot;</span>:</span><br><span class="line">                data.append(<span class="string">&quot;&quot;</span>.join(tmp))</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> lens == n:</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;\n\n&quot;</span>.join(data)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> f <span class="keyword">in</span> files:</span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(f) <span class="keyword">as</span> fp:</span><br><span class="line">        c = fp.read()</span><br><span class="line"></span><br><span class="line">    data = fmt(c.split(<span class="string">&quot;\n&quot;</span>))</span><br><span class="line">    <span class="keyword">with</span> <span class="built_in">open</span>(f, <span class="string">&quot;w&quot;</span>) <span class="keyword">as</span> fp:</span><br><span class="line">        fp.write(data)</span><br></pre></td></tr></table></figure><p>当然代码依然有一些问题，没有覆盖到所有的 markdown 语法，所以很多问题手动修改了。不过使用 Python 编写脚本确实能提升不少的效率，所以Python 是很值得学习的一门语言。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;hexo使用的是markdown渲染博客的，不过在写文章的时候，我vim并没有设置auto wrap，一般我会自己去换行。但是 markdown 语法中换行就是分段，一行多了换行后分段导致行间距增大，感觉是多了一个空格，排版就会变得很难看。如果从 hexo 的 markdo</summary>
      
    
    
    
    <category term="issues" scheme="https://blog.ibeats.top/categories/issues/"/>
    
    
    <category term="hexo" scheme="https://blog.ibeats.top/tags/hexo/"/>
    
    <category term="markdown" scheme="https://blog.ibeats.top/tags/markdown/"/>
    
    <category term="python" scheme="https://blog.ibeats.top/tags/python/"/>
    
  </entry>
  
</feed>
