<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>芝士就是菜</title>
  
  <subtitle>加油</subtitle>
  <link href="https://atong.run/atom.xml" rel="self"/>
  
  <link href="https://atong.run/"/>
  <updated>2025-09-14T13:14:51.494Z</updated>
  <id>https://atong.run/</id>
  
  <author>
    <name>atong</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>终端Terminal-AI编码助手 Crush</title>
    <link href="https://atong.run/posts/2858725456/"/>
    <id>https://atong.run/posts/2858725456/</id>
    <published>2025-09-14T13:12:43.476Z</published>
    <updated>2025-09-14T13:14:51.494Z</updated>
    
    <content type="html"><![CDATA[<p>前几天看到了一个挺好玩的Github项目-<a href="https://github.com/charmbracelet/crush">Crush</a>，这个项目是一款Terminal运行的AI工具，Go开发，可以在终端运行~</p><p>Crush是支持MacOS，Linux和Windows，不过感觉MacOS和Windows应该没啥必要用这个东西，当然 WSL除外</p><p>核心的功能如下：</p><ol><li>多模型支持，常见的API提供商都可以用</li><li>支持会话管理，能保存、切换不同项目/话题的对话上下文</li><li>LSP，可以配置，能让AI更准确的理解项目中代码</li><li>MCP，支持stdio、http、see方式接入MCP服务</li></ol><h3 id="Debian-Ubuntu-安装">Debian/Ubuntu 安装</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></pre></td><td class="code"><pre><span class="line">sudo mkdir -p /etc/apt/keyrings</span><br><span class="line">curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg</span><br><span class="line">echo &quot;deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *&quot; | sudo tee /etc/apt/sources.list.d/charm.list</span><br><span class="line">sudo apt update &amp;&amp; sudo apt install crush</span><br></pre></td></tr></table></figure><p>装上在Terminal直接运行crush即可</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202509062347923.png" alt="image.png"></p><h3 id="Crush使用">Crush使用</h3><p>界面挺简洁好看，我个人挺喜欢这个风格</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202509070001039.png" alt="image.png"></p><p>底部状态栏，有命令提示非常贴心，第一次进需要配置模型和填写API，配置完成后也可以通过ctrl+p命令调出命令窗口并切换模型<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202509070005772.png" alt="image.png"></p><p>也可以直接去下面路径的配置文件填写模型以及Key</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"><span class="meta prompt_">$</span><span class="language-bash">HOME/.local/share/crush/crush.json</span></span><br></pre></td></tr></table></figure><p>打开文件，如下图所示<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202509070123017.png" alt="image.png"></p><p>当配置好模型以及对应的API Key后，就可以直接尝试了，比如我直接说帮我创建一个c的项目，crush创建好文件夹后会列出步骤（crush会操作你的文件已经调用shell命令）</p><ol><li>创建main.c</li><li>写代码</li><li>gcc编译</li></ol><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202509070130205.png" alt="image.png"></p><p>当然，创建文件或者删除文件毕竟是敏感操作，crush会弹出窗口让确认，这个建议是保留，虽然可以通过配置将这个提醒取消~<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202509070131945.png" alt="image.png"></p><p>创建成功后，crush会继续执行编译，如果出错，它会分析bash打印的错误信息并进行纠正继续任务，直到完成<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202509070133524.png" alt="image.png"><br>当实际编译成功后，crush界面也会打印程序运行的结果，并且看本地目录，实际创建了一个c_project的文件夹，里面写了mian.c的程序并编译出来可以正确运行的可执行程序，当然这个crush可以做更多的东西，以上只是一个简单的例子，大家觉的好玩的话可以自行尝试<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202509070135051.png" alt="image.png"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;前几天看到了一个挺好玩的Github项目-&lt;a href=&quot;https://github.com/charmbracelet/crush&quot;&gt;Crush&lt;/a&gt;，这个项目是一款Terminal运行的AI工具，Go开发，可以在终端运行~&lt;/p&gt;
&lt;p&gt;Crush是支持MacOS</summary>
      
    
    
    
    <category term="人工智能" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/"/>
    
    <category term="使用AI" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/%E4%BD%BF%E7%94%A8AI/"/>
    
    
    <category term="ai" scheme="https://atong.run/tags/ai/"/>
    
  </entry>
  
  <entry>
    <title>git常用命令</title>
    <link href="https://atong.run/posts/3396067388/"/>
    <id>https://atong.run/posts/3396067388/</id>
    <published>2024-07-13T17:33:49.800Z</published>
    <updated>2024-07-13T17:38:20.413Z</updated>
    
    <content type="html"><![CDATA[<p>Git是一种分布式版本控制系统，可以进行多人的协作开发，基本大部分的软件开发相关的公司都会使用该软件，下边记录一些常用的命令</p><h2 id="安装Git">安装Git</h2><p>可以从<a href="https://git-scm.com/">Git官方网站</a>下载适合操作系统的安装程序，win可以直接下载，常用的linux系统</p><p>Ubuntu</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">apt-get install git</span><br></pre></td></tr></table></figure><p>Centos</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yum install git</span><br></pre></td></tr></table></figure><p>Linux平台下使用下述命令查看git版本：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git --version</span><br></pre></td></tr></table></figure><h2 id="创建本地Git仓库并配置">创建本地Git仓库并配置</h2><p>要在本地创建一个新的Git仓库，可以使用以下命令：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git init</span><br></pre></td></tr></table></figure><h3 id="用户信息配置">用户信息配置</h3><p>配置Git的用户信息，包括用户名和邮箱地址。在命令行中输入以下命令：</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">git config --global user.name &quot;Your Name&quot;</span><br><span class="line">git config --global user.email &quot;youremail@example.com&quot;</span><br></pre></td></tr></table></figure><p>–global是可选项，带上该选项在仓库目录下运行上述命令之后，可以在本机所有的仓库中生效</p><p>查看配置命令：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config -l</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></pre></td><td class="code"><pre><span class="line">git config [--global] --unset user.name</span><br><span class="line">git config [--global] --unset user.email</span><br></pre></td></tr></table></figure><h3 id="公钥">公钥</h3><p>生成 Git 的公钥是为了在使用 Git 时进行身份验证。输入以下命令来生成 SSH 密钥对：</p><ol><li>生成公钥<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -b 4096 -C &quot;your_email@example.com&quot;</span><br></pre></td></tr></table></figure><ul><li><code>-t rsa</code>：指定生成 RSA 类型的密钥。</li><li><code>-b 4096</code>：指定密钥的位数为 4096 位，提高安全性。</li><li><code>-C &quot;your_email@example.com&quot;</code>：在生成的密钥中添加注释，一般填写你的邮箱地址。</li></ul></li><li>系统会提示你选择保存密钥的位置，默认为 <code>~/.ssh/id_rsa</code>，也可以自定义路径。</li><li>然后系统会提示你设置密钥的密码（可选），设置密码可以提高密钥的安全性。</li><li>生成成功后，会显示公钥的路径，默认为 <code>~/.ssh/id_rsa.pub</code>。</li><li>使用文本编辑器打开公钥文件 <code>id_rsa.pub</code>，复制里面的内容。</li><li>将公钥内容粘贴到 Git 服务商（如 GitHub、GitLab）的 SSH 密钥设置中，以便进行身份验证。</li></ol><p>生成的公钥可以用于与 Git 服务商进行安全的通信和身份验证。</p><h2 id="将文件添加到Git仓库">将文件添加到Git仓库</h2><p>将文件添加到Git仓库需要两个步骤。首先，使用以下命令将文件添加到暂存区：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git add filename</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></pre></td><td class="code"><pre><span class="line">git commit -m &quot;Commit message&quot;</span><br></pre></td></tr></table></figure><h2 id="版本回退">版本回退</h2><p><code>git restore --staged &lt;file&gt;...</code> 命令用于将暂存区（Staging Area）中的文件恢复到工作目录中的状态，即取消暂存的文件更改。</p><p>执行这个命令后，指定的文件将从暂存区还原到工作目录，文件的更改将不再处于暂存状态。</p><p><code>git reset</code> 命令在 Git 中用于撤销更改、移动 HEAD 指针或重置暂存区。以下是 <code>git reset</code> 命令的常用参数和说明：</p><ol><li><p><strong><code>git reset HEAD &lt;file&gt;</code></strong>：</p><ul><li>这个命令用于将暂存区中指定文件的更改撤销，同时保留工作目录中的更改。</li><li><code>&lt;file&gt;</code> 是要撤销暂存的文件名。</li><li></li></ul></li><li><p><strong><code>git reset --soft &lt;commit&gt;</code></strong>：</p><ul><li>这个命令将当前分支的 HEAD 指针移动到指定的提交，但保留工作目录和暂存区的更改。</li><li><code>&lt;commit&gt;</code> 是要重置到的提交的引用（如 commit hash、分支名等）。</li></ul></li><li><p><strong><code>git reset --mixed &lt;commit&gt;</code></strong>：</p><ul><li>这个命令将当前分支的 HEAD 指针移动到指定的提交，并重置暂存区，但保留工作目录的更改。</li><li><code>&lt;commit&gt;</code> 是要重置到的提交的引用。</li></ul></li><li><p><strong><code>git reset --hard &lt;commit&gt;</code></strong>：</p><ul><li>这个命令将当前分支的 HEAD 指针移动到指定的提交，并重置暂存区和工作目录，丢弃所有更改。</li><li><code>&lt;commit&gt;</code> 是要重置到的提交的引用。</li></ul></li><li><p><strong><code>git reset --merge</code></strong>：</p><ul><li>这个命令用于解决合并冲突时，取消合并并重置到合并之前的状态。</li></ul></li></ol><p>通过合理使用 <code>git reset</code> 命令及其参数，可以有效地管理 Git 仓库中的提交历史和更改状态。请谨慎使用 <code>git reset --hard</code> 命令，因为它会永久丢弃工作目录中的更改。</p><p>假设工作区文件有 aaa，增加bbb，变成aaa bbb，之后add、commit</p><table><thead><tr><th>工作区</th><th>暂存区</th><th>版本库</th><th>reset携带的选项</th></tr></thead><tbody><tr><td>aaa bbb</td><td>aaa bbb</td><td>aaa</td><td>–soft</td></tr><tr><td>aaa bbb</td><td>aaa</td><td>aaa</td><td>–mixed ：默认选项</td></tr><tr><td>aaa</td><td>aaa</td><td>aaa</td><td>–hard：慎用这个选项</td></tr></tbody></table><p>在工作区修改了很多文件之后，突然发现修改错了，如何恢复？</p><ol><li>手动修改</li><li>使用 git checkout --filename</li></ol><h2 id="查看Git仓库状态">查看Git仓库状态</h2><p>你可以使用以下命令查看Git仓库的状态：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git status</span><br></pre></td></tr></table></figure><h2 id="查看提交历史">查看提交历史</h2><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><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git log</span><br><span class="line">git log --pretty=oneline</span><br><span class="line">git log --pretty=oneline --abbrev-commit</span><br><span class="line">git reflog 查看每次的log 包括撤销</span><br></pre></td></tr></table></figure><ul><li><p><code>--pretty=oneline</code>选项指定了输出格式为每个提交的一行显示，显示的信息包括提交的哈希值和提交信息。这种格式适合在终端中查看提交历史，信息简洁明了。</p></li><li><p><code>--abbrev-commit</code>选项指定了显示的提交哈希值的缩写长度。默认情况下，Git会显示完整的40位哈希值，但使用<code>--abbrev-commit</code>选项可以缩短哈希值的长度，使得显示更加简洁。</p></li></ul><h2 id="标签管理">标签管理</h2><p>在 Git 中，标签（tag）是用来标记特定提交的稳定版本或重要节点的指针。以下是一些常用的 Git 标签操作：</p><ol><li><p><strong>列出所有标签</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git tag</span><br></pre></td></tr></table></figure><p>这个命令会列出所有的标签。</p></li><li><p><strong>创建轻量标签</strong>：</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">git tag &lt;tag_name&gt;</span><br><span class="line">git tag &lt;tag_name&gt; commit_id</span><br></pre></td></tr></table></figure><p>这个命令会在当前提交上创建一个轻量标签，只包含标签名。</p></li><li><p><strong>创建附注标签</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git tag -a &lt;tag_name&gt; -m &quot;tag message&quot;</span><br></pre></td></tr></table></figure><p>这个命令会在当前提交上创建一个附注标签，可以添加标签信息。</p></li><li><p><strong>查看标签信息</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git show &lt;tag_name&gt;</span><br></pre></td></tr></table></figure><p>这个命令会显示指定标签的详细信息。</p></li><li><p><strong>推送标签到远程仓库</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push origin &lt;tag_name&gt;</span><br></pre></td></tr></table></figure><p>这个命令会将指定标签推送到远程仓库。</p></li><li><p><strong>删除本地标签</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git tag -d &lt;tag_name&gt;</span><br></pre></td></tr></table></figure><p>这个命令会删除指定的本地标签。</p></li><li><p><strong>删除远程标签</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push --delete origin &lt;tag_name&gt;</span><br></pre></td></tr></table></figure><p>这个命令会删除指定的远程标签。</p></li></ol><p>Git 中管理标签，标记重要的提交或版本，并与团队共享稳定的版本信息。</p><h2 id="Git分支">Git分支</h2><p>Git允许创建分支来并行开发不同的功能</p><p>创建分支：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch branchname</span><br></pre></td></tr></table></figure><p>要查看本地分支，可以使用以下命令：</p><ol><li><p><strong>查看所有本地分支</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch</span><br></pre></td></tr></table></figure><p>这个命令会列出所有本地分支，并在当前分支前面标记一个 <code>*</code> 符号。</p></li><li><p><strong>查看远程分支和本地分支</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch -a</span><br></pre></td></tr></table></figure><p>这个命令会列出所有本地分支和远程分支。</p></li><li><p><strong>查看本地分支的详细信息</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch -v</span><br></pre></td></tr></table></figure><p>这个命令会列出所有本地分支，并显示每个分支最后一次提交的信息。</p></li></ol><h3 id="切换分支">切换分支</h3><p>要切换到一个不同的分支，可以使用以下命令：</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">git checkout branchname</span><br><span class="line">git checkout -b branchname  # 创建并切换到新的分支</span><br></pre></td></tr></table></figure><h3 id="合并分支">合并分支</h3><p>完成一个功能的开发后，可以将分支合并到主分支。使用以下命令可以实现分支合并：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git merge branchname</span><br></pre></td></tr></table></figure><h3 id="删除分支">删除分支</h3><ol><li><p><strong>删除本地分支</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch -d &lt;branch_name&gt;</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></pre></td><td class="code"><pre><span class="line">git branch -D &lt;branch_name&gt;</span><br></pre></td></tr></table></figure><ul><li><code>-d</code>：表示删除指定分支，如果分支的工作还未合并到当前分支，会提示错误并阻止删除。</li><li><code>-D</code>：表示强制删除指定分支，即使分支的工作还未合并到当前分支也会删除。</li></ul></li><li><p><strong>删除远程分支</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push origin --delete &lt;branch_name&gt;</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></pre></td><td class="code"><pre><span class="line">git push origin :&lt;branch_name&gt;</span><br></pre></td></tr></table></figure><p>这两个命令都可以用来删除远程仓库中的指定分支。</p></li></ol><p>请注意，在删除分支之前，确保不再需要该分支的代码或提交记录。删除分支是一个不可逆的操作，删除后的分支及其提交记录将无法恢复。</p><h3 id="关联分支">关联分支</h3><p>通过以下步骤为当前分支 <code>dev</code> 设置与之关联的远程分支：</p><ol><li><p><strong>手动设置远程分支</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch --set-upstream-to=origin/dev dev</span><br></pre></td></tr></table></figure><p>这个命令会将本地的 <code>dev</code> 分支与远程的 <code>dev</code> 分支建立关联。</p></li><li><p><strong>推送本地分支到远程</strong>：<br>如果需要将本地分支 <code>dev</code> 推送到远程仓库，可以使用以下命令：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push -u origin dev</span><br></pre></td></tr></table></figure><p>这样会将本地的 <code>dev</code> 分支推送到远程仓库，并建立关联。</p></li></ol><p>通过以上步骤，可以解决当前分支没有与之关联的远程分支的问题，并确保在推送或拉取时能够正确同步代码。</p><h2 id="远程开发">远程开发</h2><p>从远程仓库克隆后，实际上 Git 会⾃动把本地的 master 分⽀和远程的 master 分⽀对应起来， 并且，远程仓库的默认名称是 origin 。在本地我们可以使⽤ git remote 命令，来查看远程库的信息</p><p>⽤ git remote -v 显⽰更详细的信息</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">tong@atong3:~/unskilled-vim$ git remote -v</span><br><span class="line">origin  git@github.com:atongrun/unskilled-vim.git (fetch)</span><br><span class="line">origin  git@github.com:atongrun/unskilled-vim.git (push)</span><br></pre></td></tr></table></figure><p>克隆完成仓库之后，git branch -a 查看分支，可以在本地创建分支，通过git checkout -b dev命令，增加并且切换到dev分支</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></pre></td><td class="code"><pre><span class="line">tong@atong3:~/unskilled-vim$ git branch -a</span><br><span class="line">* dev</span><br><span class="line">  main</span><br><span class="line">  remotes/origin/HEAD -&gt; origin/main</span><br><span class="line">  remotes/origin/dev</span><br><span class="line">  remotes/origin/main</span><br></pre></td></tr></table></figure><p>将本地的 <code>dev</code> 分支推送到远程仓库，并将本地的 <code>dev</code> 分支与远程仓库的同名分支建立关联关系</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push --set-upstream origin dev</span><br></pre></td></tr></table></figure><h2 id="推送到远程仓库">推送到远程仓库</h2><p>如果想与团队成员代码，可以将代码推送到远程仓库。首先，添加远程仓库的地址：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add origin remote_repository_url</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></pre></td><td class="code"><pre><span class="line">git push -u origin master</span><br></pre></td></tr></table></figure><p>解决Git冲突是在合并分支或拉取远程更新时可能遇到的情况。下面是解决Git冲突的一般步骤：</p><h3 id="步骤1：检测冲突">步骤1：检测冲突</h3><p>在合并分支或拉取远程更新时，如果Git检测到冲突，会在文件中标记出冲突的部分。可以使用<code>git status</code>命令查看哪些文件有冲突。</p><h3 id="步骤2：打开冲突文件">步骤2：打开冲突文件</h3><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><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD</span><br><span class="line">// 本地分支的更改</span><br><span class="line">=======</span><br><span class="line">// 远程分支的更改</span><br><span class="line">&gt;&gt;&gt;&gt;&gt;&gt;&gt; branch_name</span><br></pre></td></tr></table></figure><h3 id="步骤3：手动解决冲突">步骤3：手动解决冲突</h3><p>根据冲突标记，手动编辑文件以解决冲突。需要决定保留哪些更改或如何合并这些更改。删除冲突标记并保留想要的更改。</p><h3 id="步骤4：标记冲突已解决">步骤4：标记冲突已解决</h3><p>在解决完冲突后，保存文件并使用以下命令标记冲突已解决：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git add &lt;conflicted_file&gt;</span><br></pre></td></tr></table></figure><h3 id="步骤5：完成合并">步骤5：完成合并</h3><p>继续合并分支或拉取远程更新，并完成合并操作：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git commit -m &quot;Merge conflict resolved&quot;</span><br></pre></td></tr></table></figure><h3 id="步骤6：推送更改">步骤6：推送更改</h3><p>如果是在拉取远程更新时解决冲突，完成合并后需要将更改推送到远程仓库：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push</span><br></pre></td></tr></table></figure><p>通过以上步骤，可以解决Git冲突并成功合并分支或拉取远程更新。记得在解决冲突时仔细审查更改，确保代码的完整性和正确性。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Git是一种分布式版本控制系统，可以进行多人的协作开发，基本大部分的软件开发相关的公司都会使用该软件，下边记录一些常用的命令&lt;/p&gt;
&lt;h2 id=&quot;安装Git&quot;&gt;安装Git&lt;/h2&gt;
&lt;p&gt;可以从&lt;a href=&quot;https://git-scm.com/&quot;&gt;Git官方网站</summary>
      
    
    
    
    <category term="工具" scheme="https://atong.run/categories/%E5%B7%A5%E5%85%B7/"/>
    
    <category term="开发工具" scheme="https://atong.run/categories/%E5%B7%A5%E5%85%B7/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
    
    
  </entry>
  
  <entry>
    <title>导航页-工具</title>
    <link href="https://atong.run/posts/3356543462/"/>
    <id>https://atong.run/posts/3356543462/</id>
    <published>2024-05-02T15:40:56.140Z</published>
    <updated>2024-05-02T16:03:19.456Z</updated>
    
    <content type="html"><![CDATA[<h1>AI</h1><h2 id="1、AIGC-API">1、<a href="https://aigcapi.io/register?aff=baMV">AIGC-API</a></h2><p>提供高效且稳定的OpenAI聚合API，支持GPT-4 Turbo、DALL·E等OpenAI全模型和大量AI应用及框架，无论开发AI产品、训练自有模型，都能提供全面的支持。</p><p>链接：<a href="https://aigcapi.io/register?aff=baMV">即刻注册，免费畅享$1美金测试额度！按量付费</a></p><h1>web3</h1><h2 id="1、欧意钱包">1、<a href="https://okx.com/join/47070401">欧意钱包</a></h2>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;AI&lt;/h1&gt;
&lt;h2 id=&quot;1、AIGC-API&quot;&gt;1、&lt;a href=&quot;https://aigcapi.io/register?aff=baMV&quot;&gt;AIGC-API&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;提供高效且稳定的OpenAI聚合API，支持GPT-4 Turbo、DALL</summary>
      
    
    
    
    <category term="推荐" scheme="https://atong.run/categories/%E6%8E%A8%E8%8D%90/"/>
    
    
  </entry>
  
  <entry>
    <title>lobechat聊天机器人介绍与docker部署（有坑需注意）</title>
    <link href="https://atong.run/posts/621459748/"/>
    <id>https://atong.run/posts/621459748/</id>
    <published>2024-02-16T15:09:12.352Z</published>
    <updated>2024-02-21T13:42:09.516Z</updated>
    
    <content type="html"><![CDATA[<h1>1 lobechat介绍</h1><blockquote><p>官方介绍：LobeChat 是一个开源、高性能的聊天机器人框架。支持语音合成、多模态和可扩展插件系统。支持一键式免费部署私人ChatGPT/LLM 网络应用程序。</p></blockquote><p>lobechat的<a href="https://github.com/lobehub/lobe-chat/tree/main">github-lobe-chat🤖</a>上有详细的文档介绍（中英文都有）并且有着discord社区，这个东西呢，就相当于部署自己的一个私人的chatgpt服务，那么重点是我为什么不直接用chatgpt而去选择部署使用lobechat呢，文档给出了下面的几个优点：</p><ol><li>GPT 视觉认知</li><li>TTS &amp; STT 语音会话</li><li>Text to Image 文生图</li><li>Function Calling 插件系统</li><li>助手市场</li><li>PWA 渐进式 Web 应用</li><li>移动设备适配</li><li>自定义主题</li></ol><p>对我而言，有两个地方比较吸引我，第一个是它的插件系统，有着非常丰富的插件市场，对我来说，我装了一些学术与搜索相关的插件，日常使用还是挺方便的</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402162202322.png" alt="image.png"></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402162155844.png" alt="image.png"></p><p>当然吸引我的第二个点就是有超级多的预设助手，有各个方面的，能够大大减少我们想提示词等相关的难度</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402162144992.png" alt="image.png"></p><p>我装了下边的几个助手，这个地方的塔罗占卜师的助手还挺有意思的</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402162144589.png" alt="image.png"></p><p>当然，选择这个框架还有一个原因，就是部署特别简单，用docker几行命令就OK，官方的文档非常详细（但是用三方的api服务的话还需要有注意的地方，下边细说）</p><p><a href="https://github.com/lobehub/lobe-chat/blob/main/README.zh-CN.md">lobe-chat中文文档</a></p><h1>2 lobechat使用docker部署</h1><p>LobeChat 提供了 Vercel 的 自托管版本 和 <a href="https://hub.docker.com/r/lobehub/lobe-chat">Docker 镜像</a>，不需要任何的编程知识，就可以在几分钟部署自己的聊天机器人，这里主要说如何使用docker部署</p><h2 id="2-1-使用官方api">2.1 使用官方api</h2><p>使用openai的官方api的话最，只需要填写一个key值就可以，也就是将sk-xxxx替换成自己的key。<a href="https://platform.openai.com/docs/overview">OpenAI API官网</a>中找到API keys，然后创建复制即可，然后在终端中运行如下命令</p><figure class="highlight bash"><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">docker run -d -p 3210:3210 \\</span><br><span class="line">  -e OPENAI_API_KEY=sk-xxxx \\</span><br><span class="line">  -e ACCESS_CODE=lobe66 \\</span><br><span class="line">  --name lobe-chat \\</span><br><span class="line">  lobehub/lobe-chat</span><br></pre></td></tr></table></figure><p>注意上边的命令中，ACESS_CODE和name选项都可以自定义，第一个是使用密码（使用的时候首先要输入密码），第二个是服务的名字。</p><h2 id="2-2-使用第三方api">2.2 使用第三方api</h2><p>使用三方的API是有点坑的，有没弄好的地方就可能部署失败，我是用的<a href="https://aigcapi.io/register?aff=baMV">AIGC-API的三方API</a>，兼容各种主流AI，支持GPT-4 Turbo、DALL·E等OpenAI全模型和大量AI应用及框架，价格还是比较便宜的，重点是可以支付宝啥的付费，openai官方的api充值贵，而且我们充值的难度太大~</p><figure class="highlight bash"><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">docker run -d -p 3210:3210 \\</span><br><span class="line"> -e OPENAI_API_KEY=sk-xxxx \\</span><br><span class="line"> -e OPENAI_PROXY_URL=https://api-proxy.com/v1 \\</span><br><span class="line"> -e ACCESS_CODE=lobe66 \\</span><br><span class="line"> --name lobe-chat \\</span><br><span class="line"> lobehub/lobe-chat</span><br></pre></td></tr></table></figure><p>将 <a href="https://api-proxy.com">https://api-proxy.com</a> 替换成第三方的url，如果你要是用AIGC的API，需要将这个替换成：<a href="https://api.aigcapi.io">https://api.aigcapi.io</a>，注意不要将后边的v1选项漏掉了，OPENAI_API_KEY选项就填写AIGC令牌的key值即可，然后终端运行上边的命令</p><p>如果没有替换OPENAI_PROXY_URL，会部署失败，如果漏掉v1，会出现回复异常，回复的都是空白，如下图所示</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402162122441.png" alt="image.png"></p><h1>3 lobechat升级</h1><p>lobechat项目还是比较火的，更新也比较多，更新的流程也是非常的简单</p><ol><li>停止并删除当前正在运行的 LobeChat 容器</li></ol><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">docker stop lobe-chat</span><br><span class="line">docker rm lobe-chat</span><br></pre></td></tr></table></figure><ol start="2"><li>拉取 LobeChat 的最新 Docker 镜像：</li></ol><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">docker pull lobehub/lobe-chat</span><br></pre></td></tr></table></figure><ol start="3"><li>使用刚拉取的docker镜像重新部署：</li></ol><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></pre></td><td class="code"><pre><span class="line">docker run -d -p 3210:3210 \</span><br><span class="line">  -e OPENAI_API_KEY=sk-xxxx \</span><br><span class="line">  -e OPENAI_PROXY_URL=https://api-proxy.com/v1 \</span><br><span class="line">  -e ACCESS_CODE=lobe66 \</span><br><span class="line">  --name lobe-chat \</span><br><span class="line">  lobehub/lobe-chat</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;1 lobechat介绍&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;官方介绍：LobeChat 是一个开源、高性能的聊天机器人框架。支持语音合成、多模态和可扩展插件系统。支持一键式免费部署私人ChatGPT/LLM 网络应用程序。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p</summary>
      
    
    
    
    <category term="人工智能" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/"/>
    
    <category term="使用AI" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/%E4%BD%BF%E7%94%A8AI/"/>
    
    
    <category term="工具" scheme="https://atong.run/tags/%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>小米14购买使用体验</title>
    <link href="https://atong.run/posts/4092410180/"/>
    <id>https://atong.run/posts/4092410180/</id>
    <published>2024-02-16T04:04:55.581Z</published>
    <updated>2024-02-16T04:29:01.610Z</updated>
    
    <content type="html"><![CDATA[<h1>1-购买手机之前</h1><h2 id="1-1-预算与选择">1.1-预算与选择</h2><p>小米14买了大概10几天了，用了这几天也简单聊聊我的使用感受，我在买手机的时候预算5k，这个价位的手机有如下几个，但是最终都没选而是选择了小米14：</p><ul><li>小米14pro</li><li>荣耀magic6pro</li><li>vivo x100 pro</li><li>oppo find x7</li><li>苹果 15</li></ul><h2 id="1-2-手机权衡">1.2-手机权衡</h2><p>当然还其实有魅族什么的，但是不大敢买，我内心最认可的两个牌子是华为和苹果，口碑、质量以及稳定性都比较好，但是好点的手机价格也相当较高，基本不是很考虑了。</p><p>内心的第二梯队就是小米、vivio、oppo和荣耀，因为我上一部手机是红米的k40 gaming，用了不到三年就硬件出现问题，去售后维修，工作人员说他们那没法修，可能是CPU问题，只能返厂，所以我对小米的品控和质量是有所怀疑的</p><p>而且小米的2000-3000挡手机用1年以上会有一定的卡顿，k40g就是一个例子，虽然整体还算ok但是无论打游戏还是日常使用，时不时的卡是家常便饭，小米的系统大家都了解，就是bug比较多~</p><p>但是为什么小米还是我心里的第二梯队了，三个原因：</p><ul><li>一是因为小米的<strong>硬件</strong>性价比还是可以的；</li><li>二是因为这两年相机拍照做的还可以；</li><li>第三是因为小米的其他的杂七杂八的做的还可以，比如手环、小家电什么的</li></ul><p>当时上边的几部手机其实挺好选择，我首先想要拍照较好，就是随手拍能出图一点，硬性要求是充电要比较快，苹果15直接被pass，而且苹果15没有高刷，当然我挺喜欢15p和15pm，不过价格太高买不起。</p><p>荣耀magic6pro我感觉硬件不错的，超长续航，最护眼的屏幕，3D人脸…，都很吸引我，但是呢荣耀这个机子的外观我实在喜欢不起来，摄像头模组我感觉甚至有些丑，而且荣耀的拍照是比其他的几家稍微差一点，并且比较关键的一点是我需要Google生态，而荣耀装Google应该不是很容易~</p><p>然后就是oppo vivo和小米14pro选择，我直接把oppo排除了，看了看视频评测，好像整体是平平无奇的，拍照似乎也没另外两家好，所以就想在vivo x100p和小米14p中选择一款</p><p>x100p优点很多，外观我喜欢，拍照水平好像也非常顶，应该是上边几个拍第一的，并且vivo的橘子系统是安卓阵营的天花板，薄纱小米澎拜，但是vivo有两个地方我非常受不了，一个是线上线下价钱不一样，好像线上讲讲价会便宜不少，我总觉的会吃亏（不会讲价），二是屏幕好像有点辣眼睛</p><h2 id="1-3-最终选择">1.3-最终选择</h2><p>小米14pro呢就是别的地方都中规中矩，拍照还不错，当时我已经下单了，但是当我去店里实际体验了一下小米14pro之后，就有点想放弃了，摄像头模组太大了，拿着有点不舒服</p><p>当时我就看见旁边的小米14，拿起来感觉手感比小米14pro好多了，而且小米14的屏幕是直屏，这点真是非常的戳我，并且粉色的那一个猛男粉太爱了，相比14pro的提升（龙晶玻璃、更好一点的拍照，更快一点的快充），小米14好像已经满足我需求可，整体还便宜1000块钱</p><p>于是果断去店里拿下了小米14，小米之家送了一个耳机礼盒（耳机、笔记本、笔）和一个体重秤，线下还不错，线上应该是不会送体重秤的</p><h1>2-小米14体验</h1><h2 id="2-1-外观手感">2.1-外观手感</h2><p>小米14的外观我是感觉还可以的（就是摄像头模组不大好看），但是摄像头模组整体比小米14Pro做的要小一些的，再加上手机小，拿在手上还是非常舒服的，很适合单手操作，估摸着姑娘们应该挺喜欢这个手机，并且小米14是直屏（贴膜比曲屏简单太多啦）</p><p>当时店里是有白色、黑色、绿色、和粉色，白色和绿色是镜面玻璃，挺粘指纹的，白色的特别好看，绿色一般吧，黑色也一般，但是材质是磨砂玻璃的不容易搞上指纹，当然最好看的和拿着最舒服的是素皮的粉色，猛男粉男的可以充一手</p><p>小米14的外观还有一个比较新颖的地方，它的手机上边没有喇叭开孔，但是这个手机依然是双扬声器</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402161222878.jpeg" alt="Untitled"></p><h2 id="2-2-充电续航">2.2-充电续航</h2><p>充电速度很快90w快充，体验起来还是非常快速的，特别是冲到80左右电量极其的快，30多分钟差不多充满</p><p>但是小米14的续航也一般吧，不过也能理解，毕竟电池容量只有4610，日常轻度使用应该可以一天一充，在家的时候总是刷抖音和打游戏差不多一天要三充，甚至更多， 特别是打手游的时候耗电还是挺快的，我现在用的版本是1.31</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402161220112.jpeg" alt="Untitled"></p><h2 id="2-3-澎湃系统">2.3-澎湃系统</h2><p>小米的澎湃系统，好像还是有一些bug的，最常见的bug是锁屏的那个时间日期显示，时不时的会倒过来，也不知道是为什么，还有就是有时候操作会顿挫一下，就像是卡了，这个情况遇到了两次，另外就是打英雄联盟手游，操作偶尔也会出现不跟手的情况，就很短暂的一瞬间</p><p>其他的一些动画上好像比miui强一些，但是整体和miui好像一模一样的，没啥特别大的区别，好像是如果米家设备多的话，交互上会比较舒服，但是我没啥设备，就不清楚具体有多好了</p><h2 id="2-4-拍照体验">2.4-拍照体验</h2><p>然后呢拍照好像还可以，随手拍也能有点感觉，比我之前的手机拍照已经好太多了，但是拍远处的东西的效果不是很好，可能是没有潜望镜头的原因，拍近处的东西ok的</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402161218441.jpeg" alt="Untitled"></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202402161219443.jpeg" alt="Untitled"></p><h2 id="2-5-其他优缺点">2.5-其他优缺点</h2><p>小米14最大的优点之一是装Google特别简单，小米应用商店里面就能下载Google play，我当时看到惊讶坏了，有可能小米14是装Google生态最简单的手机了~</p><p>小米14的指纹方案是用的短焦指纹，指纹解锁对准很快，对的不准，解锁速度就一般般了，但是指纹解锁有一个很讨厌的缺点，就是指纹解锁的瞬间，指纹模块的那个位置会突然亮一下，很刺眼，有设置可以在暗光的条件下关闭这个突然一亮，但是我实际测试关闭并没有什么效果</p><p>但是指纹模块也很智能，可以设置在息屏显示一个圈，方便找到指纹的位置，他这个地方最好的一点是当你没拿起手机的时候是全息屏的，当你拿起手机的时候会有这个息屏显示方便定位，可能是有什么传感器感应</p><h1>3-购机总结</h1><p>总的来说还可以吧，女生还是比较推荐的，而且如果想要选择小直屏，综合来看只能选择小米14了（苹果15和三星的也比小米14贵一些）</p><h2 id="3-1-标准版本购买">3.1-标准版本购买</h2><p>小米14 徕卡镜头 光影猎人900定制影像传感器第三代骁龙8处理器1.5K OLED直屏5G智能手机 白色 16GB+512GB<br>———————<br>京东价：￥4599.00</p><p>抢购链接：<a href="https://u.jd.com/jbX0KdA">https://u.jd.com/jbX0KdA</a></p><h2 id="3-2-限定配色">3.2-限定配色</h2><blockquote><p>海湾蓝是和小米汽车su7同款配色，看着到是也挺好看</p></blockquote><p>小米14 徕卡光学镜头 光影猎人900 徕卡75mm浮动长焦 骁龙8Gen3 16+1T 定制色海湾蓝 小米红米手机 5G<br>———————<br>京东价：￥4999.00</p><p>抢购链接：<a href="https://u.jd.com/jqXrvNZ">https://u.jd.com/jqXrvNZ</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;1-购买手机之前&lt;/h1&gt;
&lt;h2 id=&quot;1-1-预算与选择&quot;&gt;1.1-预算与选择&lt;/h2&gt;
&lt;p&gt;小米14买了大概10几天了，用了这几天也简单聊聊我的使用感受，我在买手机的时候预算5k，这个价位的手机有如下几个，但是最终都没选而是选择了小米14：&lt;/p&gt;
&lt;ul&gt;
&lt;</summary>
      
    
    
    
    <category term="自用好物" scheme="https://atong.run/categories/%E8%87%AA%E7%94%A8%E5%A5%BD%E7%89%A9/"/>
    
    
    <category term="手机" scheme="https://atong.run/tags/%E6%89%8B%E6%9C%BA/"/>
    
  </entry>
  
  <entry>
    <title>期待这么久，Obsidian表格功能终于更新，类似notion的编辑体验！</title>
    <link href="https://atong.run/posts/611591199/"/>
    <id>https://atong.run/posts/611591199/</id>
    <published>2023-12-26T12:59:06.553Z</published>
    <updated>2023-12-26T13:04:16.867Z</updated>
    
    <content type="html"><![CDATA[<p>今天打开obsidian发现版本更新，现在是v1.5.3，看了一下官网更新日志，发现<strong>表格编辑</strong>功能终于更新！！！</p><p>以前 obsidian最让人诟病的就是表格功能，对于一个可以 all in one 的笔记软件来说，表格编辑功能还是基本纯原生的 markdown 表格的写法，基本是让人难以忍受就的。</p><p>当然 obsidian 社区插件生态很丰富，很多大神也开发了一些对应的表格增强的插件，我开始也尝试过：</p><ul><li>插件1：advanced table</li><li>插件2：markdown table editor</li></ul><p>对于插件1来说，只是对于原生 markdown 表格的轻微增强版，并没有真正的方便普通人编辑，我用的时候，超过3行3列的表会直接放弃用obsidian。并且obidian的表格展示效果并不友好。</p><p>在逛 obsidian 社区的时候，偶尔发现了插件2，装上之后有点惊叹，表格功能竟然能用了，如下图所示，在编写文章有插入表格需求时点击左侧边栏图标，会自动将页面分为两列，表格可以自定义几行几列，增删查改功能几乎可以方便轻度的使用</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202312262034119.png" alt="image.png"></p><p>但是呢，在大表格编辑以及展示，还有部分微调，也不是很灵活，只能说可以使用，没有太好的体验，不过再这次更新之后，obsidian 的表格使用下来竟然有了 notion 表格的体验，并且编辑的表格在保存时仍按照纯文本形式的markdown保存</p><p>具体使用起来也是非常简单，在写作时，右键点击插入，再点击 Table 即可，具体如下图所示：</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202312262039675.png" alt="image.png"></p><p>obsidian 的表格更新后，显示效果大大增强，编辑体验上已经类似 notion了，并且，鼠标放在表格上下左右侧，会显示出一个加号，点击即可插入行或者列。<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202312262041460.png" alt="image.png"><br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202312262042362.png" alt="image.png"></p><p>并且另外一大改变是 obsidian 表格变成了块的形式，可以很轻易的选取整个表格，或者某行或者某列，进行拖动或者编辑，实际体验非常丝滑！<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202312262042593.png" alt="image.png"></p><p>这次的 obsidian 的更新可以说完全解决了表格不好用这个最大的痛点，advanced table插件完全可以卸载，包括markdown table editor，期待obsidian越来越好！</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;今天打开obsidian发现版本更新，现在是v1.5.3，看了一下官网更新日志，发现&lt;strong&gt;表格编辑&lt;/strong&gt;功能终于更新！！！&lt;/p&gt;
&lt;p&gt;以前 obsidian最让人诟病的就是表格功能，对于一个可以 all in one 的笔记软件来说，表格编辑功能还</summary>
      
    
    
    
    <category term="工具" scheme="https://atong.run/categories/%E5%B7%A5%E5%85%B7/"/>
    
    <category term="obsidian" scheme="https://atong.run/categories/%E5%B7%A5%E5%85%B7/obsidian/"/>
    
    
  </entry>
  
  <entry>
    <title>2023-9-17-第35周 周记</title>
    <link href="https://atong.run/posts/3068727690/"/>
    <id>https://atong.run/posts/3068727690/</id>
    <published>2023-09-17T06:10:07.180Z</published>
    <updated>2024-01-13T13:18:37.610Z</updated>
    
    <content type="html"><![CDATA[<p>第一周周记，这是一次学习和坚持的尝试，差不多有三个核心点吧，整体思路和形式来自《认知觉醒》和 印记。</p><ol><li>用每天记录的形式代替每天的打卡，比起打卡模式，记录没有打卡的任务压力，可以将注意力集中到活动本身，而不是完成任务上，</li><li>对每天设置的小任务来说不设置上线，设置下限，我希望的是完成目标毫无负担，愿意顺着惯性继续学下去，多学一点都是额外的收获，心态完全不同，身心容易沉浸，不会顾虑什么时候才能完成任务</li><li>发布社交媒体账号，可以自我push~</li></ol><p>目前先采用这种形式吧，以后根据实际情况在修改细节部分</p><h2 id="2023-09-14-周四">2023-09-14-周四</h2><h4 id="一天安排">一天安排</h4><ul><li>[x] 看一集生活大爆炸 看了两集</li><li>[x] 两道题  边界处理细节问题</li><li>[x] 10个单词  30</li><li>[x] 自我拯救系列简单规划</li><li>[ ] 仿真交叉对比   (不成功~)</li><li>[x] 投递1~2个简历  北京 - 济南</li></ul><h4 id="memo">memo</h4><p>我觉得能够长期坚持一些事情有两个核心点：</p><p>一是要做适当的规划，一个比较合适的方式是将代办事项写在纸上或者记在软件上，有个著名的方法叫做GTD ， 这个方法规划任务分为五个步骤：收集、厘清、整理、检查、执行，我大概尝试了一下，并不是很适合我，这种猛地一看会有种复杂感，让对做规划和做任务清单这件事情，天然的变成了一个麻烦的任务，可能会直接导致规划与任务同时都放弃了~</p><p>为了不在规划这件事情上耗费太大经历，还是决定在obsidian上做这件事情，通过日记的形式简单做一些规划，日记的栏目只有安排和memo，安排栏只做一些简单的列表，随时添加修改，memo栏写点日常总结感想，简单并且契合日常学习工作流~</p><p>二是是坚持的事情要足够简单，很多时候总是觉得可能兴趣驱动最合适，但是兴趣驱动可能会导致规划的事情随时突破个人能力边界，一是不一定按时完成，二是可能会受挫。所以还是简单最容易坚持，定的任务足够简单，这样不仅可以轻松完成，而且时不时会超额完成~</p><p>B站关注的UP将每天多喝水作为一个任务，这个简直是不要太好，无痛完成，完成后可能还有小小的成就感~，所以呢，最近的任务规划就很简单，比如每天只背10个单词，比如看一集生活大爆炸，再比如刷两道算法题（这个可能不是很简单）~</p><p>总之呢简单才会有干劲~，今天是研三自我拯救的第一天，整体流程和方式大致确定，obsidian记录还有一个好处，如果写周记的化，可以轻松使用双链功能将每天的日记链接起来，到时候可以发布到博客平台</p><h2 id="2023-09-15-周五">2023-09-15-周五</h2><h4 id="一天安排-2">一天安排</h4><ul><li>[x] 1集生活大爆炸</li><li>[x] 晚上少吃点</li><li>[x] 详细看一篇论文</li><li>[x] 10个单词  30</li><li>[x] 一个题  两个可能太花费时间 无法保证 先从一个做起</li></ul><h4 id="memo-2">memo</h4><p>找工作真麻烦呀，我看到996这种，连投递的欲望都没有，虽然人家公司也看不上我，我想找双休的企业，但是看了一圈应该只有外企能这样</p><p>下午的时候某家企业给我打电话，说是技术面，我接到电话，两个感觉，一是觉得懵逼和紧张，二是觉得这家企业怎么下午6点面试，这不意味着加班挺严重呀</p><p>技术面也挺快，不到10分钟吧，瞎问问就完事了，随便问的东西都不怎么知道，但是呢，还给我说，薪资和其他条件会和人事谈，可能是打算招吧</p><p>总体觉的这个面试，奇奇怪怪，不管怎么样，我是不打算去，今天细细的看了下一篇SCI，看着好像有一些写法可以借鉴，给了我一点思路，这周六周天应该能把论文搞定了~</p><p>附：今天打算的memo，打算截图，发现obsidian字体非常小，放大之后很丑，看了一下网上推荐<strong>霞鹜文楷</strong>字体，看着倒是挺舒服，就整了一下，安装非常简单，windows的cmd用scoop一键安装即可~</p><p>scoop bucket add nerd-fonts &amp;&amp; scoop install LXGWWenKaiMono</p><h2 id="2023-09-16-周六">2023-09-16-周六</h2><h4 id="一天安排-3">一天安排</h4><ul><li>[x] 10个单词  20</li><li>[x] 1道题 2</li><li>[x] 生活大爆炸1集</li><li>[ ] 详细看一篇论文</li></ul><h4 id="memo-3">memo</h4><p>周六懒得动，简单看了点论文，日常小任务继续保持中，今天开始x不会发每日长文memo了，x不开会员不能能发超过100字属实挺麻烦，但是x对博客外链非常友好，会直接抓取显示封面图什么的，所以以后长文memo只在微博发，短文和总结周记写博客在x发布~</p><p>不过今天有个很让人高兴的事情是namesilo做活动，1美元拿下了一年的.com域名: <a href="http://zsjsc.com">zsjsc.com</a>（芝士就是菜拼音首字母缩写），挺开心，com顶级域名认识的人更多一些，目前只301定向到了我的博客，也不知道干啥可能也会建站吧~</p><p>hi</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;第一周周记，这是一次学习和坚持的尝试，差不多有三个核心点吧，整体思路和形式来自《认知觉醒》和 印记。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用每天记录的形式代替每天的打卡，比起打卡模式，记录没有打卡的任务压力，可以将注意力集中到活动本身，而不是完成任务上，&lt;/li&gt;
&lt;li&gt;对每天设置</summary>
      
    
    
    
    <category term="周记" scheme="https://atong.run/categories/%E5%91%A8%E8%AE%B0/"/>
    
    
    <category term="周记" scheme="https://atong.run/tags/%E5%91%A8%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>Linux常见指令和权限理解</title>
    <link href="https://atong.run/posts/4088855701/"/>
    <id>https://atong.run/posts/4088855701/</id>
    <published>2023-08-25T15:31:39.008Z</published>
    <updated>2024-01-10T13:40:38.864Z</updated>
    
    <content type="html"><![CDATA[<p><a name="NHy6H"></a></p><h2 id="常见指令">常见指令</h2><p><strong>目录</strong></p><ol><li>ls/cd/pwd</li><li>对文件操作</li><li>查看文件内容</li><li>查找</li><li>打包压缩</li></ol><p><img src="https://cdn.nlark.com/yuque/0/2022/jpeg/29247941/1664609273815-88fa2311-a0b3-4cd9-8351-f3116eee0919.jpeg" alt=""></p><p><a name="uWWyr"></a></p><h2 id="其他一些命令">其他一些命令</h2><p><code>whoami/clear/rmdir/date/cal/alias/bc/uname</code></p><p><img src="https://cdn.nlark.com/yuque/0/2022/jpeg/29247941/1664614185712-5ee18bb3-2a41-40e9-8f7c-28f103df093c.jpeg" alt=""></p><p><a name="w4LOW"></a></p><h2 id="基础知识">基础知识</h2><p><strong>目录</strong></p><ol><li>linux用户相关</li><li>路径认识</li><li>热键</li><li>重定向</li><li>shell运行原理</li><li>权限</li></ol><p><img src="https://cdn.nlark.com/yuque/0/2022/jpeg/29247941/1664613979039-e99218c0-df76-4858-aa03-d87590af5a02.jpeg" alt=""></p><p><a name="GIKiU"></a></p><h2 id="ACM时间">ACM时间</h2><p>ACM时间：stat + 文件名 查看文件状态<br /><img src="https://cdn.nlark.com/yuque/0/2022/png/29247941/1657684182790-81d8a17d-1739-41dd-90ce-61489b5dfb73.png#averageHue=%230c0a08&amp;clientId=u218417b2-f620-4&amp;from=paste&amp;height=99&amp;id=IrMkd&amp;originHeight=197&amp;originWidth=891&amp;originalType=binary&amp;ratio=1&amp;rotation=0&amp;showTitle=false&amp;size=24817&amp;status=done&amp;style=none&amp;taskId=u8126d440-166d-4bf4-88aa-cd4232145ae&amp;title=&amp;width=445.5" alt="image.png"></p><ul><li>Access：文件最后访问时间</li><li>Modify：文件最后修改时间</li><li>Change：对文件最后的Inode信息最后修改时间</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;&lt;a name=&quot;NHy6H&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;常见指令&quot;&gt;常见指令&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;目录&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ls/cd/pwd&lt;/li&gt;
&lt;li&gt;对文件操作&lt;/li&gt;
&lt;li&gt;查看文件内容&lt;/li&gt;
&lt;li&gt;查找</summary>
      
    
    
    
    <category term="Linux" scheme="https://atong.run/categories/Linux/"/>
    
    <category term="基础" scheme="https://atong.run/categories/Linux/%E5%9F%BA%E7%A1%80/"/>
    
    
    <category term="linux" scheme="https://atong.run/tags/linux/"/>
    
  </entry>
  
  <entry>
    <title>个人AI笔记知识库-钉钉个人版（内测），确定不来试试么？</title>
    <link href="https://atong.run/posts/1767113451/"/>
    <id>https://atong.run/posts/1767113451/</id>
    <published>2023-08-17T07:35:56.329Z</published>
    <updated>2023-08-17T07:38:46.598Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>今天打开阿里云盘突然提示钉钉个人内测版本推送，打开一看，好家伙，钉钉什么时候搞的这么酷了！大体一看类似于notion的页面，结合AI功能，直接有点牛波一了，如果你是笔记+AI重度用户，绝对值的一试。</p></blockquote><p>我个人是有记笔记的习惯的，也尝试过很多不同的笔记软件，从最开始的typora到语雀，再到现在的obsidian，也算一个重度的markdown笔记用户了。</p><p>为什么突然会说这个钉钉个人版本呢，钉钉个人版本除了基础的各种笔记功能之外，主要还集成了AI创作服务，关键是现在是免费的（包括文生文、文生图、角色对话、以及AI创作服务）</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202308171416026.png" alt="image.png"></p><p>我个人是AI的重度用户（ChatGPT、Cloude）基本天天用，目前钉钉的AI是阿里的大模型：通义千问、通义万相，分别负责文本生成和图片生成。</p><p>下面是普通文档，按空格建就能调出AI写作。下边图片的文字部分就是由钉钉AI完成。</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202308171427213.png" alt="image.png"></p><p>当然钉钉这种写程序也是OK的，最左侧这一栏，第二个就是AI创作的选项，贾维斯基于通义千问，可以写文档，写代码，并且钉钉个人版本提供了很多预设的指令。</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202308171433667.png" alt="image.png"></p><p>缪斯基于通义万象，就类似于midjourney，通过文本描述，它能生成对应的图片。</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202308171438456.png" alt="image.png"></p><p>整体来说，AI创作功能还是挺好使的，这个钉钉呢，还有几个优点，一个是可以直接访问阿里云盘，这样在某些场景下可以说是非常方便了。另一个和notion一样，钉钉个人版呢，很贴心的准备了很多常用的模板。</p><p>比如：四象限工作中心</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202308171443190.png" alt="image.png"></p><p>比如：旅游 checklist</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202308171443213.png" alt="image.png"></p><p>当然呢，还有很多其他的模板，大家有兴趣可以自己尝试尝试。</p><p>还有一个网盘功能，这个就是阿里云的网盘，这个整个生态还是挺不错的，直接网盘文件+笔记</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202308171449674.png" alt="image.png"></p><p>下边是内测链接，现在申请5分钟之内就能通过，感兴趣的小伙伴们可以试试，还有不少其他的功能呢。</p><p><a href="https://workspace.dingtalk.com/welcome">https://workspace.dingtalk.com/welcome</a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;今天打开阿里云盘突然提示钉钉个人内测版本推送，打开一看，好家伙，钉钉什么时候搞的这么酷了！大体一看类似于notion的页面，结合AI功能，直接有点牛波一了，如果你是笔记+AI重度用户，绝对值的一试。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我个人</summary>
      
    
    
    
    <category term="工具" scheme="https://atong.run/categories/%E5%B7%A5%E5%85%B7/"/>
    
    <category term="笔记" scheme="https://atong.run/categories/%E5%B7%A5%E5%85%B7/%E7%AC%94%E8%AE%B0/"/>
    
    
    <category term="软件" scheme="https://atong.run/tags/%E8%BD%AF%E4%BB%B6/"/>
    
  </entry>
  
  <entry>
    <title>ctemplate，安装以及出现报错处理方式</title>
    <link href="https://atong.run/posts/3029439889/"/>
    <id>https://atong.run/posts/3029439889/</id>
    <published>2023-07-22T12:04:11.321Z</published>
    <updated>2023-07-22T12:08:27.418Z</updated>
    
    <content type="html"><![CDATA[<h1>简介</h1><p>Google CTemplate是一个开源的C++模板引擎，可以生成html文件，今天安装出现一些问题，在此将遇到的问题以及解决方式记录下来# 简介</p><h1>安装</h1><ol><li><code>git clone https://github.com/OlafvdSpek/ctemplate.git</code></li><li><code>cd ctemplate</code></li><li><code>./autogen.sh</code></li><li><code>./configure</code></li><li><code> make</code></li><li><code>sudo make install（注意带sudo）</code></li></ol><h1>出现问题1</h1><p>安装ctemplate出现问题 <code>autoreconf: command not found</code></p><p>解决方式：<br>运行：<code>sudo yum install -y autoconf automake libtool</code></p><h2 id="出现问题2">出现问题2</h2><p>编写测试程序运行遇到报错：<br><code>./mytest: error while loading shared libraries: libctemplate.so.3: cannot open shared object file: No such file or directory</code></p><p>解决方式：<br>运行：<code>export LD\_LIBRARY\_PATH=$LD\_LIBRARY\_PATH:/usr/local/lib</code></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;简介&lt;/h1&gt;
&lt;p&gt;Google CTemplate是一个开源的C++模板引擎，可以生成html文件，今天安装出现一些问题，在此将遇到的问题以及解决方式记录下来# 简介&lt;/p&gt;
&lt;h1&gt;安装&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;git clone https://g</summary>
      
    
    
    
    <category term="Linux" scheme="https://atong.run/categories/Linux/"/>
    
    <category term="软件安装" scheme="https://atong.run/categories/Linux/%E8%BD%AF%E4%BB%B6%E5%AE%89%E8%A3%85/"/>
    
    
    <category term="问题记录" scheme="https://atong.run/tags/%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95/"/>
    
  </entry>
  
  <entry>
    <title>4、负载均衡式在线OJ-编译运行(网络)</title>
    <link href="https://atong.run/posts/1958496611/"/>
    <id>https://atong.run/posts/1958496611/</id>
    <published>2023-07-15T01:56:33.345Z</published>
    <updated>2023-07-15T01:57:36.024Z</updated>
    
    <content type="html"><![CDATA[<h2 id="httplib下载">httplib下载</h2><p><a href="https://github.com/yhirose/cpp-httplib/releases/tag/v0.7.15">cpp-httplib-v0.7.15下载</a></p><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;compile_run.hpp&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;../common/httplib.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> httplib;</span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> ns_compile_and_run;</span><br><span class="line"><span class="comment">//编译服务随时可能被多个人请求，必须保证传递上来的code，形成源文件名称的时候，要具有</span></span><br><span class="line"><span class="comment">////唯一性，要不然多个用户之间会互相影响</span></span><br><span class="line"><span class="comment">//int main()</span></span><br><span class="line"><span class="comment">//&#123;</span></span><br><span class="line"><span class="comment">//    //提供的编译服务，打包形成一个网络服务</span></span><br><span class="line"><span class="comment">//    //cpp-httplib</span></span><br><span class="line"><span class="comment">//    // in_json: &#123;&quot;code&quot;: &quot;#include...&quot;, &quot;input&quot;: &quot;&quot;,&quot;cpu_limit&quot;:1, &quot;mem_limit&quot;:10240&#125;</span></span><br><span class="line"><span class="comment">//    // out_json: &#123;&quot;status&quot;:&quot;0&quot;, &quot;reason&quot;:&quot;&quot;,&quot;stdout&quot;:&quot;&quot;,&quot;stderr&quot;:&quot;&quot;,&#125;</span></span><br><span class="line"><span class="comment">//    // 通过http 让client 给我们 上传一个json string</span></span><br><span class="line"><span class="comment">//    // 下面的工作，充当客户端请求的json串</span></span><br><span class="line"><span class="comment">//    std::string in_json;</span></span><br><span class="line"><span class="comment">//    Json::Value in_value;</span></span><br><span class="line"><span class="comment">//    //R&quot;()&quot;, raw string</span></span><br><span class="line"><span class="comment">//    in_value[&quot;code&quot;] = R&quot;(#include&lt;iostream&gt;</span></span><br><span class="line"><span class="comment">//    int main()&#123;</span></span><br><span class="line"><span class="comment">//        std::cout &lt;&lt; &quot;你可以看见我了&quot; &lt;&lt; std::endl;</span></span><br><span class="line"><span class="comment">//        std::cout &lt;&lt; &quot;第二次测试&quot; &lt;&lt; std::endl;</span></span><br><span class="line"><span class="comment">//        aaaaaaaa</span></span><br><span class="line"><span class="comment">//        return 0;</span></span><br><span class="line"><span class="comment">//    &#125;)&quot;;</span></span><br><span class="line"><span class="comment">//    in_value[&quot;input&quot;] = &quot;&quot;;</span></span><br><span class="line"><span class="comment">//    in_value[&quot;cpu_limit&quot;] = 1;</span></span><br><span class="line"><span class="comment">//    in_value[&quot;mem_limit&quot;] = 10240*3;</span></span><br><span class="line"><span class="comment">//    Json::FastWriter writer;</span></span><br><span class="line"><span class="comment">//    in_json = writer.write(in_value);</span></span><br><span class="line"><span class="comment">//    std::cout &lt;&lt; in_json &lt;&lt; std::endl;</span></span><br><span class="line"><span class="comment">//    //这个是将来给客户端返回的json串</span></span><br><span class="line"><span class="comment">//    std::string out_json;</span></span><br><span class="line"><span class="comment">//    CompileAndRun::Start(in_json, &amp;out_json);</span></span><br><span class="line"><span class="comment">//    std::cout &lt;&lt; out_json &lt;&lt; std::endl;</span></span><br><span class="line"><span class="comment">//    return 0;</span></span><br><span class="line"><span class="comment">//&#125;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">char</span>* argv[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(argc !=<span class="number">2</span> )</span><br><span class="line">    &#123;</span><br><span class="line">        std::cerr&lt;&lt;<span class="string">&quot;使用: &quot;</span>&lt;&lt;<span class="string">&quot;\n\t&quot;</span>&lt;&lt;argv[<span class="number">0</span>]&lt;&lt;<span class="string">&quot; port&quot;</span>&lt;&lt;std::endl;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Server svr;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//svr.Get(&quot;/hello&quot;, [](const Request&amp; req, Response &amp;resp )&#123;</span></span><br><span class="line">    <span class="comment">//            resp.set_content(&quot;hello1223&quot;, &quot;content-type: text/plain; charset=utf-8&quot;);</span></span><br><span class="line">    <span class="comment">//        &#125;);</span></span><br><span class="line">    svr.<span class="built_in">Post</span>(<span class="string">&quot;/compile_and_run&quot;</span>, [](<span class="type">const</span> Request&amp; req, Response&amp; resp)&#123;</span><br><span class="line">                std::string in_json=req.body;</span><br><span class="line">                std::string out_json;</span><br><span class="line">                <span class="keyword">if</span>(!in_json.<span class="built_in">empty</span>())</span><br><span class="line">                &#123;</span><br><span class="line">                    CompileAndRun::<span class="built_in">Start</span>(in_json, &amp;out_json);</span><br><span class="line">                    resp.<span class="built_in">set_content</span>(out_json, <span class="string">&quot;application/json;charset=utf-8&quot;</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">    svr.<span class="built_in">listen</span>(<span class="string">&quot;0.0.0.0&quot;</span>, <span class="built_in">atoi</span>(argv[<span class="number">1</span>])); <span class="comment">// 启动http服务</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="postman测试请求">postman测试请求</h2><figure class="highlight json"><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="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;code&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#include &lt;iostream&gt;\nint main()&#123;std::cout&lt;&lt;\&quot;hello, compile\&quot;&lt;&lt;std::endl;&#125;&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;intput&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;cpu_limit&quot;</span><span class="punctuation">:</span> <span class="number">1</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;mem_limit&quot;</span><span class="punctuation">:</span> <span class="number">50000</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202307092149766.png" alt="image.png"></p><p>centos服务端</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202307092150091.png" alt="image.png"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;httplib下载&quot;&gt;httplib下载&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/yhirose/cpp-httplib/releases/tag/v0.7.15&quot;&gt;cpp-httplib-v0.7.15下载&lt;/a&gt;&lt;/p&gt;
&lt;fi</summary>
      
    
    
    
    <category term="项目" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/"/>
    
    <category term="负载均衡式在线OJ" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%BC%8F%E5%9C%A8%E7%BA%BFOJ/"/>
    
    
    <category term="项目" scheme="https://atong.run/tags/%E9%A1%B9%E7%9B%AE/"/>
    
  </entry>
  
  <entry>
    <title>4、负载均衡式在线OJ-编译运行</title>
    <link href="https://atong.run/posts/2587007324/"/>
    <id>https://atong.run/posts/2587007324/</id>
    <published>2023-06-22T13:24:14.902Z</published>
    <updated>2023-06-22T13:26:23.960Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>该模块为编译运行功能，该模块需要使用json库，首先安装json，作用是将结构化的数据转化为字符串，做序列化和反序列化工作</p></blockquote><p>命令：<code>sudo yum install jsoncpp-devel</code></p><h2 id="整体逻辑">整体逻辑</h2><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202306132110496.png" alt="image.png"></p><h2 id="Start函数">Start函数</h2><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">Start</span><span class="params">(<span class="type">const</span> std::string &amp;in_json, std::string *out_json)</span></span>&#123;&#125;</span><br></pre></td></tr></table></figure><h3 id="Start函数参数">Start函数参数</h3><blockquote><p>start函数的两个参数</p></blockquote><ul><li><code>in_json</code>: {“code”: “#include …”, “input”: “”, “cpu_limit”: 1, “mem_limit”:10240}</li><li><code>out_json</code>: {“status”:0, “reason”:“”, “stdout”:“”, “stderr”:“”}</li></ul><blockquote><p>in_json字符串中的内容</p></blockquote><ul><li><code>code</code>: 用户提交的代码</li><li><code>input</code>: 用户给自己提交的代码对应的输入，暂不做处理</li><li><code>cpu_limit</code>: 时间要求</li><li><code>mem_limit</code>: 空间要求</li></ul><blockquote><p>out_json字符串中的内容</p></blockquote><ul><li><code>status</code>: 状态码 （必填）</li><li><code>reason</code>: 请求结果 （必填）</li><li><code>stdout</code>: 程序运行完结果 （选填）</li><li><code>stderr</code>: 运行完的错误结果</li></ul><h3 id="Start函数逻辑">Start函数逻辑</h3><ol><li>反序列化解析<code>in_json</code>字符串内容</li><li>根据<code>in_json</code>中的内容（代码、输入、限制条件）编译运行</li><li>将编译运行期间的状态、结果、错误等信息序列化，通过输出型参数<code>out_json</code>输出</li></ol><h3 id="具体细节代码">具体细节代码</h3><figure class="highlight cpp"><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><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">Start</span><span class="params">(<span class="type">const</span> std::string &amp;in_json, std::string *out_json)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">   <span class="comment">// 解析 in_json得到 代码 输入 限制条件</span></span><br><span class="line">   Json::Value in_value;</span><br><span class="line">   Json::Reader reader;</span><br><span class="line">   reader.<span class="built_in">parse</span>(in_json, in_value);</span><br><span class="line"></span><br><span class="line">   std::string code = in_value[<span class="string">&quot;code&quot;</span>].<span class="built_in">asString</span>();</span><br><span class="line">   std::string input = in_value[<span class="string">&quot;input&quot;</span>].<span class="built_in">asString</span>();</span><br><span class="line">   <span class="type">int</span> cpu_limit = in_value[<span class="string">&quot;cpu_limit&quot;</span>].<span class="built_in">asInt</span>();</span><br><span class="line">   <span class="type">int</span> mem_limit = in_value[<span class="string">&quot;mem_limit&quot;</span>].<span class="built_in">asInt</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 根据code 生成一份文件，该文件名必须要有唯一性</span></span><br><span class="line"></span><br><span class="line">   <span class="type">int</span> status_code=<span class="number">0</span>;</span><br><span class="line">   Json::Value out_value; </span><br><span class="line">   <span class="type">int</span> run_result = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">   std::string file_name; <span class="comment">// code文件名</span></span><br><span class="line"></span><br><span class="line">   <span class="keyword">if</span>(code.<span class="built_in">size</span>()==<span class="number">0</span>)</span><br><span class="line">   &#123;</span><br><span class="line">   status_code = <span class="number">-1</span>; <span class="comment">//代表代码为空</span></span><br><span class="line">   <span class="keyword">goto</span> END;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">   <span class="comment">// 形成的文件名要具有唯一性，只是文件名，没有前缀路径和后缀</span></span><br><span class="line">   file_name = FileUtil::<span class="built_in">UniqFileName</span>();</span><br><span class="line"></span><br><span class="line">   <span class="comment">// 文件名有了，接下来是根据文件名，形成src源文件，并将code的内容写入到源文件中</span></span><br><span class="line">   <span class="keyword">if</span>(!FileUtil::<span class="built_in">WriteFile</span>(PathUtil::<span class="built_in">Src</span>(file_name), code))</span><br><span class="line">   &#123;</span><br><span class="line">   status_code=<span class="number">-2</span>; <span class="comment">//未知错误</span></span><br><span class="line">   <span class="keyword">goto</span> END;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   </span><br><span class="line">   <span class="comment">//形成源文件之后开始编译</span></span><br><span class="line">   <span class="keyword">if</span>(!Compiler::<span class="built_in">Compile</span>(file_name))</span><br><span class="line">   &#123;</span><br><span class="line">   status_code=<span class="number">-3</span>; <span class="comment">//代码编译发生错误</span></span><br><span class="line">   <span class="keyword">goto</span> END;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">//编译完成之后运行</span></span><br><span class="line">   run_result=Runner::<span class="built_in">Run</span>(file_name, cpu_limit, mem_limit);</span><br><span class="line">   <span class="keyword">if</span>(run_result&lt;<span class="number">0</span>)</span><br><span class="line">   &#123;</span><br><span class="line">   status_code=<span class="number">-2</span>;<span class="comment">//未知错误</span></span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">else</span> <span class="keyword">if</span>(run_result&gt;<span class="number">0</span>)</span><br><span class="line">   &#123;</span><br><span class="line">   <span class="comment">//程序运行崩溃</span></span><br><span class="line">   status_code=run_result;</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="keyword">else</span></span><br><span class="line">   &#123;</span><br><span class="line">   status_code=<span class="number">0</span>; <span class="comment">//程序运行成功</span></span><br><span class="line">   &#125;</span><br><span class="line">END:</span><br><span class="line">   out_value[<span class="string">&quot;status&quot;</span>]=status_code;</span><br><span class="line">   out_value[<span class="string">&quot;reason&quot;</span>]=<span class="built_in">CodeToDesc</span>(status_code, file_name);</span><br><span class="line"></span><br><span class="line">   <span class="keyword">if</span>(status_code==<span class="number">0</span>)</span><br><span class="line">   &#123;</span><br><span class="line">   <span class="comment">//整个过程全部成功</span></span><br><span class="line">   std::string _stdout;</span><br><span class="line">   FileUtil::<span class="built_in">ReadFile</span>(PathUtil::<span class="built_in">Stdout</span>(file_name), &amp;_stdout, <span class="literal">true</span>);</span><br><span class="line">   out_value[<span class="string">&quot;stdout&quot;</span>]=_stdout;</span><br><span class="line"></span><br><span class="line">   std::string _stderr;</span><br><span class="line">   FileUtil::<span class="built_in">ReadFile</span>(PathUtil::<span class="built_in">Stderr</span>(file_name), &amp;_stderr, <span class="literal">true</span>);</span><br><span class="line">   out_value[<span class="string">&quot;stderr&quot;</span>]=_stderr;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   Json::StyledWriter writer;</span><br><span class="line">   *out_json=writer.<span class="built_in">write</span>(out_value);</span><br><span class="line"></span><br><span class="line">   <span class="built_in">RemoveTempFile</span>(file_name);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="补充工具类函数">补充工具类函数</h2><h3 id="状态码解析CodeToDesc">状态码解析CodeToDesc</h3><blockquote><p>作用：将状态码解析为对应字符串</p></blockquote><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">static</span> std::string <span class="title">CodeToDesc</span><span class="params">(<span class="type">int</span> code, <span class="type">const</span> std::string&amp; file_name)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">std::string desc;</span><br><span class="line"><span class="keyword">switch</span>(code)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">desc=<span class="string">&quot;编译运行成功&quot;</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">-1</span>:</span><br><span class="line">desc=<span class="string">&quot;提交的代码为空&quot;</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">-2</span>:</span><br><span class="line">desc=<span class="string">&quot;未知错误&quot;</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">-3</span>:</span><br><span class="line"><span class="comment">//代码编译时出错</span></span><br><span class="line">FileUtil::<span class="built_in">ReadFile</span>(PathUtil::<span class="built_in">CompilerError</span>(file_name), &amp;desc, <span class="literal">true</span>);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> SIGABRT: <span class="comment">//6</span></span><br><span class="line">desc=<span class="string">&quot;内存超过范围&quot;</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> SIGXCPU: <span class="comment">//24</span></span><br><span class="line">desc=<span class="string">&quot;CPU使用超时&quot;</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> SIGFPE: <span class="comment">//8</span></span><br><span class="line">desc=<span class="string">&quot;浮点数溢出&quot;</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line">desc=<span class="string">&quot;未知&quot;</span>+std::<span class="built_in">to_string</span>(code);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> desc;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="形成唯一文件名UniqFileName">形成唯一文件名UniqFileName</h3><figure class="highlight cpp"><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="comment">//形成唯一的文件名 </span></span><br><span class="line"><span class="comment">//通过毫秒级时间戳+原子性递增唯一值来保证唯一性</span></span><br><span class="line"><span class="function"><span class="type">static</span> std::string <span class="title">UniqFileName</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="function"><span class="type">static</span> std::atomic_uint <span class="title">id</span><span class="params">(<span class="number">0</span>)</span></span>;</span><br><span class="line">id++;</span><br><span class="line"></span><br><span class="line">std::string ms = TimeUtil::<span class="built_in">GetTimeMs</span>();</span><br><span class="line">std::string uniq_id = std::<span class="built_in">to_string</span>(id);</span><br><span class="line"><span class="keyword">return</span> ms+<span class="string">&quot;_&quot;</span>+uniq_id;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="删除临时文件RemoveTempFile">删除临时文件RemoveTempFile</h3><ol><li>判断文件是否存在</li><li>若存在使用unlink函数进行删除</li></ol><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">RemoveTempFile</span><span class="params">(<span class="type">const</span> std::string &amp;file_name)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//清理源文件</span></span><br><span class="line">    std::string _src = PathUtil::<span class="built_in">Src</span>(file_name);</span><br><span class="line">    <span class="keyword">if</span>(FileUtil::<span class="built_in">IsFileExists</span>(_src))</span><br><span class="line">        <span class="built_in">unlink</span>(_src.<span class="built_in">c_str</span>());</span><br><span class="line">    <span class="comment">//清理编译错误文件</span></span><br><span class="line">    std::string _compiler_error=PathUtil::<span class="built_in">CompilerError</span>(file_name);</span><br><span class="line">    <span class="keyword">if</span>(FileUtil::<span class="built_in">IsFileExists</span>(_compiler_error))</span><br><span class="line">        <span class="built_in">unlink</span>(_compiler_error.<span class="built_in">c_str</span>());</span><br><span class="line">    <span class="comment">//清理可执行程序</span></span><br><span class="line">    std::string _execute=PathUtil::<span class="built_in">Exe</span>(file_name);</span><br><span class="line">    <span class="keyword">if</span>(FileUtil::<span class="built_in">IsFileExists</span>(_execute))</span><br><span class="line">        <span class="built_in">unlink</span>(_execute.<span class="built_in">c_str</span>());</span><br><span class="line">    <span class="comment">//清理输入</span></span><br><span class="line">    std::string _stdin=PathUtil::<span class="built_in">Stdin</span>(file_name);</span><br><span class="line">    <span class="keyword">if</span>(FileUtil::<span class="built_in">IsFileExists</span>(_stdin))</span><br><span class="line">        <span class="built_in">unlink</span>(_stdin.<span class="built_in">c_str</span>());</span><br><span class="line">    <span class="comment">//清理输出</span></span><br><span class="line">    std::string _stdout=PathUtil::<span class="built_in">Stdout</span>(file_name);</span><br><span class="line">    <span class="keyword">if</span>(FileUtil::<span class="built_in">IsFileExists</span>(_stdout))</span><br><span class="line">        <span class="built_in">unlink</span>(_stdout.<span class="built_in">c_str</span>());</span><br><span class="line">    <span class="comment">//清理错误</span></span><br><span class="line">    std::string _stderr=PathUtil::<span class="built_in">Stderr</span>(file_name);</span><br><span class="line">    <span class="keyword">if</span>(FileUtil::<span class="built_in">IsFileExists</span>(_stderr))</span><br><span class="line">        <span class="built_in">unlink</span>(_stderr.<span class="built_in">c_str</span>());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;该模块为编译运行功能，该模块需要使用json库，首先安装json，作用是将结构化的数据转化为字符串，做序列化和反序列化工作&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;命令：&lt;code&gt;sudo yum install jsoncpp-devel&lt;/</summary>
      
    
    
    
    <category term="项目" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/"/>
    
    <category term="负载均衡式在线OJ" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%BC%8F%E5%9C%A8%E7%BA%BFOJ/"/>
    
    
    <category term="项目" scheme="https://atong.run/tags/%E9%A1%B9%E7%9B%AE/"/>
    
  </entry>
  
  <entry>
    <title>3、负载均衡式在线OJ-运行模块</title>
    <link href="https://atong.run/posts/3304561254/"/>
    <id>https://atong.run/posts/3304561254/</id>
    <published>2023-06-04T07:53:21.735Z</published>
    <updated>2023-11-09T13:42:21.993Z</updated>
    
    <content type="html"><![CDATA[<h2 id="运行模块">运行模块</h2><blockquote><p>运行模块作用是：执行编译模块编译好的可执行程序，我们希望，输出、输出、错误等信息能写入到文件中。Run模块只关心运行，不关注结果的正确与否，结果正确与否靠测试用例判断</p></blockquote><h3 id="运行逻辑">运行逻辑</h3><p>这里需要重定向工作</p><ul><li>标准输入</li><li>标准输出</li><li>标准错误</li></ul><p>运行服务大致过程类似编译：</p><ul><li>创建子进程</li><li>子进程通过execl执行编译好的可执行程序</li></ul><p>那么这里会有两个问题</p><ol><li>编译的代码可能是死循环或者恶意代码</li><li>运行出错如何知道是哪种错误</li></ol><p>问题1可以通过<a href="#%E8%B5%84%E6%BA%90%E9%99%90%E5%88%B6">资源限制</a>来解决，通过限制运行时间，和申请内存上限等方式可以解决</p><p>问题2解决方式：<br>首先设计运行类，类中提供静态方法Run，该函数通过文件名可以自动拼接路径，然后再执行对应逻辑，返回值可以代表程序运行时的各种错误，比如我们规定：</p><ul><li>返回值 &gt; 0: 程序异常了，退出时收到了信号，返回值就是对应的信号编号</li><li>返回值 == 0: 正常运行完毕的，结果保存到了对应的临时文件中</li><li>返回值 &lt; 0: 内部错误</li></ul><h3 id="具体代码">具体代码</h3><figure class="highlight cpp"><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><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;../common/util.hpp&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;../common/log.hpp&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> ns_runner</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">using</span> <span class="keyword">namespace</span> ns_util;</span><br><span class="line">    <span class="keyword">using</span> <span class="keyword">namespace</span> ns_log;</span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">Runner</span></span><br><span class="line">    &#123;</span><br><span class="line">    <span class="keyword">public</span>:</span><br><span class="line">        <span class="built_in">Runner</span>()&#123;&#125;</span><br><span class="line">        ~<span class="built_in">Runner</span>()&#123;&#125;</span><br><span class="line">    <span class="keyword">public</span>:</span><br><span class="line">        <span class="function"><span class="type">static</span> <span class="type">int</span> <span class="title">Run</span><span class="params">(<span class="type">const</span> std::string&amp; file_name)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            std::string _execute = PathUtil::<span class="built_in">Exe</span>(file_name);</span><br><span class="line">            std::string _stdin  = PathUtil::<span class="built_in">Stdin</span>(file_name);</span><br><span class="line">            std::string _stdout = PathUtil::<span class="built_in">Stdout</span>(file_name);</span><br><span class="line">            std::string _stderr = PathUtil::<span class="built_in">Stderr</span>(file_name);</span><br><span class="line">            <span class="built_in">umask</span>(<span class="number">0</span>);</span><br><span class="line">            <span class="type">int</span> _stdin_fd = <span class="built_in">open</span>(_stdin.<span class="built_in">c_str</span>(), O_CREAT|O_RDONLY, <span class="number">0644</span>);</span><br><span class="line">            <span class="type">int</span> _stdout_fd = <span class="built_in">open</span>(_stdout.<span class="built_in">c_str</span>(), O_CREAT|O_WRONLY, <span class="number">0644</span>);</span><br><span class="line">            <span class="type">int</span> _stderr_fd = <span class="built_in">open</span>(_stderr.<span class="built_in">c_str</span>(), O_CREAT|O_WRONLY, <span class="number">0644</span>);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span>(_stdin_fd &lt;<span class="number">0</span> || _stdout_fd&lt;<span class="number">0</span> || _stderr_fd&lt;<span class="number">0</span>)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="built_in">LOG</span>(ERROR)&lt;&lt;<span class="string">&quot;运行时打开文件失败&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">                <span class="keyword">return</span> <span class="number">-1</span>; <span class="comment">//-1 代表打开文件失败</span></span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="type">pid_t</span> pid = fork();</span><br><span class="line">            </span><br><span class="line">            <span class="keyword">if</span>(pid&lt;<span class="number">0</span>)</span><br><span class="line">            &#123;</span><br><span class="line">               <span class="built_in">LOG</span>(ERROR)&lt;&lt;<span class="string">&quot;运行时创建子进程失败&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">               <span class="built_in">close</span>(_stdin_fd);</span><br><span class="line">               <span class="built_in">close</span>(_stdout_fd);</span><br><span class="line">               <span class="built_in">close</span>(_stderr_fd);</span><br><span class="line"></span><br><span class="line">               <span class="keyword">return</span> <span class="number">-2</span>; <span class="comment">//-2 代表创建子进程失败</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span>(pid==<span class="number">0</span>)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">// 子进程，先进行重定向，再程序替换</span></span><br><span class="line">                <span class="built_in">dup2</span>(_stdin_fd, <span class="number">0</span>);</span><br><span class="line">                <span class="built_in">dup2</span>(_stdout_fd,<span class="number">1</span>);</span><br><span class="line">                <span class="built_in">dup2</span>(_stderr_fd, <span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">                <span class="built_in">execl</span>(_execute.<span class="built_in">c_str</span>(), _execute.<span class="built_in">c_str</span>(), <span class="literal">nullptr</span>);</span><br><span class="line">                <span class="built_in">exit</span>(<span class="number">1</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">// 父进程</span></span><br><span class="line">                <span class="comment">// 先关闭文件描述符</span></span><br><span class="line">                </span><br><span class="line">                <span class="built_in">close</span>(_stdin_fd);</span><br><span class="line">                <span class="built_in">close</span>(_stdout_fd);</span><br><span class="line">                <span class="built_in">close</span>(_stderr_fd);</span><br><span class="line">                </span><br><span class="line">                <span class="type">int</span> status=<span class="number">0</span>;</span><br><span class="line">                <span class="built_in">waitpid</span>(pid, &amp;status, <span class="number">0</span>);</span><br><span class="line">                <span class="built_in">LOG</span>(INFO)&lt;&lt;<span class="string">&quot;运行完毕 Info: &quot;</span>&lt;&lt;(status &amp; <span class="number">0x7F</span>)&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">                <span class="keyword">return</span> status &amp; <span class="number">0x7F</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="资源限制">资源限制</h2><blockquote><p>具体资源限制，我们使用linux系统的系统调用setrlimit函数</p></blockquote><h3 id="setrlimit">setrlimit</h3><p>setrlimit是一个用于设置进程资源限制的函数，它的原型如下：</p><figure class="highlight c"><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"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/resource.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">setrlimit</span><span class="params">(<span class="type">int</span> resource, <span class="type">const</span> <span class="keyword">struct</span> rlimit *rlim)</span>;</span><br></pre></td></tr></table></figure><p>其中，第一个参数resource指定了要设置的资源类型，它可以取以下值之一：</p><ul><li>RLIMIT_CORE：设置core文件的最大大小（以字节为单位）；</li><li>RLIMIT_CPU：设置CPU时间的最大值（以秒为单位）；</li><li>RLIMIT_DATA：设置数据段的最大大小（以字节为单位）；</li><li>RLIMIT_FSIZE：设置可创建文件的最大大小（以字节为单位）；</li><li>RLIMIT_NOFILE：设置进程可以打开的最大文件数；</li><li>RLIMIT_STACK：设置进程堆栈的最大大小（以字节为单位）；</li><li>RLIMIT_AS：设置进程地址空间的最大大小（以字节为单位）；</li><li>RLIMIT_NPROC：设置用户可以拥有的最大进程数；</li><li>RLIMIT_RSS：设置进程驻留集大小的最大值（以字节为单位）；</li><li>RLIMIT_MEMLOCK：设置进程能够锁定在内存中的最大字节数；</li><li>RLIMIT_NICE：设置进程的nice值的最大值。</li></ul><p>第二个参数rlim是一个指向rlimit结构体的指针，该结构体定义如下：</p><figure class="highlight c"><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="class"><span class="keyword">struct</span> <span class="title">rlimit</span> &#123;</span></span><br><span class="line">    <span class="type">rlim_t</span> rlim_cur; <span class="comment">// 资源限制的当前值</span></span><br><span class="line">    <span class="type">rlim_t</span> rlim_max; <span class="comment">// 资源限制的最大值</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>rlim_t类型的rlim_max成员可以被赋值为以下宏：</p><ul><li>RLIM_INFINITY：表示无限制，将rlim_max设置为此宏将取消对资源的任何限制；</li><li>RLIM_SAVED_MAX：表示使用之前保存的最大值，最初由系统管理员设置；</li><li>RLIM_SAVED_CUR：表示使用之前保存的当前值，最初由系统管理员设置；</li><li>其他正整数：表示将rlim_max设置为指定的正整数值，表示资源的最大限制。需要注意的是，此值必须小于或等于系统的最大限制值，并且通常应该小于或等于当前进程的软限制值。</li></ul><p>需要注意的是，不同的资源类型可能会有不同的最大限制值。例如，对于RLIMIT_NOFILE（最大打开文件数），通常的最大限制值是系统的最大文件描述符数。对于RLIMIT_CPU（CPU时间限制），通常的最大限制值是LONG_MAX（通常为2147483647）。</p><p>使用setrlimit函数可以为进程设置指定资源的限制，比如限制进程可以打开的最大文件数、限制进程的CPU时间等。调用该函数前，需要先定义并初始化一个rlimit结构体，然后将其作为参数传递给setrlimit函数。</p><p>例如，以下代码将限制进程可以打开的最大文件数为1000：</p><figure class="highlight c"><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">#<span class="keyword">include</span> <span class="string">&lt;sys/resource.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">rlimit</span> <span class="title">limit</span>;</span></span><br><span class="line"></span><br><span class="line">    limit.rlim_cur = <span class="number">1000</span>;</span><br><span class="line">    limit.rlim_max = <span class="number">1000</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (setrlimit(RLIMIT_NOFILE, &amp;limit) == <span class="number">-1</span>) &#123;</span><br><span class="line">        perror(<span class="string">&quot;setrlimit&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;限制进程可以打开的最大文件数为：%lld\n&quot;</span>, (<span class="type">long</span> <span class="type">long</span>) limit.rlim_cur);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>setrlimit函数只能将资源限制设置为小于或等于系统默认值或进程当前限制值的值。如果试图将资源限制设置为大于这些值的值，setrlimit函数将失败并返回-1。在这种情况下，可以考虑使用sysctl函数调整系统级别的资源限制。同时，需要注意，setrlimit函数只能影响当前进程以及其子进程的资源限制，无法影响其他进程。</p><h3 id="资源限制测试">资源限制测试</h3><blockquote><p>整体测试代码</p></blockquote><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/resource.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;signal.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">handler</span><span class="params">(<span class="type">int</span> signo)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::cout&lt;&lt;<span class="string">&quot;signo: &quot;</span>&lt;&lt;signo&lt;&lt;std::endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i=<span class="number">1</span>; i&lt;=<span class="number">31</span>; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">signal</span>(i, handler);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//测试死循环时间超时</span></span><br><span class="line">    <span class="comment">//struct rlimit r;</span></span><br><span class="line">    <span class="comment">//r.rlim_cur = 1; //设置1秒限制</span></span><br><span class="line">    <span class="comment">//r.rlim_max = RLIM_INFINITY;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//setrlimit(RLIMIT_CPU, &amp;r);</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">//while(1)&#123;&#125;</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">//测试申请内存</span></span><br><span class="line">    <span class="keyword">struct</span> <span class="title class_">rlimit</span> r;</span><br><span class="line">    r.rlim_cur = <span class="number">1024</span>*<span class="number">1024</span>*<span class="number">40</span>;</span><br><span class="line">    r.rlim_max = RLIM_INFINITY;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">setrlimit</span>(RLIMIT_AS, &amp;r);</span><br><span class="line">    <span class="type">int</span> count=<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">    &#123;</span><br><span class="line">        <span class="type">int</span> *p = <span class="keyword">new</span> <span class="type">int</span>[<span class="number">1024</span>*<span class="number">1024</span>];</span><br><span class="line">        count++;</span><br><span class="line">        std::cout&lt;&lt;<span class="string">&quot;count: &quot;</span>&lt;&lt;count&lt;&lt;std::endl;</span><br><span class="line">        <span class="built_in">sleep</span>(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>1、死循环时间限制测试</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305301610493.png" alt="image.png"></p><p>收到24号信号 SIGXCPU</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305301615275.png" alt="image.png"></p><p>2、申请虚拟空间大小限制</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305302121869.png" alt="image.png"></p><h2 id="运行模块加入资源限制">运行模块加入资源限制</h2><ul><li>cpu_limit: 该程序运行的时候，可以使用的最大cpu资源上限</li><li>mem_limit: 改程序运行的时候，可以使用的最大的内存大小(KB)</li></ul><h3 id="setProcLimit函数">setProcLimit函数</h3><blockquote><p>对资源做时间、空间限制</p></blockquote><figure class="highlight cpp"><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="comment">// 在运行之间需要对资源做一些限制</span></span><br><span class="line">        <span class="comment">// 包括 时间、空间</span></span><br><span class="line">        <span class="function"><span class="type">static</span> <span class="type">void</span> <span class="title">setProcLimit</span><span class="params">(<span class="type">int</span> _cpu_limit, <span class="type">int</span> _mem_limit)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="comment">// 设置CPU的时长</span></span><br><span class="line">            <span class="keyword">struct</span> <span class="title class_">rlimit</span> cpu_rlimit;</span><br><span class="line">            cpu_rlimit.rlim_cur = _cpu_limit;</span><br><span class="line">            cpu_rlimit.rlim_max = RLIM_INFINITY;</span><br><span class="line"></span><br><span class="line">            <span class="built_in">setrlimit</span>(RLIMIT_CPU, &amp;cpu_rlimit);</span><br><span class="line">            </span><br><span class="line">            <span class="comment">// 设置限制内存</span></span><br><span class="line">            <span class="keyword">struct</span> <span class="title class_">rlimit</span> mem_rlimit;</span><br><span class="line">            <span class="comment">//转成kb</span></span><br><span class="line">            mem_rlimit.rlim_cur = _mem_limit*<span class="number">1024</span>;</span><br><span class="line">            mem_rlimit.rlim_max = RLIM_INFINITY;</span><br><span class="line">            <span class="built_in">setrlimit</span>(RLIMIT_AS, &amp;mem_rlimit);</span><br><span class="line">        &#125;</span><br></pre></td></tr></table></figure><h3 id="Run方法">Run方法</h3><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">static</span> <span class="type">int</span> <span class="title">Run</span><span class="params">(<span class="type">const</span> std::string&amp; file_name, <span class="type">int</span> cpu_rlimit, <span class="type">int</span> mem_rlimit)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    std::string _execute = PathUtil::<span class="built_in">Exe</span>(file_name);</span><br><span class="line">    std::string _stdin  = PathUtil::<span class="built_in">Stdin</span>(file_name);</span><br><span class="line">    std::string _stdout = PathUtil::<span class="built_in">Stdout</span>(file_name);</span><br><span class="line">    std::string _stderr = PathUtil::<span class="built_in">Stderr</span>(file_name);</span><br><span class="line">    <span class="built_in">umask</span>(<span class="number">0</span>);</span><br><span class="line">    <span class="type">int</span> _stdin_fd = <span class="built_in">open</span>(_stdin.<span class="built_in">c_str</span>(), O_CREAT|O_RDONLY, <span class="number">0644</span>);</span><br><span class="line">    <span class="type">int</span> _stdout_fd = <span class="built_in">open</span>(_stdout.<span class="built_in">c_str</span>(), O_CREAT|O_WRONLY, <span class="number">0644</span>);</span><br><span class="line">    <span class="type">int</span> _stderr_fd = <span class="built_in">open</span>(_stderr.<span class="built_in">c_str</span>(), O_CREAT|O_WRONLY, <span class="number">0644</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span>(_stdin_fd &lt;<span class="number">0</span> || _stdout_fd&lt;<span class="number">0</span> || _stderr_fd&lt;<span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">LOG</span>(ERROR)&lt;&lt;<span class="string">&quot;运行时打开文件失败&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>; <span class="comment">//-1 代表打开文件失败</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">pid_t</span> pid = fork();</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>(pid&lt;<span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">LOG</span>(ERROR)&lt;&lt;<span class="string">&quot;运行时创建子进程失败&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">        <span class="built_in">close</span>(_stdin_fd);</span><br><span class="line">        <span class="built_in">close</span>(_stdout_fd);</span><br><span class="line">        <span class="built_in">close</span>(_stderr_fd);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="number">-2</span>; <span class="comment">//-2 代表创建子进程失败</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span>(pid==<span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">// 子进程，先进行重定向，再程序替换</span></span><br><span class="line">        <span class="built_in">dup2</span>(_stdin_fd, <span class="number">0</span>);</span><br><span class="line">        <span class="built_in">dup2</span>(_stdout_fd,<span class="number">1</span>);</span><br><span class="line">        <span class="built_in">dup2</span>(_stderr_fd, <span class="number">2</span>);</span><br><span class="line">        </span><br><span class="line">        <span class="built_in">setProcLimit</span>(cpu_rlimit, mem_rlimit);</span><br><span class="line">        <span class="built_in">execl</span>(_execute.<span class="built_in">c_str</span>(), _execute.<span class="built_in">c_str</span>(), <span class="literal">nullptr</span>);</span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">// 父进程</span></span><br><span class="line">        <span class="comment">// 先关闭文件描述符</span></span><br><span class="line">        </span><br><span class="line">        <span class="built_in">close</span>(_stdin_fd);</span><br><span class="line">        <span class="built_in">close</span>(_stdout_fd);</span><br><span class="line">        <span class="built_in">close</span>(_stderr_fd);</span><br><span class="line">        </span><br><span class="line">        <span class="type">int</span> status=<span class="number">0</span>;</span><br><span class="line">        <span class="built_in">waitpid</span>(pid, &amp;status, <span class="number">0</span>);</span><br><span class="line">        <span class="built_in">LOG</span>(INFO)&lt;&lt;<span class="string">&quot;运行完毕 Info: &quot;</span>&lt;&lt;(status &amp; <span class="number">0x7F</span>)&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span> status &amp; <span class="number">0x7F</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="问题以及记录">问题以及记录</h2><h3 id="遇到问题">遇到问题</h3><p>提问：centos，我一个c++程序，先创建子进程，然后在子进程用setrlimit函数限制程序运行时间，再用execl执行另一个a.out程序，但是父进程waitpid收到11号信号，如果不加setrlimit限制，就正常运行，这是怎么回事呢？</p><h3 id="具体原因">具体原因</h3><p>AI回复：从描述来看，你遇到的问题可能与 <code>setrlimit</code> 函数设置的资源限制有关。11号信号是 <code>SIGSEGV</code>，即段错误。这个信号通常由于进程试图访问其虚拟地址空间中无法访问的内存区域而引发，例如非法指针解引用、栈溢出等。</p><p>在这种情况下，可能的原因是你<strong>使用 <code>setrlimit</code> 设置了过于严格的资源限制。这可能导致子进程在运行时无法分配足够的资源（例如内存），从而触发 <code>SIGSEGV</code> 信号。</strong></p><p>要解决这个问题，你可以尝试以下步骤：</p><ol><li><p>仔细检查 <code>setrlimit</code> 函数设置的资源限制，确保它们不会导致子进程无法正常运行。例如，如果你设置的是 <code>RLIMIT_CPU</code>，确保所设置的时间限制允许子进程有足够的时间运行。</p></li><li><p>在子进程中添加错误处理和调试信息，以便在出现问题时更容易识别问题所在。你可以使用 <code>try</code> 和 <code>catch</code> 语句捕获异常，并在控制台上输出有关错误的详细信息。</p></li><li><p>如果仍然无法解决问题，可以考虑在父进程中使用 <code>ptrace</code> 函数来监控子进程的系统调用和信号。这样可以帮助你更详细地了解子进程中发生了什么。</p></li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;运行模块&quot;&gt;运行模块&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;运行模块作用是：执行编译模块编译好的可执行程序，我们希望，输出、输出、错误等信息能写入到文件中。Run模块只关心运行，不关注结果的正确与否，结果正确与否靠测试用例判断&lt;/p&gt;
&lt;/blockquote</summary>
      
    
    
    
    <category term="项目" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/"/>
    
    <category term="负载均衡式在线OJ" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%BC%8F%E5%9C%A8%E7%BA%BFOJ/"/>
    
    
    <category term="项目" scheme="https://atong.run/tags/%E9%A1%B9%E7%9B%AE/"/>
    
  </entry>
  
  <entry>
    <title>2、负载均衡式在线OJ-编译服务设计</title>
    <link href="https://atong.run/posts/1188400450/"/>
    <id>https://atong.run/posts/1188400450/</id>
    <published>2023-05-21T12:08:11.665Z</published>
    <updated>2023-05-21T12:09:38.888Z</updated>
    
    <content type="html"><![CDATA[<h2 id="一、编译服务框架">一、编译服务框架</h2><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305191623531.jpg" alt="3L4C005SGLF2CH(RG59U0LH.jpg"></p><h2 id="二、具体实现">二、具体实现</h2><blockquote><p>首先是编译模块，封装Compiler类，提供Compile函数接口，具体编译流程如下：</p></blockquote><ol><li>根据传入文件名，对其进行编译，这里需要实现一个工具类</li><li>工具类，对文件名进行拼接，待编译的文件放在compile_server/temp文件下，例如test.cpp</li><li>拼接目标有源文件拼接：test-&gt;./temp/test.cpp</li><li>可执行程序拼接：test-&gt;./temp/test.exe</li><li>错误信息文件拼接：test-&gt;./temp/test.stderr</li><li>正式逻辑开始，首先创建子进程，子进程进行编译服务</li><li>通过程序替换：execlp函数，执行g++编译源文件，生成text.exe</li><li>g++编译可能成功，可能失败，如果失败，会通过stderr打印，这里对stderr进行重定向到指定文件(dup2函数)：./temp/test.stderr</li><li>父进程对子进程编译结果进行判断，这里只需要判断./temp/test.exe函数是否存在，存在就是编译成功</li><li>在工具类中FileUtil类提供接口IsFileExists判断文件是否存在，其中调用stat函数</li></ol><h3 id="1、compiler-hpp">1、compiler.hpp</h3><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/wait.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;fcntl.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;../common/util.hpp&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;../common/log.hpp&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">//只提供编译服务</span></span><br><span class="line"><span class="keyword">namespace</span> ns_compiler</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//引入路径拼接功能</span></span><br><span class="line">    <span class="keyword">using</span> <span class="keyword">namespace</span> ns_util;</span><br><span class="line">    <span class="keyword">using</span> <span class="keyword">namespace</span> ns_log;</span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">Compiler</span></span><br><span class="line">    &#123;</span><br><span class="line">    <span class="keyword">public</span>:</span><br><span class="line">        <span class="built_in">Compiler</span>()&#123;&#125;;</span><br><span class="line">        ~<span class="built_in">Compiler</span>()&#123;&#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="type">static</span> <span class="type">bool</span> <span class="title">Compile</span><span class="params">(<span class="type">const</span> std::string&amp; file_name)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">           <span class="type">pid_t</span> pid = fork(); </span><br><span class="line">           <span class="keyword">if</span>(pid&lt;<span class="number">0</span>)</span><br><span class="line">           &#123;</span><br><span class="line">                <span class="built_in">LOG</span>(ERROR)&lt;&lt;<span class="string">&quot;内部错误,创建子进程失败&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">else</span> <span class="keyword">if</span>(pid == <span class="number">0</span>)</span><br><span class="line">           &#123;</span><br><span class="line">                <span class="comment">//子进程</span></span><br><span class="line">                <span class="built_in">umask</span>(<span class="number">0</span>);</span><br><span class="line">                <span class="type">int</span> _stderr = <span class="built_in">open</span>(PathUtil::<span class="built_in">Stderr</span>(file_name).<span class="built_in">c_str</span>(), O_CREAT | O_WRONLY, <span class="number">0644</span>); <span class="comment">//110 100 100</span></span><br><span class="line">                <span class="keyword">if</span>(_stderr&lt;<span class="number">0</span>)</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="built_in">LOG</span>(WARNING)&lt;&lt;<span class="string">&quot;没有成功形成stderr文件&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">                    <span class="built_in">exit</span>(<span class="number">1</span>);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="built_in">dup2</span>(_stderr, <span class="number">2</span>);</span><br><span class="line">                <span class="built_in">execlp</span>(<span class="string">&quot;g++&quot;</span>,<span class="string">&quot;g++&quot;</span>, <span class="string">&quot;-o&quot;</span>, PathUtil::<span class="built_in">Exe</span>(file_name).<span class="built_in">c_str</span>(),PathUtil::<span class="built_in">Src</span>(file_name).<span class="built_in">c_str</span>(),<span class="string">&quot;-std=c++11&quot;</span>, <span class="literal">NULL</span>);</span><br><span class="line">               <span class="comment">// 执行完成后，这里判断有没有形成.exe的可执行程序，如果形成，说明编译成功</span></span><br><span class="line">               <span class="comment">// 如果没有形成，需要将错误信息重定向到文件中</span></span><br><span class="line">                <span class="built_in">LOG</span>(ERROR)&lt;&lt;<span class="string">&quot;g++编译失败，可能是参数错误&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">                <span class="built_in">exit</span>(<span class="number">1</span>);    </span><br><span class="line">           &#125;</span><br><span class="line">           <span class="keyword">else</span></span><br><span class="line">           &#123;</span><br><span class="line">                <span class="built_in">waitpid</span>(pid, <span class="literal">nullptr</span>,<span class="number">0</span>);</span><br><span class="line">                <span class="keyword">if</span>(FileUtil::<span class="built_in">IsFileExists</span>(PathUtil::<span class="built_in">Exe</span>(file_name).<span class="built_in">c_str</span>()))</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="built_in">LOG</span>(INFO)&lt;&lt;PathUtil::<span class="built_in">Src</span>(file_name)&lt;&lt;<span class="string">&quot;编译成功&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">                    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="built_in">LOG</span>(ERROR)&lt;&lt;<span class="string">&quot;编译失败，没有形成可执行程序&quot;</span>&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">           &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="2、util-hpp">2、util.hpp</h3><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/types.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/stat.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/time.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> ns_util</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">TimeUtil</span></span><br><span class="line">    &#123;</span><br><span class="line">    <span class="keyword">public</span>:</span><br><span class="line">        <span class="function"><span class="type">static</span> std::string <span class="title">GetTimeStamp</span><span class="params">()</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">struct</span> <span class="title class_">timeval</span> _time;</span><br><span class="line">            <span class="built_in">gettimeofday</span>(&amp;_time, <span class="literal">nullptr</span>);</span><br><span class="line">            <span class="keyword">return</span> std::<span class="built_in">to_string</span>(_time.tv_sec);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="type">const</span> std::string temp_path = <span class="string">&quot;./temp/&quot;</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">PathUtil</span></span><br><span class="line">    &#123;</span><br><span class="line">    <span class="keyword">public</span>:</span><br><span class="line">        <span class="function"><span class="type">static</span> std::string <span class="title">AddSuffix</span><span class="params">(<span class="type">const</span> std::string&amp; file_name, <span class="type">const</span> std::string&amp; suffix)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            std::string path_name = temp_path+file_name;</span><br><span class="line">            path_name+=suffix;</span><br><span class="line">            <span class="keyword">return</span> path_name;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 构建源文件路径+后缀的完整文件名</span></span><br><span class="line">        <span class="comment">// ./temp/1234.cpp</span></span><br><span class="line">        <span class="function"><span class="type">static</span> std::string <span class="title">Src</span><span class="params">(<span class="type">const</span> std::string&amp; file_name)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">AddSuffix</span>(file_name, <span class="string">&quot;.cpp&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="comment">//构建可执行程序的完整路径+后缀名</span></span><br><span class="line">        <span class="comment">//1234-&gt;./temp/1234.exe</span></span><br><span class="line">        <span class="function"><span class="type">static</span> std::string <span class="title">Exe</span><span class="params">(<span class="type">const</span> std::string&amp; file_name)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">AddSuffix</span>(file_name, <span class="string">&quot;.exe&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//构建该程序对应的标准错误的完整路径+后缀名</span></span><br><span class="line">        <span class="comment">//1234-&gt;./temp/1234.stderr</span></span><br><span class="line">        <span class="function"><span class="type">static</span> std::string <span class="title">Stderr</span><span class="params">(<span class="type">const</span> std::string&amp; file_name)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="built_in">AddSuffix</span>(file_name, <span class="string">&quot;.stderr&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">FileUtil</span></span><br><span class="line">    &#123;</span><br><span class="line">    <span class="keyword">public</span>:</span><br><span class="line">        <span class="function"><span class="type">static</span> <span class="type">bool</span> <span class="title">IsFileExists</span><span class="params">(<span class="type">const</span> std::string&amp; file_name)</span></span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">            <span class="keyword">struct</span> <span class="title class_">stat</span> buf;</span><br><span class="line">            <span class="keyword">if</span>(<span class="built_in">stat</span>(file_name.<span class="built_in">c_str</span>(), &amp;buf)==<span class="number">0</span>)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3、log-hpp">3、log.hpp</h3><blockquote><p>为了更方便调试和打印信息，封装一个日志函数</p></blockquote><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;util.hpp&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> ns_log</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">using</span> <span class="keyword">namespace</span> ns_util;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">enum</span>&#123;</span><br><span class="line">        INFO,</span><br><span class="line">        DEBUG,</span><br><span class="line">        WARNING,</span><br><span class="line">        ERROR,</span><br><span class="line">        FATAL</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">inline</span> std::ostream&amp; <span class="title">Log</span><span class="params">(<span class="type">const</span> std::string&amp; level, <span class="type">const</span> std::string&amp; file_name, <span class="type">int</span> line)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="comment">//日志等级</span></span><br><span class="line">        std::string message = <span class="string">&quot;[&quot;</span>;</span><br><span class="line">        message+=level;</span><br><span class="line">        message+=<span class="string">&quot;]&quot;</span>;</span><br><span class="line">        <span class="comment">//报错文件名</span></span><br><span class="line">        message+=<span class="string">&quot;[&quot;</span>;</span><br><span class="line">        message+=file_name;</span><br><span class="line">        message+=<span class="string">&quot;]&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//报错行数</span></span><br><span class="line">        message+=<span class="string">&quot;[&quot;</span>;</span><br><span class="line">        message+=std::<span class="built_in">to_string</span>(line);</span><br><span class="line">        message+=<span class="string">&quot;]&quot;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//报错时间戳</span></span><br><span class="line">        message+=<span class="string">&quot;[&quot;</span>;</span><br><span class="line">        message+=TimeUtil::<span class="built_in">GetTimeStamp</span>();</span><br><span class="line">        message+=<span class="string">&quot;]&quot;</span>;</span><br><span class="line"></span><br><span class="line">        std::cout&lt;&lt;message;</span><br><span class="line">        <span class="keyword">return</span> std::cout;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">#<span class="keyword">define</span> LOG(level) Log(#level, __FILE__, __LINE__)</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;一、编译服务框架&quot;&gt;一、编译服务框架&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305191623531.jpg&quot; alt=&quot;3L4C005SGLF2CH(RG</summary>
      
    
    
    
    <category term="项目" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/"/>
    
    <category term="负载均衡式在线OJ" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%BC%8F%E5%9C%A8%E7%BA%BFOJ/"/>
    
    
    <category term="项目" scheme="https://atong.run/tags/%E9%A1%B9%E7%9B%AE/"/>
    
  </entry>
  
  <entry>
    <title>1、负载均衡式在线OJ-项目介绍</title>
    <link href="https://atong.run/posts/2085396799/"/>
    <id>https://atong.run/posts/2085396799/</id>
    <published>2023-05-21T09:10:54.979Z</published>
    <updated>2023-09-02T02:24:01.461Z</updated>
    
    <content type="html"><![CDATA[<h2 id="1、所用技术与开发环境">1、所用技术与开发环境</h2><p><strong>所用技术:</strong></p><blockquote><p>除了ctemplate可能会稍微写点之外，其余所有关于前端渲染相关内容不做说明~~~</p></blockquote><ul><li>C++ STL 标准库</li><li>Boost 准标准库(字符串切割)</li><li>cpp-httplib 第三方开源网络库</li><li>ctemplate 第三方开源前端网页渲染库</li><li>jsoncpp 第三方开源序列化、反序列化库</li><li>负载均衡设计</li><li>多进程、多线程</li><li>MySQL C connect</li><li>Ace前端在线编辑器（使用现成…）</li><li>html/css/js/jquery/ajax （使用现成…）</li></ul><p><strong>开发环境：</strong></p><ul><li>centos7</li><li>vim</li><li>mysql workbench</li></ul><h2 id="2、项目宏观结构">2、项目宏观结构</h2><blockquote><p>项目由3个核心模块组成</p></blockquote><ol><li><code>common</code>: 公众模块</li><li><code>compile_server:</code>编译运行模块</li><li><code>oj_server</code>: 获取题目列表，查看编写题目界面，负载均衡，其他功能</li></ol><h3 id="leetcode结构">leetcode结构</h3><blockquote><p>只实现类似leetcode的题目列表+在线编程功能</p></blockquote><h3 id="项目宏观结构">项目宏观结构</h3><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305211705704.png" alt="image.png"></p><h3 id="编写思路">编写思路</h3><ol><li>先编写 compile_server</li><li>oj_server</li><li>version1 基于文件版的在线OJ</li><li>前端的页面设计</li><li>version2 基于 MySQL 版的在线OJ</li></ol>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;1、所用技术与开发环境&quot;&gt;1、所用技术与开发环境&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;所用技术:&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;除了ctemplate可能会稍微写点之外，其余所有关于前端渲染相关内容不做说明~~~&lt;/p&gt;
&lt;/blockqu</summary>
      
    
    
    
    <category term="项目" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/"/>
    
    <category term="负载均衡式在线OJ" scheme="https://atong.run/categories/%E9%A1%B9%E7%9B%AE/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%BC%8F%E5%9C%A8%E7%BA%BFOJ/"/>
    
    
    <category term="项目" scheme="https://atong.run/tags/%E9%A1%B9%E7%9B%AE/"/>
    
  </entry>
  
  <entry>
    <title>分享几个可以免费体验GPT4的网站，感受GPT4的强大！！！</title>
    <link href="https://atong.run/posts/9168540/"/>
    <id>https://atong.run/posts/9168540/</id>
    <published>2023-05-03T04:08:31.667Z</published>
    <updated>2023-05-03T05:47:22.876Z</updated>
    
    <content type="html"><![CDATA[<p>GPT3.5的强大大家已经尝试过了吧，今天分享几个可以免费使用GPT4的网站，好东西得学会分享，也让大家体验一下高科技！</p><blockquote><p>GPT-4（Generative Pre-trained Transformer 4）是OpenAI推出的一款具有革命性影响的大型语言模型。基于Transformer架构，GPT-4的设计使其在理解和生成自然语言文本方面表现出色，让机器与人类的沟通变得更为流畅。该模型通过在大量文本数据上进行预训练，学会了诸多领域的知识，包括科技、文学、历史等。此外，GPT-4具备强大的迁移学习能力，可以在微调阶段适应各种具体任务，如问答、摘要、翻译等。</p></blockquote><h2 id="1、Poe">1、Poe</h2><blockquote><p>Poe每天免费一次试用GPT4，并且可以访问 ChatGPT、Claude instant、Claude+、等，强烈推荐！</p></blockquote><p>网址：<a href="https://poe.com/GPT-4">https://poe.com/GPT-4</a></p><p>体验：✨✨✨✨✨</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305022101501.png" alt="image.png"></p><h2 id="2、Ora">2、Ora</h2><blockquote><p>每天5条GPT4信息，并且可以创建并训练不同的机器人</p></blockquote><p>网址：<a href="https://ora.sh/openai/gpt4">https://ora.sh/openai/gpt4</a></p><p>体验：✨✨✨✨</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305022118558.png" alt="image.png"></p><h2 id="3、Forefront-Chat">3、Forefront Chat</h2><blockquote><p>看下图，有好多角色可以自定义，比较推荐</p></blockquote><p>网址：<a href="https://chat.forefront.ai">https://chat.forefront.ai</a></p><p>体验：✨✨✨✨</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305022110999.png" alt="image.png"></p><h2 id="4、ChatMind-AI">4、ChatMind AI</h2><blockquote><p>每天免费1次</p></blockquote><p>网址：<a href="https://chatmindai.cn">https://chatmindai.cn</a></p><p>体验：✨✨</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202305022102070.png" alt="image.png"></p><p>GPT-4的强大不仅体现在它可以处理多种任务，还表现在它能够理解和生成各种语言和方言。这使得GPT-4具有极高的普适性，GPT-4在多个任务中展示了惊人的性能，有时甚至超越了人类专家。</p><p>大家快用起来！！！！</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;GPT3.5的强大大家已经尝试过了吧，今天分享几个可以免费使用GPT4的网站，好东西得学会分享，也让大家体验一下高科技！&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;GPT-4（Generative Pre-trained Transformer 4）是OpenAI推出的一款具</summary>
      
    
    
    
    <category term="人工智能" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/"/>
    
    <category term="使用AI" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/%E4%BD%BF%E7%94%A8AI/"/>
    
    
    <category term="ChatGPT" scheme="https://atong.run/tags/ChatGPT/"/>
    
  </entry>
  
  <entry>
    <title>一切的基础-卦</title>
    <link href="https://atong.run/posts/844635680/"/>
    <id>https://atong.run/posts/844635680/</id>
    <published>2023-04-28T08:15:04.122Z</published>
    <updated>2023-05-01T14:23:59.805Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>太极、两仪、四象和八卦是中国古代哲学和道家思想的重要概念，它们相互关联，共同构成了一个完整的哲学体系。对于上边的几个名词基本每个人都听过，但是让大家说说是哪八个卦，每个卦象是什么样的，能说出来的人应该不多。这里就带大家认识一下，争取最快的速度让大家记住</p></blockquote><h2 id="目标">目标</h2><ul><li>八卦-卦象（最快认识、最低目标是会画）</li><li>八卦-卦序 （简单了解）</li></ul><h2 id="太极">太极</h2><blockquote><p>太极是道家哲学中的核心概念，代表了宇宙万物生成和变化的根本原因。太极即无极，无极生太极，太极生两仪。它既包含了宇宙的一切，也是宇宙的起源。太极图象往往用一副黑白相间的圆形图案表示，代表阴阳两极的和谐统一。<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304270951198.jpg" alt="taiji.jpg"></p></blockquote><h2 id="两仪">两仪</h2><blockquote><p>两仪指的是阴和阳，分别代表宇宙中的负面和正面力量。阴阳是相互依存、对立统一的，它们共同促成了宇宙的生成和变化。两仪生四象，即阴阳进一步演化所产生的四种状态。</p></blockquote><h2 id="四象">四象</h2><blockquote><p>四象是指：太阴、少阴、太阳、少阳。它们代表了阴阳两仪在宇宙中的进一步演化和辩证过程，太阴和少阳形成一对，太阳和少阴形成另一对。四象生成八卦，是由阴阳两仪演化后的八种状态。</p></blockquote><h2 id="八卦">八卦</h2><blockquote><p>八卦是古代中国的一种卜辞和预测体系，它包括八个基本符号，分别是：乾、兑、离、震、巽、坎、艮、坤。每个卦由三个爻组成，爻分为阳爻（—）和阴爻（–）两种。八卦的组合和变化可以表示宇宙万物运动变化的规律。</p></blockquote><p>八卦可以用来进行预测，这是因为它反映了宇宙中阴阳两仪的变化规律。根据阴阳的变化，可以对未来的事物发展进行推测。这种预测哲学体现了古代中国人对宇宙规律的探索和理解。</p><p>先天八卦和后天八卦是八卦的两种排列顺序。</p><p><strong>先天八卦</strong>：又称伏羲八卦，是传说中伏羲创立的八卦顺序。先天八卦的排列顺序是：乾、兑、离、震、巽、坎、艮、坤。先天八卦强调八卦的生成顺序，体现了宇宙生成和事物发展的过程。</p><p><strong>后天八卦</strong>：又称文王八卦、周易八卦，是传说中周文王创立的八卦顺序。后天八卦的排列顺序是：乾、坎、艮、震、巽、离、兑、坤。后天八卦强调八卦之间的相互关系，体现了事物发展的规律和道家的阴阳哲学。</p><p>总之，太极、两仪、四象和八卦是古代中国哲学和道家思想的重要组成部分，它们共同揭示了宇宙万物生成和变化的奥秘。先天八卦和后天八卦则是八卦的两种排列顺序，分别强调八卦的生成顺序和相互关系，体现了古代中国人对宇宙规律的探索和理解。<br><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/20230411121714.png" alt="image.png"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;blockquote&gt;
&lt;p&gt;太极、两仪、四象和八卦是中国古代哲学和道家思想的重要概念，它们相互关联，共同构成了一个完整的哲学体系。对于上边的几个名词基本每个人都听过，但是让大家说说是哪八个卦，每个卦象是什么样的，能说出来的人应该不多。这里就带大家认识一下，争取最快的速度让大家</summary>
      
    
    
    
    <category term="周易" scheme="https://atong.run/categories/%E5%91%A8%E6%98%93/"/>
    
    <category term="梅花易数" scheme="https://atong.run/categories/%E5%91%A8%E6%98%93/%E6%A2%85%E8%8A%B1%E6%98%93%E6%95%B0/"/>
    
    
    <category term="卦" scheme="https://atong.run/tags/%E5%8D%A6/"/>
    
  </entry>
  
  <entry>
    <title>还在用GPT？一直搞指令和交互麻烦么？试试AutoGPT（四个AutoGPT应用推荐）</title>
    <link href="https://atong.run/posts/1928150554/"/>
    <id>https://atong.run/posts/1928150554/</id>
    <published>2023-04-28T06:50:33.677Z</published>
    <updated>2023-04-28T06:53:25.964Z</updated>
    
    <content type="html"><![CDATA[<p>ChatGPT大家应该都已经用过了吧，ChatGPT一般来说还挺好用，但是让人不爽的是需要很多前提和限制才能让ChatGPT输出比较好的结果，也就是最近很火的Prompt。但是一旦涉及prompt就会觉的很呆，大家用ChatGPT就是图方便，那么有没有什么解决方法呢？</p><p>当然有，这个解决方法就是AutoGPT，这个核心是我们只需要提出我们想要完成的任务，其他的一切交给AI自己来，让AI自己给自己设定阶段性任务，自己给自己提示，只在必要的时候给他纠正即可，其他时候我们只用等代结果，听起来是不是很爽？</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304281405672.png" alt="image.png"></p><p>其实上边说的还是太过抽象了一点，我们还是详细举个具体的例子，比如我想让GPT写个论文，我们大概有几种种方式：</p><ul><li>直接给GPT主题或题目让它自由发挥</li><li>给GPT限定范围，并且给GPT一个具体身份</li><li>让GPT写大纲，让后根据大纲再让GPT写</li><li>…</li></ul><p>或者对其进行排列组合，但是一般来说，只有我们要求的越多，给GPT限制越多，最后的结果质量才好，但是有了AutoGPT之后会变成什么样呢？我们只需要告诉GPT我们要写的题目或者主题，它会不断的拆分任务，然后自己完成自己提出的任务，相当于让ChatGPT自己指挥自己，把我们之前不断和GPT交互的过程给省略掉。</p><h2 id="1、AutoTravel">1、AutoTravel</h2><blockquote><p>这个是我觉得最有意思得项目了，对于旅游，做攻略，做决定对很多小伙伴来说是一件非常不容易的，现在好了，有人基于AutoGPT做了这个AutoTravel，只要我们给它提出任务，它就可以自动给我们做出攻略！</p></blockquote><p>项目地址：<a href="https://auto-travel-gpt4.vercel.app/">https://auto-travel-gpt4.vercel.app/</a></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304281417024.png" alt="image.png"></p><h2 id="2、DOGPT">2、DOGPT</h2><blockquote><p>国内也可以用，完全免费，大家可以轻点薅羊毛，大佬还贴心的做了一些分类</p></blockquote><p>项目地址：<a href="https://www.dogpt.ai/">https://www.dogpt.ai/</a></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304281415550.png" alt="image.png"></p><h2 id="3、AutoGPT（程序员版）">3、AutoGPT（程序员版）</h2><blockquote><p>这个是github上非常火的一个项目，117k的恐怖star数，不过需要配置呀，稍微有点麻烦，但是还好，有教程，下边贴了鱼皮大佬的教程</p></blockquote><p>项目地址：<a href="https://github.com/atongrun/Auto-GPT">https://github.com/atongrun/Auto-GPT</a></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304281410436.png" alt="image.png"></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304281408976.png" alt="image.png"></p><p>如何用？这里大佬鱼皮写了详细的教程并且录制了视频，根据鱼皮的教程很快就能将项目配置好。</p><p><a href="https://www.zhihu.com/people/coder_yupi">(14 条消息) 程序员鱼皮 - 知乎 (zhihu.com)</a></p><h2 id="4、cognosys">4、cognosys</h2><blockquote><p>这个可以直接用不用配置</p></blockquote><p>项目地址：<a href="https://app.cognosys.ai/create">https://app.cognosys.ai/create</a></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304281413738.png" alt="image.png"></p><p>了解更多信息可以关注公众号：芝士就是菜</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;ChatGPT大家应该都已经用过了吧，ChatGPT一般来说还挺好用，但是让人不爽的是需要很多前提和限制才能让ChatGPT输出比较好的结果，也就是最近很火的Prompt。但是一旦涉及prompt就会觉的很呆，大家用ChatGPT就是图方便，那么有没有什么解决方法呢？&lt;/p</summary>
      
    
    
    
    <category term="人工智能" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/"/>
    
    <category term="使用AI" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/%E4%BD%BF%E7%94%A8AI/"/>
    
    
    <category term="ChatGPT" scheme="https://atong.run/tags/ChatGPT/"/>
    
    <category term="AutoGPT" scheme="https://atong.run/tags/AutoGPT/"/>
    
  </entry>
  
  <entry>
    <title>ChatGPT学术优化-VsCode+Anaconda配置</title>
    <link href="https://atong.run/posts/1863947790/"/>
    <id>https://atong.run/posts/1863947790/</id>
    <published>2023-04-15T14:50:50.001Z</published>
    <updated>2023-04-15T14:55:47.803Z</updated>
    
    <content type="html"><![CDATA[<h1>项目简介</h1><blockquote><p>科研工作专用ChatGPT拓展，特别优化学术Paper润色体验，支持自定义快捷按钮，支持自定义函数插件，支持markdown代码块表格显示，Tex公式双显示，新增Python/C++项目剖析/自译解功能，PDF/LaTex论文翻译/总结功能，兼容ChatGLM等本地模型</p></blockquote><p><a href="https://github.com/binary-husky/chatgpt_academic">项目地址</a></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304122140207.png" alt="image.png"></p><h1>项目功能</h1><table><thead><tr><th>功能</th><th>描述</th></tr></thead><tbody><tr><td>一键润色</td><td>支持一键润色、一键查找论文语法错误</td></tr><tr><td>一键中英互译</td><td>一键中英互译</td></tr><tr><td>一键代码解释</td><td>可以正确显示代码、解释代码</td></tr><tr><td><a href="https://www.bilibili.com/video/BV14s4y1E7jN">自定义快捷键</a></td><td>支持自定义快捷键</td></tr><tr><td><a href="https://www.bilibili.com/video/BV1rc411W7Dr">配置代理服务器</a></td><td>支持配置代理服务器</td></tr><tr><td>模块化设计</td><td>支持自定义高阶的实验性功能与[函数插件]，插件支持<a href="https://github.com/binary-husky/chatgpt_academic/wiki/%E5%87%BD%E6%95%B0%E6%8F%92%E4%BB%B6%E6%8C%87%E5%8D%97">热更新</a></td></tr><tr><td><a href="https://www.bilibili.com/video/BV1cj411A7VW">自我程序剖析</a></td><td>[函数插件] 一键读懂本项目的源代码</td></tr><tr><td><a href="https://www.bilibili.com/video/BV1cj411A7VW">程序剖析</a></td><td>[函数插件] 一键可以剖析其他Python/C/C++/Java项目树</td></tr><tr><td>读论文</td><td>[函数插件] 一键解读latex论文全文并生成摘要</td></tr><tr><td>批量注释生成</td><td>[函数插件] 一键批量生成函数注释</td></tr><tr><td>chat分析报告生成</td><td>[函数插件] 运行后自动生成总结汇报</td></tr><tr><td><a href="https://www.bilibili.com/video/BV1LM4y1279X">arxiv小助手</a></td><td>[函数插件] 输入arxiv文章url即可一键翻译摘要+下载PDF</td></tr><tr><td><a href="https://www.bilibili.com/video/BV1KT411x7Wn">PDF论文全文翻译功能</a></td><td>[函数插件] PDF论文提取题目&amp;摘要+翻译全文（多线程）</td></tr><tr><td><a href="https://www.bilibili.com/video/BV19L411U7ia">谷歌学术统合小助手</a> (Version&gt;=2.45)</td><td>[函数插件] 给定任意谷歌学术搜索页面URL，让gpt帮你选择有趣的文章</td></tr><tr><td>公式显示</td><td>可以同时显示公式的tex形式和渲染形式</td></tr><tr><td>图片显示</td><td>可以在markdown中显示图片</td></tr><tr><td>多线程函数插件支持</td><td>支持多线调用chatgpt，一键处理海量文本或程序</td></tr><tr><td>支持GPT输出的markdown表格</td><td>可以输出支持GPT的markdown表格</td></tr><tr><td>启动暗色gradio<a href="https://github.com/binary-husky/chatgpt_academic/issues/173">主题</a></td><td>在浏览器url后面添加<code>/?__dark-theme=true</code>可以切换dark主题</td></tr><tr><td>huggingface免科学上网<a href="https://huggingface.co/spaces/qingxu98/gpt-academic">在线体验</a></td><td>登陆huggingface后复制<a href="https://huggingface.co/spaces/qingxu98/gpt-academic">此空间</a></td></tr><tr><td>……</td><td>……</td></tr></tbody></table><h1>VSCode+Anaconda配置</h1><h2 id="一、git-clone项目到本地">一、git clone项目到本地</h2><h3 id="1、使用Git">1、使用Git</h3><p>本地新建一个文件夹，然后打开git工具直接clone下来就OK</p><h2 id="2、直接下载">2、直接下载</h2><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304122151887.png" alt="image.png"></p><h2 id="二、配置一下APIKEY和代理">二、配置一下APIKEY和代理</h2><blockquote><p>这里需要openai 的 apikey以及科学上网的方式，原文档讲述的非常全面</p></blockquote><p>教程：<a href="https://github.com/binary-husky/chatgpt_academic/wiki/%E4%BB%A3%E7%90%86%E8%BD%AF%E4%BB%B6%E9%97%AE%E9%A2%98%E7%9A%84%E6%96%B0%E6%89%8B%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95%EF%BC%88%E6%96%B9%E6%B3%95%E5%8F%AA%E9%80%82%E7%94%A8%E4%BA%8E%E6%96%B0%E6%89%8B%EF%BC%89">项目中纯新手教程</a></p><h2 id="三、Vscode配置环境">三、Vscode配置环境</h2><h3 id="1、打开anaconda-prompt">1、打开anaconda prompt</h3><blockquote><p>执行下述命令</p></blockquote><p>1）conda create -n gptac_venv python=3.11<br>2）conda activate gptac_venv<br>3）python -m pip install -r requirements.txt</p><p>备注：使用官方pip源或者阿里pip源，其他pip源（如一些大学的pip）有可能出问题，临时换源方法：</p><p>python -m pip install -r requirements.txt -i <a href="https://mirrors.aliyun.com/pypi/simple/">https://mirrors.aliyun.com/pypi/simple/</a></p><h3 id="2、打开vscode">2、打开vscode</h3><p>1、ctrl + shift +p 打开设置</p><p>2、搜索python编译</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304122159220.png" alt="image.png"></p><p>3、选择建好的conda环境</p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304122200398.png" alt="image.png"></p><p>4、ctrl + ~ 调出来终端，输入 python <a href="http://main.py">main.py</a></p><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304152238378.png" alt="image.png"></p><h2 id="四、大功告成">四、大功告成</h2><blockquote><p>现在就可以愉快的使用了</p></blockquote><p><img src="https://cdn.jsdelivr.net/gh/atongrun/ImageHost@main/202304152240864.png" alt="image.png"></p><p>这里面的几个功能都挺不错的，英文学术润色、中文学术润色、中英互译、查找语法错误，都挺好</p><p>PS： 以前的ChatGPT账号调用API是送18刀的免费额度的，但是这个免费的额度在4月1号就过期了，所以如果你的账号是以前注册的，有可能会显示额度不够的情况，这时候有两种解决方法。</p><ul><li>向原账户充钱，这个也挺麻烦的</li><li>创建个新的账号（推荐），这个成本最低，新创建的账号，送5刀的额度，其实就很多了，可以让我们用很久了。</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;项目简介&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;科研工作专用ChatGPT拓展，特别优化学术Paper润色体验，支持自定义快捷按钮，支持自定义函数插件，支持markdown代码块表格显示，Tex公式双显示，新增Python/C++项目剖析/自译解功能，PDF/LaTe</summary>
      
    
    
    
    <category term="科研相关" scheme="https://atong.run/categories/%E7%A7%91%E7%A0%94%E7%9B%B8%E5%85%B3/"/>
    
    <category term="科研工具" scheme="https://atong.run/categories/%E7%A7%91%E7%A0%94%E7%9B%B8%E5%85%B3/%E7%A7%91%E7%A0%94%E5%B7%A5%E5%85%B7/"/>
    
    
    <category term="ChatGPT" scheme="https://atong.run/tags/ChatGPT/"/>
    
    <category term="工具" scheme="https://atong.run/tags/%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>人工智能资源大放送：好用ChatGPT工具推荐、ChatGPT镜像站分享</title>
    <link href="https://atong.run/posts/1442069326/"/>
    <id>https://atong.run/posts/1442069326/</id>
    <published>2023-04-05T06:38:35.850Z</published>
    <updated>2023-04-28T06:49:15.098Z</updated>
    
    <content type="html"><![CDATA[<h1>一、好用ChatGPT工具推荐</h1><h2 id="1、ChatBox">1、ChatBox</h2><blockquote><p>A desktop app for ChatGPT API (OpenAI API) that supports Windows, Mac &amp; Linux. 开源的ChatGPT桌面应用，下载安装包直接运行，prompt 开发神器，Window、Mac、Linux全平台支持。（需要API key和科学上网）</p></blockquote><p>网址：<a href="https://github.com/Bin-Huang/chatbox">https://github.com/Bin-Huang/chatbox</a></p><h2 id="2、ChatPDF">2、ChatPDF</h2><blockquote><p>ChatPDF是一种人工智能工具，可以为您的PDF文件提供交互功能，让您可以像与他人交流一样与PDF文件进行交互。使用ChatPDF可以帮助您检索、搜索和总结PDF文件中的相关内容，使用户能够在更短的时间内了解重要信息。您可以通过单击此链接来访问它。（太大的还有特别多页的PDF需要付费）</p></blockquote><p>网址：<a href="https://www.chatpdf.com/">https://www.chatpdf.com/</a></p><h2 id="3、Portal">3、Portal</h2><blockquote><p>Portal是一款跨平台工具，旨在将ChatGPT的能力整合到用户的工作流程中。具体来说，他可以将任何选择的文本通过快捷键发送到ChatGPT，进行处理，然后返回到用户的剪切板，或者在光标处返回（实现打字机效果）。这意味着你可以在大部分没有接入ChatGPT能力的应用立即获得ChatGPT的加持。（需要API key和科学上网）</p></blockquote><p>网址：<a href="https://github.com/lxfater/Portal">https://github.com/lxfater/Portal</a></p><h2 id="4、Obsidian笔记ChatGPT插件">4、Obsidian笔记ChatGPT插件</h2><blockquote><p>将ChatGPT（几乎）无缝集成到Obsidian中，重度Obsidian用户和重度ChatGPT用户的福音（需要API key和科学上网）</p></blockquote><p>网址：<a href="https://github.com/bramses/chatgpt-md">https://github.com/bramses/chatgpt-md</a></p><h1>二、ChatGPT镜像（魔法版+正常版）</h1><p>继续更新一些ChatGPT的镜像站啊，以下大多数都有上下文记忆功能，大部分都是免费的或者一天有一些免费的次数，其中有几个网址有免费几次的GPT-4的试用，以下网址，希望大家且用且珍惜，如果有做的不错的网址，又有赞赏的功能的话，希望大家给大佬们打赏个水钱，毕竟你的每一次请求，大佬那边都是有成本的（OpenAI的api key免费的token只有18美金）</p><h2 id="1、正常使用">1、正常使用</h2><blockquote><p>以下网址，国内可以使用，无需魔法、无需账号，总共有5个</p></blockquote><p><a href="https://ai.bo-e.com/">https://ai.bo-e.com/</a><br><a href="https://chat.pypig.com/">https://chat.pypig.com/</a><br><a href="https://chat.huashuyunai.com/?code=0613KCGa1u451F0d4IGa1RdEIQ13KCGv&amp;state=34d026f4ca7ff889d404fd78fde31ef2#/">https://chat.huashuyunai.com/?code=0613KCGa1u451F0d4IGa1RdEIQ13KCGv&amp;state=34d026f4ca7ff889d404fd78fde31ef2#/</a><br><a href="https://ai.chatmsgz.com/h5/10001/#/pages/chat/chat/index">https://ai.chatmsgz.com/h5/10001/#/pages/chat/chat/index</a></p><h2 id="2、需要魔法">2、需要魔法</h2><blockquote><p>针对没有账号或者被封的用户但是你会科学的上网，下边的大部分都挺不错，可以都试一试，比较推荐的网站有11个，一般推荐的网站有5个</p></blockquote><h3 id="比较推荐">比较推荐</h3><p><a href="https://poe.com/">https://poe.com/</a><br><a href="https://theb.ai/">https://theb.ai/</a><br><a href="https://chat.yqcloud.top/">https://chat.yqcloud.top/</a><br><a href="https://chat.moyunav.com/">https://chat.moyunav.com/</a><br><a href="https://94gpt.com/">https://94gpt.com/</a><br><a href="https://gpt.xeasy.me/">https://gpt.xeasy.me/</a><br><a href="https://gpt.tool00.com/">https://gpt.tool00.com/</a><br><a href="https://trychatgp.com/">https://trychatgp.com/</a><br><a href="https://ai117.com/">https://ai117.com/</a><br><a href="https://chatcat.pages.dev/">https://chatcat.pages.dev/</a><br><a href="https://freegpt.one/">https://freegpt.one/</a></p><h3 id="一般推荐">一般推荐</h3><p><a href="https://chat.51buygpt.com/">https://chat.51buygpt.com/</a><br><a href="https://chat.geekr.dev/">https://chat.geekr.dev/</a><br><a href="https://desk.im">https://desk.im</a><br><a href="https://ai.ls/">https://ai.ls/</a><br><a href="https://chatforai.com/">https://chatforai.com/</a></p><h2 id="3、强烈推荐">3、强烈推荐</h2><p>Defalsh 是全球首个以 GPT 为信息处理引擎的 Web3 内容聚合平台，使用以太坊地址登录，免费体验依然保留，chat-next-web部署的gpt网页版，做的区块链项目，现在完全免费哦！加入它的 Discord 创世社区 - 限量领取 OG 身份</p><p>网址：<a href="https://www.deflash.ai/">https://www.deflash.ai/</a></p>]]></content>
    
    
    <summary type="html">人工智能资源大放送：4个好用ChatGPT相关AI工具推荐、21个ChatGPT镜像网站分享</summary>
    
    
    
    <category term="人工智能" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/"/>
    
    <category term="使用AI" scheme="https://atong.run/categories/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/%E4%BD%BF%E7%94%A8AI/"/>
    
    
    <category term="ChatGPT" scheme="https://atong.run/tags/ChatGPT/"/>
    
  </entry>
  
</feed>
