<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>YooooEX</title>
  
  <subtitle>Yoooo</subtitle>
  <link href="/rss.xml" rel="self"/>
  <link href="https://pubsubhubbub.appspot.com/" rel="hub"/>
  <link href="https://yooooex.com/"/>
  <updated>2020-12-08T07:08:12.569Z</updated>
  <id>https://yooooex.com/</id>
  
  <author>
    <name>YooooEX</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Feeder 更新日志</title>
    <link href="https://yooooex.com/2020/06/03/feeder-change-log/"/>
    <id>https://yooooex.com/2020/06/03/feeder-change-log/</id>
    <published>2020-06-03T09:53:39.000Z</published>
    <updated>2020-12-08T07:08:12.569Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>这是 <code>Feeder</code> 的更新日志留档.</p><p>应用下载请前往 <a href="https://play.google.com/store/apps/details?id=com.yooooex.feeder" target="_blank" rel="noopener">Play Store</a> 或 <a href="https://github.com/YooooEX/Feeder/releases" target="_blank" rel="noopener">GitHub</a> 下载.</p><a id="more"></a><h2 id="1-3-8"><a href="#1-3-8" class="headerlink" title="1.3.8"></a>1.3.8</h2><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">完善内置浏览器的界面样式</span><br><span class="line">在使用 OAuth 登录时,定时更新 OAuth token</span><br><span class="line">完善 token 超时处理逻辑</span><br><span class="line">弃用 kotlin-android-extensions, 启用 kotlin-parcelize</span><br><span class="line">从 Kotlin Synthetics 迁移到 Jetpack View Binding</span><br><span class="line">更新依赖</span><br><span class="line"></span><br><span class="line">Improve Integrated Browser UI</span><br><span class="line">Enable auto retrieve token via OAuth login method</span><br><span class="line">Improve token expired scene</span><br><span class="line">Migrate from Kotlin Synthetics to ViewBinding</span><br><span class="line">Migrate Kotlin Parcel plugin</span><br><span class="line">Remove deprecated plugin</span><br><span class="line">Upgrade dependencies</span><br></pre></td></tr></table></figure><h2 id="1-3-7"><a href="#1-3-7" class="headerlink" title="1.3.7"></a>1.3.7</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">增加启动时同步(在设置中调整选项)</span><br><span class="line">细节优化</span><br><span class="line"></span><br><span class="line">Now can sync on startup(config in settings)</span><br><span class="line">Minor improvement</span><br></pre></td></tr></table></figure><h2 id="1-3-6"><a href="#1-3-6" class="headerlink" title="1.3.6"></a>1.3.6</h2><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">完善详情样式</span><br><span class="line">现在在详情可以打开带链接的图片(长按图片显示菜单)</span><br><span class="line">从 Fabric 迁移到 Firebase Crashlytics</span><br><span class="line"></span><br><span class="line">Improve detail style.</span><br><span class="line">Now can long press image to show options menu if this image contains a link.</span><br><span class="line">Migrate Fabric to Firebase Crashlytics</span><br></pre></td></tr></table></figure><h2 id="1-3-5"><a href="#1-3-5" class="headerlink" title="1.3.5"></a>1.3.5</h2><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">搜索订阅增加预览内容功能.</span><br><span class="line">完善详情点击事件.</span><br><span class="line">细节完善.</span><br><span class="line"></span><br><span class="line">Now can preview subscription content in subscription search view.</span><br><span class="line">Improve detail click event.</span><br><span class="line">Minor improvement.</span><br></pre></td></tr></table></figure><h2 id="1-3-4"><a href="#1-3-4" class="headerlink" title="1.3.4"></a>1.3.4</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">现在能在订阅管理中搜索并添加订阅了.</span><br><span class="line">细节完善.</span><br><span class="line"></span><br><span class="line">Add ability to search and add subscriptions in subscription manage view.</span><br><span class="line">Minor bugfix and improvement.</span><br></pre></td></tr></table></figure><h2 id="1-3-3"><a href="#1-3-3" class="headerlink" title="1.3.3"></a>1.3.3</h2><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">增加 OAuth 登录</span><br><span class="line">更新了条目长按操作和订阅编辑操作的界面</span><br><span class="line">改善刘海屏设备的适配</span><br><span class="line"></span><br><span class="line">Now support OAuth login</span><br><span class="line">Improve UI of subscprition edit and item long press action</span><br><span class="line">Improve UI on notch devices</span><br></pre></td></tr></table></figure><h2 id="1-3-0"><a href="#1-3-0" class="headerlink" title="1.3.0"></a>1.3.0</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Rewritten with kotlin.</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;这是 &lt;code&gt;Feeder&lt;/code&gt; 的更新日志留档.&lt;/p&gt;&lt;p&gt;应用下载请前往 &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.yooooex.feeder&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Play Store&lt;/a&gt; 或 &lt;a href=&quot;https://github.com/YooooEX/Feeder/releases&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GitHub&lt;/a&gt; 下载.&lt;/p&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Feeder" scheme="https://yooooex.com/tags/Feeder/"/>
    
  </entry>
  
  <entry>
    <title>Kafka 日志清理设置</title>
    <link href="https://yooooex.com/2020/06/02/kafka-log-setting/"/>
    <id>https://yooooex.com/2020/06/02/kafka-log-setting/</id>
    <published>2020-06-02T02:25:34.000Z</published>
    <updated>2020-06-02T03:01:18.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>有关 <code>Kafka</code> 日志的设置主要就是下面几个设置,做个记录.</p><h2 id="有关时长的设置顺序"><a href="#有关时长的设置顺序" class="headerlink" title="有关时长的设置顺序"></a>有关时长的设置顺序</h2><p><strong>关于时长的设置都是优先使用小单位的设置</strong>,即:</p><blockquote><p><code>ms</code> &gt;&gt; <code>minutes</code> &gt;&gt; <code>hours</code></p></blockquote><p>当最小单位无设置时应用下一级的设置.</p><h2 id="log-cleanup-policy"><a href="#log-cleanup-policy" class="headerlink" title="log.cleanup.policy"></a><code>log.cleanup.policy</code></h2><p>日志处理动作,默认为删除</p><p>可选择 <code>delete</code> 或 <code>compact</code> 进行删除和压缩操作</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">log.cleanup.policy=delete</span><br></pre></td></tr></table></figure><h2 id="log-dirs"><a href="#log-dirs" class="headerlink" title="log.dirs"></a><code>log.dirs</code></h2><p>日志存放位置,存储到目录</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">log.dirs=/PATH/TO/KAFKA/LOG/</span><br></pre></td></tr></table></figure><h2 id="log-retention-hours"><a href="#log-retention-hours" class="headerlink" title="log.retention.hours"></a><code>log.retention.hours</code></h2><p>日志存放时长 (小时),超过值的日志将会被处理</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">log.retention.hours=24</span><br></pre></td></tr></table></figure><h2 id="log-retention-minutes"><a href="#log-retention-minutes" class="headerlink" title="log.retention.minutes"></a><code>log.retention.minutes</code></h2><a id="more"></a><p>日志存放时长 (分钟),超过值的日志将会被处理</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">log.retention.minutes=1440</span><br></pre></td></tr></table></figure><h2 id="log-retention-ms"><a href="#log-retention-ms" class="headerlink" title="log.retention.ms"></a><code>log.retention.ms</code></h2><p>日志存放时长 (毫秒),超过值的日志将会被处理</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">log.retention.ms=86400000</span><br></pre></td></tr></table></figure><h2 id="log-roll-hours"><a href="#log-roll-hours" class="headerlink" title="log.roll.hours"></a><code>log.roll.hours</code></h2><p>轮转日志时长 (小时),超过值将会切分日志</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">log.roll.hours=24</span><br></pre></td></tr></table></figure><h2 id="log-roll-ms"><a href="#log-roll-ms" class="headerlink" title="log.roll.ms"></a><code>log.roll.ms</code></h2><p>轮转日志时长 (毫秒),超过值将会切分日志</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">log.roll.ms=86400000</span><br></pre></td></tr></table></figure><h2 id="log-retention-bytes"><a href="#log-retention-bytes" class="headerlink" title="log.retention.bytes"></a><code>log.retention.bytes</code></h2><p>日志最大大小 (<code>partition</code>),超过值的日志将会被处理</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">log.retention.bytes=1073741824</span><br></pre></td></tr></table></figure><h2 id="log-segment-bytes"><a href="#log-segment-bytes" class="headerlink" title="log.segment.bytes"></a><code>log.segment.bytes</code></h2><p>单个日志文件的最大大小,超过值的日志将会被处理</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">log.segment.bytes=1073741824</span><br></pre></td></tr></table></figure><p>参考文档:</p><p><a href="https://kafka.apache.org/documentation/#configuration" target="_blank" rel="noopener">Apache Kafka</a></p><p><a href="https://docs.cloudera.com/HDPDocuments/HDP3/HDP-3.1.5/installing-configuring-kafka/content/log_settings.html" target="_blank" rel="noopener">Installing and configuring Apache Kafka</a></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;有关 &lt;code&gt;Kafka&lt;/code&gt; 日志的设置主要就是下面几个设置,做个记录.&lt;/p&gt;&lt;h2 id=&quot;有关时长的设置顺序&quot;&gt;&lt;a href=&quot;#有关时长的设置顺序&quot; class=&quot;headerlink&quot; title=&quot;有关时长的设置顺序&quot;&gt;&lt;/a&gt;有关时长的设置顺序&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;关于时长的设置都是优先使用小单位的设置&lt;/strong&gt;,即:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;ms&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;minutes&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;hours&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;当最小单位无设置时应用下一级的设置.&lt;/p&gt;&lt;h2 id=&quot;log-cleanup-policy&quot;&gt;&lt;a href=&quot;#log-cleanup-policy&quot; class=&quot;headerlink&quot; title=&quot;log.cleanup.policy&quot;&gt;&lt;/a&gt;&lt;code&gt;log.cleanup.policy&lt;/code&gt;&lt;/h2&gt;&lt;p&gt;日志处理动作,默认为删除&lt;/p&gt;&lt;p&gt;可选择 &lt;code&gt;delete&lt;/code&gt; 或 &lt;code&gt;compact&lt;/code&gt; 进行删除和压缩操作&lt;/p&gt;&lt;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;log.cleanup.policy=delete&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h2 id=&quot;log-dirs&quot;&gt;&lt;a href=&quot;#log-dirs&quot; class=&quot;headerlink&quot; title=&quot;log.dirs&quot;&gt;&lt;/a&gt;&lt;code&gt;log.dirs&lt;/code&gt;&lt;/h2&gt;&lt;p&gt;日志存放位置,存储到目录&lt;/p&gt;&lt;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;log.dirs=/PATH/TO/KAFKA/LOG/&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h2 id=&quot;log-retention-hours&quot;&gt;&lt;a href=&quot;#log-retention-hours&quot; class=&quot;headerlink&quot; title=&quot;log.retention.hours&quot;&gt;&lt;/a&gt;&lt;code&gt;log.retention.hours&lt;/code&gt;&lt;/h2&gt;&lt;p&gt;日志存放时长 (小时),超过值的日志将会被处理&lt;/p&gt;&lt;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;log.retention.hours=24&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h2 id=&quot;log-retention-minutes&quot;&gt;&lt;a href=&quot;#log-retention-minutes&quot; class=&quot;headerlink&quot; title=&quot;log.retention.minutes&quot;&gt;&lt;/a&gt;&lt;code&gt;log.retention.minutes&lt;/code&gt;&lt;/h2&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Kafka" scheme="https://yooooex.com/tags/Kafka/"/>
    
  </entry>
  
  <entry>
    <title>MongoDB 日志切分</title>
    <link href="https://yooooex.com/2020/05/21/mongodb-rotate-log/"/>
    <id>https://yooooex.com/2020/05/21/mongodb-rotate-log/</id>
    <published>2020-05-21T09:21:15.000Z</published>
    <updated>2020-05-21T09:59:31.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>今天收到监控警告,说服务器磁盘快满了.</p><p>登上去看了一下,发现 <code>MongoDB</code> 的日志没做切分,大小也达到了13G,那就给他做个切分吧.</p><h2 id="查看-MongoDB-配置"><a href="#查看-MongoDB-配置" class="headerlink" title="查看 MongoDB 配置"></a>查看 <code>MongoDB</code> 配置</h2><p>登录服务器,查看 <code>MongoDB</code> 的配置文件,看下有没有配置日志切分的参数.</p><blockquote><p>cat /PATH/TO/MONGODB/CONFIG</p></blockquote><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><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">processManagement:</span><br><span class="line">   fork: <span class="literal">true</span></span><br><span class="line">net:</span><br><span class="line">   bindIp: IP1,IP2</span><br><span class="line">   port: 27017</span><br><span class="line">storage:</span><br><span class="line">   dbPath: /PATH/TO/DB/mongodb</span><br><span class="line">systemLog:</span><br><span class="line">   destination: file</span><br><span class="line">   path: <span class="string">"/PATH/TO/LOG/mongod.log"</span></span><br><span class="line">   logAppend: <span class="literal">true</span></span><br><span class="line">storage:</span><br><span class="line">   journal:</span><br><span class="line">      enabled: <span class="literal">true</span></span><br><span class="line">replication:</span><br><span class="line">   replSetName: rs0</span><br><span class="line">security:</span><br><span class="line">   keyFile: <span class="string">"/PATH/TO/DB/mongod.key"</span></span><br></pre></td></tr></table></figure><p>查看 <code>systemLog</code> 段有没有加 <code>logAppend</code> 和 <code>logRotate</code>,没有就加上:</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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">processManagement:</span><br><span class="line">   fork: <span class="literal">true</span></span><br><span class="line">net:</span><br><span class="line">   bindIp: IP1,IP2</span><br><span class="line">   port: 27017</span><br><span class="line">storage:</span><br><span class="line">   dbPath: /PATH/TO/DB/mongodb</span><br><span class="line">systemLog:</span><br><span class="line">   destination: file</span><br><span class="line">   path: <span class="string">"/PATH/TO/LOG/mongod.log"</span></span><br><span class="line">   <span class="comment"># 在这里</span></span><br><span class="line">   logAppend: <span class="literal">true</span></span><br><span class="line">   logRotate: reopen</span><br><span class="line">storage:</span><br><span class="line">   journal:</span><br><span class="line">      enabled: <span class="literal">true</span></span><br><span class="line">replication:</span><br><span class="line">   replSetName: rs0</span><br><span class="line">security:</span><br><span class="line">   keyFile: <span class="string">"/PATH/TO/DB/mongod.key"</span></span><br></pre></td></tr></table></figure><p><code>MongoDb</code> 配置到这里就完成了,接下来搞切割配置.</p><h2 id="新建-logrotate-配置"><a href="#新建-logrotate-配置" class="headerlink" title="新建 logrotate 配置"></a>新建 <code>logrotate</code> 配置</h2><a id="more"></a><p>新建个文件,这里就叫 <code>mongod</code> 了</p><blockquote><p>touch mongod</p></blockquote><p>把配置写进去:</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><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">/PATH/TO/LOG/*<span class="built_in">log</span> &#123;</span><br><span class="line">    create 0644 root root</span><br><span class="line">    <span class="comment"># 按日切分</span></span><br><span class="line">    daily</span><br><span class="line">    <span class="comment"># 最多保留60个</span></span><br><span class="line">    rotate 60</span><br><span class="line">    <span class="comment"># 切分文件加日期后缀</span></span><br><span class="line">    dateext</span><br><span class="line">    <span class="comment"># 没有就不执行</span></span><br><span class="line">    missingok</span><br><span class="line">    <span class="comment"># 空的就不执行</span></span><br><span class="line">    notifempty</span><br><span class="line">    sharedscripts</span><br><span class="line">    postrotate</span><br><span class="line">        <span class="comment"># 切分完成后,通知 MongoDB 重开文件</span></span><br><span class="line">        /bin/<span class="built_in">kill</span> -USR1 `cat /PATH/TO/DB/mongod.lock 2&gt;/dev/null` 2&gt;/dev/null || <span class="literal">true</span></span><br><span class="line">    endscript</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><em>这里要把 <code>postrotate</code> 路径换成你 <code>pid</code> 文件的路径, 一般会在 <code>/var/run</code> 目录下.</em></p><p>测试一下配置是否正常</p><blockquote><p>logrotate -df ./mongod</p></blockquote><p>测试通过后就把它移动到 <code>logrotate</code> 的配置目录.</p><h2 id="重启-MongoDB-应用设置"><a href="#重启-MongoDB-应用设置" class="headerlink" title="重启 MongoDB, 应用设置"></a>重启 <code>MongoDB</code>, 应用设置</h2><p>这里我用的是 <code>supervisor</code> ,所以直接用 <code>supervisorctl</code> 重启 <code>MongoDB</code>.</p><blockquote><p>supervisorctl restart mongodb</p></blockquote><p>直接启动的话就在 <code>MongoDB</code> 终端中关闭:</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></pre></td><td class="code"><pre><span class="line">mongod</span><br><span class="line"></span><br><span class="line">use admin</span><br><span class="line">db.shutdownServer()</span><br></pre></td></tr></table></figure><p>关闭后重新启动即可.</p><p>参考文档:<br><a href="https://docs.mongodb.com/manual/tutorial/rotate-log-files/" target="_blank" rel="noopener">MongoDB - Rotate Log Files</a></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;今天收到监控警告,说服务器磁盘快满了.&lt;/p&gt;&lt;p&gt;登上去看了一下,发现 &lt;code&gt;MongoDB&lt;/code&gt; 的日志没做切分,大小也达到了13G,那就给他做个切分吧.&lt;/p&gt;&lt;h2 id=&quot;查看-MongoDB-配置&quot;&gt;&lt;a href=&quot;#查看-MongoDB-配置&quot; class=&quot;headerlink&quot; title=&quot;查看 MongoDB 配置&quot;&gt;&lt;/a&gt;查看 &lt;code&gt;MongoDB&lt;/code&gt; 配置&lt;/h2&gt;&lt;p&gt;登录服务器,查看 &lt;code&gt;MongoDB&lt;/code&gt; 的配置文件,看下有没有配置日志切分的参数.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;cat /PATH/TO/MONGODB/CONFIG&lt;/p&gt;&lt;/blockquote&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;processManagement:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   fork: &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   bindIp: IP1,IP2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   port: 27017&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;storage:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   dbPath: /PATH/TO/DB/mongodb&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;systemLog:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   destination: file&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   path: &lt;span class=&quot;string&quot;&gt;&quot;/PATH/TO/LOG/mongod.log&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   logAppend: &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;storage:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   journal:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      enabled: &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;replication:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   replSetName: rs0&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;security:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   keyFile: &lt;span class=&quot;string&quot;&gt;&quot;/PATH/TO/DB/mongod.key&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;查看 &lt;code&gt;systemLog&lt;/code&gt; 段有没有加 &lt;code&gt;logAppend&lt;/code&gt; 和 &lt;code&gt;logRotate&lt;/code&gt;,没有就加上:&lt;/p&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;processManagement:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   fork: &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;net:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   bindIp: IP1,IP2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   port: 27017&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;storage:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   dbPath: /PATH/TO/DB/mongodb&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;systemLog:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   destination: file&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   path: &lt;span class=&quot;string&quot;&gt;&quot;/PATH/TO/LOG/mongod.log&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;comment&quot;&gt;# 在这里&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   logAppend: &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   logRotate: reopen&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;storage:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   journal:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;      enabled: &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;replication:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   replSetName: rs0&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;security:&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   keyFile: &lt;span class=&quot;string&quot;&gt;&quot;/PATH/TO/DB/mongod.key&quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;&lt;code&gt;MongoDb&lt;/code&gt; 配置到这里就完成了,接下来搞切割配置.&lt;/p&gt;&lt;h2 id=&quot;新建-logrotate-配置&quot;&gt;&lt;a href=&quot;#新建-logrotate-配置&quot; class=&quot;headerlink&quot; title=&quot;新建 logrotate 配置&quot;&gt;&lt;/a&gt;新建 &lt;code&gt;logrotate&lt;/code&gt; 配置&lt;/h2&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="MongoDB" scheme="https://yooooex.com/tags/MongoDB/"/>
    
      <category term="logrotate" scheme="https://yooooex.com/tags/logrotate/"/>
    
      <category term="Linux" scheme="https://yooooex.com/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>从 disqus 切换到 disqusjs 过程及反代配置</title>
    <link href="https://yooooex.com/2020/05/20/disqusjs-nginx-config/"/>
    <id>https://yooooex.com/2020/05/20/disqusjs-nginx-config/</id>
    <published>2020-05-20T09:12:29.000Z</published>
    <updated>2020-05-20T10:05:37.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>最近把 <code>hexo</code> 和 主题 <code>next</code> 都升级到了最新版本,也把大部分 <code>js</code>/<code>css</code> 转到了 <code>jsDelivr</code>(国内和网宿合作),整体加载速度有了一定提升.</p><p>想着既然都搞升级了,把评论也弄正常点好了.毕竟 <code>Disqus</code> 在国内基本处于没法用的状态.</p><p><a href="https://github.com/SukkaW/DisqusJS" target="_blank" rel="noopener">DisqusJS</a> 是一个在网络状态差或无法访问 <code>Disqus</code> 下的 <code>Disqus</code> 评论展示实现,其原理是在网页加载时访问 <code>https://disqus.com/favicon.ico</code> 来判断客户端对 <code>Disqus</code> 网络连通性,在连通性差的情况下调用 <code>Disqus API</code> 获取数据来提供基本样式的评论展示.</p><h2 id="从-Disqus-切换到-DisqusJS"><a href="#从-Disqus-切换到-DisqusJS" class="headerlink" title="从 Disqus 切换到 DisqusJS"></a>从 <code>Disqus</code> 切换到 <code>DisqusJS</code></h2><p>因为我用的是 <code>next</code>(7.8.0) 主题,官方支持 <code>DisqusJS</code> 等多种评论系统,所以切换还是挺方便的.</p><ul><li><p>在主题配置文件 <code>_config.yml</code> 中,找到 <code>disqus</code> 段并把 <code>enable</code> 设为 <code>false</code>.</p></li><li><p>同主题配置文件,找到 <code>comments</code> 段,将 <code>active</code> 设为 <code>disqusjs</code>.</p></li><li><p>在 <code>Disqus 后台 -&gt; Applications -&gt; Settings</code> 中,将你要进行反代的服务器域名填入 <code>Settings -&gt; Domains</code> 中.</p></li><li><p>同主题配置文件,找到 <code>disqusjs</code> 段,将 <code>enable</code> 设为 <code>true</code>,并将相应字段填写上从 <code>Disqus</code> 获取的值.</p></li></ul><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">disqusjs:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="comment"># API Endpoint of Disqus API (https://disqus.com/api/).</span></span><br><span class="line">  <span class="comment"># Leave api empty if you are able to connect to Disqus API. Otherwise you need a reverse proxy for it.</span></span><br><span class="line">  <span class="comment"># For example:</span></span><br><span class="line">  <span class="comment"># api: https://disqus.skk.moe/disqus/</span></span><br><span class="line">  <span class="attr">api:</span> <span class="string">YOUR_REVERSE_NGINX_URL</span></span><br><span class="line">  <span class="attr">apikey:</span> <span class="string">YOUR_API_KEY</span></span><br><span class="line">  <span class="attr">shortname:</span> <span class="string">YOUR_SHORT_NAME</span></span><br><span class="line">  <span class="comment"># apikey: # Register new application from https://disqus.com/api/applications/</span></span><br><span class="line">  <span class="comment"># shortname: # See: https://disqus.com/admin/settings/general/</span></span><br></pre></td></tr></table></figure><ul><li>修改 <code>nginx</code> 配置,示例如下:</li></ul><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">  ...</span><br><span class="line">  <span class="comment"># for hexo-theme-next disqusjs.</span></span><br><span class="line">  <span class="attribute">location</span> /path/to/disqus/api/ &#123;</span><br><span class="line">    <span class="attribute">proxy_redirect</span> <span class="literal">off</span>;</span><br><span class="line">    <span class="attribute">proxy_pass</span> https://disqus.com/api/;</span><br><span class="line">  &#125;</span><br><span class="line">  ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>修改完毕后 <code>nginx -t</code> 一下,确保配置正常后 <code>nginx -s reload</code> 就好了.</p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;最近把 &lt;code&gt;hexo&lt;/code&gt; 和 主题 &lt;code&gt;next&lt;/code&gt; 都升级到了最新版本,也把大部分 &lt;code&gt;js&lt;/c
      
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="hexo" scheme="https://yooooex.com/tags/hexo/"/>
    
      <category term="disqus" scheme="https://yooooex.com/tags/disqus/"/>
    
      <category term="disqusjs" scheme="https://yooooex.com/tags/disqusjs/"/>
    
      <category term="nginx" scheme="https://yooooex.com/tags/nginx/"/>
    
  </entry>
  
  <entry>
    <title>Prometheus 和 Pushgateway 部署及使用</title>
    <link href="https://yooooex.com/2020/05/19/prometheus-deploy-query/"/>
    <id>https://yooooex.com/2020/05/19/prometheus-deploy-query/</id>
    <published>2020-05-19T05:19:53.000Z</published>
    <updated>2020-05-19T06:18:35.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>最近在弄多服务器时间的巡检和校对,选择了 <code>Prometheus</code> + <code>Pushgateway</code> 的方式来收集和输出结果,做个备忘.</p><h2 id="部署-Prometheus"><a href="#部署-Prometheus" class="headerlink" title="部署 Prometheus"></a>部署 <code>Prometheus</code></h2><p>去 <a href="https://prometheus.io/" target="_blank" rel="noopener">Prometheus 官网</a> 下载好对应系统的版本后,解压到你想放的地方运行即可,这里我使用了 <code>supervisor</code> 进行自启动和运行控制 <code>Prometheus</code> / <code>Pushgateway</code>.</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><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">wget https://github.com/prometheus/prometheus/releases/download/v2.18.1/prometheus-2.18.1.linux-amd64.tar.gz</span><br><span class="line"></span><br><span class="line">tar -xzvf /PATH/TO/STORAGE -C</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> /PATH/TO/STORAGE</span><br><span class="line"></span><br><span class="line">./prometheus</span><br></pre></td></tr></table></figure><p>这样 <code>Prometheus</code> 就运行在 <code>http://localhost:9090</code> 上了.</p><p><em>如果你不想用默认的端口,可以修改同目录下的 <code>prometheus.yml</code> 中 <code>scrape_configs</code> 区域的选项,将 <code>job_name</code> 为 <code>prometheus</code> 的 <code>static_configs -&gt; targets</code> 中的地址和端口修改成你想要的结果.</em></p><p><img data-src="https://yooooex.com/imgs/2020/05/19/prometheus-1.png" alt="prometheus"></p><h2 id="部署-Pushgateway"><a href="#部署-Pushgateway" class="headerlink" title="部署 Pushgateway"></a>部署 <code>Pushgateway</code></h2><a id="more"></a><p>去 <a href="https://github.com/prometheus/pushgateway" target="_blank" rel="noopener">Github - Pushgateway</a> 下载对应系统的版本后,解压到想放的地方.</p><p>然后运行即可,默认的地址是 <code>http://localhost:9091</code> .</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><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">wget https://github.com/prometheus/pushgateway/releases/download/v1.2.0/pushgateway-1.2.0.linux-amd64.tar.gz</span><br><span class="line"></span><br><span class="line">tar -xzvf /PATH/TO/STORAGE -C</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> /PATH/TO/STORAGE</span><br><span class="line"></span><br><span class="line">./pushgateway</span><br></pre></td></tr></table></figure><p><img data-src="https://yooooex.com/imgs/2020/05/19/pushgateway-1.png" alt="pushgateway"></p><p>如果你想修改端口,在运行时指定参数 <code>--web.listen-address=&quot;:port&quot;</code> 即可</p><p><img data-src="https://yooooex.com/imgs/2020/05/19/pushgateway-2.png" alt="pushgateway-change-port"></p><h2 id="通过-Pushgateway-向-Prometheus-推送数据"><a href="#通过-Pushgateway-向-Prometheus-推送数据" class="headerlink" title="通过 Pushgateway 向 Prometheus 推送数据"></a>通过 <code>Pushgateway</code> 向 <code>Prometheus</code> 推送数据</h2><h3 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h3><p>在推送数据前,需要先把 <code>Pushgateway</code> 的配置公告给 <code>Prometheus</code>.</p><p>编辑 <code>prometheus.yml</code> ,在 <code>scrape_configs</code> 处(<code>prometheus</code>节点下)增加以下文本:</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">  <span class="comment"># 节点名称,可自定义</span></span><br><span class="line">- job_name: <span class="string">'prometheus-pushgateway'</span></span><br><span class="line">  <span class="comment"># 这里填写你配置的端口</span></span><br><span class="line">  static_configs:</span><br><span class="line">  - targets: [<span class="string">'localhost:9091'</span>]</span><br></pre></td></tr></table></figure><p>修改完成后重启 <code>Prometheus</code> .</p><p>重启完毕后,在 <code>Prometheus</code>中查询 <code>up</code>,查看节点是否连接上</p><p><img data-src="https://yooooex.com/imgs/2020/05/19/prometheus-2.png" alt="prometheus-query-node"></p><p>如上图所示,就是成功连接了.</p><h3 id="推送数据到-Pushgateway"><a href="#推送数据到-Pushgateway" class="headerlink" title="推送数据到 Pushgateway"></a>推送数据到 <code>Pushgateway</code></h3><p><strong>强烈建议查看<a href="https://github.com/prometheus/pushgateway#api" target="_blank" rel="noopener">官方 GitHub 文档</a>来实现数据推送,以下内容可能随版本更新而失效.</strong></p><ul><li>推送基本数据</li></ul><table><thead><tr><th align="center">Fields</th><th align="center">Desc</th></tr></thead><tbody><tr><td align="center">pushgateway</td><td align="center"><code>Pushgateway</code>地址</td></tr><tr><td align="center">port</td><td align="center"><code>Pushgateway</code>端口</td></tr><tr><td align="center">job_name</td><td align="center">作业名称</td></tr><tr><td align="center">metric</td><td align="center">测量值名称</td></tr><tr><td align="center">metric_value</td><td align="center">测量值</td></tr></tbody></table><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">"[metric] [metric_value]"</span> | curl --data-binary @- http://[pushgateway]:[port]/metrics/job/[job_name]</span><br></pre></td></tr></table></figure><ul><li>推送复杂数据</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">'metric&#123;FIELD="VALUE",FIELD2="VALUE2",FIELD3="VALUE3"&#125;'</span> | curl --data-binary @- http://[pushgateway]:[port]/metrics/job/[job_name]</span><br></pre></td></tr></table></figure><ul><li>推送多个测量值</li></ul><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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 推送所有输入数据,截止到 EOF </span></span><br><span class="line">cat &lt;&lt;EOF | curl --data-binary @- http://[pushgateway]:[port]/metrics/job/[job_name]</span><br><span class="line"></span><br><span class="line"><span class="comment"># TYPE metric counter</span></span><br><span class="line">metric&#123;label=<span class="string">"val1"</span>&#125; 42</span><br><span class="line"><span class="comment"># TYPE metric2 gauge</span></span><br><span class="line"><span class="comment"># HELP metric2 Description.</span></span><br><span class="line">metric2 2398.283</span><br><span class="line">EOF</span><br></pre></td></tr></table></figure><p>具体 <code>TYPE</code> 类型请查看官方文档.</p><h3 id="在-Prometheus-中查询数据"><a href="#在-Prometheus-中查询数据" class="headerlink" title="在 Prometheus 中查询数据"></a>在 <code>Prometheus</code> 中查询数据</h3><p>在搜索框中输入你要查询的metric,并选择适当的时间段</p><p><em>示例数据</em></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ntp_check_result&#123;biz=<span class="string">"2"</span>, env=<span class="string">"test"</span>, exported_instance=<span class="string">"host-ip"</span>, exported_job=<span class="string">"ntp_check"</span>, instance=<span class="string">"localhost:9091"</span>, ip=<span class="string">"ip"</span>, job=<span class="string">"prometheus-pushgateway"</span>, ntp_server=<span class="string">"ip"</span>, offset=<span class="string">"-0.022"</span>, time=<span class="string">"2020-05-18"</span>&#125;</span><br></pre></td></tr></table></figure><p><img data-src="https://yooooex.com/imgs/2020/05/19/prometheus-3.png" alt="prometheus-query-metric"></p><p>你也可以根据上报的字段值来搜索特定的数据</p><p><img data-src="https://yooooex.com/imgs/2020/05/19/prometheus-4.png" alt="prometheus-query-metric-with-fields"></p><h3 id="在-Prometheus-中查询数据-API"><a href="#在-Prometheus-中查询数据-API" class="headerlink" title="在 Prometheus 中查询数据 - API"></a>在 <code>Prometheus</code> 中查询数据 - API</h3><p>详情请查看 <a href="https://prometheus.io/docs/prometheus/latest/querying/api/" target="_blank" rel="noopener">prometheus-doc-api</a> ,以下脚本供参考(<code>python</code> 2.7.5 环境)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><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><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># -*- coding:utf-8 -*-</span></span><br><span class="line"><span class="keyword">import</span> urllib</span><br><span class="line"><span class="keyword">import</span> urllib2</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> argparse</span><br><span class="line"></span><br><span class="line">__host_prometheus = <span class="string">'host:ip'</span></span><br><span class="line"></span><br><span class="line">__url = <span class="string">"http://&#123;host&#125;/api/v1/query"</span>.format(host=__host_prometheus)</span><br><span class="line"></span><br><span class="line">__url_2 = <span class="string">"http://&#123;host&#125;/api/v1/query_range"</span>.format(host=__host_prometheus)</span><br><span class="line"></span><br><span class="line">__fmt_query = <span class="string">'ntp_check_result&#123;&#123;time=~"&#123;date&#125;"&#125;&#125;'</span></span><br><span class="line"></span><br><span class="line">__headers = &#123;</span><br><span class="line">    <span class="string">'Content-Type'</span>: <span class="string">'application/x-www-form-urlencoded'</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">HostData</span>:</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="meta">    @classmethod</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">from_json</span><span class="params">(cls, json_data)</span>:</span></span><br><span class="line">        _instance = cls()</span><br><span class="line">        _instance.ip = json_data[<span class="string">'ip'</span>]</span><br><span class="line">        _instance.server = json_data[<span class="string">'ntp_server'</span>]</span><br><span class="line">        _instance.offset = json_data[<span class="string">'offset'</span>]</span><br><span class="line">        _instance.time = json_data[<span class="string">'time'</span>]</span><br><span class="line">        <span class="keyword">return</span> _instance</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__str__</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> str(self.__dict__)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_json</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> json.dumps(self.__dict__)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_data</span><span class="params">(query_date)</span>:</span></span><br><span class="line">    <span class="comment"># timestamp_in_sec = time.mktime(time.strptime(query_date, '%Y-%m-%d'))</span></span><br><span class="line">    timestamp_in_sec = time.mktime(time.strptime(query_date, <span class="string">'%Y-%m-%d'</span>)) + <span class="number">3600</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">print</span> <span class="string">'query_date:'</span>, query_date, <span class="string">',query_time_in_sec:'</span>, timestamp_in_sec</span><br><span class="line"></span><br><span class="line">    post_data = urllib.urlencode(&#123;</span><br><span class="line">        <span class="string">'query'</span>: __fmt_query.format(date=query_date),</span><br><span class="line">        <span class="string">'time'</span>: timestamp_in_sec</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    req = urllib2.Request(</span><br><span class="line">        __url,</span><br><span class="line">        data=post_data,</span><br><span class="line">        headers=__headers</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    resp = urllib2.urlopen(req)</span><br><span class="line">    res = json.loads(resp.read())</span><br><span class="line">    <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_data_in_range</span><span class="params">(query_date, date_start, date_end, step_in_sec=<span class="number">3600</span>)</span>:</span></span><br><span class="line">    <span class="keyword">print</span> <span class="string">'query:date='</span>, query_date, <span class="string">'date_start='</span>, date_start, <span class="string">'date_end='</span>, date_end</span><br><span class="line"></span><br><span class="line">    timestamp_start_in_sec = time.mktime(time.strptime(date_start, <span class="string">'%Y-%m-%d'</span>))</span><br><span class="line">    timestamp_end_in_sec = time.mktime(time.strptime(date_end, <span class="string">'%Y-%m-%d'</span>))</span><br><span class="line"></span><br><span class="line">    post_data = urllib.urlencode(&#123;</span><br><span class="line">        <span class="string">'query'</span>: __fmt_query.format(date=query_date),</span><br><span class="line">        <span class="string">'start'</span>: timestamp_start_in_sec,</span><br><span class="line">        <span class="string">'end'</span>: timestamp_end_in_sec,</span><br><span class="line">        <span class="string">'step'</span>: step_in_sec</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    req = urllib2.Request(</span><br><span class="line">        __url_2,</span><br><span class="line">        data=post_data,</span><br><span class="line">        headers=__headers</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    resp = urllib2.urlopen(req)</span><br><span class="line">    res = json.loads(resp.read())</span><br><span class="line">    <span class="keyword">return</span> res</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">combine_data</span><span class="params">(res)</span>:</span></span><br><span class="line">    hosts = []</span><br><span class="line">    <span class="keyword">if</span> res[<span class="string">'status'</span>] == <span class="string">'success'</span>:</span><br><span class="line">        <span class="keyword">for</span> metric_data <span class="keyword">in</span> res[<span class="string">'data'</span>][<span class="string">'result'</span>]:</span><br><span class="line">            host = metric_data[<span class="string">'metric'</span>]</span><br><span class="line">            hosts.append(HostData.from_json(host))</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line">    <span class="keyword">for</span> host <span class="keyword">in</span> hosts:</span><br><span class="line">        <span class="keyword">print</span> host.get_json()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">parser = argparse.ArgumentParser(description=<span class="string">'get server NTP config from Prometheus.'</span>)</span><br><span class="line">parser.add_argument(<span class="string">'--date'</span>, <span class="string">'-d'</span>, help=<span class="string">'date:yyyy-mm-dd'</span>, required=<span class="literal">True</span>)</span><br><span class="line">args = parser.parse_args()</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line">    <span class="keyword">if</span> <span class="string">'date'</span> <span class="keyword">in</span> args.__dict__:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            time.strptime(args.__getattribute__(<span class="string">'date'</span>), <span class="string">'%Y-%m-%d'</span>)</span><br><span class="line">        <span class="keyword">except</span> ValueError <span class="keyword">as</span> e:</span><br><span class="line">            <span class="keyword">print</span> <span class="string">'error:'</span>, e</span><br><span class="line">            exit(<span class="number">1</span>)</span><br><span class="line">    combine_data(get_data(args.__getattribute__(<span class="string">'date'</span>)))</span><br><span class="line">    <span class="comment"># combine_data(get_data_in_range(args.__getattribute__('date'), '2020-05-14', '2020-05-15'))</span></span><br></pre></td></tr></table></figure><h3 id="Prometheus-查询-Pushgateway-的-job-和-instance-名称问题"><a href="#Prometheus-查询-Pushgateway-的-job-和-instance-名称问题" class="headerlink" title="Prometheus 查询 Pushgateway 的 job 和 instance 名称问题"></a><code>Prometheus</code> 查询 <code>Pushgateway</code> 的 <code>job</code> 和 <code>instance</code> 名称问题</h3><p>在默认配置中, <code>Pushgateway</code> 会将上报的 <code>job</code> 和 <code>instance</code> 数据带到 <code>exported_job</code> 和 <code>exported_instance</code> 中,如要修改此行为,修改 <code>prometheus.yml</code> 中 <code>Pushgateway</code> 的配置:</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">- job_name: <span class="string">'prometheus-pushgateway'</span></span><br><span class="line"></span><br><span class="line">  honor_labels: <span class="literal">true</span> </span><br><span class="line"></span><br><span class="line">  static_configs:</span><br><span class="line">  - targets: [<span class="string">'localhost:9091'</span>]</span><br></pre></td></tr></table></figure><p>修改完毕后重启即可生效.</p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;最近在弄多服务器时间的巡检和校对,选择了 &lt;code&gt;Prometheus&lt;/code&gt; + &lt;code&gt;Pushgateway&lt;/code&gt; 的方式来收集和输出结果,做个备忘.&lt;/p&gt;&lt;h2 id=&quot;部署-Prometheus&quot;&gt;&lt;a href=&quot;#部署-Prometheus&quot; class=&quot;headerlink&quot; title=&quot;部署 Prometheus&quot;&gt;&lt;/a&gt;部署 &lt;code&gt;Prometheus&lt;/code&gt;&lt;/h2&gt;&lt;p&gt;去 &lt;a href=&quot;https://prometheus.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Prometheus 官网&lt;/a&gt; 下载好对应系统的版本后,解压到你想放的地方运行即可,这里我使用了 &lt;code&gt;supervisor&lt;/code&gt; 进行自启动和运行控制 &lt;code&gt;Prometheus&lt;/code&gt; / &lt;code&gt;Pushgateway&lt;/code&gt;.&lt;/p&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;wget https://github.com/prometheus/prometheus/releases/download/v2.18.1/prometheus-2.18.1.linux-amd64.tar.gz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;tar -xzvf /PATH/TO/STORAGE -C&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;cd&lt;/span&gt; /PATH/TO/STORAGE&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;./prometheus&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;这样 &lt;code&gt;Prometheus&lt;/code&gt; 就运行在 &lt;code&gt;http://localhost:9090&lt;/code&gt; 上了.&lt;/p&gt;&lt;p&gt;&lt;em&gt;如果你不想用默认的端口,可以修改同目录下的 &lt;code&gt;prometheus.yml&lt;/code&gt; 中 &lt;code&gt;scrape_configs&lt;/code&gt; 区域的选项,将 &lt;code&gt;job_name&lt;/code&gt; 为 &lt;code&gt;prometheus&lt;/code&gt; 的 &lt;code&gt;static_configs -&amp;gt; targets&lt;/code&gt; 中的地址和端口修改成你想要的结果.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;img data-src=&quot;https://yooooex.com/imgs/2020/05/19/prometheus-1.png&quot; alt=&quot;prometheus&quot;&gt;&lt;/p&gt;&lt;h2 id=&quot;部署-Pushgateway&quot;&gt;&lt;a href=&quot;#部署-Pushgateway&quot; class=&quot;headerlink&quot; title=&quot;部署 Pushgateway&quot;&gt;&lt;/a&gt;部署 &lt;code&gt;Pushgateway&lt;/code&gt;&lt;/h2&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Prometheus,Pushgateway" scheme="https://yooooex.com/tags/Prometheus-Pushgateway/"/>
    
  </entry>
  
  <entry>
    <title>记 WireGuard 部署及注意事项</title>
    <link href="https://yooooex.com/2019/05/23/wireguard-deploy/"/>
    <id>https://yooooex.com/2019/05/23/wireguard-deploy/</id>
    <published>2019-05-23T09:31:15.000Z</published>
    <updated>2019-05-23T09:54:33.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>接上一篇 <a href="https://yooooex.com/2019/01/28/n1-armbian/">斐讯 N1 -&gt; Armbian</a> 后, 我往上面丢了一些服务(<code>Gitea</code>, <del><code>vlmcsd</code>喂</del>, <code>Transmission</code> 等). 玩了一阵后我就因为别的事情搁置了最开始的目的 - 跳板, 直到四月份回坑 Apex Legends 后才因为联通的外网想起这台小机器.</p><p>接下来就开始填坑吧<img data-src="https://yooooex.com/imgs/2019/05/23/img-1.jpg" alt="emoji"></p><h2 id="选型"><a href="#选型" class="headerlink" title="选型"></a>选型</h2><ul><li>PPTP/L2TP/IPSEC/SSTP</li></ul><p>这些就很烦,不怎么想搞</p><ul><li>OpenVPN/Softether</li></ul><p>其实我是想直接用 <code>Softether</code> 的, 毕竟服务端启动后就能用有 UI 的管理工具, 点点点就搞好了.</p><p>问题是我到现在都没找到 <code>ARM64</code> 的预编译文件(官方不支持此架构)…</p><ul><li>WireGuard</li></ul><p>新玩具 - 轻量/性能不差/IP 漫游/配置相对简单/未来会支持混淆</p><p>好了就你了, 开搞开搞</p><h2 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h2><p><em>下文中部分参数意义请查看下表</em></p><table><thead><tr><th>参数</th><th>意义</th></tr></thead><tbody><tr><td>server_private_key_value</td><td>服务器私钥</td></tr><tr><td>server_public_key_value</td><td>服务器公钥</td></tr><tr><td>client_private_key_value</td><td>客户端私钥</td></tr><tr><td>client_public_key_value</td><td>客户端公钥</td></tr></tbody></table><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>去 <a href="https://www.wireguard.com/install/" target="_blank" rel="noopener">WireGuard 官网</a> 安装对应系统的版本, 你也可以下源码自己编译, 有现成的我一般都不会自己编译(哈哈).</p><p>以 <code>Armbian</code> (<code>Debian</code> or <code>Ubuntu</code>) 为例:</p><a id="more"></a><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><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">"deb http://deb.debian.org/debian/ unstable main"</span> &gt; /etc/apt/sources.list.d/unstable.list</span><br><span class="line"></span><br><span class="line"><span class="built_in">printf</span> <span class="string">'Package: *\nPin: release a=unstable\nPin-Priority: 90\n'</span> &gt; /etc/apt/preferences.d/<span class="built_in">limit</span>-unstable</span><br><span class="line"></span><br><span class="line">apt update</span><br><span class="line"></span><br><span class="line">apt install wireguard</span><br></pre></td></tr></table></figure><p>看看装好了没有</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><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment"># lsmod | grep wireguard</span></span><br><span class="line">root@S-Armbian:~<span class="comment"># lsmod | grep wireguard</span></span><br><span class="line"></span><br><span class="line">wireguard             155648  0</span><br><span class="line">ip6_udp_tunnel         16384  1 wireguard</span><br><span class="line">udp_tunnel             16384  1 wireguard</span><br><span class="line">ipv6                  487424  42 nf_nat_ipv6,wireguard</span><br><span class="line"></span><br><span class="line"><span class="comment"># dpkg -l | grep wireguard</span></span><br><span class="line">root@S-Armbian:~<span class="comment"># dpkg -l | grep wireguard</span></span><br><span class="line"></span><br><span class="line">ii  wireguard                       0.0.20190406-1                 all         fast, modern, secure kernel VPN tunnel (metapackage)</span><br><span class="line">ii  wireguard-dkms                  0.0.20190406-1                 all         fast, modern, secure kernel VPN tunnel (DKMS version)</span><br><span class="line">ii  wireguard-tools                 0.0.20190406-1                 arm64       fast, modern, secure kernel VPN tunnel (userland utilities)</span><br></pre></td></tr></table></figure><p>这就装完了, 就下来就是配置了.</p><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><ul><li>生成公私钥</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wg genkey | tee privatekey | wg pubkey &gt; publickey</span><br></pre></td></tr></table></figure><p><em>服务器私钥存好, 丢了就要把所有客户端的配置收回来了.</em></p><h4 id="服务器端"><a href="#服务器端" class="headerlink" title="服务器端"></a>服务器端</h4><ul><li>开启端口转发</li></ul><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"><span class="comment"># 打开转发</span></span><br><span class="line"><span class="built_in">echo</span> 1 &gt; /proc/sys/net/ipv4/ip_forward</span><br><span class="line"><span class="built_in">echo</span> <span class="string">"net.ipv4.ip_forward = 1"</span> &gt;&gt; /etc/sysctl.conf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 应用规则</span></span><br><span class="line">sysctl -p</span><br></pre></td></tr></table></figure><ul><li>看下要连外网的网卡是哪个</li></ul><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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># ip addr</span></span><br><span class="line"></span><br><span class="line">root@S-Armbian:~<span class="comment"># ip addr</span></span><br><span class="line"></span><br><span class="line">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000</span><br><span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br><span class="line">    inet 127.0.0.1/8 scope host lo</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">    inet6 ::1/128 scope host</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP group default qlen 1000</span><br><span class="line">    link/ether <span class="comment">##:##:##:##:##:## brd ff:ff:ff:ff:ff:ff</span></span><br><span class="line">    inet <span class="comment">#.#.#.#/24 brd #.#.#.# scope global dynamic eth0</span></span><br><span class="line">       valid_lft 71134sec preferred_lft 71134sec</span><br><span class="line">    inet6 ffff::f/64 scope global noprefixroute dynamic</span><br><span class="line">       valid_lft 586sec preferred_lft 586sec</span><br><span class="line">    inet6 ffff::f/64 scope link</span><br><span class="line">       valid_lft forever preferred_lft forever</span><br><span class="line">3: wlan0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000</span><br><span class="line">    link/ether <span class="comment">##:##:##:##:##:## brd ff:ff:ff:ff:ff:ff</span></span><br></pre></td></tr></table></figure><p>这里可以看见我的外网网卡名称是 <code>eth0</code> , 这个记下来.</p><ul><li>建配置</li></ul><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 目录不存在时就给它建个</span></span><br><span class="line"><span class="comment"># mkdir /etc/wireguard</span></span><br><span class="line">vim /etc/wireguard/wg0.conf</span><br></pre></td></tr></table></figure><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><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></pre></td><td class="code"><pre><span class="line">[Interface]</span><br><span class="line"><span class="comment"># 服务器私钥, 就是上面生成的 privatekey</span></span><br><span class="line">PrivateKey = server_private_key_value</span><br><span class="line"></span><br><span class="line"><span class="comment"># 绑定地址</span></span><br><span class="line">Address = 10.0.0.1/24</span><br><span class="line"></span><br><span class="line"><span class="comment"># 是否保存配置, 可以在运行中通过命令行添加新客户端, 并保存到此配置</span></span><br><span class="line">SaveConfig = <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动动作, 这里就要把 eth0 替换成之前记下的外网网卡名称 , wg0 是等下创建的虚拟网卡名称</span></span><br><span class="line"><span class="comment"># 配置防火墙规则</span></span><br><span class="line">PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE</span><br><span class="line"></span><br><span class="line"><span class="comment"># 关闭动作, 操作同上</span></span><br><span class="line">PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE</span><br><span class="line"></span><br><span class="line"><span class="comment"># 监听端口</span></span><br><span class="line">ListenPort = 56660</span><br><span class="line"></span><br><span class="line"><span class="comment"># 客户端配置</span></span><br><span class="line">[Peer]</span><br><span class="line"><span class="comment"># 客户端公钥, 生成步骤同服务器, 两端都可生成</span></span><br><span class="line">PublicKey = client_public_key_value</span><br><span class="line"></span><br><span class="line"><span class="comment"># 分配给客户端的地址, 我这里让他随便选, 你也可以指定给他</span></span><br><span class="line">AllowedIPs = 10.0.0.0/24</span><br><span class="line"><span class="comment">#AllowedIPs = 10.0.0.2/32</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 加客户端就在 Peer 节点下加公钥和 IP 就可以了, 操作同上</span></span><br></pre></td></tr></table></figure><ul><li>提权, 免得出问题</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chmod 777 -R /etc/wireguard</span><br></pre></td></tr></table></figure><ul><li>测试启动</li></ul><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><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># wg-quick up wg0</span></span><br><span class="line"></span><br><span class="line">root@S-Armbian:~<span class="comment"># wg-quick up wg0</span></span><br><span class="line"></span><br><span class="line">[<span class="comment">#] ip link add wg0 type wireguard</span></span><br><span class="line">[<span class="comment">#] wg setconf wg0 /dev/fd/63</span></span><br><span class="line">[<span class="comment">#] ip address add 10.0.0.1/24 dev wg0</span></span><br><span class="line">[<span class="comment">#] ip link set mtu 1420 up dev wg0</span></span><br><span class="line">[<span class="comment">#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># wg</span></span><br><span class="line"></span><br><span class="line">root@S-Armbian:~<span class="comment"># wg</span></span><br><span class="line"></span><br><span class="line">interface: wg0</span><br><span class="line">   public key: server_public_key_value</span><br><span class="line">   private key: (hidden)</span><br><span class="line">   listening port: 56660</span><br><span class="line"> </span><br><span class="line">peer: client_public_key_value</span><br><span class="line">   endpoint: [ffff::f]:port</span><br><span class="line">   allowed ips: 10.0.0.0/24</span><br></pre></td></tr></table></figure><p>接下来就是配置客户端了</p><h4 id="客户端"><a href="#客户端" class="headerlink" title="客户端"></a>客户端</h4><p>这里以 <code>Windows</code> 平台, 客户端 <code>TunSafe</code> 为例, 其他平台就不多讲了, 区别不大</p><ul><li>安装</li></ul><p>去 <a href="https://tunsafe.com/download" target="_blank" rel="noopener">TunSafe</a> 下载客户端和虚拟网卡驱动(TunSafe-TAP), 安装完成即可.</p><p><img data-src="https://yooooex.com/imgs/2019/05/23/tunsafe-1.png" alt="TunSafe 界面"></p><ul><li>配置</li></ul><p>点击 File - Generate Key Pair 来生成公私钥</p><p><img data-src="https://yooooex.com/imgs/2019/05/23/tunsafe-2.png" alt="TunSafe 选项 - 生成公私钥"></p><p><img data-src="https://yooooex.com/imgs/2019/05/23/tunsafe-3.png" alt="TunSafe 选项 - 生成公私钥 - 生成"></p><p>记下生成的公私钥, 点击 Edit Config ,开始配置.</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">[Interface]</span><br><span class="line"># 上文生成的客户端私钥</span><br><span class="line">PrivateKey &#x3D; client_private_key_value</span><br><span class="line"></span><br><span class="line"># 使用的 DNS 服务器</span><br><span class="line">DNS &#x3D; 114.114.114.114</span><br><span class="line"></span><br><span class="line"># 绑定地址</span><br><span class="line">Address &#x3D; 10.0.0.3&#x2F;24</span><br><span class="line"></span><br><span class="line">[Peer]</span><br><span class="line"># 上文生成的服务器公钥</span><br><span class="line">PublicKey &#x3D; server_public_key_value</span><br><span class="line"></span><br><span class="line"># 要代理的地址, 这里是全局代理, 可根据需求调整</span><br><span class="line">AllowedIPs &#x3D; 0.0.0.0&#x2F;0</span><br><span class="line"></span><br><span class="line"># 服务器地址</span><br><span class="line">Endpoint &#x3D; server_ip:port</span><br><span class="line"></span><br><span class="line"># 心跳包间隔时间</span><br><span class="line">PersistentKeepalive &#x3D; 25</span><br></pre></td></tr></table></figure><p>完事, 开始测试</p><ul><li>测试启动</li></ul><p>点击 Connect 测试</p><p><img data-src="https://yooooex.com/imgs/2019/05/23/tunsafe-4.png" alt="TunSafe 连接"></p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">[user.DESKTOP-DEV] ➤ ping 10.0.0.1</span><br><span class="line"></span><br><span class="line">正在 Ping 10.0.0.1 具有 32 字节的数据:</span><br><span class="line">来自 10.0.0.1 的回复: 字节&#x3D;32 时间&#x3D;56ms TTL&#x3D;64</span><br><span class="line">来自 10.0.0.1 的回复: 字节&#x3D;32 时间&#x3D;78ms TTL&#x3D;64</span><br><span class="line">来自 10.0.0.1 的回复: 字节&#x3D;32 时间&#x3D;76ms TTL&#x3D;64</span><br><span class="line">来自 10.0.0.1 的回复: 字节&#x3D;32 时间&#x3D;52ms TTL&#x3D;64</span><br><span class="line"></span><br><span class="line">[user.DESKTOP-DEV] ➤ ping 114.114.114.114</span><br><span class="line"></span><br><span class="line">正在 Ping 114.114.114.114 具有 32 字节的数据:</span><br><span class="line">来自 114.114.114.114 的回复: 字节&#x3D;32 时间&#x3D;63ms TTL&#x3D;80</span><br><span class="line">来自 114.114.114.114 的回复: 字节&#x3D;32 时间&#x3D;78ms TTL&#x3D;66</span><br><span class="line">来自 114.114.114.114 的回复: 字节&#x3D;32 时间&#x3D;75ms TTL&#x3D;67</span><br><span class="line">来自 114.114.114.114 的回复: 字节&#x3D;32 时间&#x3D;59ms TTL&#x3D;87</span><br></pre></td></tr></table></figure><p>到这里就部署完毕了.</p><h3 id="坑"><a href="#坑" class="headerlink" title="坑"></a>坑</h3><ul><li>坑啊</li></ul><p>你以为到这就结束了? 接下来才是重点, 耗时一个月才解决的<del>血泪史</del>坑</p><p>连接成功后,我 <code>ping</code> 了服务器和外网, 都能正常连接, 我兴冲冲跑去 <a href="speedtest.net">Speedtest</a> 测试速度, 却发现所有网站都连接超时, 连路由的管理页面都上不去</p><p>于是开始检查, 防火墙和转发都配置了, <code>ssh</code> 没问题, <code>traceroute</code> 没问题, 还是不能上</p><p>这什么情况<img data-src="https://yooooex.com/imgs/2019/05/23/img-2.jpg" alt="emoji"></p><p>妈耶, 搞不定啊, 放狗!</p><p>于是就断断续续搜索了一个月(你没看错, 是一个月, 这篇文章本来是要在四月发的<img data-src="https://yooooex.com/imgs/2019/05/23/img-2.jpg" alt="emoji">), 还是没找到头绪.</p><p>反反复复配置, 问题依然存在</p><p>我差点都认命去装 <code>OpenVPN</code> 了, 这时脑子一抽, 想起以前瞎折腾给网卡开了巨型帧, 导致无法连接网络的情况, 会不会是 MTU 设置不正确导致出现碎片?</p><ul><li>调查</li></ul><p>赶紧连到小机器, 查看网卡情况</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><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"># ip link</span></span><br><span class="line"></span><br><span class="line">root@S-Armbian:~<span class="comment"># ip link</span></span><br><span class="line"></span><br><span class="line">1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000</span><br><span class="line">    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00</span><br><span class="line">2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000</span><br><span class="line">    link/ether ff:ff:ff:ff:ff:ff brd ff:ff:ff:ff:ff:ff</span><br><span class="line">3: wlan0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc pfifo_fast state DOWN mode DORMANT group default qlen 1000</span><br><span class="line">    link/ether ff:ff:ff:ff:ff:ff brd ff:ff:ff:ff:ff:ff</span><br><span class="line">33: wg0: &lt;POINTOPOINT,NOARP,UP,LOWER_UP&gt; mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000</span><br><span class="line">    link/none</span><br></pre></td></tr></table></figure><p>这里可看到 <code>wg0</code> 的 <code>mtu</code> 是 1420, 编辑客户端配置</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">[Interface]</span><br><span class="line">PrivateKey &#x3D; client_private_key_value</span><br><span class="line"></span><br><span class="line">DNS &#x3D; 114.114.114.114</span><br><span class="line"></span><br><span class="line">Address &#x3D; 10.0.0.3&#x2F;24</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line">MTU &#x3D; 1420</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line">[Peer]</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>保存后重新连接, 问题依旧, 这到底是怎么肥事啊<img data-src="https://yooooex.com/imgs/2019/05/23/img-3.gif" alt="emoji"></p><p>不死心, 放狗搜索后找到了这个邮件列表: <a href="https://lists.zx2c4.com/pipermail/wireguard/2017-December/002201.html" target="_blank" rel="noopener">[WireGuard] Header / MTU sizes for Wireguard</a> , 里面提到了 <code>WireGuard</code> 协议的开销:</p><blockquote><p>The overhead of WireGuard breaks down as follows:</p><ul><li>20-byte IPv4 header or 40 byte IPv6 header</li><li>8-byte UDP header</li><li>4-byte type</li><li>4-byte key index</li><li>8-byte nonce</li><li>N-byte encrypted data</li><li>16-byte authentication tag</li></ul></blockquote><p>妈耶, 我看见曙光了!</p><ul><li>填坑</li></ul><p>赶紧去改配置:</p><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">[Interface]</span><br><span class="line">PrivateKey &#x3D; client_private_key_value</span><br><span class="line"></span><br><span class="line">DNS &#x3D; 114.114.114.114</span><br><span class="line"></span><br><span class="line">Address &#x3D; 10.0.0.3&#x2F;24</span><br><span class="line">...</span><br><span class="line"># 这里按照最大开销计算, 实际的 mtu 为 1420 - (40 + 8 + 4 + 4 + 8 + 16) &#x3D; 1344</span><br><span class="line"># 我怕有坑, 再给点余量</span><br><span class="line">MTU &#x3D; 1300</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line">[Peer]</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>保存 -&gt; 重新连接 -&gt; <a href="speedtest.net">Speedtest</a></p><p><img data-src="https://yooooex.com/imgs/2019/05/23/tunsafe-result.png" alt="速度"></p><p>好了, 坑填上了, Apex Legneds 启动!</p><p>以下是一些参考链接, 供有意者研究(多看文档少踩坑):</p><ul><li><a href="https://www.wireguard.com/protocol/" target="_blank" rel="noopener">协议总览</a></li><li><a href="https://www.wireguard.com/papers/wireguard.pdf" target="_blank" rel="noopener">白皮书</a></li></ul><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;接上一篇 &lt;a href=&quot;https://yooooex.com/2019/01/28/n1-armbian/&quot;&gt;斐讯 N1 -&amp;gt; Armbian&lt;/a&gt; 后, 我往上面丢了一些服务(&lt;code&gt;Gitea&lt;/code&gt;, &lt;del&gt;&lt;code&gt;vlmcsd&lt;/code&gt;喂&lt;/del&gt;, &lt;code&gt;Transmission&lt;/code&gt; 等). 玩了一阵后我就因为别的事情搁置了最开始的目的 - 跳板, 直到四月份回坑 Apex Legends 后才因为联通的外网想起这台小机器.&lt;/p&gt;&lt;p&gt;接下来就开始填坑吧&lt;img data-src=&quot;https://yooooex.com/imgs/2019/05/23/img-1.jpg&quot; alt=&quot;emoji&quot;&gt;&lt;/p&gt;&lt;h2 id=&quot;选型&quot;&gt;&lt;a href=&quot;#选型&quot; class=&quot;headerlink&quot; title=&quot;选型&quot;&gt;&lt;/a&gt;选型&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;PPTP/L2TP/IPSEC/SSTP&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这些就很烦,不怎么想搞&lt;/p&gt;&lt;ul&gt;&lt;li&gt;OpenVPN/Softether&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;其实我是想直接用 &lt;code&gt;Softether&lt;/code&gt; 的, 毕竟服务端启动后就能用有 UI 的管理工具, 点点点就搞好了.&lt;/p&gt;&lt;p&gt;问题是我到现在都没找到 &lt;code&gt;ARM64&lt;/code&gt; 的预编译文件(官方不支持此架构)…&lt;/p&gt;&lt;ul&gt;&lt;li&gt;WireGuard&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;新玩具 - 轻量/性能不差/IP 漫游/配置相对简单/未来会支持混淆&lt;/p&gt;&lt;p&gt;好了就你了, 开搞开搞&lt;/p&gt;&lt;h2 id=&quot;部署&quot;&gt;&lt;a href=&quot;#部署&quot; class=&quot;headerlink&quot; title=&quot;部署&quot;&gt;&lt;/a&gt;部署&lt;/h2&gt;&lt;p&gt;&lt;em&gt;下文中部分参数意义请查看下表&lt;/em&gt;&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;参数&lt;/th&gt;&lt;th&gt;意义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;server_private_key_value&lt;/td&gt;&lt;td&gt;服务器私钥&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;server_public_key_value&lt;/td&gt;&lt;td&gt;服务器公钥&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;client_private_key_value&lt;/td&gt;&lt;td&gt;客户端私钥&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;client_public_key_value&lt;/td&gt;&lt;td&gt;客户端公钥&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h3 id=&quot;安装&quot;&gt;&lt;a href=&quot;#安装&quot; class=&quot;headerlink&quot; title=&quot;安装&quot;&gt;&lt;/a&gt;安装&lt;/h3&gt;&lt;p&gt;去 &lt;a href=&quot;https://www.wireguard.com/install/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WireGuard 官网&lt;/a&gt; 安装对应系统的版本, 你也可以下源码自己编译, 有现成的我一般都不会自己编译(哈哈).&lt;/p&gt;&lt;p&gt;以 &lt;code&gt;Armbian&lt;/code&gt; (&lt;code&gt;Debian&lt;/code&gt; or &lt;code&gt;Ubuntu&lt;/code&gt;) 为例:&lt;/p&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Linux" scheme="https://yooooex.com/tags/Linux/"/>
    
      <category term="Armbian" scheme="https://yooooex.com/tags/Armbian/"/>
    
      <category term="WireGuard" scheme="https://yooooex.com/tags/WireGuard/"/>
    
      <category term="TunSafe" scheme="https://yooooex.com/tags/TunSafe/"/>
    
  </entry>
  
  <entry>
    <title>瞎折腾 - 斐讯 N1 变身 Armbian Linux 记录</title>
    <link href="https://yooooex.com/2019/01/28/n1-armbian/"/>
    <id>https://yooooex.com/2019/01/28/n1-armbian/</id>
    <published>2019-01-28T05:56:47.000Z</published>
    <updated>2019-05-23T10:02:56.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><p>现在在宿舍用的是联通的网络(广州联通,50Mbps). 之所以在南方还选择联通的原因是想着在直连的情况下去日本等亚洲国家的速度会比电信好, 事实也的确是这样(非高峰时段 100ms 以内).</p><p>但是吧,不知道是联通特别关照我还是出国路由抽风, 针对国外 IP 的连接不定时会全部被阻断 <del>(港澳台都断,妈个鸡)</del>, 几分钟后恢复正常. 我 IW4x(ID: YooooEX,来玩耍呀) 一个服务器都找不到, 这还能玩耍?</p><p>需求有了, 接下来就是要怎么解决的问题了.</p><h2 id="想法"><a href="#想法" class="headerlink" title="想法"></a>想法</h2><pre><code>既然国外连接都会被阻断, 那就只能在国内弄个中转跳板了.</code></pre><ul><li>加速器</li></ul><p>pass <img data-src="https://yooooex.com/imgs/2019/01/28/poor.jpg" alt="poor"></p><ul><li>国内VPS中转</li></ul><p>现在深港/沪日的 IPLC 价格其实还好, NAT VPS 一个月能控制在 100 以内, 就是流量和带宽余量都很捉急, 而且就为了这个似乎有点浪费啊 <img data-src="https://yooooex.com/imgs/2019/01/28/poor.jpg" alt="poor"></p><ul><li>家宽中转</li></ul><p>家里的电信宽带办的时间也是挺久的, 所以拨号有外网 IP, 即使在升级过多次套餐后也依然如此(现为 200Mbps / 30Mbps uplink). 那不就可以玩耍了? 又不是没当过高 Ping 战士…</p><p>对于 NAT 网络, 2018年底三大运营商已经在很多地方配置和开放了 IPv6 路由, 这使得以往部署个人服务最大的门槛 - <strong>公网IP</strong> 被消除了. 只要你的路由支持 IPv6 并且正确下发配置(我这边是无状态,使用DHCPv6-PD分配地址), 在路由后的设备都是可以获取到公网 IP 的.</p><p>不过随着 Ipv6 的普及, 越来越多未被正确配置隔离的设备会被直接暴露在公网上, 到时又是黑产丰收的季节了.</p><h2 id="设备选择"><a href="#设备选择" class="headerlink" title="设备选择"></a>设备选择</h2><a id="more"></a><p>本来想的是用 <code>Raspberry Pi 3b+</code> 来做服务器的, 后来算了一下成本:</p><ul><li>开发板: 200+</li><li>外壳+散热+电源+好SD卡: 200+</li></ul><p>emmmm,这价格再加点都能捡套 3317u 的平台了,而且 3b+ 的有线走的USB通道, 感觉 300Mbps 的吞吐量在未来一两年内就不太够用了.</p><p>在纠结是选择 x86 还是 3b+ 的过程中, 我在网上和各个论坛中游荡, 当逛到恩山时,想着更新下路由固件的我看到了跑路讯的两个设备: <code>斐讯N1</code> 和 <code>斐讯T1</code>, 被其性价比折服.</p><p>具体硬件配置:</p><table><thead><tr><th align="center"></th><th align="center">T1</th><th align="center">N1</th></tr></thead><tbody><tr><td align="center">CPU</td><td align="center">Amlogic S912(b?), 8-Core Cortex-A53, 1.5Ghz</td><td align="center">Amlogic S905D, 4-Core Cortex-A53, 1.8Ghz</td></tr><tr><td align="center">GPU</td><td align="center">Mali-T820 MP3</td><td align="center">Mail-450</td></tr><tr><td align="center">RAM</td><td align="center">2G</td><td align="center">2G</td></tr><tr><td align="center">Storage</td><td align="center">16G EMMC</td><td align="center">8G EMMC</td></tr><tr><td align="center">Network</td><td align="center">BT4, 802.11 n/ac</td><td align="center">BT4, 802.11 n/ac</td></tr><tr><td align="center">Interface</td><td align="center">HDMI * 1, USB * 1, 100M Ethernet * 1, AV * 1</td><td align="center">HDMI * 1, USB * 2, 1000M Ethernet * 1</td></tr></tbody></table><p>配置上来说是 T1 比较高, 但是 T1 的有线是 100M 的, 而且 USB 接口也比 N1 少一个, 最后还是选了 N1.</p><p>目前 N1 在咸鱼上 80 左右就能收到,而 T1 还是要小一百的,怎么选择就看你自己的需求了.</p><h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><ul><li>USB 双公头线</li><li>USB 键盘和显示器(HDMI, 其他接口需转接)</li><li>电脑</li><li>正常U盘 (8G+)</li><li>Win32 Disk Imager: 镜像烧录工具,你也可以选择自行选择工具. <a href="https://sourceforge.net/projects/win32diskimager/" target="_blank" rel="noopener">下载地址</a></li><li>ADB(Android SDK Platform Tools): <strong><a href="https://developer.android.com/studio/releases/platform-tools" target="_blank" rel="noopener">Android Developers</a></strong></li><li><code>Armbian</code> 镜像: <strong><a href="https://yadi.sk/d/pHxaRAs-tZiei" target="_blank" rel="noopener">下载地址</a></strong> (N1 选择 S905,T1 选择 S912)</li><li>降级分区: <strong><a href="https://mega.nz/#!4NcTSS7J!a9pq-9PQU_zvCrnjPBSV_Nuhi4H1LjWRcTl8Ao-9Rpk" target="_blank" rel="noopener">Mega</a></strong>/<strong><a href="https://pan.baidu.com/s/1rwTH08uz_byobA2qw7XIHg" target="_blank" rel="noopener">百度云</a></strong> (提取码: <code>n21w</code>)</li></ul><p>将东西都准备好之后就可以开始弄了.</p><h2 id="设备降级"><a href="#设备降级" class="headerlink" title="设备降级"></a>设备降级</h2><p>由于我的 N1 到手就是官改的版本, 自带 root, 所以我是直接在终端里面开启网络ADB的</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></pre></td><td class="code"><pre><span class="line">su</span><br><span class="line">setprop service.adb.tcp.port 5555</span><br><span class="line">stop adbd</span><br><span class="line">start adbd</span><br></pre></td></tr></table></figure><p>原版系统请参考下文</p><blockquote><p>在N1的主界面的 <strong>固件版本</strong> 点击4次，会看到adb打开的提示</p><p><img data-src="https://yooooex.com/imgs/2019/01/28/ref1.jpg" alt="ref1"></p></blockquote><p>开启后连接即可</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">adb connect ip-address</span><br><span class="line"><span class="comment"># adb 连接默认端口是5555,如果使用自定端口</span></span><br><span class="line"><span class="comment"># adb connect ip-address:port</span></span><br><span class="line"></span><br><span class="line">adb reboot fastboot</span><br></pre></td></tr></table></figure><p>等设备进入 <code>Fastboot</code> 模式后, 用双公头连接 N1 靠近 HDMI 的 USB 口和电脑</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></pre></td><td class="code"><pre><span class="line">fastboot flash boot boot.img</span><br><span class="line">fastboot flash bootloader bootloader.img</span><br><span class="line">fastboot flash recovery recovery.img</span><br></pre></td></tr></table></figure><p>刷入分区后重启</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fastboot reboot</span><br></pre></td></tr></table></figure><h2 id="烧录镜像"><a href="#烧录镜像" class="headerlink" title="烧录镜像"></a>烧录镜像</h2><p>解压镜像, 打开 <code>Win32 Disk Imager</code>, 选镜像和U盘, 搞定</p><p>烧录完成后,进入新显示的磁盘(Boot),修改 <code>uEnv.ini</code></p><figure class="highlight"><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="comment">; meson-gxl-s905d-p230.dtb ---&gt; N1</span></span><br><span class="line"><span class="comment">; meson-gxm-q201.dtb       ---&gt; T1</span></span><br><span class="line"><span class="attr">dtb_name</span>=/dtb/meson-gxl-s905d-p230.dtb</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>修改完毕后弹出U盘.</p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>将显示器和键盘连接到 N1, 将U盘插入到 N1 靠近 HDMI 的 USB 口, 然后进入更新模式</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb reboot update</span><br></pre></td></tr></table></figure><p>设备重启完毕后,你应该进入 <code>Live CD</code> 了, 默认账号密码是 <code>root</code> 和 <code>1234</code></p><p>进入系统后, 在 <code>/root/</code> 目录下有一个名字叫 <code>install-22018.sh</code> 的文件, 运行并根据提示配置 <code>Armbian</code>, 等待安装完毕</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">./install.sh</span><br><span class="line">...</span><br><span class="line">...</span><br><span class="line"><span class="comment"># reboot 重启设备</span></span><br><span class="line"><span class="comment"># poweroff 关闭设备</span></span><br></pre></td></tr></table></figure><p>关闭或重启设备时将U盘拔出,就可以进入安装到 EMMC 的系统了.</p><p>如果要配置和使用无线可以用 <code>nmtui</code>, 至少还有个界面看</p><p>如果没有公网 IP 可以使用 <code>Frp</code> 等工具来打洞: <strong><a href="https://github.com/fatedier/frp" target="_blank" rel="noopener">Frp</a></strong></p><p>有公网就直接上 DDNS 吧,我使用的是 <code>CloudFlare</code>, 一个脚本加定时任务就能搞定:</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><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="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">localIpv6=`ip -6 a | grep global | awk <span class="string">'&#123;print $2&#125;'</span> | awk -F <span class="string">'/'</span> <span class="string">'&#123;print $1&#125;'</span>`</span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"ipv6 is: <span class="variable">$localIpv6</span>, updating to CloudFlare..."</span></span><br><span class="line"></span><br><span class="line">curl -X PUT https://api.cloudflare.com/client/v4/zones/<span class="variable">$zone</span>/dns_records/<span class="variable">$domain</span> \</span><br><span class="line">  -H <span class="string">'Content-Type: application/json'</span> \</span><br><span class="line">  -H <span class="string">'X-Auth-Email: youremail@example.com'</span> \</span><br><span class="line">  -H <span class="string">'X-Auth-Key: yourapikey'</span> \</span><br><span class="line">  -H <span class="string">'cache-control: no-cache'</span> \</span><br><span class="line">  -d <span class="string">'&#123;"type": "AAAA","proxied": false,"name": "example.com","content": "'</span><span class="variable">$localIpv6</span><span class="string">'"&#125;'</span></span><br></pre></td></tr></table></figure><p><code>crontab</code> 加个任务</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># */5 * * * * sh /root/ddns.sh &gt; /dev/null</span></span><br></pre></td></tr></table></figure><p>其他玩法就慢慢发掘吧, 这和正常的 <code>Linux</code> 并没有多大的区别. <strong><em>说起来这是目前我玩过最大内存的 Linux 设备了…</em></strong></p><p>如果你对 <code>Armbian</code> 不感冒的话, 这里也有其他系统可以玩: <strong><a href="https://github.com/yangxuan8282/phicomm-n1" target="_blank" rel="noopener">phicomm-n1</a></strong></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;h2 id=&quot;起因&quot;&gt;&lt;a href=&quot;#起因&quot; class=&quot;headerlink&quot; title=&quot;起因&quot;&gt;&lt;/a&gt;起因&lt;/h2&gt;&lt;p&gt;现在在宿舍用的是联通的网络(广州联通,50Mbps). 之所以在南方还选择联通的原因是想着在直连的情况下去日本等亚洲国家的速度会比电信好, 事实也的确是这样(非高峰时段 100ms 以内).&lt;/p&gt;&lt;p&gt;但是吧,不知道是联通特别关照我还是出国路由抽风, 针对国外 IP 的连接不定时会全部被阻断 &lt;del&gt;(港澳台都断,妈个鸡)&lt;/del&gt;, 几分钟后恢复正常. 我 IW4x(ID: YooooEX,来玩耍呀) 一个服务器都找不到, 这还能玩耍?&lt;/p&gt;&lt;p&gt;需求有了, 接下来就是要怎么解决的问题了.&lt;/p&gt;&lt;h2 id=&quot;想法&quot;&gt;&lt;a href=&quot;#想法&quot; class=&quot;headerlink&quot; title=&quot;想法&quot;&gt;&lt;/a&gt;想法&lt;/h2&gt;&lt;pre&gt;&lt;code&gt;既然国外连接都会被阻断, 那就只能在国内弄个中转跳板了.&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;加速器&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;pass &lt;img data-src=&quot;https://yooooex.com/imgs/2019/01/28/poor.jpg&quot; alt=&quot;poor&quot;&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;国内VPS中转&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;现在深港/沪日的 IPLC 价格其实还好, NAT VPS 一个月能控制在 100 以内, 就是流量和带宽余量都很捉急, 而且就为了这个似乎有点浪费啊 &lt;img data-src=&quot;https://yooooex.com/imgs/2019/01/28/poor.jpg&quot; alt=&quot;poor&quot;&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;家宽中转&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;家里的电信宽带办的时间也是挺久的, 所以拨号有外网 IP, 即使在升级过多次套餐后也依然如此(现为 200Mbps / 30Mbps uplink). 那不就可以玩耍了? 又不是没当过高 Ping 战士…&lt;/p&gt;&lt;p&gt;对于 NAT 网络, 2018年底三大运营商已经在很多地方配置和开放了 IPv6 路由, 这使得以往部署个人服务最大的门槛 - &lt;strong&gt;公网IP&lt;/strong&gt; 被消除了. 只要你的路由支持 IPv6 并且正确下发配置(我这边是无状态,使用DHCPv6-PD分配地址), 在路由后的设备都是可以获取到公网 IP 的.&lt;/p&gt;&lt;p&gt;不过随着 Ipv6 的普及, 越来越多未被正确配置隔离的设备会被直接暴露在公网上, 到时又是黑产丰收的季节了.&lt;/p&gt;&lt;h2 id=&quot;设备选择&quot;&gt;&lt;a href=&quot;#设备选择&quot; class=&quot;headerlink&quot; title=&quot;设备选择&quot;&gt;&lt;/a&gt;设备选择&lt;/h2&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Linux" scheme="https://yooooex.com/tags/Linux/"/>
    
      <category term="Armbian" scheme="https://yooooex.com/tags/Armbian/"/>
    
      <category term="N1" scheme="https://yooooex.com/tags/N1/"/>
    
  </entry>
  
  <entry>
    <title>解决 ScrollView 嵌套 WebView 高度问题(高度不正确,底部留白)</title>
    <link href="https://yooooex.com/2018/05/23/android-scrollview-webview/"/>
    <id>https://yooooex.com/2018/05/23/android-scrollview-webview/</id>
    <published>2018-05-23T07:47:13.000Z</published>
    <updated>2020-09-18T04:09:40.993Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>先给<code>WebView</code>一个固定高度,在页面加载时重新设置高度</p><figure class="highlight xml"><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="tag">&lt;<span class="name">com.yooooex.widget.CustomWebView</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">"@+id/wv_custom"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">"match_parent"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">"200dp"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_marginHorizontal</span>=<span class="string">"@dimen/d_10"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:scrollbars</span>=<span class="string">"none"</span> /&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">mWebView.setWebViewClient(<span class="keyword">new</span> WebViewClient() &#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onPageStarted</span><span class="params">(WebView view, String url, Bitmap favicon)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onPageStarted(view, url, favicon);</span><br><span class="line">        ViewGroup.LayoutParams params = mWebView.getLayoutParams();</span><br><span class="line">        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;</span><br><span class="line">        mWebView.setLayoutParams(params);</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>你也可以先把 <code>WebView</code> GONE 掉,在页面加载完毕时显示</p><figure class="highlight xml"><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></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">com.yooooex.widget.CustomWebView</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">"@+id/wv_custom"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">"match_parent"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">"wrap_content"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_marginHorizontal</span>=<span class="string">"@dimen/d_10"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:scrollbars</span>=<span class="string">"none"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:visibility</span>=<span class="string">"gone"</span>/&gt;</span></span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">mWebView.setWebViewClient(<span class="keyword">new</span> WebViewClient() &#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onPageFinished</span><span class="params">(WebView view, String url)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onPageFinished(view, url);</span><br><span class="line">        mWebView.setVisibility(View.VISIBLE);</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;先给&lt;code&gt;WebView&lt;/code&gt;一个固定高度,在页面加载时重新设置高度&lt;/p&gt;&lt;figure class=&quot;highlight xm
      
    
    </summary>
    
    
      <category term="开发" scheme="https://yooooex.com/categories/%E5%BC%80%E5%8F%91/"/>
    
    
      <category term="Android" scheme="https://yooooex.com/tags/Android/"/>
    
      <category term="WebView" scheme="https://yooooex.com/tags/WebView/"/>
    
      <category term="ScrollView" scheme="https://yooooex.com/tags/ScrollView/"/>
    
  </entry>
  
  <entry>
    <title>备忘 - 记一次坑爹的 Nginx 反代环境配置</title>
    <link href="https://yooooex.com/2018/04/20/nginx-reverse-problem/"/>
    <id>https://yooooex.com/2018/04/20/nginx-reverse-problem/</id>
    <published>2018-04-20T08:55:24.000Z</published>
    <updated>2020-05-11T05:47:07.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><h1 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h1><p>今天中午朋友找到我,说想要给自己的游戏针对国外做反向代理 <del>(被老外喷卡,哈哈)</del>,那就做一个咯</p><h1 id="准备挖坑"><a href="#准备挖坑" class="headerlink" title="准备挖坑"></a>准备挖坑</h1><p>因为只需要转发请求,配置需求不高. 所以我就在 <a href="https://www.dediserve.com/" target="_blank" rel="noopener">DediSERVE</a> 注册了个账号,创了个 5欧 1G 内存,25G 硬盘的实例(<strong>AFF警告</strong>: <a href="https://manage.dediserve.com/?affid=895" target="_blank" rel="noopener">链接在此</a>)</p><p>服务器使用 <code>Debian 8</code>, Server Hostname 填写的是要 <strong>代理的域名</strong> (重点,后面就因为这个掉坑里了)</p><h1 id="挖坑中"><a href="#挖坑中" class="headerlink" title="挖坑中"></a>挖坑中</h1><p>老规矩,自己动手丰衣足食</p><h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><h3 id="工具"><a href="#工具" class="headerlink" title="工具"></a>工具</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev git</span><br></pre></td></tr></table></figure><h3 id="Nginx"><a href="#Nginx" class="headerlink" title="Nginx"></a>Nginx</h3><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></pre></td><td class="code"><pre><span class="line">wget -c https://nginx.org/download/nginx-1.11.13.tar.gz</span><br><span class="line"></span><br><span class="line">tar zxf nginx-1.13.12.tar.gz</span><br></pre></td></tr></table></figure><h3 id="OpenSSL"><a href="#OpenSSL" class="headerlink" title="OpenSSL"></a>OpenSSL</h3><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">wget -O openssl.tar.gz -c https://github.com/openssl/openssl/archive/OpenSSL_1_0_2k.tar.gz</span><br><span class="line"></span><br><span class="line">tar zxf openssl.tar.gz</span><br><span class="line"></span><br><span class="line">mv openssl-OpenSSL_1_0_2k/ openssl</span><br></pre></td></tr></table></figure><h2 id="编译"><a href="#编译" class="headerlink" title="编译"></a>编译</h2><p>如果没指定安装位置的话,默认会安装到 <code>/usr/local/nginx/</code></p><a id="more"></a><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><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> nginx-1.13.12/</span><br><span class="line"></span><br><span class="line">./configure --with-openssl=../openssl --with-http_v2_module --with-http_ssl_module --with-http_gzip_static_module</span><br><span class="line"></span><br><span class="line">make</span><br><span class="line"></span><br><span class="line">sudo make install</span><br></pre></td></tr></table></figure><h2 id="创建管理服务"><a href="#创建管理服务" class="headerlink" title="创建管理服务"></a>创建管理服务</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/init.d/nginx</span><br></pre></td></tr></table></figure><p>输入以下内容:</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><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#! /bin/sh</span></span><br><span class="line"></span><br><span class="line"><span class="comment">### BEGIN INIT INFO</span></span><br><span class="line"><span class="comment"># Provides:          nginx</span></span><br><span class="line"><span class="comment"># Required-Start:    $all</span></span><br><span class="line"><span class="comment"># Required-Stop:     $all</span></span><br><span class="line"><span class="comment"># Default-Start:     2 3 4 5</span></span><br><span class="line"><span class="comment"># Default-Stop:      0 1 6</span></span><br><span class="line"><span class="comment"># Short-Description: starts the nginx web server</span></span><br><span class="line"><span class="comment"># Description:       starts nginx using start-stop-daemon</span></span><br><span class="line"><span class="comment">### END INIT INFO</span></span><br><span class="line"></span><br><span class="line">PATH=/usr/<span class="built_in">local</span>/sbin:/usr/<span class="built_in">local</span>/bin:/sbin:/bin:/usr/sbin:/usr/bin</span><br><span class="line">DAEMON=/usr/<span class="built_in">local</span>/nginx/sbin/nginx</span><br><span class="line">NAME=nginx</span><br><span class="line">DESC=nginx</span><br><span class="line"></span><br><span class="line"><span class="built_in">test</span> -x <span class="variable">$DAEMON</span> || <span class="built_in">exit</span> 0</span><br><span class="line"></span><br><span class="line"><span class="comment"># Include nginx defaults if available</span></span><br><span class="line"><span class="keyword">if</span> [ -f /etc/default/nginx ] ; <span class="keyword">then</span></span><br><span class="line">  . /etc/default/nginx</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"></span><br><span class="line">. /lib/lsb/init-functions</span><br><span class="line"></span><br><span class="line"><span class="keyword">case</span> <span class="string">"<span class="variable">$1</span>"</span> <span class="keyword">in</span></span><br><span class="line">  start)</span><br><span class="line">    <span class="built_in">echo</span> -n <span class="string">"Starting <span class="variable">$DESC</span>: "</span></span><br><span class="line">    start-stop-daemon --start --quiet --pidfile /usr/<span class="built_in">local</span>/nginx/logs/<span class="variable">$NAME</span>.pid \</span><br><span class="line">        --<span class="built_in">exec</span> <span class="variable">$DAEMON</span> -- <span class="variable">$DAEMON_OPTS</span> || <span class="literal">true</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">"<span class="variable">$NAME</span>."</span></span><br><span class="line">    ;;</span><br><span class="line">  stop)</span><br><span class="line">    <span class="built_in">echo</span> -n <span class="string">"Stopping <span class="variable">$DESC</span>: "</span></span><br><span class="line">    start-stop-daemon --stop --quiet --pidfile /usr/<span class="built_in">local</span>/nginx/logs/<span class="variable">$NAME</span>.pid \</span><br><span class="line">        --<span class="built_in">exec</span> <span class="variable">$DAEMON</span> || <span class="literal">true</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">"<span class="variable">$NAME</span>."</span></span><br><span class="line">    ;;</span><br><span class="line">  restart|force-reload)</span><br><span class="line">    <span class="built_in">echo</span> -n <span class="string">"Restarting <span class="variable">$DESC</span>: "</span></span><br><span class="line">    start-stop-daemon --stop --quiet --pidfile \</span><br><span class="line">        /usr/<span class="built_in">local</span>/nginx/logs/<span class="variable">$NAME</span>.pid --<span class="built_in">exec</span> <span class="variable">$DAEMON</span> || <span class="literal">true</span></span><br><span class="line">    sleep 1</span><br><span class="line">    start-stop-daemon --start --quiet --pidfile \</span><br><span class="line">        /usr/<span class="built_in">local</span>/nginx/logs/<span class="variable">$NAME</span>.pid --<span class="built_in">exec</span> <span class="variable">$DAEMON</span> -- <span class="variable">$DAEMON_OPTS</span> || <span class="literal">true</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">"<span class="variable">$NAME</span>."</span></span><br><span class="line">    ;;</span><br><span class="line">  reload)</span><br><span class="line">    <span class="built_in">echo</span> -n <span class="string">"Reloading <span class="variable">$DESC</span> configuration: "</span></span><br><span class="line">    start-stop-daemon --stop --signal HUP --quiet --pidfile /usr/<span class="built_in">local</span>/nginx/logs/<span class="variable">$NAME</span>.pid \</span><br><span class="line">        --<span class="built_in">exec</span> <span class="variable">$DAEMON</span> || <span class="literal">true</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">"<span class="variable">$NAME</span>."</span></span><br><span class="line">    ;;</span><br><span class="line">  status)</span><br><span class="line">    status_of_proc -p /usr/<span class="built_in">local</span>/nginx/logs/<span class="variable">$NAME</span>.pid <span class="string">"<span class="variable">$DAEMON</span>"</span> nginx &amp;&amp; <span class="built_in">exit</span> 0 || <span class="built_in">exit</span> $?</span><br><span class="line">    ;;</span><br><span class="line">  *)</span><br><span class="line">    N=/etc/init.d/<span class="variable">$NAME</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">"Usage: <span class="variable">$N</span> &#123;start|stop|restart|reload|force-reload|status&#125;"</span> &gt;&amp;2</span><br><span class="line">    <span class="built_in">exit</span> 1</span><br><span class="line">    ;;</span><br><span class="line"><span class="keyword">esac</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">exit</span> 0</span><br></pre></td></tr></table></figure><p>授权</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo chmod a+x /etc/init.d/nginx</span><br></pre></td></tr></table></figure><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /usr/<span class="built_in">local</span>/nginx/conf/nginx.conf</span><br></pre></td></tr></table></figure><p>修改为以下内容:</p><figure class="highlight nginx"><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="comment">#user  nobody;</span></span><br><span class="line"><span class="attribute">worker_processes</span>  <span class="number">4</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">#error_log  logs/error.log;</span></span><br><span class="line"><span class="comment">#error_log  logs/error.log  notice;</span></span><br><span class="line"><span class="comment">#error_log  logs/error.log  info;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#pid        logs/nginx.pid;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="section">events</span> &#123;</span><br><span class="line">    <span class="attribute">worker_connections</span>  <span class="number">1024</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="section">http</span> &#123;</span><br><span class="line">    <span class="attribute">include</span>       mime.types;</span><br><span class="line">    <span class="attribute">default_type</span>  application/octet-stream;</span><br><span class="line">    <span class="attribute">charset</span>            UTF-<span class="number">8</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">sendfile</span>           <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">tcp_nopush</span>         <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">tcp_nodelay</span>        <span class="literal">on</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">keepalive_timeout</span>  <span class="number">60</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">gzip</span>               <span class="literal">on</span>;</span><br><span class="line">    <span class="attribute">gzip_vary</span>          <span class="literal">on</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">gzip_comp_level</span>    <span class="number">6</span>;</span><br><span class="line">    <span class="attribute">gzip_buffers</span>       <span class="number">16</span> <span class="number">8k</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">gzip_min_length</span>    <span class="number">1000</span>;</span><br><span class="line">    <span class="attribute">gzip_proxied</span>       any;</span><br><span class="line">    <span class="attribute">gzip_disable</span>       <span class="string">"msie6"</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">gzip_http_version</span>  <span class="number">1</span>.<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="attribute">gzip_types</span>         text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;</span><br><span class="line"></span><br><span class="line">    <span class="section">server</span> &#123;</span><br><span class="line">        <span class="attribute">listen</span>       <span class="number">80</span>;</span><br><span class="line">        <span class="attribute">server_name</span>  proxy.domain.com;</span><br><span class="line"></span><br><span class="line">        <span class="attribute">location</span> / &#123;   </span><br><span class="line">            <span class="attribute">proxy_pass</span> http://domain.com;</span><br><span class="line">            <span class="attribute">proxy_redirect</span> <span class="literal">off</span>;</span><br><span class="line"></span><br><span class="line">            <span class="attribute">proxy_set_header</span>         X-Real_IP        <span class="variable">$remote_addr</span>;</span><br><span class="line">            <span class="attribute">proxy_set_header</span>         X-Forwarded-For  <span class="variable">$proxy_add_x_forwarded_for</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">service nginx start</span><br></pre></td></tr></table></figure><p>万事俱备,是时候看结果了!</p><p>这是什么鬼! <img data-src="https://yooooex.com/imgs/2018/04/17/reverse-problem.png" alt="HTTP 400"></p><p>检查开启!</p><ol><li><p>检查配置文件 ☑</p></li><li><p>检查日志 ☑</p></li><li><p>放狗搜索 ☑</p></li></ol><p>然而并没有什么用 <img data-src="https://yooooex.com/imgs/2018/04/17/face.jpg" alt="face"></p><p>在20多分钟的放狗后,我找到了一篇文章 - <a href="https://www.cnblogs.com/EmptyFS/p/6253545.html" target="_blank" rel="noopener">nginx配置反向代理或跳转出现400问题处理记录</a></p><p>文章作者也遇到了和我差不多的问题,而他的问题在 <code>proxy_pass</code> 由域名换为IP后解决</p><p>然而对我并没有什么作用 <img data-src="https://yooooex.com/imgs/2018/04/17/face.jpg" alt="face"></p><p>从中午找到下午,接近两个小时依然没有解决这个问题</p><p>万念俱灰之际,我随手 <code>ping</code> 了一下域名</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><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">64 bytes from example.com (255.255.255.255): icmp_seq=1 ttl=64 time=0.051 ms</span><br><span class="line">64 bytes from example.com (255.255.255.255): icmp_seq=2 ttl=64 time=0.063 ms</span><br><span class="line">64 bytes from example.com (255.255.255.255): icmp_seq=3 ttl=64 time=0.055 ms</span><br><span class="line">64 bytes from example.com (255.255.255.255): icmp_seq=4 ttl=64 time=0.049 ms</span><br><span class="line">64 bytes from example.com (255.255.255.255): icmp_seq=5 ttl=64 time=0.050 ms</span><br><span class="line">64 bytes from example.com (255.255.255.255): icmp_seq=6 ttl=64 time=0.040 ms</span><br><span class="line">64 bytes from example.com (255.255.255.255): icmp_seq=7 ttl=64 time=0.047 ms</span><br><span class="line">64 bytes from example.com (255.255.255.255): icmp_seq=8 ttl=64 time=0.037 ms</span><br></pre></td></tr></table></figure><p>看到这结果,马上跑去看 hosts ,结果让我看到了浪费两个小时的原因:</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></pre></td><td class="code"><pre><span class="line">cat /etc/hosts</span><br><span class="line"><span class="comment"># Automatically generated by OnApp</span></span><br><span class="line">127.0.0.1       localhost</span><br><span class="line">127.0.0.1       example.com</span><br></pre></td></tr></table></figure><p>原因是在创建VPS实例时,会将填写的域名记录写到 hosts 里头. 因为当时还没有定好域名,就随手把 <strong>要反代的域名</strong> 填上去了</p><p>唉,今天真高兴啊……</p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;h1 id=&quot;起因&quot;&gt;&lt;a href=&quot;#起因&quot; class=&quot;headerlink&quot; title=&quot;起因&quot;&gt;&lt;/a&gt;起因&lt;/h1&gt;&lt;p&gt;今天中午朋友找到我,说想要给自己的游戏针对国外做反向代理 &lt;del&gt;(被老外喷卡,哈哈)&lt;/del&gt;,那就做一个咯&lt;/p&gt;&lt;h1 id=&quot;准备挖坑&quot;&gt;&lt;a href=&quot;#准备挖坑&quot; class=&quot;headerlink&quot; title=&quot;准备挖坑&quot;&gt;&lt;/a&gt;准备挖坑&lt;/h1&gt;&lt;p&gt;因为只需要转发请求,配置需求不高. 所以我就在 &lt;a href=&quot;https://www.dediserve.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;DediSERVE&lt;/a&gt; 注册了个账号,创了个 5欧 1G 内存,25G 硬盘的实例(&lt;strong&gt;AFF警告&lt;/strong&gt;: &lt;a href=&quot;https://manage.dediserve.com/?affid=895&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;链接在此&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;服务器使用 &lt;code&gt;Debian 8&lt;/code&gt;, Server Hostname 填写的是要 &lt;strong&gt;代理的域名&lt;/strong&gt; (重点,后面就因为这个掉坑里了)&lt;/p&gt;&lt;h1 id=&quot;挖坑中&quot;&gt;&lt;a href=&quot;#挖坑中&quot; class=&quot;headerlink&quot; title=&quot;挖坑中&quot;&gt;&lt;/a&gt;挖坑中&lt;/h1&gt;&lt;p&gt;老规矩,自己动手丰衣足食&lt;/p&gt;&lt;h2 id=&quot;准备&quot;&gt;&lt;a href=&quot;#准备&quot; class=&quot;headerlink&quot; title=&quot;准备&quot;&gt;&lt;/a&gt;准备&lt;/h2&gt;&lt;h3 id=&quot;工具&quot;&gt;&lt;a href=&quot;#工具&quot; class=&quot;headerlink&quot; title=&quot;工具&quot;&gt;&lt;/a&gt;工具&lt;/h3&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev git&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h3 id=&quot;Nginx&quot;&gt;&lt;a href=&quot;#Nginx&quot; class=&quot;headerlink&quot; title=&quot;Nginx&quot;&gt;&lt;/a&gt;Nginx&lt;/h3&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;wget -c https://nginx.org/download/nginx-1.11.13.tar.gz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;tar zxf nginx-1.13.12.tar.gz&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h3 id=&quot;OpenSSL&quot;&gt;&lt;a href=&quot;#OpenSSL&quot; class=&quot;headerlink&quot; title=&quot;OpenSSL&quot;&gt;&lt;/a&gt;OpenSSL&lt;/h3&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;wget -O openssl.tar.gz -c https://github.com/openssl/openssl/archive/OpenSSL_1_0_2k.tar.gz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;tar zxf openssl.tar.gz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;mv openssl-OpenSSL_1_0_2k/ openssl&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h2 id=&quot;编译&quot;&gt;&lt;a href=&quot;#编译&quot; class=&quot;headerlink&quot; title=&quot;编译&quot;&gt;&lt;/a&gt;编译&lt;/h2&gt;&lt;p&gt;如果没指定安装位置的话,默认会安装到 &lt;code&gt;/usr/local/nginx/&lt;/code&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Nginx" scheme="https://yooooex.com/tags/Nginx/"/>
    
  </entry>
  
  <entry>
    <title>备忘 - Android 的轮子们</title>
    <link href="https://yooooex.com/2018/01/25/useful-libraries-android/"/>
    <id>https://yooooex.com/2018/01/25/useful-libraries-android/</id>
    <published>2018-01-25T12:35:41.000Z</published>
    <updated>2018-02-26T03:22:53.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>看到好用的就记下来,以后填坑用</p><h1 id="UI-界面"><a href="#UI-界面" class="headerlink" title="UI 界面"></a>UI 界面</h1><h2 id="BRVAH-BaseRecyclerViewAdapterHelper"><a href="#BRVAH-BaseRecyclerViewAdapterHelper" class="headerlink" title="BRVAH (BaseRecyclerViewAdapterHelper)"></a>BRVAH (BaseRecyclerViewAdapterHelper)</h2><p><a href="https://github.com/CymChad/BaseRecyclerViewAdapterHelper" target="_blank" rel="noopener">BRVAH</a></p><p>一个 <code>RecyclerView.Adapter</code> 框架,写得少干得多</p><ul><li>Item 事件(点击, 长按, 子 Item 点击, 长按)</li><li>列表加载动画</li><li>添加 Header 和 Footer</li><li>上下拉加载</li><li>空数据布局</li><li>树形 Item</li></ul><h2 id="指示器-CircleIndicator"><a href="#指示器-CircleIndicator" class="headerlink" title="指示器 - CircleIndicator"></a>指示器 - CircleIndicator</h2><p><a href="https://github.com/ongakuer/CircleIndicator" target="_blank" rel="noopener">CircleIndicator 演示</a></p><p>当前页面指示器 Lite<br><img data-src="https://github.com/ongakuer/CircleIndicator/raw/master/screenshot.gif" alt="CircleIndicator"></p><h2 id="指示器-MagicIndicator"><a href="#指示器-MagicIndicator" class="headerlink" title="指示器 - MagicIndicator"></a>指示器 - MagicIndicator</h2><p>当前页面指示器 Advanced</p><a id="more"></a><p><img data-src="https://github.com/hackware1993/MagicIndicator/raw/master/magicindicator.gif" alt="MagicIndicator 演示"></p><h2 id="评分栏-ProperRatingBar"><a href="#评分栏-ProperRatingBar" class="headerlink" title="评分栏 - ProperRatingBar"></a>评分栏 - ProperRatingBar</h2><p><a href="https://github.com/techery/ProperRatingBar" target="_blank" rel="noopener">ProperRatingBar</a></p><p><img data-src="https://raw.githubusercontent.com/techery/ProperRatingBar/master/readme_imgs/ProperRatingBar_v001_demo.gif" alt="ProperRatingBar 演示"></p><h2 id="时间格式化-PrettyTime"><a href="#时间格式化-PrettyTime" class="headerlink" title="时间格式化 - PrettyTime"></a>时间格式化 - PrettyTime</h2><p><a href="https://github.com/ocpsoft/prettytime" target="_blank" rel="noopener">PrettyTime</a></p><h1 id="文本"><a href="#文本" class="headerlink" title="文本"></a>文本</h1><h2 id="RichEditor"><a href="#RichEditor" class="headerlink" title="RichEditor"></a>RichEditor</h2><p><strong><a href="https://github.com/wasabeef/richeditor-android" target="_blank" rel="noopener">RichEditor</a></strong></p><p>功能齐全的富文本编辑器</p><p><img data-src="https://github.com/wasabeef/richeditor-android/raw/master/art/demo.gif" alt="RichEditor 演示"></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;看到好用的就记下来,以后填坑用&lt;/p&gt;&lt;h1 id=&quot;UI-界面&quot;&gt;&lt;a href=&quot;#UI-界面&quot; class=&quot;headerlink&quot; title=&quot;UI 界面&quot;&gt;&lt;/a&gt;UI 界面&lt;/h1&gt;&lt;h2 id=&quot;BRVAH-BaseRecyclerViewAdapterHelper&quot;&gt;&lt;a href=&quot;#BRVAH-BaseRecyclerViewAdapterHelper&quot; class=&quot;headerlink&quot; title=&quot;BRVAH (BaseRecyclerViewAdapterHelper)&quot;&gt;&lt;/a&gt;BRVAH (BaseRecyclerViewAdapterHelper)&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/CymChad/BaseRecyclerViewAdapterHelper&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BRVAH&lt;/a&gt;&lt;/p&gt;&lt;p&gt;一个 &lt;code&gt;RecyclerView.Adapter&lt;/code&gt; 框架,写得少干得多&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Item 事件(点击, 长按, 子 Item 点击, 长按)&lt;/li&gt;&lt;li&gt;列表加载动画&lt;/li&gt;&lt;li&gt;添加 Header 和 Footer&lt;/li&gt;&lt;li&gt;上下拉加载&lt;/li&gt;&lt;li&gt;空数据布局&lt;/li&gt;&lt;li&gt;树形 Item&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;指示器-CircleIndicator&quot;&gt;&lt;a href=&quot;#指示器-CircleIndicator&quot; class=&quot;headerlink&quot; title=&quot;指示器 - CircleIndicator&quot;&gt;&lt;/a&gt;指示器 - CircleIndicator&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ongakuer/CircleIndicator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CircleIndicator 演示&lt;/a&gt;&lt;/p&gt;&lt;p&gt;当前页面指示器 Lite&lt;br&gt;&lt;img data-src=&quot;https://github.com/ongakuer/CircleIndicator/raw/master/screenshot.gif&quot; alt=&quot;CircleIndicator&quot;&gt;&lt;/p&gt;&lt;h2 id=&quot;指示器-MagicIndicator&quot;&gt;&lt;a href=&quot;#指示器-MagicIndicator&quot; class=&quot;headerlink&quot; title=&quot;指示器 - MagicIndicator&quot;&gt;&lt;/a&gt;指示器 - MagicIndicator&lt;/h2&gt;&lt;p&gt;当前页面指示器 Advanced&lt;/p&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Android" scheme="https://yooooex.com/tags/Android/"/>
    
  </entry>
  
  <entry>
    <title>更方便的 Let&#39;s Encrypt 证书工具 - acme.sh</title>
    <link href="https://yooooex.com/2017/12/01/lets-encrypt-certificate-issue-acme-sh/"/>
    <id>https://yooooex.com/2017/12/01/lets-encrypt-certificate-issue-acme-sh/</id>
    <published>2017-12-01T08:32:50.000Z</published>
    <updated>2018-03-14T13:19:49.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p><code>Let&#39;s Encrypt</code> 在近两年的发展中十分迅速. 官方在2016年3月8日宣布签发证书达到一百万张后( <a href="https://letsencrypt.org/2016/03/08/our-millionth-cert.html" target="_blank" rel="noopener">Our Millionth Certificate</a> ), 在一年半后的2017年6月28号便宣布签发证书达到了一亿张( <a href="https://letsencrypt.org/2017/06/28/hundred-million-certs.html" target="_blank" rel="noopener">Milestone: 100 Million Certificates Issued</a> ).</p><p>官方也宣布在2018年<del>一月份</del>(鸽了,三月份)开始支持签发泛域名证书( <a href="https://letsencrypt.org/2017/07/06/wildcard-certificates-coming-jan-2018.html" target="_blank" rel="noopener">Wildcard Certificates Coming January 2018</a> ),在使用和部署上会变得更加方便.</p><p>官方的签发工具是 <code>certbot</code> ,它可以启动一个 Web 服务器来验证域名所有权,也可以用配置文件指定 <code>Nginx</code> 的 <code>WebRoot</code> 目录来验证( 需要在 <code>Nginx</code> 配置相应路由 <code>.well-known/</code> ).</p><p>但是在开始使用 <a href="https://www.cloudflare.com/" target="_blank" rel="noopener">CloudFlare</a> 的服务后,我发现 <code>certbot</code> 使用 <code>DNS-01</code> 验证方式比较麻烦<del>懒的看官方的 Authenticator</del>. 然后我就换成 <code>acme.sh</code> 了.</p><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><p>自动安装 ( 喜欢手动安装看 <a href="https://github.com/Neilpang/acme.sh/wiki/How-to-install#4-advanced-installation" target="_blank" rel="noopener">这里</a> )</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></pre></td><td class="code"><pre><span class="line">wget -O -  https://get.acme.sh | sh</span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">curl https://get.acme.sh | sh</span><br></pre></td></tr></table></figure><a id="more"></a><p>运行这个脚本会干以下事情:</p><ul><li><p>将 <code>acme.sh</code> 安装到你的用户目录下: <code>~/.acme.sh/acme.sh</code></p></li><li><p>创建 alias : <code>. &quot;/root/.acme.sh/acme.sh.env&quot;</code></p></li><li><p>创建定时任务 :</p></li></ul><figure class="highlight bash"><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">root@yooooex:~<span class="comment"># crontab -l</span></span><br><span class="line">14 0 * * * <span class="string">"/root/.acme.sh"</span>/acme.sh --cron --home <span class="string">"/root/.acme.sh"</span> &gt; /dev/null</span><br></pre></td></tr></table></figure><p>手动更新</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">acme.sh --upgrade</span><br></pre></td></tr></table></figure><p>自动更新</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">acme.sh  --upgrade  --auto-upgrade</span><br></pre></td></tr></table></figure><p>关闭自动更新</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">acme.sh  --upgrade  --auto-upgrade 0</span><br></pre></td></tr></table></figure><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><h3 id="WebRoot-和-Standalone-验证"><a href="#WebRoot-和-Standalone-验证" class="headerlink" title="WebRoot 和 Standalone 验证"></a><code>WebRoot</code> 和 <code>Standalone</code> 验证</h3><p><code>WebRoot</code> 和 <code>Standalone</code> 验证方式就不多说了,和 <code>certbot</code> 大同小异,看文档就好( <a href="https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert#1-webroot-mode" target="_blank" rel="noopener">English</a> | <a href="https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E#1-http-%E6%96%B9%E5%BC%8F%E9%9C%80%E8%A6%81%E5%9C%A8%E4%BD%A0%E7%9A%84%E7%BD%91%E7%AB%99%E6%A0%B9%E7%9B%AE%E5%BD%95%E4%B8%8B%E6%94%BE%E7%BD%AE%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6-%E6%9D%A5%E9%AA%8C%E8%AF%81%E4%BD%A0%E7%9A%84%E5%9F%9F%E5%90%8D%E6%89%80%E6%9C%89%E6%9D%83%E5%AE%8C%E6%88%90%E9%AA%8C%E8%AF%81-%E7%84%B6%E5%90%8E%E5%B0%B1%E5%8F%AF%E4%BB%A5%E7%94%9F%E6%88%90%E8%AF%81%E4%B9%A6%E4%BA%86" target="_blank" rel="noopener">中文</a> )</p><h3 id="DNS-01-验证"><a href="#DNS-01-验证" class="headerlink" title="DNS-01 验证"></a><code>DNS-01</code> 验证</h3><h4 id="使用-–dns-选项来创建要验证域名的-TXT-记录"><a href="#使用-–dns-选项来创建要验证域名的-TXT-记录" class="headerlink" title="使用 –dns 选项来创建要验证域名的 TXT 记录"></a>使用 –dns 选项来创建要验证域名的 <code>TXT</code> 记录</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">acme.sh --issue -d example.com --dns</span><br></pre></td></tr></table></figure><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><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></pre></td><td class="code"><pre><span class="line">[Fri Dec  1 15:17:45 +06 2017] Creating domain key</span><br><span class="line">[Fri Dec  1 15:17:45 +06 2017] The domain key is here: /root/.acme.sh/example.com/example.com.key</span><br><span class="line">[Fri Dec  1 15:17:45 +06 2017] Single domain=<span class="string">'example.com'</span></span><br><span class="line">[Fri Dec  1 15:17:46 +06 2017] Getting domain auth token <span class="keyword">for</span> each domain</span><br><span class="line">[Fri Dec  1 15:17:46 +06 2017] Getting webroot <span class="keyword">for</span> domain=<span class="string">'example.com'</span></span><br><span class="line">[Fri Dec  1 15:17:46 +06 2017] Getting new-authz <span class="keyword">for</span> domain=<span class="string">'example.com'</span></span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] The new-authz request is ok.</span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] Add the following TXT record:</span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] Domain: <span class="string">'_acme-challenge.example.com'</span></span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] TXT value: <span class="string">'h8cmiQ5_jqzqKK2ZDSnLjmosKGsjIoo69Tj9TbACHbw'</span></span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] Please be aware that you prepend _acme-challenge. before your domain</span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] so the resulting subdomain will be: _acme-challenge.example.com</span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] Please add the TXT records to the domains, and retry again.</span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] Please add <span class="string">'--debug'</span> or <span class="string">'--log'</span> to check more details.</span><br><span class="line">[Fri Dec  1 15:17:47 +06 2017] See: https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh</span><br></pre></td></tr></table></figure><h4 id="添加-TXT-记录"><a href="#添加-TXT-记录" class="headerlink" title="添加 TXT 记录"></a>添加 <code>TXT</code> 记录</h4><p>将 <code>Domain</code> 和 <code>TXT value</code> 记录下来,在域名管理商处添加对应的 <code>TXT</code> 记录,并等待其生效.</p><blockquote><p>查询域名 <code>TXT</code> 记录</p></blockquote><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nslookup -<span class="built_in">type</span>=txt _acme-challenge.example.com</span><br></pre></td></tr></table></figure><p>当 <code>TXT</code> 记录生效后,便可生成证书.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">acme.sh --renew -d example.com</span><br></pre></td></tr></table></figure><h3 id="使用第三方-API-验证"><a href="#使用第三方-API-验证" class="headerlink" title="使用第三方 API 验证"></a>使用第三方 API 验证</h3><p>因为我用的是 <code>CloudFlare</code>,以下操作都是在此基础上进行的,不过和其他 API 也只是参数不同而已. 详看 <a href="https://github.com/Neilpang/acme.sh/blob/master/dnsapi/README.md" target="_blank" rel="noopener">这里</a></p><p>先去 <a href="https://www.cloudflare.com/" target="_blank" rel="noopener">CloudFlare</a> 拿到 API key ( Overview -&gt; Domain Summary -&gt; Global API Key )</p><figure class="highlight bash"><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"><span class="built_in">export</span> CF_Key=<span class="string">"your key"</span></span><br><span class="line"><span class="built_in">export</span> CF_Email=<span class="string">"yourname@example.com"</span></span><br></pre></td></tr></table></figure><p>设置完毕后便可以生成证书了.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">acme.sh --issue --dns dns_cf -d example.com -d www.example.com</span><br></pre></td></tr></table></figure><blockquote><p>* 输入的参数会保存到 <code>~/.acme.sh/account.conf</code> 中,以后会自动调用.</p></blockquote><h3 id="导出证书"><a href="#导出证书" class="headerlink" title="导出证书"></a>导出证书</h3><p>使用 <code>--installcert</code> 命令来导出证书</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></pre></td><td class="code"><pre><span class="line">acme.sh  --installcert  -d  example.com   \</span><br><span class="line">        --key-file   /etc/nginx/ssl/private.key \</span><br><span class="line">        --fullchain-file /etc/nginx/ssl/fullchain.cer \</span><br><span class="line">        --reloadcmd  <span class="string">"service nginx force-reload"</span></span><br></pre></td></tr></table></figure><ul><li>-d: 要导出的域名</li><li>–key-file: 导出私钥的位置</li><li>–fullchain-file: 导出证书的位置</li><li>–reloadcmd: 重载命令,这里用的是 <code>Nginx</code> ,具体的命令要看你用什么了</li></ul><h3 id="Wildcard-通配符证书"><a href="#Wildcard-通配符证书" class="headerlink" title="Wildcard - 通配符证书"></a>Wildcard - 通配符证书</h3><p><strong>2018-3-14 更新:</strong></p><p><a href="https://letsencrypt.org" target="_blank" rel="noopener">Let’s Encrypt</a> 已在昨天上线 Wildcard 证书(目前只支持 <code>DNS-01</code> 验证方式),步骤其实和普通的域名差不多,只需增加通配符就可以了.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">acme.sh --issue --dns dns_cf -d example.com -d *.example.com</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;h2 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Let&amp;#39;s Encrypt&lt;/code&gt; 在近两年的发展中十分迅速. 官方在2016年3月8日宣布签发证书达到一百万张后( &lt;a href=&quot;https://letsencrypt.org/2016/03/08/our-millionth-cert.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Our Millionth Certificate&lt;/a&gt; ), 在一年半后的2017年6月28号便宣布签发证书达到了一亿张( &lt;a href=&quot;https://letsencrypt.org/2017/06/28/hundred-million-certs.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Milestone: 100 Million Certificates Issued&lt;/a&gt; ).&lt;/p&gt;&lt;p&gt;官方也宣布在2018年&lt;del&gt;一月份&lt;/del&gt;(鸽了,三月份)开始支持签发泛域名证书( &lt;a href=&quot;https://letsencrypt.org/2017/07/06/wildcard-certificates-coming-jan-2018.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wildcard Certificates Coming January 2018&lt;/a&gt; ),在使用和部署上会变得更加方便.&lt;/p&gt;&lt;p&gt;官方的签发工具是 &lt;code&gt;certbot&lt;/code&gt; ,它可以启动一个 Web 服务器来验证域名所有权,也可以用配置文件指定 &lt;code&gt;Nginx&lt;/code&gt; 的 &lt;code&gt;WebRoot&lt;/code&gt; 目录来验证( 需要在 &lt;code&gt;Nginx&lt;/code&gt; 配置相应路由 &lt;code&gt;.well-known/&lt;/code&gt; ).&lt;/p&gt;&lt;p&gt;但是在开始使用 &lt;a href=&quot;https://www.cloudflare.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CloudFlare&lt;/a&gt; 的服务后,我发现 &lt;code&gt;certbot&lt;/code&gt; 使用 &lt;code&gt;DNS-01&lt;/code&gt; 验证方式比较麻烦&lt;del&gt;懒的看官方的 Authenticator&lt;/del&gt;. 然后我就换成 &lt;code&gt;acme.sh&lt;/code&gt; 了.&lt;/p&gt;&lt;h2 id=&quot;配置&quot;&gt;&lt;a href=&quot;#配置&quot; class=&quot;headerlink&quot; title=&quot;配置&quot;&gt;&lt;/a&gt;配置&lt;/h2&gt;&lt;p&gt;自动安装 ( 喜欢手动安装看 &lt;a href=&quot;https://github.com/Neilpang/acme.sh/wiki/How-to-install#4-advanced-installation&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;这里&lt;/a&gt; )&lt;/p&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;wget -O -  https://get.acme.sh | sh&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# or&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;curl https://get.acme.sh | sh&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="证书" scheme="https://yooooex.com/tags/%E8%AF%81%E4%B9%A6/"/>
    
      <category term="Nginx" scheme="https://yooooex.com/tags/Nginx/"/>
    
      <category term="HTTPS" scheme="https://yooooex.com/tags/HTTPS/"/>
    
  </entry>
  
  <entry>
    <title>LeakCanary - 内存泄露检测</title>
    <link href="https://yooooex.com/2016/12/22/leakcanary-memory-leak-detecter/"/>
    <id>https://yooooex.com/2016/12/22/leakcanary-memory-leak-detecter/</id>
    <published>2016-12-22T08:17:03.000Z</published>
    <updated>2016-12-22T12:41:53.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>之前说了 <a href="/2016/12/22/leakcanary-memory-leak-detecter/">Fabric</a> ,这次就来说说内存使用这个东西吧.</p><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><blockquote><p>千里之堤，溃于蚁穴 - 韩非《韩非子·喻老》 <del>都能用,就这样吧</del></p></blockquote><p>因为开源的特性, <code>Android</code> 拥有着各种各样不同尺寸屏幕和硬件配置的设备.<br>顶级到 5-6 寸 Snapdragon 821/Exynos 8890 + 6GB 的旗舰机型</p><a id="more"></a><blockquote><p><img data-src="/imgs/2016/12/22/phone1.png" alt="Oneplus 3T"><br>目测到新机型出来为止还是要靠抢的 4T</p></blockquote><blockquote><p><img data-src="/imgs/2016/12/22/phone2.png" alt="Samsung Galaxy S7 Edge"><br>在 BOOM7 宣布回收后独立支撑的 S7E</p></blockquote><p>低端到充几百块电话费就能送的联发科/瑞芯微 + 1GB / 512MB 的运营商定制手机</p><blockquote><p><img data-src="/imgs/2016/12/22/phone3.png" alt="LT999"><br>移动定制机,放狗搜了下这货貌似还用的 YunOS</p></blockquote><p>种类繁多的设备决定你在开始开发应用时就要想好要不要考虑使用低端设备的用户,这使得你要在系统版本,动画效果,依赖的使用等方面有所取舍,毕竟在低版本低配置的设备上做兼容会增加一部分代码和工作量.</p><p>如果你选择了兼容的道路,那就要在优化上面下点功夫了(当然写任何程序都应当在优化上面下功夫).</p><p>在代码方面只能靠深入学习来慢慢优化,但在内存泄漏上, <a href="https://github.com/square" target="_blank" rel="noopener">Square</a> 的 <code>LeakCanary</code> 拯救了 <code>Android</code> 开发者于水火之中,只需把它丢进你的依赖列表里面,然后再写上两三行代码, <code>LeakCanary</code> 就能自动检测内存泄漏并在发现泄露时通知开发者.</p><h3 id="安装和使用"><a href="#安装和使用" class="headerlink" title="安装和使用"></a>安装和使用</h3><p>先在 <code>LeakCanary</code> 的 <a href="https://github.com/square/leakcanary" target="_blank" rel="noopener">Github</a> 上查看最新的版本,毕竟在理论上来说新的总比旧的好.</p><h4 id="导入依赖"><a href="#导入依赖" class="headerlink" title="导入依赖"></a>导入依赖</h4><p>在 <code>Module</code> 级别的 <code>build.gradle</code> 中添加依赖并同步</p><p><code>build.gradle</code></p><figure class="highlight groovy"><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></pre></td><td class="code"><pre><span class="line">dependencies &#123;</span><br><span class="line">    compile fileTree(<span class="string">include:</span> [<span class="string">'*.jar'</span>], <span class="string">dir:</span> <span class="string">'libs'</span>)</span><br><span class="line">    testCompile <span class="string">'junit:junit:4.12'</span></span><br><span class="line">    testCompile <span class="string">'com.squareup.leakcanary:leakcanary-android-no-op:1.5'</span></span><br><span class="line">    debugCompile <span class="string">'com.squareup.leakcanary:leakcanary-android:1.5'</span></span><br><span class="line">    releaseCompile <span class="string">'com.squareup.leakcanary:leakcanary-android-no-op:1.5'</span></span><br><span class="line">...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h4><p>在你的 <code>Application</code> 类中初始化 <code>LeakCanary</code></p><p><code>Application.class</code></p><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate();</span><br><span class="line">        <span class="keyword">if</span> (LeakCanary.isInAnalyzerProcess(<span class="keyword">this</span>)) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        LeakCanary.install(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>如果你有使用<code>Fragment</code>,那么要多写几行</p><p><code>Application.class</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">YooooEXApplication</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> RefWatcher refWatcher;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> RefWatcher <span class="title">getWatcher</span><span class="params">(Context context)</span> </span>&#123;</span><br><span class="line">        YooooEXApplication application = (YooooEXApplication) context.getApplicationContext();</span><br><span class="line">        <span class="keyword">return</span> application.refWatcher;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate();</span><br><span class="line">        <span class="keyword">if</span> (LeakCanary.isInAnalyzerProcess(<span class="keyword">this</span>)) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        refWatcher = LeakCanary.install(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>YourFragment.class</code></p><figure class="highlight java"><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="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>.onDestroy();</span><br><span class="line">    RefWatcher refWatcher = YooooEXApplication.getWatcher(getActivity());</span><br><span class="line">    refWatcher.watch(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>到这里 <code>LeakCanary</code> 就已经配置完成了,当你使用的 Build Variant 中 Debuggable 为 true 时, <code>LeakCanary</code> 在发现内存泄漏时会弹出通知提示你它发现你露出了,并会给出泄露源头.</p><blockquote><p><img data-src="/imgs/2016/12/22/LeakCanary-1.png" alt="memory leaks"><br>妈蛋我漏了</p></blockquote><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;之前说了 &lt;a href=&quot;/2016/12/22/leakcanary-memory-leak-detecter/&quot;&gt;Fabric&lt;/a&gt; ,这次就来说说内存使用这个东西吧.&lt;/p&gt;&lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;千里之堤，溃于蚁穴 - 韩非《韩非子·喻老》 &lt;del&gt;都能用,就这样吧&lt;/del&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;因为开源的特性, &lt;code&gt;Android&lt;/code&gt; 拥有着各种各样不同尺寸屏幕和硬件配置的设备.&lt;br&gt;顶级到 5-6 寸 Snapdragon 821/Exynos 8890 + 6GB 的旗舰机型&lt;/p&gt;
    
    </summary>
    
    
      <category term="开发" scheme="https://yooooex.com/categories/%E5%BC%80%E5%8F%91/"/>
    
    
      <category term="Android" scheme="https://yooooex.com/tags/Android/"/>
    
      <category term="LeakCanary" scheme="https://yooooex.com/tags/LeakCanary/"/>
    
  </entry>
  
  <entry>
    <title>中国的开发者们终于能有个不用扶梯的 Google Developers 了!</title>
    <link href="https://yooooex.com/2016/12/09/google-developers-china/"/>
    <id>https://yooooex.com/2016/12/09/google-developers-china/</id>
    <published>2016-12-09T02:13:33.000Z</published>
    <updated>2016-12-09T05:13:07.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>在昨天举行的 GDD BeiJIng 2016 上,Google 宣布了中国版 Google Developers 网站的上线. 开发者们能在这上面找到 Google 各种产品的 API 文档,开发案例和讲解视频等资源. 在中国的开发者终于不用扶梯就能查看和学习由官方发布的最新技术和资讯了!</p><blockquote><p><img data-src="/imgs/2016/12/09/google-developers-china-1.png" alt="Google Developers China"><br>中文诶!</p></blockquote><a id="more"></a><p>不过网站上面还是有一部分资源是你不扶梯就看不见的,而且数量还不少:</p><p>想玩 GCE ?</p><blockquote><p><img data-src="/imgs/2016/12/09/google-developers-china-2.png" alt="Google Developers China"><br>嗯…</p></blockquote><p>开发者控制台所有链接无法直接访问( GAE 你就更别想了)</p><blockquote><p><img data-src="/imgs/2016/12/09/google-developers-china-3.png" alt="Google Developers China"><br>嗯嗯…</p></blockquote><p>同上</p><blockquote><p><img data-src="/imgs/2016/12/09/google-developers-china-4.png" alt="Google Developers China"><br>唔唔唔…</p></blockquote><p>虽然有部分东西不能用,但有 API 文档看就足够了!(部分有中文)</p><p>链接: <a href="https://developers.google.cn/" target="_blank" rel="noopener">Google Developers China</a></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;在昨天举行的 GDD BeiJIng 2016 上,Google 宣布了中国版 Google Developers 网站的上线. 开发者们能在这上面找到 Google 各种产品的 API 文档,开发案例和讲解视频等资源. 在中国的开发者终于不用扶梯就能查看和学习由官方发布的最新技术和资讯了!&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;img data-src=&quot;/imgs/2016/12/09/google-developers-china-1.png&quot; alt=&quot;Google Developers China&quot;&gt;&lt;br&gt;中文诶!&lt;/p&gt;&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Android" scheme="https://yooooex.com/tags/Android/"/>
    
      <category term="Google" scheme="https://yooooex.com/tags/Google/"/>
    
  </entry>
  
  <entry>
    <title>出色的多平台开发 SDK - Fabric</title>
    <link href="https://yooooex.com/2016/11/29/fabric-usage-statistics/"/>
    <id>https://yooooex.com/2016/11/29/fabric-usage-statistics/</id>
    <published>2016-11-29T07:33:18.000Z</published>
    <updated>2016-12-09T05:21:54.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><h3 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h3><p>不久前我曾经说过要做个回顾(嗯,这很不久),我就先从应用选用的工具说起吧.</p><blockquote><p>千里之堤，溃于蚁穴 - 韩非《韩非子·喻老》</p></blockquote><p>为了写一个质量较好的应用,一个趁手的数据/崩溃统计 SDK 是必不可少的.</p><p>其实国内友盟这些做的还是不错的,只是太臃肿了(大而全的后果),最新的 6.0.4 就达到 1.5MB 了,我的应用才 2M 不到,也不需要那么多的功能.</p><p>而且我更希望使用 <code>Gradle</code> 来管理和更新这些东西,这也避免了 SDK 版本需要更新的麻烦<del>(还是懒)</del>.</p><p>最后我选择了 Twitter 带来的 <a href="https://fabric.io/" target="_blank" rel="noopener">Fabric</a>.</p><blockquote><p><img data-src="/imgs/2016/11/29/Fabric-1.png" alt="Fabric"><br>Free<del>~</del></p></blockquote><p><code>Fabric</code> 支持 Android/IOS/Unity (纪念在天国的 Windows Phone),它可以根据你的需求来自定义模块,而且集成也是十分简单的.</p><a id="more"></a><blockquote><p><img data-src="/imgs/2016/11/29/Fabric-2.png" alt="Fabric"><br>Fabric 的模块们</p></blockquote><p>目前我使用的只有两个模块: Crashlytics 和 Answers. 前者用来检测应用崩溃和分发 Beta 应用,后者用来统计数据(用户量/事件等).</p><h3 id="安装和使用"><a href="#安装和使用" class="headerlink" title="安装和使用"></a>安装和使用</h3><p>因为我写的是 Android 应用,所以就只有 Android 版本的了. 其他平台步骤应该差不了多少.</p><h4 id="导入依赖"><a href="#导入依赖" class="headerlink" title="导入依赖"></a>导入依赖</h4><p><strong>Android Studio/IntelliJ IDEA</strong></p><p>步骤十分简单:</p><ol><li>在 IDE 中打开 Plugins 选项(Settings-&gt;Plugins/Ctrl+Shift+A then type <strong>plugins</strong>)</li><li>选择 Browse repositories,在搜索框中输入 Fabric for Android Studio 并安装重启</li><li>打开 <code>Fabric</code> 并登陆账号</li><li>一路下一步-&gt;选择你要的模块-&gt;一路下一步</li><li>完成,我真是个天才!</li></ol><blockquote><p><img data-src="/imgs/2016/11/29/Fabric-3.png" alt="Fabric"><br><code>Fabric</code> 的位置,你也可以 Ctrl+Shift+A then type <strong>fabric</strong> 来开启它.</p><p><img data-src="/imgs/2016/11/29/Fabric-4.png" alt="Fabric"><br>你可以直接在这里添加你需要的模块</p><p><img data-src="/imgs/2016/11/29/Fabric-5.png" alt="Fabric"><br>应用异常查看(我都不好意思发这张图了哈哈)</p></blockquote><p>在 IDE 中你可以简略的查看应用的崩溃信息,详细信息还是要去网页和客户端看的.</p><h4 id="查看信息"><a href="#查看信息" class="headerlink" title="查看信息"></a>查看信息</h4><p>在网页端你能详细的查看各类信息.</p><blockquote><p><img data-src="/imgs/2016/11/29/Fabric-6.png" alt="Fabric"><br>即时的统计信息</p><p><img data-src="/imgs/2016/11/29/Fabric-7.png" alt="Fabric"><br>各类事件统计</p><p><img data-src="/imgs/2016/11/29/Fabric-8.png" alt="Fabric"><br>崩溃详细信息</p></blockquote><h4 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h4><h5 id="手动初始化"><a href="#手动初始化" class="headerlink" title="手动初始化"></a>手动初始化</h5><p>要使用 <code>Fabric</code>,我们需要:</p><ul><li>在 <code>fabric.properties</code> 中添加你应用的 <a href="https://fabric.io/settings/organizations/" target="_blank" rel="noopener">apiSecret</a>.</li><li>更新 <code>Module</code> 级别的<code>build.gradle</code>.</li><li>在应用的 <code>Application</code> 类中将其初始化.</li></ul><p><code>build.gradle</code></p><figure class="highlight groovy"><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></pre></td><td class="code"><pre><span class="line">buildscript &#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        maven &#123; url <span class="string">'https://maven.fabric.io/public'</span> &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    dependencies &#123;</span><br><span class="line">        classpath <span class="string">'io.fabric.tools:gradle:1.+'</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">repositories &#123;</span><br><span class="line">    maven &#123; url <span class="string">'https://maven.fabric.io/public'</span> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">apply <span class="string">plugin:</span> <span class="string">'io.fabric'</span></span><br><span class="line">...</span><br><span class="line"></span><br><span class="line">dependencies &#123;</span><br><span class="line">...</span><br><span class="line">    compile(<span class="string">'com.crashlytics.sdk.android:crashlytics:2.6.5@aar'</span>) &#123;</span><br><span class="line">        transitive = <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>Application</code> 类</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">YooooEXApplication</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>&#123;</span><br><span class="line">...</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate();</span><br><span class="line">        Fabric.with(<span class="keyword">this</span>, <span class="keyword">new</span> Crashlytics());</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>fabric.properties</code></p><figure class="highlight plain"><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">#Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public.</span><br><span class="line">apiSecret&#x3D;apiSecret</span><br></pre></td></tr></table></figure><h5 id="自动初始化"><a href="#自动初始化" class="headerlink" title="自动初始化"></a>自动初始化</h5><p>如果你按照 <a href="/2016/11/29/fabric-usage-statistics/#导入依赖"><strong>导入依赖</strong></a> 一路走下去的话,<code>Fabric</code>就已经自动初始化完毕了. <del>(把这个放在后面是因为我想让你们看看手动配置是很麻烦的一件事情哈哈哈哈哈哈哈)</del></p><p>至此, <code>Fabric</code> 就已经完成初始化并开始收集数据了.</p><h5 id="自定义提交数据"><a href="#自定义提交数据" class="headerlink" title="自定义提交数据"></a>自定义提交数据</h5><p><strong>手动提交异常</strong></p><p><code>Fabric</code> 默认的设置已经能满足我的大部分需求,但是不折腾一下还是不行滴(不然写这个东西干嘛呢).</p><p>一般来说我们对可遇见的程序异常都会捕捉起来并返回错误信息给用户,但对于不可预料的异常便无能为力了. 下面是我在 <a href="/2016/11/11/com-yooooex-feeder/">Feeder</a> 中对网络请求发生异常的一段处理代码:</p><figure class="highlight java"><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></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="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> context 上下文</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> e       异常</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 错误信息</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">getExceptionMessage</span><span class="params">(Context context, Throwable e)</span> </span>&#123;</span><br><span class="line">    Log.d(TAG, <span class="string">"getExceptionMessage: "</span> + e.getClass());</span><br><span class="line">    String message = context.getString(R.string.err_unknow);</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (e.getClass() == HttpException<span class="class">.<span class="keyword">class</span>) </span>&#123;</span><br><span class="line">            String errorBody = ((HttpException) e).response().errorBody().string();</span><br><span class="line">            <span class="keyword">switch</span> (((HttpException) e).code()) &#123;</span><br><span class="line">                <span class="keyword">case</span> HttpURLConnection.HTTP_UNAUTHORIZED:</span><br><span class="line">                    <span class="keyword">if</span> (TextUtils.equals(errorBody, NetworkUtils.ERROR_LOGIN_FAILED)) &#123;</span><br><span class="line">                        message = context.getString(R.string.err_wrong_credential);</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        message = context.getString(R.string.err_user_token_expired);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="keyword">case</span> HttpURLConnection.HTTP_BAD_GATEWAY:</span><br><span class="line">                    message = context.getString(R.string.err_proxy);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (e.getClass() == SocketTimeoutException<span class="class">.<span class="keyword">class</span> ||</span></span><br><span class="line"><span class="class">                <span class="title">e</span>.<span class="title">getClass</span>() </span>== SSLHandshakeException<span class="class">.<span class="keyword">class</span> ||</span></span><br><span class="line"><span class="class">                <span class="title">e</span>.<span class="title">getClass</span>() </span>== UnknownHostException<span class="class">.<span class="keyword">class</span> ||</span></span><br><span class="line"><span class="class">                <span class="title">e</span>.<span class="title">getClass</span>() </span>== SSLException<span class="class">.<span class="keyword">class</span>) </span>&#123;</span><br><span class="line">            message = context.getString(R.string.err_network_timeout);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            Crashlytics.log(<span class="string">"An unexcepted exception occurred. Context: "</span> + context.toString());</span><br><span class="line">            Crashlytics.logException(e);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (IOException e1) &#123;</span><br><span class="line">        e1.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> message;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="/2016/11/11/com-yooooex-feeder/">Feeder</a> 的网络请求是通过 <code>Retrofit</code> + <code>RxJava</code> 来实现的,当发生异常时,这段代码会判断异常是不是网络请求抛出的. 如果是 <code>HttpException</code> 则展示相对应的错误信息给用户. 当没有相对应的异常时就会返回一个”未知错误”信息给用户.</p><p>在这里我已经对可预见的网络异常加入了判断语句当中,但当发生了意料之外的异常时, <code>Fabric</code> 中的 <code>Crashlytics</code> 模块就能起到作用了.</p><p>我们看向 31-32 行:<br><code>Crashlytics.logException(e);</code><br><code>Crashlytics.log(&quot;An unexcepted exception occurred. Context: &quot; + context.toString());</code></p><p>在这里我调用了 <code>Crashlytics.logException(Throwable throwable)</code> 和 <code>Crashlytics.log(String msg)</code> 这两个方法.当发生意料之外的网络异常时, <code>Fabric</code> 会向服务器提交这个异常,并附上了相应的 <code>Context</code> 来帮助我更快速的定位到问题所在.</p><p>当然, <code>Crashlytics</code> 还能提交变量,帮助你更详细的分析异常原因:</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Crashlytics.setString(key, value);</span><br><span class="line">Crashlytics.setBool(String key, <span class="keyword">boolean</span> value);</span><br><span class="line">Crashlytics.setDouble(String key, <span class="keyword">double</span> value);</span><br><span class="line">Crashlytics.setFloat(String key, <span class="keyword">float</span> value);</span><br><span class="line">Crashlytics.setInt(String key, <span class="keyword">int</span> value);</span><br><span class="line">Crashlytics.setLong(String key, <span class="keyword">long</span> value);</span><br><span class="line">Crashlytics.setUserIdentifier(String identifier);</span><br><span class="line">Crashlytics.setUserName(String name);</span><br><span class="line">Crashlytics.setUserEmail(String email);</span><br></pre></td></tr></table></figure><p><strong>提交统计信息</strong></p><p>和异常一样,要想让 <code>Fabric</code> 收集统计你自定义的数据,你还需要运用好 <code>Answers</code> 模块.</p><p><code>Answers</code> 默认会统计的手机型号和系统版本等信息,如果你想要更详细的事件统计信息(用户登录/注册/分享内容等),你就需要自定义一些东西来满足你的需求了.</p><p>还是拿 <a href="/2016/11/11/com-yooooex-feeder/">Feeder</a> 来做例子,来一个登录事件的统计吧.</p><p>用户登录</p><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LoginPresenterCompl</span> <span class="keyword">implements</span> <span class="title">LoginPresenter</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = <span class="string">"LoginPresenterCompl"</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> LoginView view;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Context loginContext;</span><br><span class="line"></span><br><span class="line">    ...</span><br><span class="line">    <span class="comment">//来自 LoginPresenter 接口的说明</span></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 用户登录-客户端方式</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> email    邮箱</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> password 密码</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">login</span><span class="params">(String email, String password)</span> </span>&#123;</span><br><span class="line">            ...</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onError</span><span class="params">(Throwable e)</span> </span>&#123;</span><br><span class="line">                view.dismissProgressDialog();</span><br><span class="line">                String reason = CommonUtils.getExceptionMessage(loginContext, e);</span><br><span class="line">                view.showMessage(reason);</span><br><span class="line">            &#125;</span><br><span class="line">            ...</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCompleted</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                <span class="keyword">if</span> (TextUtils.isEmpty(UserData.getToken())) &#123;</span><br><span class="line">                    view.loginResult(<span class="keyword">false</span>);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    getUserInfo();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            ...</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>登录事件完成后的回调</p><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">loginResult</span><span class="params">(<span class="keyword">boolean</span> flag)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (flag) &#123;</span><br><span class="line">        Answers.getInstance().logLogin(<span class="keyword">new</span> LoginEvent()</span><br><span class="line">                .putMethod(<span class="string">"Client"</span>)</span><br><span class="line">                .putSuccess(<span class="keyword">true</span>));</span><br><span class="line">        startActivity(<span class="keyword">new</span> Intent(<span class="keyword">this</span>, MainActivity<span class="class">.<span class="keyword">class</span>))</span>;</span><br><span class="line">        finish();</span><br><span class="line">    &#125;</span><br><span class="line">    Answers.getInstance().logLogin(<span class="keyword">new</span> LoginEvent()</span><br><span class="line">            .putMethod(<span class="string">"Client"</span>)</span><br><span class="line">            .putSuccess(<span class="keyword">false</span>));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以看见,在用户点击登录后,程序开始向服务器进行验证,当验证完毕后,根据验证结果调用 <code>loginResult(flag)</code>.</p><p><code>loginResult(flag)</code> 中则根据结果调用了 <code>Answers</code></p><figure class="highlight java"><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">Answers.getInstance().logLogin(<span class="keyword">new</span> LoginEvent()</span><br><span class="line">        .putMethod(<span class="string">"Client"</span>)<span class="comment">// Login method</span></span><br><span class="line">        .putSuccess(flag));<span class="comment">// Login status</span></span><br></pre></td></tr></table></figure><p>当调用此方法后,<code>Answers</code> 模块就会向服务器提交事件信息,你就可以得知用户的登录状况统计了.</p><p>想要自定义事件也是比较简单的,如果你只是在一个地方提交这个事件,你可以使用 <code>CustomEvent</code>:</p><figure class="highlight plain"><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">Answers.getInstance().logCustom(new CustomEvent(&quot;EventName&quot;)</span><br><span class="line">        .putCustomAttribute(&quot;key&quot;, &quot;value&quot;)</span><br><span class="line">        .putCustomAttribute(&quot;key&quot;,Number number)</span><br></pre></td></tr></table></figure><p>如果该事件在多个地方都要提交,你可以把它封装好或照着 <code>Answers</code> 中官方提供的事件写一个.</p><p>参考连接:</p><ul><li><a href="https://fabric.io/" target="_blank" rel="noopener">Fabric</a></li><li><a href="https://docs.fabric.io/" target="_blank" rel="noopener">Fabric-doc</a></li></ul><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;h3 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h3&gt;&lt;p&gt;不久前我曾经说过要做个回顾(嗯,这很不久),我就先从应用选用的工具说起吧.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;千里之堤，溃于蚁穴 - 韩非《韩非子·喻老》&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;为了写一个质量较好的应用,一个趁手的数据/崩溃统计 SDK 是必不可少的.&lt;/p&gt;&lt;p&gt;其实国内友盟这些做的还是不错的,只是太臃肿了(大而全的后果),最新的 6.0.4 就达到 1.5MB 了,我的应用才 2M 不到,也不需要那么多的功能.&lt;/p&gt;&lt;p&gt;而且我更希望使用 &lt;code&gt;Gradle&lt;/code&gt; 来管理和更新这些东西,这也避免了 SDK 版本需要更新的麻烦&lt;del&gt;(还是懒)&lt;/del&gt;.&lt;/p&gt;&lt;p&gt;最后我选择了 Twitter 带来的 &lt;a href=&quot;https://fabric.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Fabric&lt;/a&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;img data-src=&quot;/imgs/2016/11/29/Fabric-1.png&quot; alt=&quot;Fabric&quot;&gt;&lt;br&gt;Free&lt;del&gt;~&lt;/del&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;code&gt;Fabric&lt;/code&gt; 支持 Android/IOS/Unity (纪念在天国的 Windows Phone),它可以根据你的需求来自定义模块,而且集成也是十分简单的.&lt;/p&gt;
    
    </summary>
    
    
      <category term="开发" scheme="https://yooooex.com/categories/%E5%BC%80%E5%8F%91/"/>
    
    
      <category term="Android" scheme="https://yooooex.com/tags/Android/"/>
    
      <category term="Fabric" scheme="https://yooooex.com/tags/Fabric/"/>
    
  </entry>
  
  <entry>
    <title>好久不见,哲♂学教徒又回来了!</title>
    <link href="https://yooooex.com/2016/11/11/com-yooooex-feeder/"/>
    <id>https://yooooex.com/2016/11/11/com-yooooex-feeder/</id>
    <published>2016-11-11T04:01:33.000Z</published>
    <updated>2016-11-29T07:29:30.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p><del>因为懒癌</del>好久没更新了,今天就来写点东西吧.</p><p>这段时间回了家乡,然后写了个 <del>简陋</del> 简洁的第三方 Inoreader Rss阅读器客户端(能做出个给大伙玩的东西,我很欣慰),现在已经上架了.</p><p>在写这个应用的过程中重温和学习了很多东西,在近期会做个回顾,防止以后再踩到这些坑,也希望能给看到的人学习到什么吧.</p><p><strong>没错这就是个广告-快来下快来下快来下给我意见啊啊啊啊啊</strong></p><p><a href="http://www.coolapk.com/apk/com.yooooex.feeder" target="_blank" rel="noopener">酷安 - 和谐友好的地方</a></p><p><a href="http://www.wandoujia.com/apps/com.yooooex.feeder" target="_blank" rel="noopener">豌豆荚</a></p><p><a href="http://sj.qq.com/myapp/detail.htm?apkName=com.yooooex.feeder" target="_blank" rel="noopener">应用宝</a></p><p>另外求求 dalao 们赏个脸给小的做个图标吧,做设计实在是太痛苦了…</p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;&lt;del&gt;因为懒癌&lt;/del&gt;好久没更新了,今天就来写点东西吧.&lt;/p&gt;&lt;p&gt;这段时间回了家乡,然后写了个 &lt;del&gt;简陋&lt;/del&gt; 简洁的第
      
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Android" scheme="https://yooooex.com/tags/Android/"/>
    
      <category term="Feeder" scheme="https://yooooex.com/tags/Feeder/"/>
    
  </entry>
  
  <entry>
    <title>证书有效期监控 - LetsMonitor</title>
    <link href="https://yooooex.com/2016/08/31/certificate-monitor/"/>
    <id>https://yooooex.com/2016/08/31/certificate-monitor/</id>
    <published>2016-08-31T15:47:50.000Z</published>
    <updated>2016-08-31T17:10:08.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p><a href="https://letsmonitor.org/" target="_blank" rel="noopener">Let’s Monitor</a> 是一个由 <a href="https://letsencrypt.org/" target="_blank" rel="noopener">Let’s Encrypt</a> 所提供的免费监控服务,通过它你可以方便的查看你的证书剩余有效期,而且在证书接近过期时得到提醒.</p><p><img data-src="/imgs/2016/08/31/Certificate-Monitor-1.png" alt="首页"></p><a id="more"></a><p><img data-src="/imgs/2016/08/31/Certificate-Monitor-2.png" alt="总览"></p><p><img data-src="/imgs/2016/08/31/Certificate-Monitor-3.png" alt="监控服务"></p><p><img data-src="/imgs/2016/08/31/Certificate-Monitor-4.png" alt="提醒设置"></p><p>网站地址: <a href="https://letsmonitor.org/" target="_blank" rel="noopener">Let’s Monitor</a></p><p>免费证书申请:</p><ul><li><a href="https://letsencrypt.org/" target="_blank" rel="noopener">Let’s Encrypt</a></li><li><a href="https://www.startssl.com/" target="_blank" rel="noopener">StartSSL</a></li></ul><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;&lt;a href=&quot;https://letsmonitor.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Let’s Monitor&lt;/a&gt; 是一个由 &lt;a href=&quot;https://letsencrypt.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Let’s Encrypt&lt;/a&gt; 所提供的免费监控服务,通过它你可以方便的查看你的证书剩余有效期,而且在证书接近过期时得到提醒.&lt;/p&gt;&lt;p&gt;&lt;img data-src=&quot;/imgs/2016/08/31/Certificate-Monitor-1.png&quot; alt=&quot;首页&quot;&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="tool" scheme="https://yooooex.com/tags/tool/"/>
    
      <category term="证书" scheme="https://yooooex.com/tags/%E8%AF%81%E4%B9%A6/"/>
    
  </entry>
  
  <entry>
    <title>重新上路的文件管理器 - Clover</title>
    <link href="https://yooooex.com/2016/08/01/clover-explorer-addon/"/>
    <id>https://yooooex.com/2016/08/01/clover-explorer-addon/</id>
    <published>2016-08-01T11:01:48.000Z</published>
    <updated>2016-08-02T14:25:22.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p><em>本来以为这工具已经停止开发了,今天整理书签时去看了看,没想到它前几天竟然又开始更新了.<br><del>看来定时整理书签还是有好处的哈哈哈</del>既然这样就推荐给大家使用吧.</em></p><h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p><code>Clover</code> 是一个 <code>Windows Explorer</code> 插件,它能让你的文件管理器拥有跟浏览器相似的体验.</p><p><img data-src="/imgs/2016/08/01/Clover-1.png" alt="Clover"></p><h3 id="功能"><a href="#功能" class="headerlink" title="功能"></a>功能</h3><a id="more"></a><p>就像 <a href="/2016/08/01/clover-explorer-addon/#简介">简介</a> 说的那样, <code>Clover</code> 为 <code>Windows Explorer</code>提供了跟游览器类似的标签栏和收藏栏,让你能快捷的在文件夹之间转换,提高你的工作效率.</p><ul><li><p>标签栏(多标签页)</p></li><li><p>收藏夹(快速跳转)</p></li><li><p>主题支持( Chrome 主题)</p></li><li><p>返回上一级(双击空白位置)</p></li></ul><p><img data-src="/imgs/2016/08/01/Clover-2.png" alt="Clover"></p><p><code>Clover</code> 的快捷键与 <code>Chrome</code> 十分相似,可以说到手即用,学习成本十分小.</p><table><thead><tr><th align="center">快捷键</th><th align="center">效果</th></tr></thead><tbody><tr><td align="center">Ctrl + 数字</td><td align="center">切换到指定的标签页</td></tr><tr><td align="center">Ctrl + N</td><td align="center">打开一个新的 Clover 窗口</td></tr><tr><td align="center">Ctrl + T</td><td align="center">新建标签页</td></tr><tr><td align="center">Ctrl + W</td><td align="center">关闭当前标签页</td></tr><tr><td align="center">Ctrl + Shift + T</td><td align="center">重新打开关闭的标签页</td></tr><tr><td align="center">Ctrl + D</td><td align="center">添加书签（有选择文件、文件夹的情况下，是删除文件）</td></tr><tr><td align="center">Ctrl + Shift + D</td><td align="center">为所有打开的标签页添加书签</td></tr><tr><td align="center">Ctrl + Tab</td><td align="center">切换到下一个标签页</td></tr><tr><td align="center">Ctrl + Shift + Tab</td><td align="center">切换到上一个标签页</td></tr><tr><td align="center">Ctrl + Shift + B</td><td align="center">显示或隐藏书签栏</td></tr></tbody></table><h3 id="简评"><a href="#简评" class="headerlink" title="简评"></a>简评</h3><p>优点:</p><ul><li><p>轻量</p><p>与 <code>QTTabBar</code> 等工具相比, <code>Clover</code> 功能相对简单.但对于不折腾的日常用户来说, <code>Clover</code> 对他们来说应该是更好上手使用的.</p><p>对于折腾帝和效率狂人,他们眼中应该只有 <code>Total Commander</code> 才对吧哈哈哈哈哈</p></li><li><p>集成在 <code>Windows Explorer</code> 中</p><p>无需专门打开软件,使用体验较好.</p></li></ul><p>缺点:</p><ul><li>速度<br>新建标签页的速度和 <code>Windows</code> 7 / 8.1 相比慢了许多,不过这是支持新系统的第一个 <code>Beta</code> 版本,后续应该会修正这个问题.</li><li>外观<br>使用 <code>Clover</code> 后, <code>Windows Explorer</code> 的边框会变得有点奇怪(注意在 <a href="/2016/08/01/clover-explorer-addon/#功能">功能</a> 的配图, <code>Windows Explorer</code> 的边框会有蓝色的边框),之前版本的 <code>Windows</code> 中是不会出现这个情况的.<br>事实上不止 <code>Clover</code> ,我使用的一些软件也出现了这样的现象,例如下图的 <code>Internet Download Manager</code> :</li></ul><p><img data-src="/imgs/2016/08/01/Clover-3.png" alt="Internet Download Manager"></p><p>目前软件处于 <code>Beta</code> 状态(版本号:3.1.1.07271 ,2016-08-01),而且这是适配 <code>Windows 10</code> 的第一个版本,后续更新应该会完善这些问题.</p><p><a href="http://cn.ejie.me/" target="_blank" rel="noopener">Clover 网站</a></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;&lt;em&gt;本来以为这工具已经停止开发了,今天整理书签时去看了看,没想到它前几天竟然又开始更新了.&lt;br&gt;&lt;del&gt;看来定时整理书签还是有好处的哈哈哈&lt;/del&gt;既然这样就推荐给大家使用吧.&lt;/em&gt;&lt;/p&gt;&lt;h3 id=&quot;简介&quot;&gt;&lt;a href=&quot;#简介&quot; class=&quot;headerlink&quot; title=&quot;简介&quot;&gt;&lt;/a&gt;简介&lt;/h3&gt;&lt;p&gt;&lt;code&gt;Clover&lt;/code&gt; 是一个 &lt;code&gt;Windows Explorer&lt;/code&gt; 插件,它能让你的文件管理器拥有跟浏览器相似的体验.&lt;/p&gt;&lt;p&gt;&lt;img data-src=&quot;/imgs/2016/08/01/Clover-1.png&quot; alt=&quot;Clover&quot;&gt;&lt;/p&gt;&lt;h3 id=&quot;功能&quot;&gt;&lt;a href=&quot;#功能&quot; class=&quot;headerlink&quot; title=&quot;功能&quot;&gt;&lt;/a&gt;功能&lt;/h3&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="Windows Explorer" scheme="https://yooooex.com/tags/Windows-Explorer/"/>
    
      <category term="tool" scheme="https://yooooex.com/tags/tool/"/>
    
  </entry>
  
  <entry>
    <title>自己在开发中使用到的工具</title>
    <link href="https://yooooex.com/2016/07/06/my-dev-tools/"/>
    <id>https://yooooex.com/2016/07/06/my-dev-tools/</id>
    <published>2016-07-06T02:47:30.000Z</published>
    <updated>2016-07-07T02:51:41.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><p>自用的 Android 开发工具,在此分享给大家.</p><h3 id="Genymotion-虚拟机调试"><a href="#Genymotion-虚拟机调试" class="headerlink" title="Genymotion - 虚拟机调试"></a>Genymotion - 虚拟机调试</h3><p><em>如图所示,它的确很快</em></p><p>虽说 Google 虐我千百遍, 我待 Google 如初恋 ,但是 <code>Android</code> 官方的模拟器性能真的是不忍直视,即使是 Android Studio 2.1 + <a href="https://software.intel.com/zh-cn/android/articles/intel-hardware-accelerated-execution-manager" target="_blank" rel="noopener">Intel HAXM</a> 还是能感觉到明显的卡顿,直到我发现了它:</p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Genymotion-1.png" alt="Genymotion"></p><p>好了,以后再也不用点完手机再看屏幕了,YEEEEEEEEEEEEEEEEE!</p><a id="more"></a><p><img data-src="https://yooooex.com/imgs/2016/07/06/Genymotion-2.png" alt="Genymotion"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Genymotion-3.png" alt="Genymotion"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Genymotion-4.png" alt="Genymotion"></p><p>Genymotion 提供了各种尺寸的模拟器,速度快的飞起,还提供了电池状态/摄像头/GPS/网络状态/电话等硬件状态模拟,让你在电脑方便的调试.</p><h3 id="Vysor-真机调试"><a href="#Vysor-真机调试" class="headerlink" title="Vysor - 真机调试"></a>Vysor - 真机调试</h3><p><em><del>我要找点什么玩呢</del></em></p><p>虽然虚拟机调试是很方便,但真机调试是开发应用中不可缺少的一环,要一台台接线调试又很麻烦,用无线调试也只是减少了接线的步骤,你还是要拿起一台台设备慢慢测试.</p><blockquote><p>Perl 之父 Larry Wall 曾说过,程序员的三大美德是 “懒惰” “不耐烦” 以及 “傲慢”.</p></blockquote><p>作为一个想成为合格程序员的人来说,我认为我还是挺符合第一点的.</p><p>然后我就到处乱逛找到了这个:</p><p><a href="http://www.vysor.io/" target="_blank" rel="noopener">Vysor - A window to your Android</a></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Vysor-1.png" alt="Vysor-website"></p><p>Vysor 是一个让你在电脑上控制手机的 Chrome 应用(不需要 Root ),你可以使用有线/无线来连接并控制多个设备.</p><p>真机测试开发不用再看来看去了,在电脑上就能完成一切工作.<br>拿来给客户演示效果也是很不错的.</p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Vysor-2.png" alt="Vysor-application"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Vysor-3.png" alt="Vysor-application"></p><p>* <em>注意,要正常使用软件, Chrome 需要先安装 PNaCl 组件.</em></p><p>查看安装状态: <code>chrome://nacl</code></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Vysor-4.png" alt="chrome-nacl"></p><p>安装 Pnacl 组件(点击 “检查是否有更新” ): <code>chrome://components/</code></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Vysor-5.png" alt="chrome-components"></p><h3 id="ChromeADB"><a href="#ChromeADB" class="headerlink" title="ChromeADB"></a>ChromeADB</h3><p><em>你是 Terminal 党还是 GUI 党?</em></p><p>就像名字一样, <a href="https://chrome.google.com/webstore/detail/chromeadb/fhdoijgfljahinnpbolfdimpcfoicmnm" target="_blank" rel="noopener">Chrome ADB</a> 是一个使用 ADB 调试设备的 Chrome 应用,它能进行安装/卸载/清除应用数据等操作,也能查看各个应用占用的内存,而且还提供了基本的设备控制功能.</p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Chrome-ADB-1.png" alt="ChromeADB"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Chrome-ADB-2.png" alt="ChromeADB"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Chrome-ADB-3.png" alt="ChromeADB"></p><h3 id="Postman-API-调试"><a href="#Postman-API-调试" class="headerlink" title="Postman - API 调试"></a>Postman - API 调试</h3><p><em>我感觉我还能再懒一点</em></p><p><a href="https://www.getpostman.com/" target="_blank" rel="noopener">Postman</a> (Chrome, Mac) 是一个功能强大的 API 调试工具,使用它能快速的构建 API 请求(POST, GET, HEAD, PATCH 等),还可以添加 OAUTH 等认证,并测试返回结果是否符合需要求.</p><p>它还可以将你写的测试添加成一个集合,并同步到服务器,你还能把它分享给他人或在团队中共享,想想就觉得生活原来可以这么美好~</p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Postman-1.png" alt="Postman"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Postman-4.png" alt="Postman"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Postman-3.png" alt="Postman"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Postman-2.png" alt="Postman"></p><h3 id="TinyPNG-图片素材压缩"><a href="#TinyPNG-图片素材压缩" class="headerlink" title="TinyPNG - 图片素材压缩"></a>TinyPNG - 图片素材压缩</h3><p><em>从此不求设计师,翻身做主人</em></p><p><a href="https://tinypng.com/" target="_blank" rel="noopener">TinyPng</a> 是一个图片压缩(有损)工具,支持 <code>.jpg</code> <code>.png</code> 格式,压缩效率还是挺不错的.</p><p>如果你需要无损压缩或离线处理的话,我建议使用 <a href="https://yooooex.com/2016/06/23/png-compress-tool/">limitPNG</a> 来处理,目前本站所有的图片都是由它来完成压缩工作的.</p><p><img data-src="https://yooooex.com/imgs/2016/07/06/TinyPng-1.png" alt="TinyPng"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/TinyPng-2.png" alt="TinyPng"></p><h3 id="Android-Arsenal-装备仓库"><a href="#Android-Arsenal-装备仓库" class="headerlink" title="Android Arsenal - 装备仓库"></a>Android Arsenal - 装备仓库</h3><p><em>你想要最新最流行的轮子吗?这里就是你的天堂!</em></p><p><a href="https://android-arsenal.com/" target="_blank" rel="noopener">Android Arsenal</a> 是一个聚合类的网站,展示了流行的 <code>Android</code> 开发库和各种各样的 Demo , 你可以在这里快速找到大部分开发者对 UI/网络/数据处理所选择的类库,众人拾柴火焰高,能让你少走点不必要的坑.</p><p><img data-src="https://yooooex.com/imgs/2016/07/06/AndroidLib-1.png" alt="Android Arsenal"></p><h3 id="Codota-代码仓库"><a href="#Codota-代码仓库" class="headerlink" title="Codota - 代码仓库"></a>Codota - 代码仓库</h3><p><em>面向 Google 编程 2nd gen</em></p><p><a href="https://www.codota.com/" target="_blank" rel="noopener">Codota</a> (Chrome, Android Studio) 是一个代码实例仓库,目前已经收集超过700万来自 GitHub/StackOverFlow/知名博客/开发者网站的代码示例.</p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Codota-1.png" alt="Codota"></p><p><img data-src="https://yooooex.com/imgs/2016/07/06/Codota-2.png" alt="Codota"></p><p>除了网页版, <a href="https://www.codota.com/" target="_blank" rel="noopener">Codota</a> 还提供了 Chrome 和 Android Studio (需要 Token ,插件会提示) 插件,让你可以在这两个应用中直接查看和收藏代码,<del>妈妈再也不担心我会加班了</del>也能参考下其他人的思路,好评!</p><p>暂时写到这里,等我想到新的再补充吧.</p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;自用的 Android 开发工具,在此分享给大家.&lt;/p&gt;&lt;h3 id=&quot;Genymotion-虚拟机调试&quot;&gt;&lt;a href=&quot;#Genymotion-虚拟机调试&quot; class=&quot;headerlink&quot; title=&quot;Genymotion - 虚拟机调试&quot;&gt;&lt;/a&gt;Genymotion - 虚拟机调试&lt;/h3&gt;&lt;p&gt;&lt;em&gt;如图所示,它的确很快&lt;/em&gt;&lt;/p&gt;&lt;p&gt;虽说 Google 虐我千百遍, 我待 Google 如初恋 ,但是 &lt;code&gt;Android&lt;/code&gt; 官方的模拟器性能真的是不忍直视,即使是 Android Studio 2.1 + &lt;a href=&quot;https://software.intel.com/zh-cn/android/articles/intel-hardware-accelerated-execution-manager&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Intel HAXM&lt;/a&gt; 还是能感觉到明显的卡顿,直到我发现了它:&lt;/p&gt;&lt;p&gt;&lt;img data-src=&quot;https://yooooex.com/imgs/2016/07/06/Genymotion-1.png&quot; alt=&quot;Genymotion&quot;&gt;&lt;/p&gt;&lt;p&gt;好了,以后再也不用点完手机再看屏幕了,YEEEEEEEEEEEEEEEEE!&lt;/p&gt;
    
    </summary>
    
    
      <category term="开发" scheme="https://yooooex.com/categories/%E5%BC%80%E5%8F%91/"/>
    
    
      <category term="Android" scheme="https://yooooex.com/tags/Android/"/>
    
      <category term="tool" scheme="https://yooooex.com/tags/tool/"/>
    
      <category term="Chrome" scheme="https://yooooex.com/tags/Chrome/"/>
    
  </entry>
  
  <entry>
    <title>高效 Png 压缩软件 - limitPNG</title>
    <link href="https://yooooex.com/2016/06/23/png-compress-tool/"/>
    <id>https://yooooex.com/2016/06/23/png-compress-tool/</id>
    <published>2016-06-23T05:06:03.000Z</published>
    <updated>2016-12-07T08:36:55.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><h3 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h3><p><code>limitPNG</code> 是一个使用 <code>Electron</code> 构建的 <code>Png</code> 有损/无损压缩软件.<br>对于不熟悉终端命令和配置 <code>pngout</code> <code>pngwolf</code> , <code>pngquant</code> 等 <code>Png</code> 压缩工具的苦手<del>(我,测试配置真痛苦)</del>来说,这是一个很不错的工具.</p><p><img data-src="https://yooooex.com/imgs/2016/06/23/limitPng.png" alt="软件界面"></p><blockquote><p>针对有损和无损压缩, <code>limitPNG</code> 提供了丰富的压缩选项让我们选择.</p></blockquote><a id="more"></a><p>无损:</p><p><img data-src="https://yooooex.com/imgs/2016/06/23/limitPng-2.png" alt="软件介绍"></p><p><img data-src="https://yooooex.com/imgs/2016/06/23/limitPng-3.png" alt="软件介绍"></p><ul><li>快速: 速度快,能达到极限压缩 ~=90% 的效果.</li><li>强力: 耗时较长,但压缩效果比极限差不了多少.</li><li>极限: 不是强迫症和太有空的我不建议选择这个…</li></ul><p>有损:</p><p><img data-src="https://yooooex.com/imgs/2016/06/23/limitPng-4.png" alt="软件介绍"></p><ul><li>快速: 同上</li><li>低质量: 牺牲质量换来较高的压缩率</li><li>高质量: 同上,质量损耗较小</li><li>256色高质量: 256 色 PNG ,其余同上</li><li>256色低质量: 同上</li><li>极低色: 这个选项没试过</li></ul><p>输出选项有覆盖/添加后缀,输出到指定文件夹,足够日常使用了.</p><h3 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h3><table><thead><tr><th align="center">处理方式</th><th align="center">文档大小</th><th align="center">压缩百分比</th><th align="center">效果</th></tr></thead><tbody><tr><td align="center">原图</td><td align="center">241 KB</td><td align="center">100%</td><td align="center"><a href="https://yooooex.com/imgs/2016/06/23/limitPng-original.png">图片</a></td></tr><tr><td align="center">无损(强力)</td><td align="center">217 KB</td><td align="center">90.04%</td><td align="center"><a href="https://yooooex.com/imgs/2016/06/23/limitPng-lossless-strong.png">图片</a></td></tr><tr><td align="center">无损(快速)</td><td align="center">215 KB</td><td align="center">89.21%</td><td align="center"><a href="https://yooooex.com/imgs/2016/06/23/limitPng-lossless-quick.png">图片</a></td></tr><tr><td align="center">有损(高质量)</td><td align="center">132 KB</td><td align="center">54.77%</td><td align="center"><a href="https://yooooex.com/imgs/2016/06/23/limitPng-loss.png">图片</a></td></tr></tbody></table><h3 id="简评"><a href="#简评" class="headerlink" title="简评"></a>简评</h3><p>优点:</p><ul><li>界面美观</li><li>压缩率高</li><li>操作简单</li></ul><p>缺点:</p><ul><li>大,真的很大: 目前看到 <code>Electron</code> 构建的软件和同类软件比较体积都是巨无霸级别的了.</li></ul><p>目前软件还处于 <code>Beta</code> 状态(2016-6-23),期待正式版出来会带来各方面的改善和加强.</p><p><strong><a href="http://nullice.com/limitPNG/" target="_blank" rel="noopener">limitPNG 网站</a></strong></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;h3 id=&quot;介绍&quot;&gt;&lt;a href=&quot;#介绍&quot; class=&quot;headerlink&quot; title=&quot;介绍&quot;&gt;&lt;/a&gt;介绍&lt;/h3&gt;&lt;p&gt;&lt;code&gt;limitPNG&lt;/code&gt; 是一个使用 &lt;code&gt;Electron&lt;/code&gt; 构建的 &lt;code&gt;Png&lt;/code&gt; 有损/无损压缩软件.&lt;br&gt;对于不熟悉终端命令和配置 &lt;code&gt;pngout&lt;/code&gt; &lt;code&gt;pngwolf&lt;/code&gt; , &lt;code&gt;pngquant&lt;/code&gt; 等 &lt;code&gt;Png&lt;/code&gt; 压缩工具的苦手&lt;del&gt;(我,测试配置真痛苦)&lt;/del&gt;来说,这是一个很不错的工具.&lt;/p&gt;&lt;p&gt;&lt;img data-src=&quot;https://yooooex.com/imgs/2016/06/23/limitPng.png&quot; alt=&quot;软件界面&quot;&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;针对有损和无损压缩, &lt;code&gt;limitPNG&lt;/code&gt; 提供了丰富的压缩选项让我们选择.&lt;/p&gt;&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="tool" scheme="https://yooooex.com/tags/tool/"/>
    
      <category term="nodejs" scheme="https://yooooex.com/tags/nodejs/"/>
    
      <category term="png" scheme="https://yooooex.com/tags/png/"/>
    
  </entry>
  
  <entry>
    <title>记本博客搭建过程（二）：Nginx 配置</title>
    <link href="https://yooooex.com/2016/06/15/my-blog-config-2/"/>
    <id>https://yooooex.com/2016/06/15/my-blog-config-2/</id>
    <published>2016-06-15T05:28:27.000Z</published>
    <updated>2016-12-07T08:36:54.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --><h3 id="编译"><a href="#编译" class="headerlink" title="编译"></a>编译</h3><h4 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h4><p>为了能同时支持 <code>HTTP/2</code> 和 <code>Spdy</code> ,所以我使用了 <code>Nginx</code> 1.9.7 + Cloudflare 的补丁.<br>我使用的系统是 <code>Debian</code> 8.0,请根据自己的系统调整相应的包管理器命令.</p><p>首先安装编译要用到的依赖库和工具.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev unzip git</span><br></pre></td></tr></table></figure><p>然后获取 <code>OpenSSL</code> , Cloudflare 的补丁和 Certificate Transparency 补丁.</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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">wget -O openssl.zip -c https://github.com/openssl/openssl/archive/OpenSSL_1_0_2h.zip</span><br><span class="line">unzip openssl.zip &amp;&amp; mv openssl-OpenSSL_1_0_2h/ openssl</span><br><span class="line">wget -O nginx-ct.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/v1.2.0.zip</span><br><span class="line">unzip nginx-ct.zip</span><br><span class="line"></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/cloudflare/sslconfig</span><br><span class="line"><span class="built_in">cd</span> openssl</span><br><span class="line">patch -p1 &lt; ../sslconfig/patches/openssl__chacha20_poly1305_draft_and_rfc_ossl102g.patch</span><br><span class="line"><span class="built_in">cd</span> ../</span><br></pre></td></tr></table></figure><h4 id="开始编译"><a href="#开始编译" class="headerlink" title="开始编译"></a>开始编译</h4><p>默认安装到 /usr/local/nginx ,如果想更改路径可以在编译时指定 <code>--prefix</code> 参数.</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><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">wget -c http://nginx.org/download/nginx-1.9.7.tar.gz</span><br><span class="line">tar zxf nginx-1.9.7.tar.gz</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> nginx-1.9.7</span><br><span class="line">patch -1 &lt; ../sslconfig/patches/nginx__http2_spdy.patch</span><br><span class="line"></span><br><span class="line">./configure --add-module=../nginx-ct-1.2.0 --with-openssl=../openssl --with-http_v2_module --with-http_spdy_module --with-http_ssl_module --with-ipv6 --with-http_gzip_static_module</span><br><span class="line"></span><br><span class="line">make</span><br><span class="line">sudo make install</span><br></pre></td></tr></table></figure><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><h4 id="创建管理脚本"><a href="#创建管理脚本" class="headerlink" title="创建管理脚本"></a>创建管理脚本</h4><p>为了方便管理 <code>Nginx</code> ,我使用脚本来对 <code>Nginx</code> 进行操作.</p><a id="more"></a><blockquote><p>sudo vim /etc/init.d/nginx</p></blockquote><figure class="highlight plain"><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></pre></td><td class="code"><pre><span class="line">#! &#x2F;bin&#x2F;sh</span><br><span class="line"></span><br><span class="line">### BEGIN INIT INFO</span><br><span class="line"># Provides:          nginx</span><br><span class="line"># Required-Start:    $all</span><br><span class="line"># Required-Stop:     $all</span><br><span class="line"># Default-Start:     2 3 4 5</span><br><span class="line"># Default-Stop:      0 1 6</span><br><span class="line"># Short-Description: starts the nginx web server</span><br><span class="line"># Description:       starts nginx using start-stop-daemon</span><br><span class="line">### END INIT INFO</span><br><span class="line"></span><br><span class="line">PATH&#x3D;&#x2F;usr&#x2F;local&#x2F;sbin:&#x2F;usr&#x2F;local&#x2F;bin:&#x2F;sbin:&#x2F;bin:&#x2F;usr&#x2F;sbin:&#x2F;usr&#x2F;bin</span><br><span class="line"># Nginx 路径</span><br><span class="line">DAEMON&#x3D;&#x2F;etc&#x2F;nginx&#x2F;sbin&#x2F;nginx</span><br><span class="line">NAME&#x3D;nginx</span><br><span class="line">DESC&#x3D;nginx</span><br><span class="line"></span><br><span class="line">test -x $DAEMON || exit 0</span><br><span class="line"></span><br><span class="line"># Include nginx defaults if available</span><br><span class="line">if [ -f &#x2F;etc&#x2F;default&#x2F;nginx ] ; then</span><br><span class="line">  . &#x2F;etc&#x2F;default&#x2F;nginx</span><br><span class="line">fi</span><br><span class="line"></span><br><span class="line">set -e</span><br><span class="line"></span><br><span class="line">. &#x2F;lib&#x2F;lsb&#x2F;init-functions</span><br><span class="line"></span><br><span class="line">case &quot;$1&quot; in</span><br><span class="line">  start)</span><br><span class="line">    echo -n &quot;Starting $DESC: &quot;</span><br><span class="line">    start-stop-daemon --start --quiet --pidfile &#x2F;etc&#x2F;nginx&#x2F;logs&#x2F;$NAME.pid \</span><br><span class="line">        --exec $DAEMON -- $DAEMON_OPTS || true</span><br><span class="line">    echo &quot;$NAME.&quot;</span><br><span class="line">    ;;</span><br><span class="line">  stop)</span><br><span class="line">    echo -n &quot;Stopping $DESC: &quot;</span><br><span class="line">    start-stop-daemon --stop --quiet --pidfile &#x2F;etc&#x2F;nginx&#x2F;logs&#x2F;$NAME.pid \</span><br><span class="line">        --exec $DAEMON || true</span><br><span class="line">    echo &quot;$NAME.&quot;</span><br><span class="line">    ;;</span><br><span class="line">  restart|force-reload)</span><br><span class="line">    echo -n &quot;Restarting $DESC: &quot;</span><br><span class="line">    start-stop-daemon --stop --quiet --pidfile \</span><br><span class="line">        &#x2F;etc&#x2F;nginx&#x2F;logs&#x2F;$NAME.pid --exec $DAEMON || true</span><br><span class="line">    sleep 1</span><br><span class="line">    start-stop-daemon --start --quiet --pidfile \</span><br><span class="line">        &#x2F;etc&#x2F;nginx&#x2F;logs&#x2F;$NAME.pid --exec $DAEMON -- $DAEMON_OPTS || true</span><br><span class="line">    echo &quot;$NAME.&quot;</span><br><span class="line">    ;;</span><br><span class="line">  reload)</span><br><span class="line">    echo -n &quot;Reloading $DESC configuration: &quot;</span><br><span class="line">    start-stop-daemon --stop --signal HUP --quiet --pidfile &#x2F;etc&#x2F;nginx&#x2F;logs&#x2F;$NAME.pid \</span><br><span class="line">        --exec $DAEMON || true</span><br><span class="line">    echo &quot;$NAME.&quot;</span><br><span class="line">    ;;</span><br><span class="line">  status)</span><br><span class="line">    status_of_proc -p &#x2F;etc&#x2F;nginx&#x2F;logs&#x2F;$NAME.pid &quot;$DAEMON&quot; nginx &amp;&amp; exit 0 || exit $?</span><br><span class="line">    ;;</span><br><span class="line">  *)</span><br><span class="line">    N&#x3D;&#x2F;etc&#x2F;init.d&#x2F;$NAME</span><br><span class="line">    echo &quot;Usage: $N &#123;start|stop|restart|reload|force-reload|status&#125;&quot; &gt;&amp;2</span><br><span class="line">    exit 1</span><br><span class="line">    ;;</span><br><span class="line">esac</span><br><span class="line"></span><br><span class="line">exit 0</span><br></pre></td></tr></table></figure><p>为脚本增加执行权限</p><blockquote><p>sudo chmod a+x /etc/init.d/nginx</p></blockquote><h4 id="Nginx-全局配置"><a href="#Nginx-全局配置" class="headerlink" title="Nginx 全局配置"></a>Nginx 全局配置</h4><p>打开 <code>Nginx</code> 安装目录下的 conf/nginx.conf 配置.</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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">#user  nobody;</span></span><br><span class="line">worker_processes  4;</span><br><span class="line"></span><br><span class="line"><span class="comment">#error_log  logs/error.log;</span></span><br><span class="line"><span class="comment">#error_log  logs/error.log  notice;</span></span><br><span class="line"><span class="comment">#error_log  logs/error.log  info;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#pid        logs/nginx.pid;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">events &#123;</span><br><span class="line">    worker_connections  1024;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">http &#123;</span><br><span class="line">    include       mime.types;</span><br><span class="line">    default_type  application/octet-stream;</span><br><span class="line"></span><br><span class="line">    <span class="comment">#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '</span></span><br><span class="line">    <span class="comment">#                  '$status $body_bytes_sent "$http_referer" '</span></span><br><span class="line">    <span class="comment">#                  '"$http_user_agent" "$http_x_forwarded_for"';</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">#access_log  logs/access.log  main;</span></span><br><span class="line">    <span class="comment"># Display Version</span></span><br><span class="line">    server_tokens      off;</span><br><span class="line"></span><br><span class="line">    sendfile           on;</span><br><span class="line">    tcp_nopush         on;</span><br><span class="line">    tcp_nodelay        on;</span><br><span class="line"></span><br><span class="line">    <span class="comment">#keepalive_timeout  0;</span></span><br><span class="line">    keepalive_timeout  60;</span><br><span class="line"></span><br><span class="line">    gzip               on;</span><br><span class="line">    gzip_vary          on;</span><br><span class="line">    </span><br><span class="line">    gzip_comp_level    6;</span><br><span class="line">    gzip_buffers       16 8k;</span><br><span class="line">    </span><br><span class="line">    gzip_min_length    1000;</span><br><span class="line">    gzip_proxied       any;</span><br><span class="line">    gzip_disable       <span class="string">"msie6"</span>;</span><br><span class="line">    </span><br><span class="line">    gzip_http_version  1.0;</span><br><span class="line">    </span><br><span class="line">    gzip_types         text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;</span><br><span class="line"></span><br><span class="line"><span class="comment"># 加载配置文件路径</span></span><br><span class="line">    include             /point/to/your/path/*;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="Nginx-站点配置"><a href="#Nginx-站点配置" class="headerlink" title="Nginx 站点配置"></a>Nginx 站点配置</h4><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><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># Port 80</span></span><br><span class="line">server &#123;</span><br><span class="line"><span class="comment"># Go to Https</span></span><br><span class="line">  listen 80 default_server;</span><br><span class="line">  server_name _;</span><br><span class="line"><span class="comment">#  listen [::]:80       ;</span></span><br><span class="line">  rewrite ^(.*) https://yooooex.com/<span class="variable">$1</span> permanent;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># Port 443</span></span><br><span class="line">server &#123;</span><br><span class="line">listen               443 ssl http2 fastopen=3 reuseport;</span><br><span class="line"><span class="comment">#listen               [::]:443;</span></span><br><span class="line"> server_name www.yooooex.com yooooex.com;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$host</span> != <span class="string">'yooooex.com'</span>) &#123;</span><br><span class="line"> rewrite ^/(.*)$ https://yooooex.com/<span class="variable">$1</span> permanent;</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"># SSL Settings</span></span><br><span class="line"><span class="comment">##</span></span><br><span class="line"></span><br><span class="line">  <span class="comment"># 证书设置</span></span><br><span class="line">  ssl_certificate      /etc/letsencrypt/live/yooooex.com/fullchain.pem;</span><br><span class="line">  ssl_certificate_key  /etc/letsencrypt/live/yooooex.com/privkey.pem;</span><br><span class="line">  ssl_session_timeout 1d;</span><br><span class="line">  ssl_session_cache shared:SSL:50m;</span><br><span class="line">  ssl_session_tickets off;</span><br><span class="line">  ssl_trusted_certificate /etc/letsencrypt/live/yooooex.com/root_CA_cert_plus_intermediates;</span><br><span class="line"> </span><br><span class="line">  <span class="comment"># 协议选择和加密方法</span></span><br><span class="line">  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;</span><br><span class="line">  ssl_ciphers   EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;</span><br><span class="line">  ssl_prefer_server_ciphers on;</span><br><span class="line"></span><br><span class="line">  <span class="comment"># Http 头字段</span></span><br><span class="line">  <span class="comment"># 开启HSTS</span></span><br><span class="line">  add_header Strict-Transport-Security <span class="string">"max-age=15768000; includeSubDomains; preload"</span>;  </span><br><span class="line">  <span class="comment"># 不允许 iFrame 嵌套</span></span><br><span class="line">  add_header X-Frame-Options SAMEORIGIN;</span><br><span class="line">  <span class="comment"># 禁止内容类型嗅探</span></span><br><span class="line">  add_header X-Content-Type-Options: nosniff;</span><br><span class="line">  <span class="comment"># XSS</span></span><br><span class="line">  <span class="comment"># add_header X-XSS-Protection: 1; mode=block;</span></span><br><span class="line">  <span class="comment"># 指数密钥交换,推荐使用2048位</span></span><br><span class="line">  <span class="comment"># 生成:sudo openssl dhparam -out /path/dhparam.pem 2048</span></span><br><span class="line">  ssl_dhparam /root/nginx/ssl/dhparam.pem;</span><br><span class="line">  </span><br><span class="line">  <span class="comment"># OCSP Stapling ---</span></span><br><span class="line">  <span class="comment"># fetch OCSP records from URL in ssl_certificate and cache them</span></span><br><span class="line">  ssl_stapling on;</span><br><span class="line">  ssl_stapling_verify on;</span><br><span class="line">  </span><br><span class="line">  resolver lv3ns1.ffdns.net lv3ns2.ffdns.net;</span><br><span class="line"></span><br><span class="line">  <span class="comment"># 日志</span></span><br><span class="line">  access_log /root/nginx/logs/yooooex.com.access.log;</span><br><span class="line">  error_log /root/nginx/logs/yooooex.com.error.log;</span><br><span class="line">  root /var/www/blog/static;</span><br><span class="line"></span><br><span class="line">index index.html index.htm;</span><br><span class="line"></span><br><span class="line">  location / &#123;</span><br><span class="line">  <span class="comment"># First attempt to serve request as file, then</span></span><br><span class="line">  <span class="comment"># as directory, then fall back to displaying a 404.</span></span><br><span class="line">    try_files <span class="variable">$uri</span> <span class="variable">$uri</span>/ =404;</span><br><span class="line">  &#125;</span><br><span class="line"> </span><br><span class="line">  location ~ /\. &#123;</span><br><span class="line">    <span class="built_in">return</span> 403;</span><br><span class="line">  &#125;</span><br><span class="line"> </span><br><span class="line">  location /imgs/ &#123;</span><br><span class="line">    <span class="built_in">alias</span> /var/www/blog/imgs/;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><p>当配置完成后,可以到 <a href="https://www.ssllabs.com/ssltest/" target="_blank" rel="noopener">Qualy’s SSL LABS</a> 来测试配置.<br>如果配置没出现什么问题的话,你的网站测试应该是像我这样的:</p><p><img data-src="https://yooooex.com/imgs/2016/06/15/ssl.png" alt="ssl"></p><h3 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h3><ul><li><code>OCSP Stapling</code> 未启用,可能与我使用的证书有关.</li><li><code>Public Key Pinning</code> (HPKP) 未配置,找个时间看看.</li></ul><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      &lt;!-- build time:Thu Mar 11 2021 17:30:15 GMT+0800 (GMT+08:00) --&gt;&lt;h3 id=&quot;编译&quot;&gt;&lt;a href=&quot;#编译&quot; class=&quot;headerlink&quot; title=&quot;编译&quot;&gt;&lt;/a&gt;编译&lt;/h3&gt;&lt;h4 id=&quot;准备工作&quot;&gt;&lt;a href=&quot;#准备工作&quot; class=&quot;headerlink&quot; title=&quot;准备工作&quot;&gt;&lt;/a&gt;准备工作&lt;/h4&gt;&lt;p&gt;为了能同时支持 &lt;code&gt;HTTP/2&lt;/code&gt; 和 &lt;code&gt;Spdy&lt;/code&gt; ,所以我使用了 &lt;code&gt;Nginx&lt;/code&gt; 1.9.7 + Cloudflare 的补丁.&lt;br&gt;我使用的系统是 &lt;code&gt;Debian&lt;/code&gt; 8.0,请根据自己的系统调整相应的包管理器命令.&lt;/p&gt;&lt;p&gt;首先安装编译要用到的依赖库和工具.&lt;/p&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;sudo apt-get install build-essential libpcre3 libpcre3-dev zlib1g-dev unzip git&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;然后获取 &lt;code&gt;OpenSSL&lt;/code&gt; , Cloudflare 的补丁和 Certificate Transparency 补丁.&lt;/p&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;wget -O openssl.zip -c https://github.com/openssl/openssl/archive/OpenSSL_1_0_2h.zip&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;unzip openssl.zip &amp;amp;&amp;amp; mv openssl-OpenSSL_1_0_2h/ openssl&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;wget -O nginx-ct.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/v1.2.0.zip&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;unzip nginx-ct.zip&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;git &lt;span class=&quot;built_in&quot;&gt;clone&lt;/span&gt; https://github.com/cloudflare/sslconfig&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;cd&lt;/span&gt; openssl&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;patch -p1 &amp;lt; ../sslconfig/patches/openssl__chacha20_poly1305_draft_and_rfc_ossl102g.patch&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;cd&lt;/span&gt; ../&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h4 id=&quot;开始编译&quot;&gt;&lt;a href=&quot;#开始编译&quot; class=&quot;headerlink&quot; title=&quot;开始编译&quot;&gt;&lt;/a&gt;开始编译&lt;/h4&gt;&lt;p&gt;默认安装到 /usr/local/nginx ,如果想更改路径可以在编译时指定 &lt;code&gt;--prefix&lt;/code&gt; 参数.&lt;/p&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;wget -c http://nginx.org/download/nginx-1.9.7.tar.gz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;tar zxf nginx-1.9.7.tar.gz&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;cd&lt;/span&gt; nginx-1.9.7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;patch -1 &amp;lt; ../sslconfig/patches/nginx__http2_spdy.patch&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;./configure --add-module=../nginx-ct-1.2.0 --with-openssl=../openssl --with-http_v2_module --with-http_spdy_module --with-http_ssl_module --with-ipv6 --with-http_gzip_static_module&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;make&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;sudo make install&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h3 id=&quot;配置&quot;&gt;&lt;a href=&quot;#配置&quot; class=&quot;headerlink&quot; title=&quot;配置&quot;&gt;&lt;/a&gt;配置&lt;/h3&gt;&lt;h4 id=&quot;创建管理脚本&quot;&gt;&lt;a href=&quot;#创建管理脚本&quot; class=&quot;headerlink&quot; title=&quot;创建管理脚本&quot;&gt;&lt;/a&gt;创建管理脚本&lt;/h4&gt;&lt;p&gt;为了方便管理 &lt;code&gt;Nginx&lt;/code&gt; ,我使用脚本来对 &lt;code&gt;Nginx&lt;/code&gt; 进行操作.&lt;/p&gt;
    
    </summary>
    
    
      <category term="日志" scheme="https://yooooex.com/categories/%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="证书" scheme="https://yooooex.com/tags/%E8%AF%81%E4%B9%A6/"/>
    
      <category term="Hexo" scheme="https://yooooex.com/tags/Hexo/"/>
    
      <category term="Nginx" scheme="https://yooooex.com/tags/Nginx/"/>
    
      <category term="HTTPS" scheme="https://yooooex.com/tags/HTTPS/"/>
    
      <category term="SPDY" scheme="https://yooooex.com/tags/SPDY/"/>
    
      <category term="HTTP/2" scheme="https://yooooex.com/tags/HTTP-2/"/>
    
  </entry>
  
</feed>
