<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Linux on EuDs&#39;s Blog</title>
    <link>https://ds63.eu.org/tags/linux/</link>
    <follow_challenge>
      <feedId>55788057182175234</feedId>
      <userId>67186528297029632</userId>
    </follow_challenge>
    <description>Recent content in Linux on EuDs&#39;s Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Sun, 15 Dec 2024 23:15:49 +0800</lastBuildDate><atom:link href="https://ds63.eu.org/tags/linux/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>frp实现ssh内网穿透连接</title>
      <link>https://ds63.eu.org/2024/use_frp_to_ssh/</link>
      <pubDate>Sun, 15 Dec 2024 23:15:49 +0800</pubDate>
      
      <guid>https://ds63.eu.org/2024/use_frp_to_ssh/</guid>
      <description>frp is awesome</description>
      <content:encoded><![CDATA[<h2 id="版本">版本</h2>
<p>本文章使用的版本为frp_0.61.0_linux_amd64</p>
<hr>
<h2 id="工作原理">工作原理</h2>
<p>frp 主要由两个组件组成：客户端(frpc) 和 服务端(frps)。通常情况下，服务端部署在具有公网 IP 地址的机器上，而客户端部署在需要穿透的内网服务所在的机器上。</p>
<p>由于内网服务缺乏公网 IP 地址，因此无法直接被非局域网内的用户访问。用户通过访问服务端的 frps，frp 负责根据请求的端口或其他信息将请求路由到相应的内网机器，从而实现通信。</p>
<hr>
<h2 id="需求">需求</h2>
<p>我有一台配有公网ip的服务器，以及两台linux电脑，分别称为电脑a和电脑b。</p>
<p>我希望使用电脑a，在非局域网环境下，也能使用ssh访问电脑b。</p>
<hr>
<h2 id="服务端配置">服务端配置</h2>
<ul>
<li>假定我的服务器的ip为<code>6.6.6.6</code></li>
<li>安装目录位于: <code>/home/ubuntu/frp/frp_0.61.0_linux_amd64</code></li>
<li><code>frps.toml</code>文件为服务端的配置文件,内容如下
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="c">#服务绑定的IP与端口</span>
</span></span><span class="line"><span class="cl"><span class="nx">bindAddr</span> <span class="p">=</span> <span class="s2">&#34;0.0.0.0&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">bindPort</span> <span class="p">=</span> <span class="mi">7000</span>
</span></span><span class="line"><span class="cl"><span class="c">#web dashboard配置</span>
</span></span><span class="line"><span class="cl"><span class="nx">webServer</span><span class="p">.</span><span class="nx">addr</span> <span class="p">=</span> <span class="s2">&#34;0.0.0.0&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">webServer</span><span class="p">.</span><span class="nx">port</span> <span class="p">=</span> <span class="mi">7001</span>
</span></span><span class="line"><span class="cl"><span class="nx">webServer</span><span class="p">.</span><span class="nx">user</span> <span class="p">=</span> <span class="s2">&#34;admin&#34;</span> <span class="c"># change</span>
</span></span><span class="line"><span class="cl"><span class="nx">webServer</span><span class="p">.</span><span class="nx">password</span> <span class="p">=</span> <span class="s2">&#34;admin&#34;</span> <span class="c"># change</span>
</span></span><span class="line"><span class="cl"><span class="c">#启用prometheus监控指标</span>
</span></span><span class="line"><span class="cl"><span class="nx">enablePrometheus</span> <span class="p">=</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="c">#token权限验证，需与客户端配置一致</span>
</span></span><span class="line"><span class="cl"><span class="nx">auth</span><span class="p">.</span><span class="nx">method</span> <span class="p">=</span> <span class="s2">&#34;token&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">auth</span><span class="p">.</span><span class="nx">token</span> <span class="p">=</span> <span class="s2">&#34;simpletoken&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c">#日志配置</span>
</span></span><span class="line"><span class="cl"><span class="nx">log</span><span class="p">.</span><span class="nx">to</span> <span class="p">=</span> <span class="s2">&#34;/home/ubuntu/frp/frp_0.61.0_linux_amd64/frps/logs/frps.log&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">log</span><span class="p">.</span><span class="nx">level</span> <span class="p">=</span> <span class="s2">&#34;info&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">log</span><span class="p">.</span><span class="nx">maxDays</span> <span class="p">=</span> <span class="mi">3</span>
</span></span></code></pre></div></li>
</ul>
<h3 id="启动服务端">启动服务端</h3>
<ul>
<li>
<p><strong>命令行方式启动</strong>:</p>
<p><code>./frps -c ./frps.toml</code></p>
</li>
<li>
<p><strong>使用systemd方式启动</strong></p>
<ol>
<li>配置文件<code>/etc/systemd/system/frps.service</code>,具体内容如下</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="o">[</span>Unit<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 服务名称，可自定义</span>
</span></span><span class="line"><span class="cl"><span class="nv">Description</span> <span class="o">=</span> frp server
</span></span><span class="line"><span class="cl"><span class="nv">After</span> <span class="o">=</span> network.target syslog.target
</span></span><span class="line"><span class="cl"><span class="nv">Wants</span> <span class="o">=</span> network.target
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Service<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">Type</span> <span class="o">=</span> simple
</span></span><span class="line"><span class="cl"><span class="c1"># 启动frps的命令，需修改为您的frps的安装路径</span>
</span></span><span class="line"><span class="cl"><span class="nv">ExecStart</span> <span class="o">=</span> /home/ubuntu/frp/frp_0.61.0_linux_amd64/frps -c /home/ubuntu/frp/frp_0.61.0_linux_amd64/frps.toml
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Install<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">WantedBy</span> <span class="o">=</span> multi-user.target
</span></span></code></pre></div><ol start="2">
<li>启动服务
<ul>
<li><code>systemctl daemon-reload</code></li>
<li><code>systemctl start frps</code></li>
</ul>
</li>
</ol>
</li>
</ul>
<hr>
<h2 id="客户端配置">客户端配置</h2>
<ul>
<li>我将电脑b作为客户端</li>
<li>安装目录位于: <code>/home/ubuntu/Desktop/frp_0.61.0_linux_amd64</code></li>
<li><code>frpc.toml</code>文件为服务端的配置文件,内容如下
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="cl"><span class="nx">serverAddr</span> <span class="p">=</span> <span class="s2">&#34;6.6.6.6&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">serverPort</span> <span class="p">=</span> <span class="mi">7000</span> <span class="c">#要和frps.toml的bindPort一致</span>
</span></span><span class="line"><span class="cl"><span class="nx">auth</span><span class="p">.</span><span class="nx">method</span> <span class="p">=</span> <span class="s2">&#34;token&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">auth</span><span class="p">.</span><span class="nx">token</span> <span class="p">=</span> <span class="s2">&#34;simpleToken&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c">#日志配置</span>
</span></span><span class="line"><span class="cl"><span class="nx">log</span><span class="p">.</span><span class="nx">to</span> <span class="p">=</span> <span class="s2">&#34;/home/ubuntu/Desktop/frp_0.61.0_linux_amd64/logs/frpc.log&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">log</span><span class="p">.</span><span class="nx">level</span> <span class="p">=</span> <span class="s2">&#34;info&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">log</span><span class="p">.</span><span class="nx">maxDays</span> <span class="p">=</span> <span class="mi">3</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">[[</span><span class="nx">proxies</span><span class="p">]]</span>
</span></span><span class="line"><span class="cl"><span class="nx">name</span> <span class="p">=</span> <span class="s2">&#34;ssh&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">type</span> <span class="p">=</span> <span class="s2">&#34;tcp&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">localIP</span> <span class="p">=</span> <span class="s2">&#34;127.0.0.1&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nx">localPort</span> <span class="p">=</span> <span class="mi">22</span>
</span></span><span class="line"><span class="cl"><span class="nx">remotePort</span> <span class="p">=</span> <span class="mi">6000</span>
</span></span></code></pre></div></li>
</ul>
<h3 id="启动客户端">启动客户端</h3>
<ul>
<li>
<p><strong>命令行方式启动</strong>:</p>
<p><code>./frpc -c ./frpc.toml</code></p>
</li>
<li>
<p><strong>使用systemd方式启动</strong></p>
<ol>
<li>配置文件<code>/etc/systemd/system/frpc.service</code>,具体内容如下</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="o">[</span>Unit<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">Description</span> <span class="o">=</span> frp client
</span></span><span class="line"><span class="cl"><span class="nv">After</span> <span class="o">=</span> network.target syslog.target
</span></span><span class="line"><span class="cl"><span class="nv">Wants</span> <span class="o">=</span> network.target 
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Service<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">Type</span> <span class="o">=</span> simple
</span></span><span class="line"><span class="cl"><span class="c1"># 启动frps的命令，需修改为您的frpc的安装路径</span>
</span></span><span class="line"><span class="cl"><span class="nv">ExecStart</span> <span class="o">=</span> /home/ubuntu/Desktop/frp_0.61.0_linux_amd64/frpc -c /home/ubuntu/Desktop/frp_0.61.0_linux_amd64/frpc.toml
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>Install<span class="o">]</span> 
</span></span><span class="line"><span class="cl"><span class="nv">WantedBy</span> <span class="o">=</span> multi-user.target
</span></span></code></pre></div><ol start="2">
<li>启动服务
<ul>
<li><code>systemctl daemon-reload</code></li>
<li><code>systemctl start frpc</code></li>
</ul>
</li>
</ol>
</li>
</ul>
<h2 id="访问">访问</h2>
<ul>
<li>命令: <code>ssh -o Port=6000 ubuntu@6.6.6.6 -i ~/my_key.pem</code></li>
<li>注释
<ul>
<li>这里的<code>Port</code>为<code>frpc.toml</code>中设置的<code>remotePort</code></li>
<li><code>-i ~/my_key.pem</code> ，我是用来ssh连接<code>6.6.6.6</code>的</li>
<li>这里的<code>ubuntu</code>为电脑b的用户名</li>
<li>登录上后如果需要密码,那尝试输入电脑b的密码</li>
</ul>
</li>
<li>可以这样配置<code>~/.ssh/config</code>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">Host 电脑b
</span></span><span class="line"><span class="cl">  HostName 6.6.6.6
</span></span><span class="line"><span class="cl">  Port <span class="m">6000</span>
</span></span><span class="line"><span class="cl">  User ubuntu
</span></span><span class="line"><span class="cl">  IdentityFile ~/.ssh/my_key.pem
</span></span></code></pre></div></li>
</ul>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://github.com/fatedier/frp"  target="_blank" rel="noopener" >fatedier/frp: A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.</a></li>
<li><a href="https://gofrp.org/zh-cn/docs/"  target="_blank" rel="noopener" >文档 | frp</a></li>
<li><a href="https://github.com/fatedier/frp/issues/1607"  target="_blank" rel="noopener" >请问frpc里面可以设置多个server_addr吗？ · Issue #1607 · fatedier/frp</a></li>
<li><a href="https://www.cnblogs.com/hovin/p/18023593#_label4_2"  target="_blank" rel="noopener" >使用Frp配置内网访问（穿透） - hovin - 博客园</a></li>
<li><a href="https://wiki-power.com/%E4%BD%BF%E7%94%A8frp%E8%AE%BF%E9%97%AE%E7%BE%A4%E6%99%96NAS/"  target="_blank" rel="noopener" >使用 frp 访问群晖 NAS - Power&rsquo;s Wiki</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>ssh连接二三事</title>
      <link>https://ds63.eu.org/2024/things_about_ssh/</link>
      <pubDate>Sat, 17 Aug 2024 23:15:49 +0800</pubDate>
      
      <guid>https://ds63.eu.org/2024/things_about_ssh/</guid>
      <description>some thing about ssh</description>
      <content:encoded><![CDATA[<h2 id="免密登录">免密登录</h2>
<ol>
<li>将公钥添加到 <code>~/.ssh/authorized_keys </code></li>
<li>添加权限: <code>chmod 600 ~/.ssh/authorized_keys</code>, <code>chmod 700 ~/.ssh</code></li>
<li>登录: <code>ssh username@server_ip</code></li>
</ol>
<h2 id="github相关">Github相关</h2>
<ul>
<li>
<p>作用：use SSH to perform Git operations in repositories on GitHub.com</p>
</li>
<li>
<p>步骤:</p>
<ol>
<li><a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key"  target="_blank" rel="noopener" >Generating a new SSH key and adding it to the ssh-agent - GitHub Docs</a></li>
</ol>
<p><code>ssh-keygen -t ed25519 -C &quot;your_email@example.com&quot;</code>
2. <a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key"  target="_blank" rel="noopener" >Generating a new SSH key and adding it to the ssh-agent - GitHub Docs</a>
3. Testing your SSH connection: <code>ssh -T git@github.com</code>
4. <a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account"  target="_blank" rel="noopener" >Adding a new SSH key to your GitHub account - GitHub Docs</a></p>
</li>
</ul>
<h2 id="使用端口转发来远程连接内网的机器">使用端口转发来远程连接内网的机器</h2>
<ul>
<li>涉及到三台机器，身边的电脑a，具有公网ip的机器b，远程需要被访问的电脑c</li>
<li>核心思想: 使用一台能被双方访问得到的公网机器作为代理</li>
<li>步骤:
<ol>
<li>电脑c需要执行<code>ssh -oPort=22 -CNfg -R 40000:localhost:22 root@公网ip -oPort</code></li>
<li>使用电脑a通过ssh登陆到机器b，再通过ssh连接本地40000端口，这样就相当于连接到了电脑c的22端口</li>
</ol>
</li>
<li>参考: <a href="https://blog.fatedier.com/2015/07/22/ssh-port-forwarding/"  target="_blank" rel="noopener" >SSH 端口转发</a></li>
</ul>
<h2 id="持续部署">持续部署</h2>
<ul>
<li><a href="https://github.com/webfactory/ssh-agent"  target="_blank" rel="noopener" >webfactory/ssh-agent: GitHub Action to setup <code>ssh-agent</code> with a private key</a>这个action可以用来在GitHub Action进行ssh连接。</li>
<li>不过考虑到安全问题，最好是是利用SSHD来限制可执行的指令, 具体参见<a href="https://blog.caomingjun.com/secure-ssh-continuous-deployment-with-forcecommand/"  target="_blank" rel="noopener" >安全地使用 SSH 进行持续部署 - Cmj&rsquo;s Blog</a></li>
</ul>
<h2 id="id_rsa和-xxpem的区别和联系">id_rsa和 xx.pem的区别和联系</h2>
<ul>
<li>id_rsa 是一个私钥文件，通常用于 SSH 认证</li>
<li>xx.pem 文件则通常是 PEM 格式，可能包含私钥、公钥或证书，广泛用于 SSL/TLS,可以用于多种加密场景</li>
</ul>
<h2 id="参考">参考</h2>
<ul>
<li><a href="https://zhuanlan.zhihu.com/p/472660528"  target="_blank" rel="noopener" >如何优雅地在你的Windows主力机上通过SSH远程控制你的服务器（centos） - 知乎</a></li>
<li><a href="https://blog.legalhub.cn/2022/10/16/qunhui-nas-ssh-login/"  target="_blank" rel="noopener" >群晖 NAS 实现 SSH 免密码登录 | LEGALGEEK</a></li>
<li><a href="https://blog.csdn.net/YYwxcsdn/article/details/134764938"  target="_blank" rel="noopener" >VS Code Remote-ssh 远程控制Windows主机 + 免密登录 + 内网穿透_vscode 免密ssh 连接 windows-CSDN博客</a></li>
<li><a href="https://plantegg.github.io/2019/06/02/%E5%8F%B2%E4%B8%8A%E6%9C%80%E5%85%A8_SSH_%E6%9A%97%E9%BB%91%E6%8A%80%E5%B7%A7%E8%AF%A6%E8%A7%A3--%E6%94%B6%E8%97%8F%E4%BF%9D%E5%B9%B3%E5%AE%89/"  target="_blank" rel="noopener" >史上最全 SSH 暗黑技巧详解 | plantegg</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>腾讯高性能应用服务体验</title>
      <link>https://ds63.eu.org/2024/the-use-experience-of-tencent-hai/</link>
      <pubDate>Wed, 07 Aug 2024 23:05:49 +0800</pubDate>
      
      <guid>https://ds63.eu.org/2024/the-use-experience-of-tencent-hai/</guid>
      <description>国内真卷啊</description>
      <content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>最近刚好有将stable-difussion服务运行在服务器的需求，首先考虑的是amazon，但最便宜的那款一小时都要1美元多，偶然间发现腾讯云有活动<a href="https://cloud.tencent.com/product/hai"  target="_blank" rel="noopener" >高性能应用服务HAI_GPU云服务器_腾讯云</a>，价格如下</p>
<ul>
<li>GPU 基础型算力套餐
<ul>
<li>显存大小：16 GB</li>
<li>算力大小：8+TFlops SP</li>
<li>CPU：8 核，内存：32GB</li>
<li>1.2元每h</li>
<li>学生特惠，150元买250 小时 GPU基础型算力套餐</li>
</ul>
</li>
<li>这参数其实就是<a href="https://www.nvidia.com/en-us/data-center/tesla-t4/"  target="_blank" rel="noopener" >NVIDIA T4 Tensor Core GPU for AI Inference | NVIDIA Data Center</a></li>
</ul>
<p>这价格快比电费还便宜了，于是买了一张150元的现金券来体验下。</p>
<h2 id="需求">需求</h2>
<p>我想使用该服务器跑一个被我魔改后的stable-difussion-webui，而它提供了一键部署Stable Difussion WebUI的选项。</p>
<p>如果能使用这装好的python环境，那我能省事很多。而且我也好奇这是怎么做的。以下是我的过程。</p>
<h2 id="ssh连接">ssh连接</h2>
<p>第一步肯定是得连接上去。</p>
<p>但在<a href="https://console.cloud.tencent.com/hai/instance"  target="_blank" rel="noopener" >腾讯云 - 控制台</a>并不能找到连接的按钮，还以为不提供,找文档找到了<a href="https://cloud.tencent.com/document/product/1721/102197"  target="_blank" rel="noopener" >高性能应用服务 连接 Linux 算力-操作指南-文档中心-腾讯云</a>。</p>
<p>看到方式一，很熟悉啊，于是就去做了。</p>
<p>(写这篇文章的时候我又看了遍这个文档，发现还有方式二：通过 Terminal 连接算力)，然后我才发现它提供的JupyterLab有项目的基础介绍。所以其实我下面写的这些很大一部分其实人都写得很明白了,╮(╯-╰)╭  ）</p>
<h2 id="找到python依赖的安装位置">找到python依赖的安装位置</h2>
<p>一进去先<code>ls</code>,发现有个miniconda3,答案就呼之欲出了，请ChatGPT写了个简单的cheatsheet:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 创建一个新的 Conda 环境</span>
</span></span><span class="line"><span class="cl">conda create --name myenv <span class="nv">python</span><span class="o">=</span>3.8
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 激活环境</span>
</span></span><span class="line"><span class="cl">conda activate myenv
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 停用环境</span>
</span></span><span class="line"><span class="cl">conda deactivate
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 列出所有 Conda 环境</span>
</span></span><span class="line"><span class="cl">conda env list
</span></span></code></pre></div><h2 id="node运行装在conda的python">node运行装在conda的python</h2>
<p>我需要用node去调用python，可以这样做</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-javascript" data-lang="javascript"><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">workDir</span> <span class="o">=</span> <span class="s2">&#34;/root/my-stable-diffusion-webui&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">webUIProcess</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">url</span> <span class="o">=</span> <span class="nx">process</span><span class="p">.</span><span class="nx">env</span><span class="p">.</span><span class="nx">URL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">initWebGUI</span> <span class="o">=</span> <span class="nx">_</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="nx">resolve</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;initWebGUI start&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">process</span><span class="p">.</span><span class="nx">chdir</span><span class="p">(</span><span class="nx">workDir</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="nx">webUIProcess</span> <span class="o">=</span> <span class="nx">spawn</span><span class="p">(</span><span class="s1">&#39;/root/miniconda3/bin/python&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;launch.py&#39;</span><span class="p">,</span> <span class="s1">&#39;--xformers&#39;</span><span class="p">,</span> <span class="s1">&#39;--api&#39;</span><span class="p">,</span><span class="s1">&#39;--nobrowser&#39;</span><span class="p">]);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="nx">webUIProcess</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="sb">`stdout: </span><span class="si">${</span><span class="nx">data</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="nx">resolve</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">        <span class="nx">webUIProcess</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">=&gt;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kr">const</span> <span class="nx">errorMessage</span> <span class="o">=</span> <span class="nx">data</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">            <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="sb">`stderr: </span><span class="si">${</span><span class="nx">errorMessage</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="c1">// Check for errors, assuming warnings do not contain &#39;error&#39;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>            <span class="k">if</span> <span class="p">(</span><span class="sr">/error/i</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">errorMessage</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Kill process...&#39;</span><span class="p">,</span> <span class="nx">webUIProcess</span><span class="p">.</span><span class="nx">pid</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">                <span class="nx">webUIProcess</span><span class="p">.</span><span class="nx">kill</span><span class="p">();</span>  <span class="c1">// Kill the current process
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>                <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;Process&#39;</span><span class="p">,</span> <span class="nx">webUIProcess</span><span class="p">.</span><span class="nx">pid</span><span class="p">,</span> <span class="s1">&#39; killed.&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>值得一提的是，因为该服务器将依赖将依赖全安装在了base这个环境下，所以路径就是<code>/root/miniconda3/bin/python</code></p>
<h2 id="基础环境配置">基础环境配置</h2>
<ol>
<li>nvm安装
<ul>
<li><a href="https://github.com/nvm-sh/nvm"  target="_blank" rel="noopener" >nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></li>
<li><code>wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash</code></li>
</ul>
</li>
<li>redis安装: <code>apt-get install redis</code></li>
</ol>
<h2 id="下载所需的底模和lora文件">下载所需的底模和lora文件</h2>
<ol>
<li>因为我本地已经有相应的文件，于是我首先想的是上传。先是用的<a href="https://cyberduck.io/"  target="_blank" rel="noopener" >Cyberduck</a>,但连接失败，检查了下端口，也有开放，不知道啥原因，于是放弃</li>
<li>尝试直接使用sftp,<code>sftp username@your_server_ip</code> ,确实可行，于是请请ChatGPT写了个简单的cheatsheet:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 连接到服务器</span>
</span></span><span class="line"><span class="cl">sftp username@your_server_ip
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 切换到远程目录</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> /home/root/
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 使用 lpwd 查看本地工作目录，lcd 切换本地目录：</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 上传本地文件</span>
</span></span><span class="line"><span class="cl">put C:<span class="se">\p</span>ath<span class="se">\t</span>o<span class="se">\e</span>xample.txt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 使用 get 命令从远程服务器下载文件到本地：</span>
</span></span><span class="line"><span class="cl">get remotefile.txt
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 退出 sftp 会话</span>
</span></span><span class="line"><span class="cl"><span class="nb">exit</span>
</span></span></code></pre></div><p>但发现速度不尽如人意，于是放弃</p>
<ol start="3">
<li>
<p>这时候就可以将思维逆转过来。既然不能上传，那我就下载啊。我需要的底模文件是在<a href="https://civitai.com/models/276298/sdxl-pixel-art-or-base"  target="_blank" rel="noopener" >【SDXL】 Pixel Art | Base - v1.0 | Stable Diffusion Checkpoint | Civitai</a>，当我直接复制下载链接，使用wget会报错，需要认证。查文档查到了<a href="https://education.civitai.com/civitais-guide-to-downloading-via-api/#step-by-step"  target="_blank" rel="noopener" >Civitai&rsquo;s Guide to Downloading via API - Civitai Education</a>。最终能运行的命令类似于:  <code>curl -L -H &quot;Content-Type: application/json&quot; -H &quot;Authorization: Bearer your_token&quot; https://civitai.com/api/download/models/311399 -o SDXLPixelArtBase_v10.safetensors</code></p>
</li>
<li>
<p>lora文件我则将上传到了s3上。它有个<code>share with presigned URL</code>,于是我想当然地使用，但发现还是报错。最后还是直接用的<code>Object URL</code></p>
</li>
<li>
<p>后来发现文档中推荐的下载是这样写的:</p>
<ul>
<li>建议将基础模型文件转存至与HAI实例同地域的COS桶中，再在HAI实例中拉取COS文件，速度最快</li>
<li>国内地域HAI实例可能存在网络不稳定情况，推荐启用“学术加速”；国外地域HAI实例下载模型、插件速度更快</li>
</ul>
<p>好一个“学术加速”</p>
</li>
</ol>
<h2 id="运行时报错">运行时报错</h2>
<ul>
<li>
<p><a href="https://stackoverflow.com/questions/59572174/no-module-named-dotenv-python-3-8"  target="_blank" rel="noopener" >import - no module named &lsquo;dotenv&rsquo; python 3.8 - Stack Overflow</a></p>
<p><code>pip install python-dotenv</code></p>
</li>
</ul>
<h2 id="pm2使用">pm2使用</h2>
<p>再再请ChatGPT写了个简单的cheatsheet:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># 安装</span>
</span></span><span class="line"><span class="cl">npm install pm2 -g
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 指定env文件 </span>
</span></span><span class="line"><span class="cl">pm2 start <span class="s2">&#34;node --env-file=.env app.js&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 查看 PM2 中正在运行的进程</span>
</span></span><span class="line"><span class="cl">pm2 list
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 查看应用程序日志</span>
</span></span><span class="line"><span class="cl">pm2 logs my-app
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 停止应用程序：</span>
</span></span><span class="line"><span class="cl">pm2 stop my-app
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 重启应用程序：</span>
</span></span><span class="line"><span class="cl">pm2 restart my-app
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 删除应用程序：</span>
</span></span><span class="line"><span class="cl">pm2 delete my-app
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 检查日志</span>
</span></span><span class="line"><span class="cl">pm2 logs app
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 实时监控</span>
</span></span><span class="line"><span class="cl">pm2 monit
</span></span></code></pre></div><h2 id="怎么开机自启的">怎么开机自启的</h2>
<p>服务跑着跑着爆显存了，感觉问题可能出在这个服务器运行了两个stable-difussion-webui，重启后发现还是有，那么它是怎么做到开机自启的呢？</p>
<p>我先后检查了以下几处（还是请ChatGPT帮的忙）:</p>
<ol>
<li>systemctl</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">systemctl list-unit-files --type<span class="o">=</span>service --state<span class="o">=</span>enabled
</span></span><span class="line"><span class="cl">systemctl list-units --type<span class="o">=</span>service --state<span class="o">=</span>running
</span></span></code></pre></div><p>这个命令将列出所有在系统启动时启用的服务。</p>
<ol start="2">
<li>检查 <code>/etc/init.d/</code>
在一些较旧的系统或特定的服务中，可以通过检查 <code>/etc/init.d/</code> 目录来查看初始化脚本：</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">ls /etc/init.d/
</span></span></code></pre></div><p>这些脚本通常用于传统的 <code>init</code> 系统，在启动时运行。</p>
<ol start="4">
<li>cron</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo crontab -l
</span></span><span class="line"><span class="cl">sudo crontab -u &lt;username&gt; -l
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">cat /etc/crontab
</span></span><span class="line"><span class="cl">cat /etc/cron.*/*
</span></span></code></pre></div><h3 id="5-检查-rclocal">5. <strong>检查 <code>rc.local</code></strong></h3>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo vim /etc/rc.local
</span></span></code></pre></div><p>以上检查都无果后，我想起了查看当前进程:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="c1"># 显示当前终端中的所有进程：</span>
</span></span><span class="line"><span class="cl">ps -ef
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 比较可疑的包括</span>
</span></span><span class="line"><span class="cl">root           <span class="m">1</span>       <span class="m">0</span>  <span class="m">0</span> 12:35 ?        00:00:00 /usr/bin/dumb-init -- /usr/local/bin/application_init.s
</span></span><span class="line"><span class="cl">root           <span class="m">7</span>       <span class="m">1</span>  <span class="m">0</span> 12:35 pts/0    00:00:00 /bin/bash /usr/local/bin/application_init.sh
</span></span><span class="line"><span class="cl">root          <span class="m">16</span>       <span class="m">7</span>  <span class="m">0</span> 12:35 pts/0    00:00:00 /usr/bin/python3 /usr/bin/supervisord -c /etc/superviso
</span></span><span class="line"><span class="cl">root          <span class="m">18</span>      <span class="m">16</span>  <span class="m">0</span> 12:35 pts/0    00:00:00 /bin/bash /usr/local/bin/launch_jupyter.sh
</span></span><span class="line"><span class="cl">root          <span class="m">19</span>      <span class="m">16</span>  <span class="m">0</span> 12:35 pts/0    00:00:00 sshd: /usr/sbin/sshd -D <span class="o">[</span>listener<span class="o">]</span> <span class="m">0</span> of 10-100 startups
</span></span><span class="line"><span class="cl">root          <span class="m">20</span>      <span class="m">16</span>  <span class="m">0</span> 12:35 pts/0    00:00:00 /bin/bash /usr/local/bin/launch_stable_diffusion_webui.
</span></span><span class="line"><span class="cl">root          <span class="m">21</span>      <span class="m">18</span>  <span class="m">0</span> 12:35 pts/0    00:00:04 /root/miniconda3/bin/python3 /root/miniconda3/bin/jupyt
</span></span><span class="line"><span class="cl">root          <span class="m">22</span>      <span class="m">18</span>  <span class="m">0</span> 12:35 pts/0    00:00:00 tee -a /var/log/jupyter_service.log
</span></span><span class="line"><span class="cl">root          <span class="m">23</span>      <span class="m">20</span>  <span class="m">1</span> 12:35 pts/0    00:01:03 python3 -u launch.py --skip-prepare-environment --xform
</span></span><span class="line"><span class="cl">root          <span class="m">24</span>      <span class="m">20</span>  <span class="m">0</span> 12:35 pts/0    00:00:00 tee -a /var/log/sd_service.log
</span></span><span class="line"><span class="cl">root        <span class="m">1225</span>      <span class="m">68</span>  <span class="m">0</span> 12:50 pts/1    00:00:00 vim /etc/systemd/system/supervisord.service
</span></span><span class="line"><span class="cl">root        <span class="m">1994</span>      <span class="m">21</span>  <span class="m">0</span> 13:29 ?        00:00:00 /root/miniconda3/bin/python3 -m ipykernel_launcher -f /
</span></span></code></pre></div><p>于是找到了<code>supervisord</code></p>
<h2 id="supervisord的使用">supervisord的使用</h2>
<ol>
<li>请ChatGPT写了个简单的介绍:</li>
</ol>
<blockquote>
<p>supervisord 是一个流行的进程控制系统，用于管理和监控 Unix-like 操作系统上的进程。它提供了一种简单的方式来启动、停止、重启和监控进程。supervisord 是 supervisor 的守护进程，而 supervisor 是用于管理进程的客户端工具。</p>
</blockquote>
<ol start="2">
<li>用<code>whereis supervisord</code>找到了配置文件的位置，是在<code>/etc/supervisord.conf</code>,
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>program:stable_diffusion_webui<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">command</span><span class="o">=</span>/usr/local/bin/launch_stable_diffusion_webui.sh
</span></span><span class="line"><span class="cl"><span class="nv">autostart</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">autorestart</span><span class="o">=</span><span class="nb">false</span>
</span></span><span class="line"><span class="cl"><span class="nv">numprocs</span><span class="o">=</span><span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="nv">redirect_stderr</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">startretries</span><span class="o">=</span><span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="nv">startsecs</span><span class="o">=</span><span class="m">300</span>
</span></span><span class="line"><span class="cl"><span class="nv">stdout_logfile</span><span class="o">=</span>/dev/stdout
</span></span><span class="line"><span class="cl"><span class="nv">stdout_logfile_maxbytes</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl"><span class="nv">stdout_events_enabled</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">stderr_events_enabled</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">stopasgroup</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">killasgroup</span><span class="o">=</span><span class="nb">true</span>
</span></span></code></pre></div></li>
<li>那么刚才的问题得到了解答，开机自启的是<code>supervisor.service</code>，然后supervisor将<code>stable_diffusion_webui</code>给启动了</li>
<li><code>/usr/local/bin/launch_stable_diffusion_webui.sh</code>这个文件内容是
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span><span class="nb">source</span> /mnt/application_env.txt
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> /root/stable-diffusion-webui/ <span class="o">&amp;&amp;</span> python3 -u launch.py --skip-prepare-environment --xformers --listen --enable-insecure-extension-access --port<span class="o">=</span><span class="nv">$STABLE_DIFFUSION_WEBUI_PORT</span> 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">|</span> tee -a /var/log/sd_service.log<span class="sb">`</span>
</span></span></code></pre></div></li>
</ol>
<h2 id="开机自启">开机自启</h2>
<p>找到了它开机自启动服务的办法，那么就可以利用它来实现我想要的开机自启。</p>
<ol>
<li>先写了个脚本<code>/usr/local/bin/check_and_start_pm2.sh</code>:</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="cl"><span class="c1"># 进入程序目录</span>
</span></span><span class="line"><span class="cl"><span class="nb">cd</span> /path/to/SD-server/stable-difussion-server/
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 检查 pm2 中是否已有名为 &#34;app&#34; 的程序</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> ! pm2 list <span class="p">|</span> grep -q <span class="s1">&#39;app&#39;</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># 如果没有，启动 pm2 进程</span>
</span></span><span class="line"><span class="cl">    pm2 start <span class="s2">&#34;node --env-file=.env app.js&#34;</span> --name app
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> <span class="s2">&#34;PM2 process &#39;app&#39; is already running.&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span></code></pre></div><ol start="2">
<li>给权限<code>chmod +x /usr/local/bin/check_and_start_pm2.sh</code></li>
<li>改<code>/etc/supervisord.conf</code>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>program:stable_diffusion_webui<span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="nv">command</span><span class="o">=</span>/usr/local/bin/check_and_start_pm2.sh
</span></span><span class="line"><span class="cl"><span class="nv">autostart</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">autorestart</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">numprocs</span><span class="o">=</span><span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="nv">redirect_stderr</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">startretries</span><span class="o">=</span><span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="nv">startsecs</span><span class="o">=</span><span class="m">300</span>
</span></span><span class="line"><span class="cl"><span class="nv">stdout_logfile</span><span class="o">=</span>/dev/stdout
</span></span><span class="line"><span class="cl"><span class="nv">stdout_logfile_maxbytes</span><span class="o">=</span><span class="m">0</span>
</span></span><span class="line"><span class="cl"><span class="nv">stdout_events_enabled</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">stderr_events_enabled</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">stopasgroup</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl"><span class="nv">killasgroup</span><span class="o">=</span><span class="nb">true</span>
</span></span></code></pre></div></li>
<li>重新加载 supervisord 配置
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">supervisorctl reread
</span></span><span class="line"><span class="cl">supervisorctl update
</span></span></code></pre></div></li>
<li>这里我还踩到了自己挖的一个坑，<code>/usr/local/bin/check_and_start_pm2.sh</code>文件首行我是写<code>#!/bin/bash</code>，但我nvm是在zsh上装的，于是pm2在bash环境下就识别不到，再加上就行了。 <code>export PATH=$PATH:/root/.nvm/versions/node/v20.16.0/bin</code></li>
</ol>
<h2 id="体验">体验</h2>
<p>之前用过好几家国内的云服务器，最大的感受是ui很糟糕，然后就是费劲折腾的网络。</p>
<p>但这次体验却着实不赖，因为有了“学术加速”，呵呵。</p>
<h2 id="特别鸣谢">特别鸣谢</h2>
<p>感谢ChatGPT! 它省去了不少我查文档的功夫。</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>从零开始的ubuntu使用</title>
      <link>https://ds63.eu.org/2024/ubuntu-experience-in-a-different-world-from-zero/</link>
      <pubDate>Wed, 07 Aug 2024 15:37:49 +0800</pubDate>
      
      <guid>https://ds63.eu.org/2024/ubuntu-experience-in-a-different-world-from-zero/</guid>
      <description>Long may the Jammy Jellyfish!</description>
      <content:encoded><![CDATA[<p><strong>Ubuntu对我来说是一个既熟悉又陌生的系统。过去几年来，接触得最多的Linux系统就是它了。但除了wsl，虚拟机，云服务器，我还真没正儿八经的从零开始使用过。最近刚好有机会从装系统开始从零使用，以下记录我踩过的各种坑。</strong></p>
<h2 id="安装">安装</h2>
<ul>
<li><a href="https://blog.csdn.net/2401_84064328/article/details/137232169"  target="_blank" rel="noopener" >Windows11 + Linux (Ubuntu22.04) 双系统最简安装详细避坑版_win11安装linux双系统-CSDN博客</a></li>
<li><a href="https://releases.ubuntu.com/jammy/"  target="_blank" rel="noopener" >Ubuntu 22.04.4 LTS (Jammy Jellyfish)</a></li>
<li>踩坑到怀疑人生后，最后放弃使用24.04，回退到22.04,原本寸步难行的泥泞沼泽也成了康庄大道,赞美Jammy Jellyfish。</li>
</ul>
<h2 id="安装wifi驱动">安装wifi驱动</h2>
<p>无果。我使用的主版官网上只提供了win11或win10的驱动。网上找的几种办法，包括更新内核，都没能成功。放弃。</p>
<ul>
<li>更新内核后报错 <code>bad shim signature &amp; load the kernel first</code>
<a href="https://www.reddit.com/r/linux4noobs/comments/10152n7/how_to_fix_bad_shim_signature_load_the_kernel/"  target="_blank" rel="noopener" >How to fix &ldquo;bad shim signature &amp; load the kernel first&rdquo; errors on my triple boot setup? : r/linux4noobs</a></li>
</ul>
<h2 id="安装显卡驱动">安装显卡驱动</h2>
<ol>
<li>菜单栏找到 <code>Additional drivers</code>,点击安装</li>
<li><code>nvidia-smi</code> 检查是否安装成功</li>
</ol>
<h2 id="查看配置">查看配置</h2>
<ol>
<li><a href="https://blog.csdn.net/lxfHaHaHa/article/details/95769201"  target="_blank" rel="noopener" >查看ubuntu服务器的配置（cpu+显卡+内存+硬盘）_ubuntu查看服务器配置-CSDN博客</a></li>
</ol>
<h2 id="中文输入法">中文输入法</h2>
<p>参考以下几篇</p>
<ul>
<li><a href="https://blog.csdn.net/fr16021028/article/details/125891812"  target="_blank" rel="noopener" >Ubuntu中文设置与安装中文输入法（超详细）_ubuntu中文输入法安装-CSDN博客</a></li>
<li><a href="https://hk.v2ex.com/t/1055546"  target="_blank" rel="noopener" >各位 Linux 用的输入法都是？ - V2EX</a></li>
<li><a href="https://github.com/iDvel/rime-ice"  target="_blank" rel="noopener" >iDvel/rime-ice: Rime 配置：雾凇拼音 | 长期维护的简体词库</a></li>
</ul>
<h2 id="代理">代理</h2>
<ul>
<li><a href="https://v2ex.com/t/988113"  target="_blank" rel="noopener" >求助， Linux 如何使用全局代理？ - V2EX</a></li>
<li>ShellCrash
<ul>
<li><a href="https://github.com/juewuy/ShellCrash"  target="_blank" rel="noopener" >juewuy/ShellCrash: Run sing-box/mihomo as client in shell</a></li>
</ul>
</li>
<li>v2rayA
<ul>
<li><a href="https://github.com/v2rayA/v2rayA"  target="_blank" rel="noopener" >v2rayA/v2rayA: A web GUI client of Project V which supports VMess, VLESS, SS, SSR, Trojan, Tuic and Juicity protocols. 🚀</a></li>
<li><a href="https://www.sky350.com/1210.html"  target="_blank" rel="noopener" >V2RayA——新一代Linux客户端安装配置教程 | SKY博客</a></li>
<li><a href="https://v2raya.org/en/docs/prologue/installation/debian/#start-v2raya--enable-v2raya-start-automatically"  target="_blank" rel="noopener" >Debian / Ubuntu - v2rayA</a></li>
<li><a href="https://v2raya.org/en/docs/prologue/installation/debian/"  target="_blank" rel="noopener" >Debian / Ubuntu - v2rayA</a>
<ol>
<li><code>wget -qO - https://apt.v2raya.org/key/public-key.asc | sudo tee /etc/apt/keyrings/v2raya.asc</code></li>
<li><code>echo &quot;deb [signed-by=/etc/apt/keyrings/v2raya.asc] https://apt.v2raya.org/ v2raya main&quot; | sudo tee /etc/apt/sources.list.d/v2raya.list</code></li>
<li><code>sudo apt update</code></li>
<li><code>sudo apt install v2raya v2ray</code></li>
<li><code>sudo systemctl start v2raya.service</code></li>
</ol>
</li>
</ul>
</li>
<li>dae
<ul>
<li><a href="https://v2ex.com/t/982840"  target="_blank" rel="noopener" >V2 上关于 dae（大鹅）（ebpf）的讨论还是比较少啊，完美的旁路科学方案了吧？ - V2EX</a></li>
<li><a href="https://github.com/daeuniverse/dae/blob/main/docs/zh/how-it-works.md"  target="_blank" rel="noopener" >dae/docs/zh/how-it-works.md at main · daeuniverse/dae</a></li>
<li><a href="https://github.com/daeuniverse/dae/tree/main/docs/zh"  target="_blank" rel="noopener" >dae/docs/zh at main · daeuniverse/dae</a></li>
<li><a href="https://github.com/daeuniverse/dae/issues/468"  target="_blank" rel="noopener" >[Bug Report] <!-- raw HTML omitted -->Ubuntu 启动不起来 · Issue #468 · daeuniverse/dae</a></li>
</ul>
</li>
<li>electron-ssr
<ul>
<li><a href="https://github.com/shadowsocksrr/electron-ssr"  target="_blank" rel="noopener" >shadowsocksrr/electron-ssr: Shadowsocksr client using electron</a></li>
<li><a href="https://victrid.dev/2020/linux-pei-zhi-ssr/"  target="_blank" rel="noopener" >linux配置SSR | Victrid&rsquo;s Personal Site</a></li>
</ul>
</li>
<li>clash
<ul>
<li><a href="https://victrid.dev/2021/pei-zhi-tou-ming-dai-li-shi-xian-wu-gan-shang-wang/"  target="_blank" rel="noopener" >配置透明代理，实现无感上网 | Victrid&rsquo;s Personal Site</a></li>
</ul>
</li>
</ul>
<p>ps: 在这上折腾最久，最终使用的是v2raya。</p>
<h2 id="ssh">ssh</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo apt update <span class="o">&amp;&amp;</span> sudo apt upgrade
</span></span><span class="line"><span class="cl">sudo apt install openssh-server
</span></span><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> --now ssh
</span></span></code></pre></div><ul>
<li><a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh"  target="_blank" rel="noopener" >Connecting to GitHub with SSH - GitHub Docs</a></li>
</ul>
<h2 id="杂">杂</h2>
<ul>
<li><a href="https://www.reddit.com/r/archlinux/comments/11dqzj0/weird_error_when_shutting_down_after_update/"  target="_blank" rel="noopener" >Weird error when shutting down after update : r/archlinux</a></li>
<li><a href="https://juejin.cn/post/7097032561092165640"  target="_blank" rel="noopener" >查看Linux系统架构的命令，查看linux系统是哪种架构：AMD、ARM、x86、x86_64、pcc 或 查看Ubuntu的版本号 - 掘金</a></li>
</ul>
<h2 id="steam">steam</h2>
<p>之前看SteamDeck用的系统是Linux魔改，以为现在Linux上跑游戏很成熟了，但自己实际体验后，发现支持Linux的还不算多。</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Linux常用命令</title>
      <link>https://ds63.eu.org/2024/linux_cheatsheet/</link>
      <pubDate>Wed, 03 Apr 2024 23:15:49 +0800</pubDate>
      
      <guid>https://ds63.eu.org/2024/linux_cheatsheet/</guid>
      <description>a cheatsheet of vim commands</description>
      <content:encoded><![CDATA[<h2 id="命令执行">命令执行</h2>
<ul>
<li><code>cmd1;cmd2</code> 首先运行命令1，然后运行命令2</li>
<li><code>cmd1&amp;&amp;cmd2</code> 仅在命令1成功结束时才运行命令2</li>
<li><code>cmd1||cmd2</code> 仅当命令1失败时才运行命令2</li>
<li>执行多次，或循环执行
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#for i in {1..5}; do  // while true; do</span>
</span></span><span class="line"><span class="cl">&gt;  <span class="nb">command</span> 
</span></span><span class="line"><span class="cl">&gt;done
</span></span></code></pre></div></li>
</ul>
<hr>
<h2 id="bash">bash</h2>
<ul>
<li>可以利用 TAB 补全查看所有可用的命令选项(连按两次 TAB 键)</li>
<li><code>~/.bashrc</code>是 Bash shell 在每次启动时都会自动执行的一个脚本文件,可以用于设置环境变量、别名和一些其他 Bash shell 配置。
<ul>
<li><code>source /opt/rh/devtoolset-9/enable</code> 更新gcc版本</li>
<li>export PS1=&rsquo;[][\W]$ []&rsquo; 修改PS1变量，让其更加简洁。PS1的默认设置为<code>\[\][\u@\h \W]\$ \[\]</code></li>
</ul>
</li>
</ul>
<hr>
<h2 id="管道">管道</h2>
<h3 id="输出流">输出流</h3>
<ul>
<li>在Unix/Linux系统中，每个进程都有两个默认的输出流，即标准输出（文件描述符1，stdout）和标准错误输出（文件描述符2，stderr）</li>
<li>用<code>|</code>连接两个命令，以前面一个命令的输出作为后面命令的输入</li>
<li><code>strace -f gcc a.c 2&gt;&amp;1 | vim -</code> This will pipe both stdout and stderr to vim. The <code>-</code> argument tells vim to read from stdin.</li>
<li><code>strace pmap 152 |&amp; vim - </code>
<code>|&amp;</code> : This is a shorthand for <code>2&gt;&amp;1 |</code> in bash and zsh. It passes both standard output and standard error of one command as input to another.</li>
<li><code>find / -newermt &quot;2022-12-31 23:00&quot; ! -newermt &quot;2023-01-01 01:00&quot; 2&gt;/dev/null</code>
<ul>
<li>查找 2022年12月31日23:00 到 2023年1月1日1:00 期间发生变动的文件</li>
<li><code>2&gt;/dev/null</code> 丢弃错误信息</li>
</ul>
</li>
</ul>
<hr>
<h2 id="crontab">crontab</h2>
<ul>
<li><code>crontab -e</code></li>
<li>注意：crontab运行的环境并不包含docker命令。需要指定完整的路径。</li>
</ul>
<h2 id="进程">进程</h2>
<h3 id="ps">ps</h3>
<ul>
<li><code>ps</code>: 显示当前终端窗口关联的进程</li>
<li><code>ps aux</code>: 显示所有用户的详细进程列表，包括进程的PID（进程ID）、CPU利用率、内存使用等信息</li>
</ul>
<h3 id="lsof">lsof</h3>
<ul>
<li><code>lsof -i:端口号</code>:查看端口占用情况</li>
<li><code>lsof -nP -iTCP -sTCP:LISTEN</code></li>
<li>
<blockquote>
<p>-n inhibits the conversion of network numbers to host names for network files.  Inhibiting conversion may make lsof run faster.It is also useful when host name lookup is not working properly.</p>
</blockquote>
</li>
<li>
<blockquote>
<p>-P inhibits the conversion of port numbers to port names for network files.  Inhibiting the conversion may make lsof run a little faster.  It is also useful when port name lookup is not working properly.</p>
</blockquote>
</li>
</ul>
<h3 id="others">others</h3>
<ul>
<li><code>kill -9 PID</code>:杀掉对应的进程</li>
</ul>
<hr>
<h2 id="tar"><code>tar</code></h2>
<ul>
<li><code>tar cvf file.tar *.c</code> creates a tar file called file.tar which is the Archive of all .c files in current directory.</li>
<li><code>tar xvf file.tar</code> extracts files from Archives.</li>
<li><code>z</code>tells tar command that creates tar file using gzip 即<code>tar.gz</code></li>
</ul>
<hr>
<h2 id="find">find</h2>
<ul>
<li>
<p>配合grep查找文件内关键字</p>
<p><code>seq 1 10 | xargs -n2 -P5 sh -c 'find / -type f -mindepth $1 -maxdepth $2 -exec grep -inl &quot;keyword&quot; {} 2&gt;/dev/null \;' _</code></p>
</li>
<li>
<p>find查找指定时间段内变动的文件</p>
<p><code>find / -newermt &quot;2022-12-31 23:00&quot; ! -newermt &quot;2023-01-01 01:00&quot; 2&gt;/dev/null</code></p>
</li>
<li>
<p>查找根目录下的所有可执行文件，但排除/usr目录</p>
<p><code>find / -path /usr -prune -o -type f -executable</code></p>
</li>
</ul>
<hr>
<h2 id="查看信息">查看信息</h2>
<ul>
<li>查看架构 <code>arch</code></li>
<li>查看内核版本
<ul>
<li><code>uname -r</code></li>
<li><code>uname -a</code></li>
<li><code>cat /proc/version</code></li>
</ul>
</li>
</ul>
<hr>
<h2 id="杂项">杂项</h2>
<ul>
<li><code>sudo passwd root</code>: 修改root用户的密码</li>
<li><code>su</code> 切换用户，默认为切换到root用户</li>
<li><code>strace</code>  追踪程序系统调用</li>
<li><code>touch</code> 新建文件,内容为空</li>
<li><code>cat</code>
<ul>
<li><code>cat filename</code> To view a single file</li>
<li><code>cat [filename-whose-contents-is-to-be-copied] &gt; [destination-filename]</code> Copy the contents of one file to another file.</li>
<li><code>cat file1 &gt;&gt; file2</code> Cat command can append the contents of one file to the end of another file.</li>
</ul>
</li>
<li><code>sort -nk 6</code> 依第6列升序排列</li>
<li><code>grep</code> (global regular expression)  用于查找文件里符合条件的字符串或正则表达式</li>
<li><code>which</code> 查找安装路径 如<code>which docker</code></li>
<li><code>alias</code>
<ul>
<li><code>alias name='command line'</code></li>
<li>列出目前所有的别名设置 <code>alias</code></li>
<li>持久化: 添加到<code>~/.bashrc</code>即可</li>
</ul>
</li>
<li><a href="https://i.hsfzxjy.site/a-trick-to-retrieve-web-contents-without-curl-or-wget/"  target="_blank" rel="noopener" >Retrieve Contents over HTTP without curl or wget</a></li>
</ul>
<hr>
<h2 id="参考链接">参考链接</h2>
<ul>
<li><a href="https://zgao.top/find%e5%91%bd%e4%bb%a4%e5%9c%a8%e5%ba%94%e6%80%a5%e4%b8%ad%e7%9a%84%e9%ab%98%e6%95%88%e6%8e%92%e6%9f%a5%e6%8a%80%e5%b7%a7"  target="_blank" rel="noopener" >find命令在应急中的高效排查技巧 – Zgao&rsquo;s blog</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Linux内核编译</title>
      <link>https://ds63.eu.org/2023/compile-the-linux-kernel/</link>
      <pubDate>Thu, 14 Dec 2023 17:07:22 +0800</pubDate>
      
      <guid>https://ds63.eu.org/2023/compile-the-linux-kernel/</guid>
      <description>记一次操作系统实验</description>
      <content:encoded><![CDATA[<h2 id="步骤">步骤</h2>
<ol>
<li>在<a href="https://www.kernel.org/"  target="_blank" rel="noopener" >The Linux Kernel Archives</a>下载所需的内核代码</li>
<li>解压缩 <code>tar xvf linux-5.10.203.tar.xz</code> （以linux-5.10.203.tar.xz为例）</li>
<li><code>cd linux-5.10.203</code></li>
<li><code>cp -v /boot/config-$(uname -r) .config</code></li>
<li><code>make menuconfig</code> 进行配置</li>
<li><code>make -j$(nproc) 2&gt; error.log</code>  并发编译,并记录错误信息</li>
<li><code>make modules</code></li>
<li><code>make modules_install</code></li>
<li><code>make install</code></li>
<li><code>reboot</code></li>
<li>在GRUB菜单选择编译好的内核</li>
<li>可使用<code>uname -r</code> 查看内核版本，进行验证</li>
</ol>
<hr>
<h2 id="脚本">脚本</h2>
<p>我编写了一个脚本，用于自动化内核编译</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-Makefile" data-lang="Makefile"><span class="line"><span class="cl"><span class="c">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="c"></span>
</span></span><span class="line"><span class="cl"><span class="c"># 设置在出现错误或使用未定义的变量时立即退出
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="err">set</span> <span class="err">-e</span>
</span></span><span class="line"><span class="cl"><span class="err">set</span> <span class="err">-u</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 获取当前时间戳
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="nv">timestamp</span><span class="o">=</span><span class="k">$(</span>date +<span class="s2">&#34;%Y%m%d%H%M%S&#34;</span><span class="k">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 配置内核
</span></span></span><span class="line"><span class="cl"><span class="c"># make menuconfig
</span></span></span><span class="line"><span class="cl"><span class="c"></span>
</span></span><span class="line"><span class="cl"><span class="c"># 创建日志文件，带有时间戳
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="nv">log_file</span><span class="o">=</span><span class="s2">&#34;compile_log_</span><span class="si">${</span><span class="nv">timestamp</span><span class="si">}</span><span class="s2">.txt&#34;</span>
</span></span><span class="line"><span class="cl"><span class="err">touch</span> <span class="s2">&#34;$log_file&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 编译内核，将标准错误输出记录到日志文件并显示在终端
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="err">make</span> <span class="err">-j</span><span class="k">$(</span><span class="nv">nproc</span><span class="k">)</span> <span class="nv">INCREMENTAL</span><span class="o">=</span><span class="m">1</span> 2&gt; &gt;<span class="o">(</span>tee -a <span class="s2">&#34;</span><span class="nv">$log_file</span><span class="s2">&#34;</span> &gt;<span class="p">&amp;</span>2<span class="o">)</span> <span class="o">||</span> <span class="o">{</span> <span class="nb">echo</span> <span class="s2">&#34;Make failed&#34;</span><span class="p">;</span> <span class="nb">exit</span> 1<span class="p">;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 编译内核模块
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="err">make</span> <span class="err">modules</span> <span class="err">2&gt;</span> <span class="err">&gt;(tee</span> <span class="err">-a</span> <span class="s2">&#34;$log_file&#34;</span> <span class="err">&gt;&amp;2)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 安装内核模块
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="err">make</span> <span class="err">modules_install</span> <span class="err">2&gt;</span> <span class="err">&gt;(tee</span> <span class="err">-a</span> <span class="s2">&#34;$log_file&#34;</span> <span class="err">&gt;&amp;2)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 安装内核
</span></span></span><span class="line"><span class="cl"><span class="c"></span><span class="err">make</span> <span class="err">install</span> <span class="err">2&gt;</span> <span class="err">&gt;(tee</span> <span class="err">-a</span> <span class="s2">&#34;$log_file&#34;</span> <span class="err">&gt;&amp;2)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c"># 更新 GRUB 配置（如果使用 GRUB 引导）
</span></span></span><span class="line"><span class="cl"><span class="c"># update-grub 2&gt; &gt;(tee -a &#34;$log_file&#34; &gt;&amp;2)
</span></span></span></code></pre></div><hr>
<h2 id="添加新的系统调用">添加新的系统调用</h2>
<h3 id="hello">hello</h3>
<p><strong>方法一：</strong></p>
<ol>
<li>编辑arch/x86/entry/syscalls/syscall_64.tbl,添加
<code>441     64      hello                   sys_hello</code></li>
<li>在include/linux/syscalls.h中添加函数声明
<pre tabindex="0"><code>/* test */
asmlinkage long sys_hello(void);
</code></pre></li>
<li>在kernel/sys.c中末尾添加如下代码
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="cm">/* test */</span>
</span></span><span class="line"><span class="cl"><span class="nf">SYSCALL_DEFINE0</span><span class="p">(</span><span class="n">hello</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nf">printk</span><span class="p">(</span><span class="s">&#34;hello,world! </span><span class="se">\n</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></li>
</ol>
<p><strong>方法二：</strong></p>
<p>摘自<a href="https://dev.to/omergulen/how-to-add-system-call-syscall-to-the-kernel-compile-and-test-it-3e6p"  target="_blank" rel="noopener" >How to add system call (syscall) to the kernel, compile and test it? - DEV Community</a></p>
<ol>
<li>在<code>/usr/src/linux-5.15.142</code>建立新文件夹(以linux-5.15.142为例)
<code>mkdir hello &amp;&amp; cd hello</code></li>
<li><code>vim hello.c</code></li>
</ol>
<pre tabindex="0"><code>#include &lt;linux/kernel.h&gt;

asmlinkage long sys_hello(void) 
{
        //printk prints to the kernel’s log file.
        printk(&#34;Hello world\n&#34;);
        return 0;
}
</code></pre><ol start="3">
<li><code>vim Makefile</code></li>
</ol>
<pre tabindex="0"><code>obj-y := hello.o
</code></pre><ol start="4">
<li>go to the parent directory (kernel source main directory)</li>
<li>add our new syscall directory to Makefile,search for core-y,and add hello/ to the end of this line.</li>
<li>同方法一第一步</li>
<li>同方法一第二步</li>
</ol>
<h3 id="hide">hide</h3>
<ol>
<li>编辑include/linux/sched.h 文件，在task_struct新增</li>
</ol>
<pre tabindex="0"><code>        /* wyd: store the old pidS */
        pid_t old_pid;

        /* wyd: 0:hide */
        int hide;
</code></pre><ol start="2">
<li>修改kernel/fork.c中的copy_process函数</li>
</ol>
<pre tabindex="0"><code>        /* wyd: init the append values */
        p-&gt;hide =0;
        p-&gt;old_pid = p-&gt;pid;
</code></pre><ol start="3">
<li>编辑arch/x86/entry/syscalls/syscall_64.tbl,添加
<code>442     common  hide                    sys_hide</code></li>
<li>在include/linux/syscalls.h中添加函数声明</li>
</ol>
<pre tabindex="0"><code>asmlinkage int sys_hide(pid_t pid,int on);
</code></pre><ol start="5">
<li>在kernel/sys.c中末尾添加如下代码</li>
</ol>
<p><strong>此代码有问题，仅作为示例</strong></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl"><span class="nf">SYSCALL_DEFINE2</span><span class="p">(</span><span class="n">hide</span><span class="p">,</span><span class="kt">pid_t</span><span class="p">,</span><span class="n">pid</span><span class="p">,</span> <span class="kt">int</span><span class="p">,</span><span class="n">on</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">struct</span> <span class="n">task_struct</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">struct</span> <span class="n">task_struct</span> <span class="o">*</span><span class="n">me</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">p</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">init_task</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">do</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span><span class="p">(</span><span class="n">p</span><span class="o">-&gt;</span><span class="n">old_pid</span> <span class="o">==</span> <span class="n">pid</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="n">me</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                        <span class="k">break</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span><span class="k">while</span><span class="p">((</span><span class="n">p</span> <span class="o">=</span> <span class="nf">next_task</span><span class="p">(</span><span class="n">p</span><span class="p">))</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="n">p</span><span class="o">!=</span> <span class="o">&amp;</span><span class="n">init_task</span><span class="p">))</span><span class="o">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="n">current</span><span class="o">-&gt;</span><span class="n">uid</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">me</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">on</span> <span class="o">==</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">me</span><span class="o">-&gt;</span><span class="n">pid</span> <span class="o">=</span><span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="n">me</span><span class="o">-&gt;</span><span class="n">hide</span> <span class="o">=</span><span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">else</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">if</span><span class="p">(</span><span class="n">me</span><span class="o">-&gt;</span><span class="n">hide</span> <span class="o">==</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="p">{</span>
</span></span><span class="line"><span class="cl">                        <span class="n">me</span><span class="o">-&gt;</span><span class="n">pid</span> <span class="o">=</span> <span class="n">me</span><span class="o">-&gt;</span><span class="n">old_pid</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                        <span class="n">me</span><span class="o">-&gt;</span><span class="n">hide</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><ol>
<li>修改fs/proc/base.c中proc_pid_lookup的代码，添加</li>
</ol>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">task</span><span class="o">-&gt;</span><span class="n">hide</span><span class="o">==</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">                <span class="k">goto</span> <span class="n">out</span><span class="p">;</span>
</span></span></code></pre></div><hr>
<h2 id="grub">GRUB</h2>
<h3 id="默认启动的内核">默认启动的内核</h3>
<ol>
<li>打开 GRUB 配置文件：
<code>sudo vim /etc/default/grub</code></li>
<li>找到 GRUB_DEFAULT 行，并更改其值为你想要设置的默认内核的索引,保存并关闭。如
<code>GRUB_DEFAULT=2</code></li>
<li>更新 GRUB 配置
<code>sudo update-grub</code></li>
</ol>
<hr>
<h2 id="报错及解决">报错及解决</h2>
<h3 id="缺少xxx工具">缺少xxx工具</h3>
<p>可以在编译之前先安装编译所需要的所有工具
<code>sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison</code></p>
<h3 id="no-rule-to-make-target-debiancertsdebian-uefi-certspem">No rule to make target &lsquo;debian/certs/debian-uefi-certs.pem</h3>
<p>我参考了<a href="https://stackoverflow.com/questions/67670169/compiling-kernel-gives-error-no-rule-to-make-target-debian-certs-debian-uefi-ce"  target="_blank" rel="noopener" >Stack Overflow上的回答</a>，执行以下两条命令</p>
<pre tabindex="0"><code>sudo scripts/config --disable SYSTEM_TRUSTED_KEYS
sudo scripts/config --disable SYSTEM_REVOCATION_KEYS
</code></pre><h3 id="sed-cant-read-modulesorder-no-such-file-or-directory">sed: can&rsquo;t read modules.order: No such file or directory</h3>
<p>参考<a href="https://forums.gentoo.org/viewtopic-p-8686340.html?sid=5a87359186073a04049d6fc85eb51c32"  target="_blank" rel="noopener" >Gentoo Forums :: 阅读主题 - sed: can&rsquo;t read modules.order: No such file or directory</a></p>
<p>发现原来是刚才的<code>make -j$(nproc)</code>指令并没有执行成功。</p>
<h3 id="no-space-left-to-place">No space left to place</h3>
<p>我的选择是重装虚拟机，在设置的时候加大硬盘</p>
<p>看到两篇似乎可行的操作</p>
<ul>
<li><a href="https://blog.csdn.net/m0_61549260/article/details/129751313"  target="_blank" rel="noopener" >编译内核时，磁盘爆满的问题-CSDN博客</a></li>
</ul>
<h3 id="btf-tmp_vmlinuxbtf-pahole-pahole-is-not-available">BTF: .tmp_vmlinux.btf: pahole (pahole) is not available</h3>
<p>参考<a href="https://stackoverflow.com/questions/61657707/btf-tmp-vmlinux-btf-pahole-pahole-is-not-available"  target="_blank" rel="noopener" >compilation - BTF: .tmp_vmlinux.btf: pahole (pahole) is not available - Stack Overflow</a></p>
<p><code>sudo apt install dwarves</code></p>
<h3 id="warning-os-prober-will-not-be-executed-to-detect-other-bootable-partitions">Warning: os-prober will not be executed to detect other bootable partitions.</h3>
<ul>
<li>具体描述：
<code>make install</code>最后得到，
<pre tabindex="0"><code>Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
done
</code></pre>看网上的教程，这时候直接重启就可以进到GRUB菜单，但我没有。原因应该是以上导致的。</li>
<li>解决：
我的解决方法是在电脑开机的时候(出现操作系统的开机画面之前)，按F4键进入GRUB菜单</li>
</ul>
<h3 id="vmware开启了共享文件夹却不显示">VMware开启了共享文件夹却不显示</h3>
<p>在/mnt 文件夹下执行
<code>vmhgfs-fuse /mnt/hgfs</code></p>
<hr>
<h2 id="参考链接">参考链接</h2>
<ul>
<li><a href="https://blog.csdn.net/lingshengxueyuan/article/details/117597019"  target="_blank" rel="noopener" >Linux内核编译很简单，6步编译一个自己的内核_0基础编译内核教程-CSDN博客</a></li>
<li><a href="https://stackoverflow.com/questions/67670169/compiling-kernel-gives-error-no-rule-to-make-target-debian-certs-debian-uefi-ce"  target="_blank" rel="noopener" >linux - Compiling kernel gives error No rule to make target &lsquo;debian/certs/debian-uefi-certs.pem&rsquo; - Stack Overflow</a></li>
<li><a href="https://forums.gentoo.org/viewtopic-p-8686340.html?sid=5a87359186073a04049d6fc85eb51c32"  target="_blank" rel="noopener" >Gentoo Forums :: 阅读主题 - sed: can&rsquo;t read modules.order: No such file or directory</a></li>
<li><a href="https://blog.csdn.net/weixin_51480590/article/details/127776698"  target="_blank" rel="noopener" >Linux内核编译_linux内核编译后多大-CSDN博客</a></li>
<li><a href="https://blog.csdn.net/weixin_51480590/article/details/127767660"  target="_blank" rel="noopener" >Ubuntu磁盘扩充_ubuntu扩展磁盘空间-CSDN博客</a></li>
<li><a href="https://unix.stackexchange.com/questions/534596/hiding-processes-on-unix-linux"  target="_blank" rel="noopener" >process - Hiding processes on Unix/Linux - Unix &amp; Linux Stack Exchange</a></li>
<li><a href="https://nickdesaulniers.github.io/blog/2018/06/02/speeding-up-linux-kernel-builds-with-ccache/"  target="_blank" rel="noopener" >Speeding Up Linux Kernel Builds With ccache</a></li>
<li><a href="https://dev.to/omergulen/how-to-add-system-call-syscall-to-the-kernel-compile-and-test-it-3e6p"  target="_blank" rel="noopener" >How to add system call (syscall) to the kernel, compile and test it? - DEV Community</a></li>
<li><a href="https://www.kernel.org/doc/html/v4.10/process/adding-syscalls.html"  target="_blank" rel="noopener" >Adding a New System Call — The Linux Kernel documentation</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Vim常用命令</title>
      <link>https://ds63.eu.org/2023/vim_cheatsheet/</link>
      <pubDate>Wed, 29 Nov 2023 23:15:49 +0800</pubDate>
      
      <guid>https://ds63.eu.org/2023/vim_cheatsheet/</guid>
      <description>a cheatsheet of vim commands</description>
      <content:encoded><![CDATA[<h2 id="vim">Vim</h2>
<h3 id="另存为">另存为</h3>
<ul>
<li><code>:saveas ~/some/path/</code>: save your file to that locationvim</li>
</ul>
<h3 id="查找">查找</h3>
<ul>
<li>光标停留在想要查找的单词的任意一个字母上面， 然后输入<code>Shift</code> + <code>*</code>  ，即可快速选中该单词，并且可以通过 n  或  N 进行上一个或下一个的匹配。</li>
</ul>
<h3 id="cmd模式">cmd模式</h3>
<ul>
<li><code>:!cmd </code> execute a shell command from within Vim
<ul>
<li><code>!gcc %</code> 编译</li>
<li><code>!xxd</code>  将当前文件转换为十六进制表示并显示在终端中</li>
<li><code>%!xxd</code> 将当前文件的内容通过管道传递给外部命令xxd，并将其输出替换为当前文件的内容</li>
</ul>
</li>
<li><code>:set nu</code> 显示行号</li>
<li><code>:set wrap</code></li>
<li><code>:%!grep execve</code></li>
<li><code>:%! grep -v ENOENT</code></li>
<li><code>:%s/term/another_term/g </code> 替换</li>
</ul>
<hr>
<h2 id="浏览器-vimium">浏览器 vimium</h2>
<ol>
<li>标记
<ul>
<li><code>m</code> + <code>m</code> 创建一个新的标记</li>
<li>```+<code>m</code> 跳转到标记的位置</li>
</ul>
</li>
<li><code>g</code>
<ul>
<li><code>g</code> + <code>u</code> 访问当前网址的上一层（目录的上一层）</li>
<li><code>g</code> + <code>U</code> 访问当前网址的首页</li>
</ul>
</li>
<li>标签页</li>
</ol>
<ul>
<li><code>x</code> 关闭标签页</li>
<li><code>X</code> 恢复最近关闭的标签页</li>
</ul>
<hr>
<h2 id="vscode插件vim">vscode插件Vim</h2>
<h3 id="注释">注释</h3>
<ul>
<li>g + c 单行注释</li>
<li>g + C 多行注释</li>
</ul>
<h3 id="宏使用">宏使用</h3>
<ol>
<li>在normal模式下输入qa(当然也可以输入qb, qc, etc，这里的a, b, c是指寄存器名称，vim会把录制好的宏放在这个寄存器中)</li>
<li>录制操作</li>
<li>normal模式下输入q，结束宏录制。</li>
</ol>
<h3 id="跳转">跳转</h3>
<ul>
<li><code>%</code> 跳转到与当前括号所匹配的位置</li>
<li><code>f&lt;</code>  Jump forward and land on the <code>&lt;</code> character</li>
<li><code>t&gt;</code>  Jump forward and land right before the <code>&lt;</code> character</li>
</ul>
<hr>
<h2 id="杂">杂</h2>
<h3 id="vim-life">Vim Life</h3>
<p>看<a href="https://normalmo.de/vimlife/#footnotereturn3"  target="_blank" rel="noopener" >Vim Life - Normal Mode</a>，作者使用macro，实现了一个生命游戏。</p>
<h3 id="esc的替代">esc的替代</h3>
<ul>
<li>默认的代替Esc键的组合键是CTRL C 或者 Ctrl+[</li>
</ul>
<h2 id="参考链接">参考链接</h2>
<ul>
<li><a href="https://github.com/mudi24/keyborad-man/tree/main/%E6%B5%8F%E8%A7%88%E5%99%A8"  target="_blank" rel="noopener" >mudi24/keyborad-man</a></li>
<li><a href="https://www.cnblogs.com/ini_always/archive/2011/09/21/2184446.html"  target="_blank" rel="noopener" >vim重复操作的宏录制 - ini_always - 博客园</a></li>
<li><a href="https://danielmiessler.com/p/vim/"  target="_blank" rel="noopener" >Learn Vim For the Last Time</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Linux学习笔记</title>
      <link>https://ds63.eu.org/2023/linux%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Sun, 19 Mar 2023 18:38:50 +0800</pubDate>
      
      <guid>https://ds63.eu.org/2023/linux%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</guid>
      <description>Linux学习笔记</description>
      <content:encoded><![CDATA[<h2 id="linux命令">Linux命令</h2>
<ul>
<li><code>ctrl + C</code> 打断执行</li>
<li><code>pwd</code> 输出当前位置</li>
<li><code>cmd1;cmd2</code> 首先运行命令1，然后运行命令2</li>
<li><code>cmd1&amp;&amp;cmd2</code> 仅在命令1成功结束时才运行命令2</li>
<li><code>cmd1||cmd2</code> 仅当命令1失败时才运行命令2</li>
<li><code>strace</code>  追踪程序系统调用</li>
<li><code>touch</code> 新建文件,内容为空</li>
<li><code>cat</code>
<ul>
<li><code>cat filename</code> To view a single file</li>
<li><code>cat [filename-whose-contents-is-to-be-copied] &gt; [destination-filename]</code> Copy the contents of one file to another file.</li>
<li><code>cat file1 &gt;&gt; file2</code> Cat command can append the contents of one file to the end of another file.</li>
</ul>
</li>
<li>管道；用<code>|</code>连接两个命令，以前面一个命令的输出作为后面命令的输入
<ul>
<li><code>strace -f gcc a.c 2&gt;&amp;1 | vim -</code> This will pipe both stdout and stderr to vim. The <code>-</code> argument tells vim to read from stdin.</li>
<li><code>strace pmap 152 |&amp; vim - </code>
<code>|&amp;</code> : This is a shorthand for <code>2&gt;&amp;1 |</code> in bash and zsh. It passes both standard output and standard error of one command as input to another.</li>
</ul>
</li>
<li><code>sort -nk 6</code> 依第6列升序排列</li>
<li>执行多次，或循环执行
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">#for i in {1..5}; do  // while true; do</span>
</span></span><span class="line"><span class="cl">&gt;  <span class="nb">command</span> 
</span></span><span class="line"><span class="cl">&gt;done
</span></span></code></pre></div></li>
<li>crontab的使用
<ul>
<li><code>crontab -e</code></li>
<li>注意：crontab运行的环境并不包含docker命令。需要指定完整的路径。</li>
</ul>
</li>
<li><code>lsof -i:端口号</code>查看端口占用情况</li>
<li><code>kill -9 PID</code> 杀掉对应的进程</li>
<li><code>grep</code> (global regular expression)  用于查找文件里符合条件的字符串或正则表达式</li>
<li><code>which</code> 查找安装路径 如<code>which docker</code></li>
<li><code>ls -l</code> 详细信息</li>
<li><code>~/.bashrc</code>是 Bash shell 在每次启动时都会自动执行的一个脚本文件,可以用于设置环境变量、别名和一些其他 Bash shell 配置。
<ul>
<li><code>source /opt/rh/devtoolset-9/enable</code> 更新gcc版本</li>
<li>export PS1=&rsquo;[][\W]$ []&rsquo; 修改PS1变量，让其更加简洁。PS1的默认设置为<code>\[\][\u@\h \W]\$ \[\]</code></li>
</ul>
</li>
<li><code>tar</code>
<ul>
<li><code>tar cvf file.tar *.c</code> creates a tar file called file.tar which is the Archive of all .c files in current directory.</li>
<li><code>tar xvf file.tar</code> extracts files from Archives.</li>
<li><code>z</code>tells tar command that creates tar file using gzip 即<code>tar.gz</code></li>
</ul>
</li>
<li>可以利用 TAB 补全查看所有可用的命令选项(连按两次 TAB 键)</li>
</ul>
<h2 id="汇编相关">汇编相关</h2>
<ul>
<li><code>objdump -d filename</code> print the assembler content of the sections capable of execution.</li>
<li><code>objdump -s filename</code>  print the complete content of all the sections of the file</li>
</ul>
<h2 id="gcc">gcc</h2>
<ul>
<li><code>gcc - E a.c</code> 对a.c进行宏展开</li>
<li>升级gcc版本到gcc9 <a href="https://blog.csdn.net/xunye_dream/article/details/108918316"  target="_blank" rel="noopener" >CentOS7 升级gcc版本到gcc9</a>
<code>source /opt/rh/devtoolset-9/enable</code></li>
<li><code>-static</code> 静态编译，省去动态链接相关的系统调用</li>
</ul>
<h2 id="vim">vim</h2>
<ul>
<li>cmd模式
<ul>
<li><code>:!cmd </code> execute a shell command from within Vim
<ul>
<li><code>!gcc %</code> 编译</li>
<li><code>!xxd</code>  将当前文件转换为十六进制表示并显示在终端中</li>
<li><code>%!xxd</code> 将当前文件的内容通过管道传递给外部命令xxd，并将其输出替换为当前文件的内容</li>
</ul>
</li>
<li><code>:set nu</code> 显示行号</li>
<li><code>:set wrap</code></li>
<li><code>:%!grep execve</code></li>
<li><code>:%! grep -v ENOENT</code></li>
<li><code>:%s/term/another_term/g </code> 替换</li>
</ul>
</li>
<li>visual模式 按v进入
<ul>
<li><code>y</code> 复制选中内容</li>
<li><code>d</code> 删除</li>
</ul>
</li>
<li><code>u</code> undo</li>
</ul>
<h2 id="gdb">gdb</h2>
<ul>
<li>编译时要带<code>-g</code></li>
<li><code>bt</code> :but trace</li>
</ul>
<hr>
<h2 id="参考链接">参考链接</h2>
<ul>
<li><a href="https://www.geeksforgeeks.org/cat-command-in-linux-with-examples/"  target="_blank" rel="noopener" >Cat command in Linux with examples</a></li>
<li><a href="https://blog.csdn.net/xunye_dream/article/details/108918316"  target="_blank" rel="noopener" >CentOS7 升级gcc版本到gcc9</a></li>
<li><a href="https://jyywiki.cn/OS/2022/"  target="_blank" rel="noopener" >操作系统：设计与实现 (2022 春季学期)</a></li>
<li><a href="https://blog.csdn.net/lc013/article/details/103775702"  target="_blank" rel="noopener" >Linux 定时执行shell 脚本</a></li>
<li><a href="https://www.geeksforgeeks.org/tar-command-linux-examples"  target="_blank" rel="noopener" >tar command in Linux with examples</a></li>
</ul>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
