<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>工具使用 on 月盾的博客</title>
    <link>https://blog.hopefly.top/categories/%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8/</link>
    <description>Recent content in 工具使用 on 月盾的博客</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sat, 01 Jul 2023 18:13:43 +0800</lastBuildDate>
    <atom:link href="https://blog.hopefly.top/categories/%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>阿里云oss私有桶图片处理</title>
      <link>https://blog.hopefly.top/2023/07/ali-oss-process/</link>
      <pubDate>Sat, 01 Jul 2023 18:13:43 +0800</pubDate>
      <guid>https://blog.hopefly.top/2023/07/ali-oss-process/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;针对OSS内存储的图片文件（Object），您可以在GetObject请求中携带图片处理参数对图片文件进行处理。例如添加图片水印、转换格式等。详情见：&lt;a href=&#34;https://help.aliyun.com/document_detail/183902.html?spm=a2c4g.44686.0.0.3c532793kTBeVm&#34;&gt;官方文档&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;对于允许公共读写的文件可以直接在图片URL后面拼接参数的方式进行图片处理，格式：https://bucketname.endpoint/objectname?x-oss-process=image/action,parame_value&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;对于不允许匿名访问的私有图片文件，不支持通过文件URL直接添加参数的方式处理图片，您需要通过SDK的方式将图片处理操作加入签名URL中。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;重要：&lt;/strong&gt; &lt;em&gt;通过文件URL访问图片时，默认是下载行为。如需确保通过文件URL访问图片时是预览行为，您需要绑定自定义域名并添加CNAME记录。具体操作，请参见绑定&lt;a href=&#34;https://help.aliyun.com/document_detail/31902.html?spm=a2c4g.44686.0.0.4e5c24cby8yy9K#concept-ozw-m2r-5fb&#34;&gt;自定义域名&lt;/a&gt;。&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;所以，私有桶的图片是不能直接添加参数处理，否则会返回错误信息：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;SignatureDoesNotMatch&lt;br&gt;&#xA;The request signature we calculated does not match the signature you provided. Check your key and signing method.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;SDK处理方法，以go版本为例：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github.com/aliyun/aliyun-oss-go-sdk/oss&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;HandleError&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error:&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Exit&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 创建OSSClient实例。&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// yourEndpoint填写Bucket对应的Endpoint，以华东1（杭州）为例，填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;client&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;oss&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;New&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;yourEndpoint&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;yourAccessKeyId&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;yourAccessKeySecret&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;HandleError&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 指定图片所在Bucket的名称，例如examplebucket。&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;bucketName&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;examplebucket&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;bucket&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;client&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Bucket&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;bucketName&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;HandleError&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 指定图片名称。如果图片不在Bucket根目录，需携带文件完整路径，例如exampledir/example.jpg。&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;ossImageName&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;exampledir/example.jpg&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 生成带签名的URL，并指定过期时间为600s。&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;signedURL&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;bucket&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SignURL&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ossImageName&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;oss&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;HTTPGet&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;oss&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Process&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;image/format,png&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;HandleError&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;signedURL&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中，&lt;code&gt;yourAccessKeyId&lt;/code&gt;,&lt;code&gt;yourAccessKeySecret&lt;/code&gt;的来源参考该文，&lt;a href=&#34;https://blog.csdn.net/iteye_19045/article/details/106721450&#34;&gt;阿里云OSS上传报错: You have no right to access this object because of bucket acl&lt;/a&gt;。创建完用户需要创建AccessKeyId，接着就可以创建yourAccessKeyId和AccessKeySecret。&#xA;最后会生成完整的图片链接，注意，如果发现链接中多出了bucket，需要排查yourEndpoint是否已经加上了bucket，需要删除掉。&lt;/p&gt;</description>
    </item>
    <item>
      <title>jenkins代替品</title>
      <link>https://blog.hopefly.top/2023/05/ci-cd/</link>
      <pubDate>Wed, 10 May 2023 18:55:23 +0800</pubDate>
      <guid>https://blog.hopefly.top/2023/05/ci-cd/</guid>
      <description>&lt;p&gt;如果你打算搭建一套发布系统，你可能会考虑jenkins，或者其他。&#xA;我要介绍的则是一些现成的，使用更简单的工具。没用特殊环境要求的情况下则完全可以代替jenkins。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;GitHub Actions&lt;/li&gt;&#xA;&lt;li&gt;gitlab ci&lt;/li&gt;&#xA;&lt;li&gt;阿里云流水线&lt;/li&gt;&#xA;&lt;li&gt;coding持续部署&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;上面只是列举了四类，实际上你会发现市面上的云服务商和代码仓库都提供了类似的工具，虽然有些是收费的，但是也有不少免费的，对于个人来说其实大多数都是够用了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>chrome开发者工具显示接口完整路径</title>
      <link>https://blog.hopefly.top/2022/02/chrome-devtool-show-all-path/</link>
      <pubDate>Fri, 18 Feb 2022 16:23:26 +0800</pubDate>
      <guid>https://blog.hopefly.top/2022/02/chrome-devtool-show-all-path/</guid>
      <description>&lt;p&gt;chrome浏览器的开发者工具是前端开发必不可少的工具，其中接口查看是最常用的功能之一。默认情况下显示如下：&#xA;&lt;img src=&#34;https://qn-img.hopefly.top/2a067be4926308c85147f1b39b8ce549&#34; alt=&#34;chrome开发者工具&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;主要是红框内的接口显示只有很短的名称，并没有完整的显示出整个接口，这对于一些最后名称一样的接口就不能知晓是哪个接口了，只能点击查看详情。我们希望的当然是能够显示完整的接口，实际上也是能做到的。&lt;/p&gt;&#xA;&lt;p&gt;在名称栏上右击：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/3a5fd9c34183471f3b5cafb1575c06c4&#34; alt=&#34;chrome开发者工具&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;可以显示很多选项，其中路径和网址就是我们先要的，点击以后就可以显示完整的接口路径了。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/de31aa9c16b9fd3c54e1df44e1aca43f&#34; alt=&#34;chrome开发者工具&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>postman header中自动添加cookie</title>
      <link>https://blog.hopefly.top/2021/11/postman-auto-add-cookie/</link>
      <pubDate>Mon, 08 Nov 2021 14:31:17 +0800</pubDate>
      <guid>https://blog.hopefly.top/2021/11/postman-auto-add-cookie/</guid>
      <description>&lt;p&gt;使用postman进行接口测试时，经常需要使用到cookie参数。我们会先调用登陆接口，得到sessionid，然后使用sessionID来调用其他需要登陆的接口。&#xA;但是有些情况下，cookie不会自动添加到header中，总是需要手动添加cookie。或许又发现有的接口却能自动添加上cookie，为什么会区别对待呢？&#xA;其实这是postman根据登陆接口返回的cookie来操作的，如果cookie的path指定来某个路径，那么所有在这个路径下的接口都会自动加上cookie。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Chrome插件hook Ajax</title>
      <link>https://blog.hopefly.top/2021/07/chrome-extensions-hook-ajax/</link>
      <pubDate>Sat, 10 Jul 2021 20:15:08 +0800</pubDate>
      <guid>https://blog.hopefly.top/2021/07/chrome-extensions-hook-ajax/</guid>
      <description>&lt;h3 id=&#34;如何hook-ajax请求&#34;&gt;如何Hook Ajax请求&lt;/h3&gt;&#xA;&lt;p&gt;现在很多网站都使用Ajax作为数据接口，这样其实也方便爬虫爬取数据，但是，如果站点对IP，访问频率做&#xA;了限制，或者网站定位就是搜索类，无法遍历完所有页面，或者是数据实时变化，无法预期的。这样就可能需要&#xA;直接在浏览器中模拟人的行为，对于这样的网站(使用Ajax作数据接口，有一定防范措施)&#xA;，如果我们可以通过hook得到Ajax请求，就可以搞定它的数据了。&lt;/p&gt;&#xA;&lt;h3 id=&#34;单页面web应用&#34;&gt;单页面Web应用&lt;/h3&gt;&#xA;&lt;p&gt;对于单页面的Web应用，在console中使用如下代码，就能在浏览器进行Ajax请求时候，得到返回内容，&#xA;然后在post给存储接口就好了:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;origOpen&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;XMLHttpRequest&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;prototype&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;open&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;XMLHttpRequest&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;prototype&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;open&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// console.log(&amp;#39;request started!&amp;#39;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;addEventListener&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;load&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;console&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;responseText&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// 得到Ajax的返回内容&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;origOpen&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;apply&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;arguments&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;比如百度图片:&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/e11ad5848d47af4db195906e3e7e0ff9&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;我们可以看到请求图片的路径，这段代码 直接使用了一个匿名函数，重写了Ajax请求的open方法，给load事件加上一个事件监听器，从而把内容得到:&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/7a2805ce46aa176227952ba13c63c49b&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;对于单页面的Web应用，基本可以满足需求，但是如果翻页的话，每次翻页上一页的代码就失效了，&#xA;不可能每页都把这段代码复制进console中，还是需要使用类似Chrome插件的方式才能实现。&lt;/p&gt;&#xA;&lt;h3 id=&#34;翻页web应用&#34;&gt;翻页Web应用&lt;/h3&gt;&#xA;&lt;p&gt;有了上面的代码，如果我们把它直接丢到Chrome插件的JS文件里面(官方叫Content Scripts)，发现是无法执行的，XMLHttpRequest.prototype.open 还是浏览器自身的代码。&lt;/p&gt;&#xA;&lt;p&gt;这样看来，就无法实现自动翻页，自动获取ajax请求内容了。&lt;/p&gt;&#xA;&lt;p&gt;Chrome官方说法如下:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Content scripts execute in a special environment called an isolated world.&#xA;They have access to the DOM of the page they are injected into, but not to any&#xA;JavaScript variables or functions created by the page. It looks to each&#xA;content script as if there is no other JavaScript executing on the page it is&#xA;running on. The same is true in reverse: JavaScript running on the page cannot&#xA;call any functions or access any variables defined by content scripts.&lt;/p&gt;</description>
    </item>
    <item>
      <title>七牛在线管理图片预览chrome插件</title>
      <link>https://blog.hopefly.top/2021/07/qiuniu-image-preivew/</link>
      <pubDate>Tue, 06 Jul 2021 19:32:15 +0800</pubDate>
      <guid>https://blog.hopefly.top/2021/07/qiuniu-image-preivew/</guid>
      <description>&lt;p&gt;七牛云图片存储有10G的免费额度，对于个人来说足够使用了。使用七牛图片存储涉及到图片上传，查看，管理的问题。为了能提高使用效率，我们可以利用好一些工具。&lt;/p&gt;&#xA;&lt;h3 id=&#34;vscode插件上传图片到七牛&#34;&gt;vscode插件上传图片到七牛&lt;/h3&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/0965f9bb7471b1d4a9b728c18a20e061&#34; alt=&#34;vscode插件上传图片到七牛&#34; title=&#34;vscode插件上传图片到七牛&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;vsocode扩展市场有很多上传到七牛的插件，大家可以根据需要自己选择。&lt;!-- raw HTML omitted --&gt;&lt;/p&gt;&#xA;&lt;p&gt;上传的图片多了以后，有时需要找一些已经上传的图片来使用，目前我所知道的方法还仅限于登录的七牛后台上查看。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/8e7ce912394747e8e72c8972d458be9a&#34; alt=&#34;七牛在线管理图片预览chrome插件&#34; title=&#34;七牛在线管理图片预览chrome插件&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;可以看到，七牛的管理后台做的不能说很差，可以说是很气人。要预览图片必须点击“详情”，当你关掉预览窗口时却不知道查看的是哪张图片，也没有个高亮聚焦。而且也没有时间排序，只有名称排序，真的是很难用。&lt;/p&gt;&#xA;&lt;p&gt;为了能够直观的看到图片，决定开发一款chrome插件，将图片直接显示出来，而不用再点击查看。&lt;/p&gt;&#xA;&lt;p&gt;关于chrome插件开发的细节本文暂不细说，直接上代码。&lt;/p&gt;&#xA;&lt;h3 id=&#34;代码展示&#34;&gt;代码展示&lt;/h3&gt;&#xA;&lt;p&gt;&lt;strong&gt;manifest.json&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;manifest_version&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;chome-plugin&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0.0.1&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;chrome示例插件&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;icons&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;16&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;images/icon-16x16.png&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;48&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;images/icon-48x48.png&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;128&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;images/icon-128x128.png&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;page_action&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;default_icon&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;48&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;images/icon-48x48.png&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;default_popup&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;html/popup.html&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;default_title&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello yuedun&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;author&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;yuedun&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;background&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scripts/jquery.min.js&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scripts/background.js&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;devtools_page&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;html/devtools-page.html&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;content_scripts&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;js&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scripts/jquery.min.js&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;scripts/content.js&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;css&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;styles/yuedun-insert.css&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;matches&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://portal.qiniu.com/kodo/bucket/resource?bucketName=*&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;run_at&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;document_start&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;permissions&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cookies&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;*://*/*&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;webRequest&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;homepage_url&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://www.hopefly.top&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;background.js&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>vscode正则查找替换</title>
      <link>https://blog.hopefly.top/blogdetail/5e5a3fb45bd8165f28d21307/</link>
      <pubDate>Mon, 14 Jun 2021 10:40:52 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5e5a3fb45bd8165f28d21307/</guid>
      <description>&lt;h3 id=&#34;查找某一类型字符串&#34;&gt;查找某一类型字符串：&lt;/h3&gt;&#xA;&lt;p&gt;正则表达式&lt;code&gt;onclick=.*&amp;quot;&lt;/code&gt;&#xA;会查找到所有：&#xA;&lt;code&gt;onclick=&amp;quot;_msq.push([&#39;trackEvent&#39;, &#39;210074305d6b0409-09c7759e04e98528&#39;, &#39;&#39;pcpid&#39;, &#39;&#39;]);&amp;quot;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;onclick=&lt;/code&gt;是固定一样的字符，&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;.&lt;/code&gt;代表除\r和\n之外的任意字符，等价于[^\r\n]&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;*&lt;/code&gt;代表匹配前面的模式 0或多次 {0,}&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;&amp;quot;&lt;/code&gt;这是字符串最后一个字符&lt;/p&gt;&#xA;&lt;p&gt;在vscode中的效果如下：&#xA;&lt;img src=&#34;https://qn-img.hopefly.top/vscode%E6%AD%A3%E5%88%99.png&#34; alt=&#34;vscode正则查找替换&#34; title=&#34;vscode正则查找替换&#34;&gt;&#xA;至于要替换成什么就看自己需求了，如果要给选中的字符串包裹字符串则需要修改成这样：&lt;/p&gt;&#xA;&lt;h3 id=&#34;查找替换&#34;&gt;查找替换&lt;/h3&gt;&#xA;&lt;p&gt;查找：&lt;code&gt;(onclick=.*&amp;quot;)&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;替换：&lt;code&gt;aaa($1)&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;结果：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/%E6%AD%A3%E5%88%99%E6%9B%BF%E6%8D%A2.png&#34; alt=&#34;vscode正则查找替换&#34; title=&#34;vscode正则查找替换&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;替换字符串两头保留中间&#34;&gt;替换字符串两头，保留中间&lt;/h3&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/vscodereplace.jpg&#34; alt=&#34;vscode正则查找替换&#34; title=&#34;vscode正则查找替换&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;两部分文字交换位置&#34;&gt;两部分文字交换位置&lt;/h3&gt;&#xA;&lt;p&gt;相同模式的文字交换位置。&lt;/p&gt;&#xA;&lt;p&gt;查找：&lt;code&gt;(\(\d{4}-\d{1,2}-\d{2}\)) (\[.*\))&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;替换：&lt;code&gt;$2 $1&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;结果：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/regular.gif&#34; alt=&#34;vscode正则查找替换&#34; title=&#34;vscode正则查找替换&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;vscode中一对括号&lt;code&gt;()&lt;/code&gt;代表一个变量。&lt;/p&gt;&#xA;&lt;p&gt;第一组正则 &lt;code&gt;(\(\d{4}-\d{1,2}-\d{2}\))&lt;/code&gt; 对应 &lt;code&gt;$1&lt;/code&gt;，&lt;/p&gt;&#xA;&lt;p&gt;第二组正则 &lt;code&gt;(\[.*\))&lt;/code&gt;对应 &lt;code&gt;$2&lt;/code&gt;，以此类推。&lt;/p&gt;&#xA;&lt;p&gt;所以，可以查找多组数据，在替换部分将两个对应变量交换位置即可。&lt;/p&gt;</description>
    </item>
    <item>
      <title>typescript不检查node_moduls</title>
      <link>https://blog.hopefly.top/blogdetail/60b48e405caa4b4dc69e3abf/</link>
      <pubDate>Fri, 11 Jun 2021 14:16:17 +0800</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/60b48e405caa4b4dc69e3abf/</guid>
      <description>&lt;p&gt;tsconfig.json 中 exclude node_modules，但 tsc 还是报错。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node_modules/connect-mongo/src/types.d.ts:113:66 - error TS2694: Namespace &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;global.Express&amp;#39;&lt;/span&gt; has no exported member &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;SessionData&amp;#39;&lt;/span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;113&lt;/span&gt;         get: &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;sid: string, callback: &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;err: any, session: Express.SessionData | null&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; void&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; void;                                                                     ~~~~~~~~~~~&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node_modules/connect-mongo/src/types.d.ts:114:45 - error TS2694: Namespace &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;global.Express&amp;#39;&lt;/span&gt; has no exported member &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;SessionData&amp;#39;&lt;/span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;114&lt;/span&gt;         set: &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;sid: string, session: Express.SessionData, callback?: &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;err: any&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; void&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; void;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                ~~~~~~~~~~~&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;node_modules/connect-mongo/src/types.d.ts:118:47 - error TS2694: Namespace &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;global.Express&amp;#39;&lt;/span&gt; has no exported member &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;SessionData&amp;#39;&lt;/span&gt;.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;118&lt;/span&gt;         touch: &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;sid: string, session: Express.SessionData, callback?: &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;err: any&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; void&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;gt; void;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;另一种解决方案：&lt;/p&gt;</description>
    </item>
    <item>
      <title>朱雀发布系统支持scp（rsync）发布</title>
      <link>https://blog.hopefly.top/blogdetail/60950c9ee76f307341586548/</link>
      <pubDate>Fri, 11 Jun 2021 14:16:17 +0800</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/60950c9ee76f307341586548/</guid>
      <description>&lt;p&gt;去年花了三天时间开发了一个简易版的&lt;a href=&#34;https://blog.hopefly.top/blogdetail/5f41c9d65edb9b37630b0d46&#34;&gt;nodejs发布系统&lt;/a&gt;，它是基于pm2自带的&lt;a href=&#34;https://pm2.keymetrics.io/docs/usage/deployment/&#34;&gt;deploy&lt;/a&gt;机制开发的，主要原理就是在两台装有pm2的机器直接通信，并执行相应的命令。再往简单了说就是在发布机上远程执行命令，而朱雀发布系统提供了一个图形界面而已。&lt;/p&gt;&#xA;&lt;p&gt;当时把这个系统定位为nodejs专用发布系统，因为它依赖了pm2，而pm2则是nodejs专用的进程管理工具，其他语言用不到。这个系统的上线也算是解决了我司一直以来没有合适的nodejs发布系统的空缺。&lt;/p&gt;&#xA;&lt;p&gt;经过9个月的使用，也算比较稳定。但是也存在问题，最大的问题是部署应用方面比较繁琐。&lt;/p&gt;&#xA;&lt;p&gt;基本流程如下：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;发布机和应用服务器设置ssh通信配置。&lt;/li&gt;&#xA;&lt;li&gt;应用服务器安装git（有自带，但是版本太旧）。&lt;/li&gt;&#xA;&lt;li&gt;配置git用户名，邮箱。&lt;/li&gt;&#xA;&lt;li&gt;生成ssh公钥。&lt;/li&gt;&#xA;&lt;li&gt;把应用服务器的公钥配置到git代码服务器上。以便能拉代码。&lt;/li&gt;&#xA;&lt;li&gt;发布机远程执行git pull来代码操作，各应用服务把代码拉取下来。&lt;/li&gt;&#xA;&lt;li&gt;执行编译打包操作。&lt;/li&gt;&#xA;&lt;li&gt;执行重启服务操作。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;部署一次系统还是比较麻烦的，如果应用服务器有多台，可能还要重复这样的操作多次，实在比较麻烦。&lt;/p&gt;&#xA;&lt;p&gt;使用scp同步代码的方式会比较简单一些，但是像nodejs这样的项目，node_module占了很大比重，如果每次都打包的话会拖慢同步速度，而scp又不具备排除文件夹的能力。&lt;/p&gt;&#xA;&lt;p&gt;最后找到了&lt;strong&gt;rsync&lt;/strong&gt;命令可以满足需求。然后就是基于rsync实现了一版。不用再依赖pm2，应用服务器也不用强制使用git了。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/zhuque1.jpg&#34; alt=&#34;朱雀发布系统&#34; title=&#34;朱雀发布系统&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;朱雀和jenkins对比如何&#34;&gt;朱雀和Jenkins对比如何？&lt;/h3&gt;&#xA;&lt;p&gt;要说Jenkins那绝对是持续集成领域的老大哥，自然是功能强大。但是每个团队和产品有其特殊性，Jenkins并不完全适用。而朱雀也有其优势。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;朱雀本身部署简单，使用go开发，不依赖运行时，无需安装，开箱即用。&lt;/li&gt;&#xA;&lt;li&gt;目前支持和测试过的数据库有sqlite3（目前用的，不需要繁琐的安装过程）和mysql。&lt;/li&gt;&#xA;&lt;li&gt;配置简单。&lt;/li&gt;&#xA;&lt;li&gt;部署发布一键完成，不需要单独的部署过程。&lt;/li&gt;&#xA;&lt;li&gt;并行发布。&lt;/li&gt;&#xA;&lt;li&gt;审批，通知，权限。&lt;/li&gt;&#xA;&lt;li&gt;开源，可定制开发。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;项目地址：&lt;a href=&#34;https://github.com/yuedun/zhuque&#34;&gt;朱雀发布系统&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>easy-monitor qps监控</title>
      <link>https://blog.hopefly.top/blogdetail/60861bef54277a10496a54b6/</link>
      <pubDate>Mon, 26 Apr 2021 01:48:31 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/60861bef54277a10496a54b6/</guid>
      <description>&lt;p&gt;Easy-Monitor是一款轻量级的Node性能监控工具，仅仅需要项目入口 require 一次，就可以非常便捷地展示出进程的状态细节。&lt;/p&gt;&#xA;&lt;p&gt;Easy-Monitor主要提供以下的功能：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;找出执行时长耗费最久的5个或者更多的函数&lt;/li&gt;&#xA;&lt;li&gt;找出那些执行时间超出预期的函数&lt;/li&gt;&#xA;&lt;li&gt;找出v8引擎无法优化的函数&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Easy-Monitor的特点：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;轻量级：非传统C/S物理分离模式，require 后即可使用，没有额外的监控server/agent部署成本。&lt;/li&gt;&#xA;&lt;li&gt;运行时：针对的是运行时的函数性能以及内存细节进行处理展示，可用于线上生产环境项目。&lt;/li&gt;&#xA;&lt;li&gt;无状态：永远展示的是开发者访问时的业务进程状态&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;关于监控qps，作者在文档中并没有提到&lt;strong&gt;qps&lt;/strong&gt;这样的关键字，很多人也不知道怎么监控qps。&#xA;不过在监控界面中有这样的指标数据：&#xA;&lt;img src=&#34;https://qn-img.hopefly.top/easy-monitor1.jpg&#34; alt=&#34;easy-monitor-qps&#34; title=&#34;easy-monitor-qps&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;所以我从源码入手，找到了该数据指标的源头是这样的：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;osCpu&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; Number((&lt;span style=&#34;color:#a6e22e&#34;&gt;used_cpu&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;toFixed&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;osMem&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; Number((&lt;span style=&#34;color:#a6e22e&#34;&gt;used_memory_percent&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;toFixed&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;maxDisk&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;max_disk_usage&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;disks&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;disks_json&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;load1&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; Number(&lt;span style=&#34;color:#a6e22e&#34;&gt;load1&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;toFixed&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;load5&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; Number(&lt;span style=&#34;color:#a6e22e&#34;&gt;load5&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;toFixed&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;load15&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; Number(&lt;span style=&#34;color:#a6e22e&#34;&gt;load15&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;toFixed&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;nodeCount&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;node_count&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;scavengeTotal&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;total_scavange_duration&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;scavengeAverage&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scavange_duration_last_record&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;marksweepTotal&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;total_marksweep_duration&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;marksweepAverage&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;marksweep_duration_last_record&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;qps&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; Number((&lt;span style=&#34;color:#a6e22e&#34;&gt;http_response_sent&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;60&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;toFixed&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;rtExpired&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;http_patch_timeout&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;rtAverage&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;http_rt&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这是接口返回的数据，包含了qps数据，那么qps实际上就是&lt;strong&gt;http_response_sent&lt;/strong&gt;，所以监控中就可以这样设置qps了：&#xA;&lt;code&gt;@http_response_sent/60 &amp;gt; 10&lt;/code&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>firefox火狐新标签中打开书签</title>
      <link>https://blog.hopefly.top/blogdetail/60191322ebffed4856026fc7/</link>
      <pubDate>Tue, 02 Feb 2021 08:53:54 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/60191322ebffed4856026fc7/</guid>
      <description>&lt;p&gt;火狐浏览器新建标签总是在当前打开标签之后，而不是在最后一个标签后新建。&#xA;1.about:config&#xA;2.browser.tabs.insertAfterCurrent设为false。&lt;/p&gt;&#xA;&lt;p&gt;新标签中打开书签 browser.tabs.loadBookmarksInTabs设置true。&lt;/p&gt;&#xA;&lt;p&gt;新标签中打开搜索 browser.search.openintab设置true.&lt;/p&gt;</description>
    </item>
    <item>
      <title>vscode远程开发应用场景</title>
      <link>https://blog.hopefly.top/blogdetail/5fb757025edb9b37630b808b/</link>
      <pubDate>Fri, 20 Nov 2020 05:41:22 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5fb757025edb9b37630b808b/</guid>
      <description>&lt;h1 id=&#34;vscode远程开发&#34;&gt;vscode远程开发&lt;/h1&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/vscode-remote.jpg&#34; alt=&#34;vscode-remote&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;vscode远程开发功能在2019年5月份发布，到现在已经有一年半的时间了，但是周围的人很少提及此功能，并不是没有人使用vscode，而是对此没有强烈需求。&lt;/p&gt;&#xA;&lt;p&gt;那么远程开发还有什么用呢？下面我来举些列子。&lt;/p&gt;&#xA;&lt;p&gt;关于vscode远程环境搭建本文不重复说明，网上有大量教程，大家只需要安装&lt;strong&gt;remote  development&lt;/strong&gt;插件基本都可以使用起来。&lt;/p&gt;&#xA;&lt;p&gt;远程开发，顾名思义就是连接远端服务器进行开发，这样的场景确实不是很常见，但是有时候却是很有用，能够解决燃眉之急。&lt;/p&gt;&#xA;&lt;h2 id=&#34;本地主机性能差&#34;&gt;本地主机性能差&lt;/h2&gt;&#xA;&lt;p&gt;有一些大型项目对电脑的要求也较高，编译耗时，跑起来吃内存，我们的常规解决方案是升级电脑内存，升级硬盘，总之就是换高配电脑，如果是换一台也倒罢了，如果是一个团队都要使用更高配的电脑，那这样的成本还是挺高的。&lt;/p&gt;&#xA;&lt;p&gt;此时利用远程开发功能，所有人共用一台8核16G服务器就足够了。能够解决编译耗时，吃内存等问题。&lt;/p&gt;&#xA;&lt;h2 id=&#34;开发环境统一&#34;&gt;开发环境统一&lt;/h2&gt;&#xA;&lt;p&gt;现代大多数应用服务是跑在Linux上的，而开发环境则有Windows，Mac，有些服务在开发环境下无法顺利跑起来，这种情况就可以利用远程开发，不再需要虚拟机或WSL了，在Linux上部署应用，在Windows上开发。&lt;/p&gt;&#xA;&lt;h2 id=&#34;远程调试&#34;&gt;远程调试&lt;/h2&gt;&#xA;&lt;p&gt;远程调试我想很多人都有过这样的需求，但是却从来没有过真正的实践，原因是太难搞了。线上出问题，本地无法复现，真希望能够直接调试线上代码，但是无奈无法实现。现在好了，有了vscode远程开发，调试就变得容易了。&lt;/p&gt;&#xA;&lt;h2 id=&#34;远程编辑文件&#34;&gt;远程编辑文件&lt;/h2&gt;&#xA;&lt;p&gt;在Linux上编辑文件时使用的vim编辑器对大多数人来说有些头大，能在vscode中编辑文本就舒服多了。只需要使用vscode连接远程服务可以很方便打开文件并编辑。&lt;/p&gt;&#xA;&lt;h2 id=&#34;在家临时远程开发&#34;&gt;在家临时远程开发&lt;/h2&gt;&#xA;&lt;p&gt;作为开发的我们，每天下班都要背着电脑回家，主要原因就是防止线上有问题，能够打开电脑调试代码。一般来说并不是家里没有电脑，而是没有能够正常运行的开发环境。&lt;/p&gt;&#xA;&lt;p&gt;而远程开发正好能解决该问题，我们需要的仅仅是一台装有vscode的普通电脑即可，不需要再操心开发环境，各种SDK，C++，Python，Nodejs等等八辈子不用的软件装了一大堆，还需要经常更新才行。&lt;/p&gt;&#xA;&lt;h2 id=&#34;节省成本&#34;&gt;节省成本&lt;/h2&gt;&#xA;&lt;p&gt;大多数开发人员是不需要经常开发大型项目和远程调试代码的，但是不是完全没有，这样就需要为了不时之需而配置笔记本电脑，而笔记本电脑一般相对台式机是又贵性能还低，公司要为了应对偶发情况而给开发人员配备笔记本电脑，会造成资源浪费，成本升高。&lt;/p&gt;&#xA;&lt;p&gt;如果有了远程开发环境，则能应对临时性工作，大大降低成本。&lt;/p&gt;&#xA;&lt;h1 id=&#34;用ipad写代码&#34;&gt;用iPad写代码&lt;/h1&gt;&#xA;&lt;p&gt;如果你觉得vscode远程开发还不够酷？那在iPad中写代码呢？&lt;/p&gt;&#xA;&lt;p&gt;vscode远程开发虽好，但还有有局限性，毕竟还是需要一台可以安装vscode的电脑，还是不能随时随地的写代码。现在我要告诉你如何在iPad中写代码！&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;code-server&lt;/strong&gt;是一个可以运行在服务器上的web项目，这下我们可以在浏览器中使用vscode了，可以在浏览器中打开vscode的，自然就可以使用iPad来写代码了。&#xA;&lt;strong&gt;Eclipse Theia&lt;/strong&gt;&#xA;&lt;a href=&#34;https://gitpod.io/#https://github.com/eclipse-theia/theia&#34;&gt;https://gitpod.io/#https://github.com/eclipse-theia/theia&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/2691965253-5e8d30a40f51d_articlex.png&#34; alt=&#34;&#34;&gt;&#xA;额，希望苹果能给我广告费！&lt;/p&gt;&#xA;&lt;p&gt;再或者使用使用codespaces也可以在线编辑代码，https://mp.weixin.qq.com/s/Eutjgbx_nofmuhU2yBGhxg&lt;/p&gt;&#xA;&lt;h2 id=&#34;最后&#34;&gt;最后&lt;/h2&gt;&#xA;&lt;p&gt;贴一篇带图的环境搭建教程&lt;a href=&#34;https://www.qikqiak.com/post/use-vscode-remote-dev-debug/&#34;&gt;真香！使用 VSCode 远程开发调试&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>通用的数据库GUI工具</title>
      <link>https://blog.hopefly.top/blogdetail/5fb32fc75edb9b37630b7a6a/</link>
      <pubDate>Tue, 17 Nov 2020 02:04:55 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5fb32fc75edb9b37630b7a6a/</guid>
      <description>&lt;p&gt;MySQL常用的客户端是Navicat，SQLyog等，本文推荐另一款通用的客户端：DBeaver&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/DBeaver.jpg&#34; alt=&#34;连接&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;DBeaver不能创建表？那是因为选错了视图。可以重新编辑链接&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/DBeaver_view.jpg&#34; alt=&#34;DBeaver视图&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>puppeteer模拟3G网络</title>
      <link>https://blog.hopefly.top/blogdetail/5faa34535edb9b37630b6e99/</link>
      <pubDate>Tue, 10 Nov 2020 06:33:55 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5faa34535edb9b37630b6e99/</guid>
      <description>&lt;p&gt;puppeteer要模拟3G，4G网络需要利用DevTools Protocol。&#xA;&lt;a href=&#34;https://chromedevtools.github.io/devtools-protocol/tot/Network/&#34;&gt;Chrome DevTools Protocol&lt;/a&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;page&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;browser&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;newPage&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 模拟3g网络&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cdp&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;page&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;target&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;createCDPSession&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cdp&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;send&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Network.emulateNetworkConditions&amp;#39;&lt;/span&gt;, {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;offline&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;downloadThroughput&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;,&lt;span style=&#34;color:#75715e&#34;&gt;//(bytes/sec) 3G最高600K/s 4G 最高10M/s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;uploadThroughput&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;,&lt;span style=&#34;color:#75715e&#34;&gt;//(bytes/sec)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;latency&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;page&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;setCacheEnabled&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;page&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;goto&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;url&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>postman使用技巧</title>
      <link>https://blog.hopefly.top/blogdetail/5fa0f8e55edb9b37630b65f7/</link>
      <pubDate>Tue, 03 Nov 2020 06:29:57 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5fa0f8e55edb9b37630b65f7/</guid>
      <description>&lt;p&gt;postman是开发人员必备的接口测试工具，虽然经常使用，但是并不会使用到所有功能，除了简单的接口测试外，它还有很多实用的功能，如果充分利用起来，能使我们的工作事半功倍。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;环境变量的使用&lt;/li&gt;&#xA;&lt;li&gt;捕获请求和cookie&lt;/li&gt;&#xA;&lt;li&gt;收藏接口与分享接口&lt;/li&gt;&#xA;&lt;li&gt;批量测试&lt;/li&gt;&#xA;&lt;li&gt;编写文档和示例&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;环境变量的使用&#34;&gt;环境变量的使用&lt;/h2&gt;&#xA;&lt;p&gt;环境变量的作用是使用切换变量的方式代替频繁的环境修改。这样我们只需保存一次测试接口就可以在不同环境下使用。&#xA;举例：&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;环境变量配置&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/env.jpg&#34; alt=&#34;环境变量配置&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;环境变量使用&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/env3.jpg&#34; alt=&#34;环境变量使用&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;环境变量切换&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/env2.jpg&#34; alt=&#34;环境变量切换&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;捕获请求和cookie&#34;&gt;捕获请求和cookie&lt;/h2&gt;&#xA;&lt;p&gt;能够直接将浏览器中的请求和cookie同步到postman，省去手动复制请求接口和cookie到postman中。&#xA;同时，对于需要登录后使用的接口，postman可以直接使用浏览器的登录状态，而不必复制cookie。&#xA;举例：&#xA;&lt;img src=&#34;https://qn-img.hopefly.top/capturerequest.gif&#34; alt=&#34;捕获请求&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;收藏接口与分享接口&#34;&gt;收藏接口与分享接口&lt;/h2&gt;&#xA;&lt;p&gt;将自己保存的接口分享与他人，直接拿来即可使用。&#xA;如果安装了Chrome插件，则可以直接的浏览器中打开链接。使用客户端需要使用import来导入。&#xA;&lt;img src=&#34;https://qn-img.hopefly.top/%E5%88%86%E4%BA%AB%E6%8E%A5%E5%8F%A3.png&#34; alt=&#34;分享接口&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;批量测试&#34;&gt;批量测试&lt;/h2&gt;&#xA;&lt;p&gt;保存的多个接口批量测试。&#xA;&lt;img src=&#34;https://qn-img.hopefly.top/batchtest.gif&#34; alt=&#34;接口批量测试&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;编写文档和示例&#34;&gt;编写文档和示例&lt;/h2&gt;&#xA;&lt;p&gt;对于团队协作很有用，接口交流利器。不仅有了请求参数，添加一个example还可以看到接口返回参数。&#xA;&lt;img src=&#34;https://qn-img.hopefly.top/document.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>nodejs专用发布系统</title>
      <link>https://blog.hopefly.top/blogdetail/5f41c9d65edb9b37630b0d46/</link>
      <pubDate>Sun, 23 Aug 2020 01:43:50 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5f41c9d65edb9b37630b0d46/</guid>
      <description>&lt;p&gt;Nodejs项目部署到服务器以后接下来做的最多的操作就是上线发布了。因为nodejs的语言特性决定了其开发效率高，发布自然就频繁，每个公司或个人都有自己的发布方式。&lt;/p&gt;&#xA;&lt;p&gt;有的公司会有严格的流程，必须通过CI/CD工具进行发布，有可能使用现成的工具，如：jenkins。有可能是自研发布系统。&lt;/p&gt;&#xA;&lt;p&gt;有的公司会通过FTP上传代码到服务器发布。&lt;/p&gt;&#xA;&lt;p&gt;有的公司使用更原始的发布方式，直接登录服务拉代码发布。&lt;/p&gt;&#xA;&lt;p&gt;不论哪种发布方式都有其优缺点，越高级的工具会有诸多限制，比如有权限控制，有严格的审批流程，自然就不能随时发布，也就越僵化。越原始的方式越简单越灵活，自然风险也越高。&lt;/p&gt;&#xA;&lt;p&gt;至于采用哪种发布方式，依据需要选择即可。&lt;/p&gt;&#xA;&lt;p&gt;而关于nodejs的发布方式，本人也是也是多种方式都有使用，公司项目也经历过多次变迁。公司最开始是直接登录服务器拉代码发布，后来有了运维团队，领导说开发自己发布不安全，于是就由运维搭建了Jenkins环境来发布，但是每次发布都需要走流程，后来因为发布太频繁，每1-2天要发布一次，又要灰度发布，运维也会觉得烦。于是开发就搭建了某个发布系统自己来发布，不过这个发布系统有个缺点，就是发布集群的时候是串行的，每次发布要十几分钟。&lt;/p&gt;&#xA;&lt;p&gt;另外说明一下Jenkins。它应该是使用最多的发布系统了，Jenkins基于Java开发，它已经是成熟的系统了，成熟同时也代表着复杂，复杂代表修改困难，我想大家也不太会基于Jenkins定制开发。&#xA;然后是部署困难，相比较nodejs三条命令搞定&lt;a href=&#34;https://blog.hopefly.top/blogdetail/5dd2378b00f24e1fd556d0c4&#34;&gt;linux安装nodejs——快捷版&lt;/a&gt;，go直接放二进制文件部署，Jenkins部署可能就略显复杂了。&lt;/p&gt;&#xA;&lt;p&gt;于是下定决心自己开发一个发布系统，&lt;a href=&#34;https://blog.hopefly.top/zhuque/&#34;&gt;朱雀发布系统&lt;/a&gt;因此诞生。&lt;/p&gt;&#xA;&lt;p&gt;基于以往的发布系统使用经历，我想要的是一款使用够灵活，部署够简单的发布系统。市面上现有的系统为了满足各种语言的发布，做的大而全。我自然是不想重蹈覆辙再做一个大而全的系统，我要的是小而美。正好之前了解过PM2本身集成了远程发布功能，可以在此基础上开发。PM2本身的发布过程其实已经很简单了，而且足够灵活，能够满足我的部分要求，但是公司的环境是不能在本地直接连接应用服务器的，所以需要一个中间层代理一下，放一张简单的架构图：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/zhuque.jpg&#34; alt=&#34;架构图&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;和其他工具架构逻辑一样，都是通过ssh来通信，不同的是朱雀没有直接使用ssh，而是利用了pm2,由pm2来实现通信，它已经为了做了一部分工作，比如拉代码，回滚，执行远程脚本。&#xA;由于nodejs的项目特性，它依赖了node_modules包，如果按照打包的方式发布会又大又费时，所以还是选择拉git代码的方式发布比较合适。&#xA;所以我只需要给它做一个图形界面，并有一定的管理和审批流程（可根据环境跳过）。&#xA;放一张图来看一下：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/%E6%9C%B1%E9%9B%80%E5%8F%91%E5%B8%83%E7%95%8C%E9%9D%A2.jpg&#34; alt=&#34;朱雀发布系统&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;项目地址：&lt;a href=&#34;https://github.com/yuedun/zhuque&#34;&gt;nodejs发布系统&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://blog.hopefly.top/blogdetail/60950c9ee76f307341586548&#34;&gt;朱雀发布系统支持scp（rsync）发布&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>人人都值得学习的UI自动化</title>
      <link>https://blog.hopefly.top/blogdetail/5e96f1d8bd7e796e7100a71a/</link>
      <pubDate>Wed, 15 Apr 2020 11:36:56 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5e96f1d8bd7e796e7100a71a/</guid>
      <description>&lt;h3 id=&#34;为什么需要ui自动化&#34;&gt;为什么需要UI自动化？&lt;/h3&gt;&#xA;&lt;p&gt;说起自动化，听着很厉害，可是也没见识过到底多厉害，基本是属于传说，没见过实战。但不能否认其价值，作者本人作为一个开发者也是偶然的机会接触到UI自动化，感受到了自动化的魅力，才不惜花时间来学习并使用在实际工作中。下面就来说一下为什么要做自动化。&#xA;自动化有很多种，单元测试，接口测试，UI测试。所有测试过程可以形成这样一个金字塔：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/testPyramid.png&#34; alt=&#34;测试金字塔&#34;&gt;&#xA;（图片来自网络）&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/test-pyramid.png&#34; alt=&#34;测试金字塔&#34;&gt;&#xA;（图片来自网络）&lt;/p&gt;&#xA;&lt;p&gt;从图中看出底层测试简单快速，每个单元相对独立，测试成本也较低。而最顶层的UI层聚合了底层的很多接口服务，一个测试流程相对更长更复杂，也就导致了速度慢，成本高的问题。如果由人工来完成，一个完整的测试流程往往需要几分钟，而且是不停的重复这样一个流程。所以很多开发都不愿意完整的测试自己所开发的一套业务，只能由测试人员不厌其烦的循环往复。此时如果有自动化的话就非常nice了。口说无凭，一图胜千言：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/register.gif&#34; alt=&#34;自动注册&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;是不是还没看清？没错，平时人工测试一个报名表单需要15秒左右，而自动化后几乎一瞬间即可完成，速度提升不言而喻。如果您对UI自动化已产生兴趣，请继续往下看。&lt;/p&gt;&#xA;&lt;h3 id=&#34;哪些场景可以ui自动化&#34;&gt;哪些场景可以UI自动化？&lt;/h3&gt;&#xA;&lt;p&gt;UI自动化的目的不是为了自动化而自动化，也并不能覆盖所有测试。还是以测试金字塔来说明：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/test-tower.jpg&#34; alt=&#34;测试金字塔&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;UI自动化虽然只能覆盖到约10%，但其价值却不可忽略，因为越往顶层消耗的人力成本越高，如果底层测试不够充分就只能靠顶层测试来保证。自动化虽好，但需要满足特定的场景才行，那么什么样的场景可以做UI自动化？&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;流程变化少。侧重UI的修改，而不是流程的修改。&lt;/li&gt;&#xA;&lt;li&gt;频繁的回归测试。比如一个报名表单样式修改比较频繁，需要测试其报名是否可用。&lt;/li&gt;&#xA;&lt;li&gt;界面稳定。样式可以频繁修改，但表单顺序和个数变化较少不能频繁变更。&lt;/li&gt;&#xA;&lt;li&gt;维护周期长。如果只是使用一次那也不必自动化了，毕竟自动化是解决重复劳动。&lt;/li&gt;&#xA;&lt;li&gt;开发与测试可相互配合。自动化需要程序有一定规范便于测试人员写测试程序。&lt;/li&gt;&#xA;&lt;li&gt;测试人员具备编程能力。&#xA;如果满足了上述的场景，那么UI自动化在人力消耗和效率上就有很大的提升。正确性上更有保证，手工录入会有输错重输的情况，而自动化则不会出现。&#xA;再看一个流程比较长的页面：&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/order.gif&#34; alt=&#34;自动下单&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;上面动图并没与快进，一气呵成完成了一次下单流程，基本不需要停留即可进入下一步，相比起手动操作省时省力。&lt;/p&gt;&#xA;&lt;h3 id=&#34;为什么ui自动化普及率低&#34;&gt;为什么UI自动化普及率低？&lt;/h3&gt;&#xA;&lt;p&gt;既然UI自动化能提高效率，但为什么却很少有人去使用？&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;开发自动化程序对测试人员的编程水平有一定要求，很少有人愿意花时间去写这个程序。&lt;/li&gt;&#xA;&lt;li&gt;对于互联网公司，大多数业务需要快速迭代，一个页面的生存周期很短，也可能只是一次性的，自动化测试没有存在的必要性。&lt;/li&gt;&#xA;&lt;li&gt;测试人员没有切实的感受到效率提升。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;其实说白了，就是大家觉得投入和产出不值得。如果是迫于领导压力要写自动化程序，就会不停的对程序修修补补，自己用的话有问题大不了不用自动化，手动测试一下通过就行，如果是给别人用就会不停收到反馈和吐槽，自然也就没有写下去的动力了。&#xA;所以个人觉得，自动化程序不应该成为一种流程和形式，而是应该由开发和测试人员自发的去将自身经常重复的工作做成自动化。因为自动化本身就不能覆盖所有场景，只有实际参与的人才能知道哪些是可以自动化的。&lt;/p&gt;&#xA;&lt;h3 id=&#34;有哪些工具可以选择&#34;&gt;有哪些工具可以选择？&lt;/h3&gt;&#xA;&lt;p&gt;目前市场上不仅提供了多种工具可以选择，还支持不同语言。&#xA;web端：selenium、webdriver、robotframework、puppeteer等。&#xA;APP端：Appium、Instrumentation、Robotium 、UIAutomator、Espresso、Calabash、Selendroid、Robolectric、RoboSpock、Cafe、Athrun等。&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://www.cnblogs.com/fqfanqi/p/6139435.html&#34;&gt;移动APP自动化测试框架&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;本文不对所有工具一一详解，可自行根据平台选择合适的工具和语言进行学习使用。只针对个别WEB端工具做简单说明。&#xA;拿selenium来说，selenium是一款很多人比较熟悉的工具，支持的语言有Python，Java，JavaScript等，推荐使用Python。而且其支持的浏览器也很全面：&#xA;Google Chrome&#xA;Internet Explorer 7, 8, 9, 10, 11&#xA;Firefox&#xA;Safari&#xA;Opera&#xA;HtmlUnit&#xA;phantomjs&#xA;Android&#xA;iOS&lt;/p&gt;&#xA;&lt;h3 id=&#34;一些常见问题&#34;&gt;一些常见问题&lt;/h3&gt;&#xA;&lt;p&gt;在自动化过程中最多的就是对元素进行定位，自动化工具常见的定位符有：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;id&lt;/li&gt;&#xA;&lt;li&gt;name&lt;/li&gt;&#xA;&lt;li&gt;class name&lt;/li&gt;&#xA;&lt;li&gt;tag&lt;/li&gt;&#xA;&lt;li&gt;link text&lt;/li&gt;&#xA;&lt;li&gt;partial link text&lt;/li&gt;&#xA;&lt;li&gt;xpath&lt;/li&gt;&#xA;&lt;li&gt;css selector&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;以上这些元素定位对于以前的网页来说还足以应对，因为以前开发的网页大多数元素会有id，class这些属性，定位起来也比较方便。但是对于react，vue，angular这类数据驱动的框架就不那么友好了。&#xA;比如有这么一个元素：&lt;code&gt;&amp;lt;div&amp;gt;{{element}}&amp;lt;/div&amp;gt;&lt;/code&gt;结果为：&lt;/p&gt;</description>
    </item>
    <item>
      <title>windows调整C盘大小</title>
      <link>https://blog.hopefly.top/blogdetail/5e38ea905bd8165f28d1fc55/</link>
      <pubDate>Tue, 04 Feb 2020 03:52:48 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5e38ea905bd8165f28d1fc55/</guid>
      <description>&lt;p&gt;新买的windows笔记本一般会对磁盘进行分区，虽然有说法是现代电脑没必要分区，不过目前很多人还是有这样的习惯。&#xA;然而我们往往低估了软件的吃磁盘能力，会把C盘设置50G左右的大小，觉得C盘只是装个系统而已，会自觉把软件装到其他盘下，结果就是没用几个月C盘就满了。其实，虽然我们把软件装到了其他盘，但是软件本身会下载很多内容，比如数据保存，缓存，默认下载等等都会占用C盘。所以建议C盘设置100G比较合理。&#xA;关于已经分配好大小的磁盘也可以进行调整，需要借助一些软件来操作，本文作者使用的是&lt;strong&gt;Diskgenius&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/%E6%89%A9%E5%AE%B9%E5%88%86%E5%8C%BA.jpg&#34; alt=&#34;扩容分区&#34; title=&#34;扩容分区&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/%E7%BC%A9%E5%B0%8F%E7%A3%81%E7%9B%98.jpg&#34; alt=&#34;缩容&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/%E7%BC%A9%E5%B0%8F%E5%90%8E.jpg&#34; alt=&#34;缩容后&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;很简单的三个步骤：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;选择需要扩容的磁盘右击“扩容分区”&lt;/li&gt;&#xA;&lt;li&gt;选择缩容的磁盘，用于将缩容的磁盘分配给C盘。&lt;/li&gt;&#xA;&lt;li&gt;选择需要缩容的大小。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;确认开始大约需要十几分钟就可以了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>再聊docker和nodejs</title>
      <link>https://blog.hopefly.top/blogdetail/5a6ab02e260a5391e91a525f/</link>
      <pubDate>Fri, 26 Jan 2018 04:35:58 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5a6ab02e260a5391e91a525f/</guid>
      <description>&lt;p&gt;上一篇写到了&lt;a href=&#34;http://yuedun.wang/blogdetail/5a6021fa4bdc8ea471fd2db0&#34;&gt;如何在docker中运行nodejs&lt;/a&gt;，运行方式是在docker中安装了pm2来保证node服务宕机重启，这种方式更像是把docker当做虚拟机来使用。其实，既然使用了docker的话就可以不使用pm2来管理进程，因为docker自身可以充当守护进程，在node进程退出时进行重启。只要在启动docker容器时加上&amp;ndash;restart=always参数即可。例如：&lt;code&gt;docker run -d --restart=always -p 3000:3000 mynode:1&lt;/code&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;没有pm2如何开启多进程&#34;&gt;没有pm2如何开启多进程&lt;/h3&gt;&#xA;&lt;p&gt;使用pm2可以开启多node进程，并且自带负载均衡，但是有个限制，pm2可以开启的进程数是CPU最大核心数。而使用docker的话就不会受限于此了，开启几十个上百个node服务都可以，然后通过nginx实现负载均衡。不过要手动开启几十上百个docker容器那怎么行？让我手动开启3个都很烦了，这时候就需要用到docker编排工具了，比如：&lt;code&gt;Docker Swarm、Kubernetes、docker compose&lt;/code&gt;等，可以一键开启多个容器。但是使用编排工具启动docker端口就不确定了，是由编排工具随机开启服务端口的，这又要做到服务注册发现，所以这些工具结合起来使用。&lt;/p&gt;&#xA;&lt;h3 id=&#34;哪一种部署方式支持并发高&#34;&gt;哪一种部署方式支持并发高？&lt;/h3&gt;&#xA;&lt;p&gt;使用jmeter在本机上进行了简单的并发测试，服务端进行简单的10万次hash计算，使用pm2开启4个实例，docker开启5个实例。docker使用Nginx做负载均衡，单次访问响应时间在1.2s~1.4s之间不等，在200个并发的情况下，两种模式响应时间相差不大，docker模式响应时间略占优势，大概快了0.1s。当并发数在300以上时两者的响应时间都有增加，此时docker部署方式出现了响应失败的情况，pm2就比较稳定了，虽然响应时间增加，但是并未出现过响应失败。&#xA;所以在单机上低并发docker还是有点优势，如果在高并发情况下还是pm2更稳定一些。（以上测试是单机上进行，准确性并不高）&lt;/p&gt;</description>
    </item>
    <item>
      <title>最新版火狐Firefox Quantum 57没有pocket按钮</title>
      <link>https://blog.hopefly.top/blogdetail/5a615ab64bdc8ea471fd2ddd/</link>
      <pubDate>Fri, 19 Jan 2018 02:40:54 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5a615ab64bdc8ea471fd2ddd/</guid>
      <description>&lt;p&gt;从火狐量子浏览器开始，pocket按钮集成到了地址栏右侧，&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/firefoxpocket.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;如果你找不到，那么有可能是在浏览器配置中关闭了，开启方式：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;地址栏中输入&lt;code&gt;about:config&lt;/code&gt;,点击“我了解风险”继续，搜索“pocket.enabled”，如果是false双击修改为true就会出现。&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;其他情况可参考：&lt;a href=&#34;https://help.getpocket.com/article/942-where-is-the-pocket-button-in-firefox&#34;&gt;https://help.getpocket.com/article/942-where-is-the-pocket-button-in-firefox&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>本地producer和consumer连接不上远程kafka服务</title>
      <link>https://blog.hopefly.top/blogdetail/5a584429752e661009178c06/</link>
      <pubDate>Fri, 12 Jan 2018 05:14:17 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5a584429752e661009178c06/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;Hostname and port the broker will advertise to producers and consumers. If not set,&#xA;it uses the value for &amp;ldquo;listeners&amp;rdquo; if configured.  Otherwise, it will use the value&#xA;returned from java.net.InetAddress.getCanonicalHostName().&#xA;advertised.listeners=PLAINTEXT://ip:9092&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;打开advertised.listeners=PLAINTEXT://ip:9092配置，ip为kafka服务ip&lt;/p&gt;</description>
    </item>
    <item>
      <title>推荐在Nodejs使用的java常用技术和工具</title>
      <link>https://blog.hopefly.top/blogdetail/5a430ce84aa3290e95cb0e67/</link>
      <pubDate>Tue, 26 Dec 2017 15:24:12 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5a430ce84aa3290e95cb0e67/</guid>
      <description>&lt;p&gt;作为Nodejs开发者可能会对java中常用的一些技术工具不太关心，主要原因大概除了语言级别的间隙就是Nodejs相对于java来说比较轻量级，大多用来开发简单系统，用不到其他工具。根据经验来说，开发相同功能的系统，Nodejs的开发周期和代码体量上也会比Java少太多，毕竟java出生年代长，生态丰富，如果不使用几个框架都感觉不是在开发系统。而Nodejs要开发一个web系统基本使用express或koa就差不多够了。所以对于Nodejs开发者来说，分布式，消息队列，远程调用等技术接触就少些。当然，不用这些技术其实也不会有太大影响，但是对于一个有追求有理想的码农来说我们的眼界不应该局限于系统能运行就行。&#xA;下面就来介绍一些可以在nodejs中使用的JAVA常用工具和技术。&lt;/p&gt;&#xA;&lt;h3 id=&#34;elasticsearch&#34;&gt;elasticsearch&lt;/h3&gt;&#xA;&lt;p&gt;ElasticSearch（以下简称ES）是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎，基于RESTful web接口。Elasticsearch是用Java开发的，并作为Apache许可条款下的开放源码发布，是当前流行的企业级搜索引擎。看见了吧，这就是一个使用JAVA开发的全文搜索引擎，到底有什么用呢？就是可以提供像google和百度一样的搜索功能，就算不需要这样功能，也可以用于管理后台的字段搜索，大家知道数据库的搜索效率比较差，有索引的字段还好，没有的就很慢了，这时ES就可以派上用场了，把数据同步进ES,不论查询列表还是以字段搜索都是极快的，是redis缓存的很好补充。&lt;/p&gt;&#xA;&lt;h3 id=&#34;elk&#34;&gt;ELK&lt;/h3&gt;&#xA;&lt;p&gt;ELK（ElasticSearch,LogStash,Kibana）是三个工具的组合,&#xA;Logstash是一款轻量级的日志搜集处理框架，可以方便的把分散的、多样化的日志搜集起来，并进行自定义的处理，然后传输到指定的位置，比如某个服务器或者文件。&#xA;Kibana是一个使用nodejs开发的web应用，用于查询和操作ES，就是一个ES的图形界面。&#xA;如果nodejs系统布署在多台服务器，那么查看日志是件很头疼的事，你不知道请求发送到哪一台服务器，需要挨个查看，如果服务超过5台，这绝对是噩梦。这时候ELK就是很好的解决方案，LogStash收集每一台服务器的日志统一存到ES中，利用ES的优点，查询任何关键字都很快很方便。&lt;/p&gt;&#xA;&lt;h3 id=&#34;消息中间件kafka&#34;&gt;消息中间件（kafka）&lt;/h3&gt;&#xA;&lt;p&gt;拿用户注册为例，需要发送邮件，短信，这两个服务之间本没有关联关系，但我们的一贯作风是用户注册的时候调用邮件服务，短信服务，严谨一点会放在事务中操作，假如一个服务失败可能会让事务回滚，所有操作都失败。这是一种情况，另一种情况是如果要再注册后加积分，那么就得改代码，要是有更多服务要添加就得每次改代码发布，启停服务，不送积分了又要删代码，这就是耦合度太高导致的结果。使用消息中间件不仅能保证服务完整性还可以有效解耦，有兴趣可以去了解kafka,rabbitMQ,roketMQ等消息中间件。&lt;/p&gt;&#xA;&lt;h3 id=&#34;远程调用rpc&#34;&gt;远程调用RPC&lt;/h3&gt;&#xA;&lt;p&gt;通俗的来讲就是两台服务器A和B，A服务器直接调用B服务器上的函数，如果没有一个具体事例很难理解A服务器怎么可能调用到B服务器的函数，感兴趣可下载尝试：&lt;a href=&#34;https://github.com/yuedun/nodejs-grpc&#34;&gt;https://github.com/yuedun/nodejs-grpc&lt;/a&gt;&#xA;那么为什么要用rpc呢？A服务器要调用B服务的资源直接用http提供接口不就行了吗？其实http也算是一种远程调用，而且也比较简单直观，但是其效率较低，调用成本高，三次握手耗时，甚至请求头的数据量比请求体还大。那么就需要一种更高效的调用协议了——rpc。&lt;a href=&#34;http://yuedun.wang/blogdetail/5a375f52e9a4cf008860c09b&#34;&gt;为什么需要RPC，而不是简单的HTTP接口&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;总结：以上的这些工具和技术和语言并没有绑定，java可以使用，nodejs也可以使用，推荐理由：投入成本小，使用收益高。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Dockerfile CMD命令没有执行npm start</title>
      <link>https://blog.hopefly.top/blogdetail/5a1be456da5c711b612f4d39/</link>
      <pubDate>Mon, 27 Nov 2017 10:09:26 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5a1be456da5c711b612f4d39/</guid>
      <description>&lt;p&gt;Dockerfile&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;FROM hub.c.163.com/public/nodejs:6.11.0&#xA;&#xA;WORKDIR /app&#xA;&#xA;COPY . /app&#xA;&#xA;RUN npm install&#xA;&#xA;EXPOSE 3000&#xA;&#xA;# CMD [&amp;#34;npm&amp;#34;, &amp;#34;start&amp;#34;]&#xA;ENTRYPOINT [&amp;#34;npm&amp;#34;, &amp;#34;start&amp;#34;]&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;&#xA;&lt;p&gt;docker ps:&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CONTAINER ID    IMAGE  COMMAND                  &#xA;59988bd90894    myfd   &amp;#34;/bin/sh -c &amp;#39;/usr/...&amp;#34;   &#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在Dockerfile中配置了&lt;code&gt;CMD [&amp;quot;npm&amp;quot;, &amp;quot;start&amp;quot;]&lt;/code&gt;,&lt;code&gt;docker ps&lt;/code&gt;后显示COMMAND为&lt;code&gt;&amp;quot;/bin/sh -c &#39;/usr/...&amp;quot;&lt;/code&gt;&#xA;改为&lt;code&gt;ENTRYPOINT [&amp;quot;npm&amp;quot;, &amp;quot;start&amp;quot;]&lt;/code&gt;就可以了&lt;/p&gt;</description>
    </item>
    <item>
      <title>windows好用的bash工具——ConEmu</title>
      <link>https://blog.hopefly.top/blogdetail/598aaf0525207f400eeb1b87/</link>
      <pubDate>Wed, 09 Aug 2017 06:43:17 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/598aaf0525207f400eeb1b87/</guid>
      <description>&lt;p&gt;其实git-bash-for-windows这个git bash工具已经很好用了，不过对于平时需要开3-5的bash窗口的我来说就比较烦了，一直要不停的切换窗口，所以想找一款像linux terminal一样可以多开的工具，幸好有这样的工具，那就是&lt;a href=&#34;https://conemu.github.io/&#34;&gt;ConEmu&lt;/a&gt;。&lt;/p&gt;&#xA;&lt;p&gt;使用前需要一些配置，不配置也没关系，就是使用起来不方便，我是按照的习惯完全配置成了git bash的使用方式。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第一步&#34;&gt;第一步:&lt;/h3&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/bash1.png&#34; alt=&#34;设置&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;第二步-配置本地git-bash地址此步骤可适当配置&#34;&gt;第二步： 配置本地git bash地址（此步骤可适当配置&lt;/h3&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/bash2.png&#34; alt=&#34;设置&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;第三步-设置conemu启动即打开bash而非windows-cmd&#34;&gt;第三步： 设置ConEmu启动即打开bash而非windows cmd&lt;/h3&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/bash3.png&#34; alt=&#34;设置&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;第四步-如果前面都没问题可以设置自动保存打开的窗口以便下次打开即可使用&#34;&gt;第四步： 如果前面都没问题，可以设置自动保存打开的窗口，以便下次打开即可使用&lt;/h3&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/bash4.png&#34; alt=&#34;设置&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;最后-根据个人喜好修改字体等&#34;&gt;最后： 根据个人喜好修改字体等&lt;/h3&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/bash5.png&#34; alt=&#34;设置&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;这样就可以完美使用git bash，不论是自动补全还是颜色主题都和git bash无异。&lt;/p&gt;&#xA;&lt;p&gt;另外&lt;a href=&#34;http://cmder.net/&#34;&gt;cmder&lt;/a&gt;其实也是我使用过的一个不错的工具，同时推荐试用。&lt;/p&gt;</description>
    </item>
    <item>
      <title>npm ERR! Error: EPERM: operation not permitted</title>
      <link>https://blog.hopefly.top/blogdetail/59532a3233c3c869639761db/</link>
      <pubDate>Wed, 28 Jun 2017 04:01:54 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/59532a3233c3c869639761db/</guid>
      <description>&lt;p&gt;windows下&lt;code&gt;npm install&lt;/code&gt;安装依赖的时候出现下面的错误：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;npm ERR! Windows_NT 6.1.7601&#xA;npm ERR! argv &amp;#34;D:\\Program Files\\nodejs\\node.exe&amp;#34; &amp;#34;D:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js&amp;#34; &amp;#34;install&amp;#34; &amp;#34;yog2@1.0.0&amp;#34;&#xA;npm ERR! node v4.8.0&#xA;npm ERR! npm  v2.15.11&#xA;npm ERR! path C:\Users\Administrator\AppData\Roaming\npm-cache\images\3.0.0\package.tgz.1683947925&#xA;npm ERR! code EPERM&#xA;npm ERR! errno -4048&#xA;npm ERR! syscall rename&#xA;&#xA;npm ERR! Error: EPERM: operation not permitted, rename &amp;#39;C:\Users\Administrator\AppData\Roaming\npm-cache\images\3.0.0\package.tgz.1683947925&amp;#39; -&amp;gt; &amp;#39;C:\Users\Administrator\AppData\Roaming\npm-cache\images\3.0.0\package.tgz&amp;#39;&#xA;npm ERR!     at Error (native)&#xA;npm ERR!  { [Error: EPERM: operation not permitted, rename &amp;#39;C:\Users\Administrator\AppData\Roaming\npm-cache\images\3.0.0\package.tgz.1683947925&amp;#39; -&amp;gt; &amp;#39;C:\Users\Administrator\AppData\Roaming\npm-cache\images\3.0.0\package.tgz&amp;#39;]&#xA;npm ERR!   errno: -4048,&#xA;npm ERR!   code: &amp;#39;EPERM&amp;#39;,&#xA;npm ERR!   syscall: &amp;#39;rename&amp;#39;,&#xA;npm ERR!   path: &amp;#39;C:\\Users\\Administrator\\AppData\\Roaming\\npm-cache\\images\\3.0.0\\package.tgz.1683947925&amp;#39;,&#xA;npm ERR!   dest: &amp;#39;C:\\Users\\Administrator\\AppData\\Roaming\\npm-cache\\images\\3.0.0\\package.tgz&amp;#39;,&#xA;npm ERR!   parent: &amp;#39;fis-spriter-csssprites&amp;#39; }&#xA;npm ERR!&#xA;npm ERR! Please try running this command again as root/Administrator.&#xA;&#xA;npm ERR! Please include the following file with any support request:&#xA;npm ERR!     E:\workspace\zm-platform\npm-debug.log&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;解决方案：&lt;code&gt;npm cache clear &lt;/code&gt;&#xA;详细参阅：&lt;a href=&#34;https://alastaircrabtree.com/fixing-intermittant-eperm-operation-not-permitted-on-npm-install/&#34;&gt;Fixing intermittant &amp;lsquo;EPERM: operation not permitted&amp;rsquo; on npm install&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>RockMongo使用方法</title>
      <link>https://blog.hopefly.top/blogdetail/591ea6966af6717b614f9b2b/</link>
      <pubDate>Fri, 19 May 2017 08:02:30 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/591ea6966af6717b614f9b2b/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;RockMongo是一个PHP5写的MongoDB管理工具。&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;鉴于百度bce的mongodb数据使用了RockMongo来管理数据，就以此来说明。&lt;/p&gt;&#xA;&lt;h3 id=&#34;查询操作&#34;&gt;查询操作&lt;/h3&gt;&#xA;&lt;p&gt;点击某个collection后的默认画面：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/rockmongo1.png&#34; alt=&#34;rockmongo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;查询界面很简单，关键是怎么写查询语句？&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/rockmongo2.png&#34; alt=&#34;rockmongo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;点击文本可以查看所有数据字段，查询title为“测试”文档：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;array(&#xA;&#x9;&amp;#39;title&amp;#39; =&amp;gt; &amp;#39;测试&amp;#39;&#xA;)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;模糊查询：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;array(&#xA;&#x9;&amp;#39;title&amp;#39;=&amp;gt; new MongoRegex(&amp;#34;/测试/i&amp;#34;)&#xA;)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;字段名要加引号，中间使用&lt;code&gt;=&amp;gt;&lt;/code&gt;而不是使用&lt;code&gt;:&lt;/code&gt;分割，需要查询的值也需要注意，字符串加引号，数字不加，如果类型不匹配就会查不出数据。查询结果有一条数据&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/rockmongo3.png&#34; alt=&#34;rockmongo&#34;&gt;&lt;/p&gt;&#xA;&lt;h3 id=&#34;修改操作&#34;&gt;修改操作&lt;/h3&gt;&#xA;&lt;p&gt;动作中选择“modify”&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/rockmongo4.png&#34; alt=&#34;rockmongo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;再查询一下&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/rockmongo5.png&#34; alt=&#34;rockmongo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;基本操作就是这样，删除操作不用说也应该能知道怎么做了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>VMware重新安装VMware Tool</title>
      <link>https://blog.hopefly.top/blogdetail/5742d3bb44b00beb2d26238d/</link>
      <pubDate>Mon, 23 May 2016 09:56:11 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/5742d3bb44b00beb2d26238d/</guid>
      <description>&lt;h3 id=&#34;vmware重新安装vmware-tool&#34;&gt;VMware重新安装VMware Tool&lt;/h3&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;将虚拟机从Ubuntu 14重新安装为Ubuntu 16以后不能将Windows的文本内容复制到Linux中，需要重新安装VMware Tool,VMware版本为12&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h4 id=&#34;一安装vmware-tool&#34;&gt;一、安装VMware Tool&lt;/h4&gt;&#xA;&lt;p&gt;安装时需要在虚拟机启动登录的情况下进行，&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/176512086866100.png&#34; alt=&#34;重新安装VMware Tool&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;点击以后应该会弹出磁盘图标并且打开一个文件夹&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/167905236582112.png&#34; alt=&#34;打开DVD&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;文件夹中包含一个压缩文件，需要解压，解压需要root权限，打开命令行&#xA;&lt;code&gt;# sudo su&lt;/code&gt;&#xA;提升为超级用户，可以右击查看gz压缩文件路径，并切换到该目录下，或者可以直接使用图形界面，右击-提取，不能提取到当前目录下，该目录为磁盘目录，不能写入数据，解压到其他目录下即可。解压完成会得到vmware-tools-distrib文件夹，文件夹下有多个文件，其中有vmware-install.pl，命令行中执行这个文件&#xA;&lt;code&gt;./vmware-install.pl&lt;/code&gt;&#xA;基本可以一路按回车，安装完成后需要重启。重启后可能会有这样的显示，不过不影响。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/164002276410682.png&#34; alt=&#34;重启linux&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/17491110021917.png&#34; alt=&#34;重启linux&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>webuploader模态框按钮不起作用或每次打开都会变大</title>
      <link>https://blog.hopefly.top/blogdetail/568b2d05db1fef9e0cda949f/</link>
      <pubDate>Tue, 05 Jan 2016 02:40:05 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/568b2d05db1fef9e0cda949f/</guid>
      <description>&lt;p&gt;在bootstra模态框中放置webuploader上传控件，每次打开模态框按钮都会成倍放大，原因是每次打开模态框都会进行一次初始化，在原来按钮的基础上又加了一层样式，那么初始化一次应该可以吧。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/anniubianda.png&#34; alt=&#34;https://qn-img.hopefly.top/anniubianda.png&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;修改后的确不会再放大了，可以又有新问题出现了，就是不能点击上传文件了。&lt;/p&gt;&#xA;&lt;p&gt;上传实例初始化一次，先然按钮正常显示，&#xA;&lt;code&gt;var uploader = WebUploader.create({})&lt;/code&gt;，&#xA;再通过uploader提供的API重新添加一个按钮&lt;code&gt;uploader.addButton({})&lt;/code&gt;，这样类似于将前一个按钮覆盖了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>TortoiseGit提交到远程仓库时git did not exit cleanly (exit code 128)</title>
      <link>https://blog.hopefly.top/blogdetail/564554fec888d8070f145c36/</link>
      <pubDate>Fri, 13 Nov 2015 03:11:58 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/564554fec888d8070f145c36/</guid>
      <description>&lt;p&gt;虽然出现git did not exit cleanly (exit code 128)的情况各有不同，不过其中一种是提交时的读写权限有问题，如果本地代码连接的是SSH仓库，那么可能是服务端没有配置SSH Key。github有两个地方配置sshkey，有一个是全局的，另一个是针对单个仓库的，如果给某个仓库配置了Deploy keys（其实和SSHkey一样），提交另一个代码时就会出现git did not exit cleanly。对于我这种不熟练的人来说就想着再添加一个Deploy keys，但是又提示Key already in use，这时就要看看是不是其他仓库单独配置了ssh key。如果仓库太多具体哪个配置了也不太清楚，有个简单快读的办法是在命令行执行 ssh -T -ai .\id_rsa &lt;a href=&#34;mailto:git@github.com&#34;&gt;git@github.com&lt;/a&gt;，会告诉你哪个仓库在使用本地的id_rsa内容。删掉Deploy keys，配置为全局SSH Keys就行了&lt;/p&gt;</description>
    </item>
    <item>
      <title>Git SSH Key在windows下生成过程</title>
      <link>https://blog.hopefly.top/blogdetail/56400429c888d8070f145c35/</link>
      <pubDate>Mon, 09 Nov 2015 02:25:45 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/56400429c888d8070f145c35/</guid>
      <description>&lt;p&gt;切换到C:\Users\&lt;!-- raw HTML omitted --&gt;\.ssh&lt;/p&gt;&#xA;&lt;p&gt;执行命令：ssh-keygen -t rsa -C &amp;ldquo;邮箱地址&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;Generating public/private rsa key pair.&lt;/p&gt;&#xA;&lt;p&gt;Enter file in which to save the key (//.ssh/id_rsa):&lt;/p&gt;&#xA;&lt;p&gt;第一次生成由于没有id_rsa文件和id_rsa.pub文件，所以需要生成这两个文件，然后手动输入：./id_rsa&lt;/p&gt;&#xA;&lt;p&gt;Enter file in which to save the key (//.ssh/id_rsa): ./id_rsa，虽然要求输入//.ssh/id_rsa，但这种方式不是在当前目录下&lt;/p&gt;&#xA;&lt;p&gt;接下来两部是要求输入密码，不输入直接回车就完成了。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PS C:&lt;span style=&#34;color:#ae81ff&#34;&gt;\U&lt;/span&gt;sers&lt;span style=&#34;color:#ae81ff&#34;&gt;\a&lt;/span&gt;dmin&lt;span style=&#34;color:#ae81ff&#34;&gt;\.&lt;/span&gt;ssh&amp;gt; ssh-keygen -t rsa -C &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;myemail@163.com&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Generating public/private rsa key pair.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Enter file in which to save the key &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;//.ssh/id_rsa&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;: ./id_rsa&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Enter passphrase &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;empty &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; no passphrase&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Enter same passphrase again:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Your identification has been saved in ./id_rsa.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Your public key has been saved in ./id_rsa.pub.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The key fingerprint is:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9c:cc:db:3e:72:82:73:2e:41:0e:17:f4:3c:ea:70:4a myemail@163.com&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The key&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;s randomart image is:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;+--[ RSA 2048]----+&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| .o |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| + |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| . o + |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| O o . |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| E S |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| . = = |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| . * = + |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| = = . |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;| . |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;+-----------------+&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;最后将.ssh目录下id_rsa.pub文件中的内容复制并添加到github或其他支持资源库中就可以使用ssh的协议clone资源了，没有添加进去是不能克隆的。&lt;/p&gt;</description>
    </item>
    <item>
      <title>检测网站中未使用的css样式</title>
      <link>https://blog.hopefly.top/blogdetail/563069efaa0d5223f187dfa4/</link>
      <pubDate>Wed, 28 Oct 2015 06:23:43 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/563069efaa0d5223f187dfa4/</guid>
      <description>&lt;p&gt;网站的css样式文件在多次修改后会有很多样式废弃不再使用，使得维护起来困难，还可能出现重名样式，后面的覆盖掉前面的效果，所以有必要清除掉不再使用的样式。可以使用的工具很多，不过在使用了Dust-Me Selectors觉得足够了。&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://addons.mozilla.org/en-US/firefox/addon/dust-me-selectors/&#34;&gt;https://addons.mozilla.org/en-US/firefox/addon/dust-me-selectors/&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;打开上面网址安装&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/dust1.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;直接点击这个小扫把会检测当前页面没有使用的样式，不过这样的结果还不是我们想要的，因为当前页面没有使用不代表其他页面也没有使用。我们更需要的是找出整个网站中未使用的样式。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/dust2.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;选择第一项“Spider Sitemap”，就像是百度蜘蛛爬取整个网站数据一样。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/dust3.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;输入网址，本地网址和网络地址都可以检测，点击“Start”后很快就有结果了，如果页面较多会费时些。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/dust4.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;可以看到有橘黄色部分就是没有使用的样式，但是这也不能完全代表就是没有使用过，上面三个未使用的样式是我对于博客内容的图片和引用块使用的样式，因为本地的测试内容中的确没有使用这三个样式，但是线上的网站却使用了，遇到这种情况就需要仔细甄别了。&lt;/p&gt;&#xA;&lt;p&gt;再看一下扫描的页面日志&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/dust5.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;基本的页面都有扫描过了。此时可以手动删除掉没有使用的样式，这个插件对于简单的网站够用了，但是大型网站就不准确了，当然有些其他工具还可以导出检测后的结果。有必要的可以去下载。&lt;/p&gt;</description>
    </item>
    <item>
      <title>linux下添加svn用户名密码</title>
      <link>https://blog.hopefly.top/blogdetail/562d9ca9c6ed32d312337025/</link>
      <pubDate>Mon, 26 Oct 2015 03:23:21 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/562d9ca9c6ed32d312337025/</guid>
      <description>&lt;p&gt;首先需要知道配置文件的位置，比如我们的服务器中我就找到很多关于svn的目录，甚至分不清哪个目录下才是真正的配置文件&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;root@handou:~# find / -name subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/home/handou/workspace/subversion-1.8.11/subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/home/handou/workspace/subversion-1.8.11/subversion/bindings/javahl/src/org/apache/subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/home/handou/workspace/subversion-1.8.11/subversion/bindings/javahl/src/org/tigris/subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/home/handou/workspace/subversion-1.8.11/subversion/bindings/javahl/tests/org/apache/subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/home/handou/workspace/subversion-1.8.11/subversion/bindings/javahl/tests/org/tigris/subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/etc/bash_completion.d/subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/etc/subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;/usr/share/doc/subversion&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;查找所得结果可以确定应该是在 /etc/subversion下，切换到subversion下有多个文件：&lt;/p&gt;&#xA;&lt;p&gt;config  config.dpkg-dist  dav_svn.authz  dav_svn.passwd   passwd  servers&lt;/p&gt;&#xA;&lt;p&gt;可能需要一一查看下都是什么内容，其实主要是dav_svn.authz  dav_svn.passwd这两个文件，一个存放用户名，一个存放密码，dav_svn.authz内容包含账号和权限：&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;[groups]&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;apiadmin=yuedun&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;[handou:/]&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;@admin=rw&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;@apiadmin=rw&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;可以编辑这个文件添加账号，然后添加密码，但是不能直接编辑dav_svn.passwd，这里面是加密数据，需要使用Apache的htpasswd命令添加。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;htpasswd /etc/subversion/dav_svn.passwd  &amp;lt;用户名&amp;gt;&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;然后会提示输入密码，就此完成svn账号设置。&lt;/p&gt;</description>
    </item>
    <item>
      <title>手机和PC联机调试Debugging Firefox for Android with WebIDE</title>
      <link>https://blog.hopefly.top/blogdetail/56286fd6ce46c19e89132969/</link>
      <pubDate>Thu, 22 Oct 2015 05:10:46 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/56286fd6ce46c19e89132969/</guid>
      <description>&lt;p&gt;Firefox提供了在PC端调试手机端页面的工具，详情查看：&#xA;&lt;a href=&#34;https://developer.mozilla.org/zh-CN/docs/Tools/Remote_Debugging/Debugging_Firefox_for_Android_with_WebIDE&#34;&gt;https://developer.mozilla.org/zh-CN/docs/Tools/Remote_Debugging/Debugging_Firefox_for_Android_with_WebIDE&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://mdn.mozillademos.org/files/9011/remote-debugging-overview-fx36.png&#34; alt=&#34;https://mdn.mozillademos.org/files/9011/remote-debugging-overview-fx36.png&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>使用sublime开发node.js快速跳转到变量函数声明处</title>
      <link>https://blog.hopefly.top/blogdetail/56286643ce46c19e89132968/</link>
      <pubDate>Thu, 22 Oct 2015 04:29:55 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/56286643ce46c19e89132968/</guid>
      <description>&lt;p&gt;开发中最常用的操作之一就是快速跳转到变量，方法声明处，比如在eclipse中按住Ctrl键鼠标点击变量或方法就能跳转到对应的位置或文件中，开发nodejs程序当然也需要这样的功能，比较强大的开发工具有webstorm，也是支持这种操作的。不过webstorm太占内存，4G的内存下总是提示内存不足，需要关闭占用内存程序，而首当其冲的就是webstorm，所以最近试了试另一款被大家熟知和推荐的开发神器sublime。虽然sublime是个文本编辑器，还不能算的上IDE，不过它可以安装各种插件来丰富功能，最重要的是它占用内存少，速度快。&lt;/p&gt;&#xA;&lt;p&gt;所以，我要介绍的是在ST下如何做到跳转到变量或方法声明处。&lt;/p&gt;&#xA;&lt;p&gt;首先在uses.js文件中有一个函数&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//我是一个测试方法&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;router&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;get&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/commeHere&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;req&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;res&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/st1.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;然后我要从其他文件中跳转到这个函数。先关掉这个文件，打开其他文件。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/st2.jpg&#34; alt=&#34;st2.jpg&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;可以双击或鼠标选中commeHere这个关键词（才发现单词打错了），键盘按下Ctrl+shift+F就会出现类似搜索框，选中的关键字会填充到find框中，需要手动选择where框，选择Add Open  Folders，文本框中填充的就是&lt;!-- raw HTML omitted --&gt;，然后回车就可以了，很快就会搜索出我们需要的关键字所在的文件。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/st3.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/st4.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;双击就可以跳转到对应的文件和行上。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/st5.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;当然，不可能像eclipse中那么方便，但其实只有两步操作，第一ctrl+shift+F搜索关键字，第二双击搜索结果跳转到对应文件位置。如果你习惯使用ST的话肯定很满足这样的设计，根本不会觉得繁琐。&lt;/p&gt;</description>
    </item>
    <item>
      <title>微信开发通过公网访问本地服务器</title>
      <link>https://blog.hopefly.top/blogdetail/55ab0f6ed366f15412cbf596/</link>
      <pubDate>Sun, 19 Jul 2015 02:46:06 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/55ab0f6ed366f15412cbf596/</guid>
      <description>&lt;p&gt;做微信开发的时候，在开发者中心需要进行服务器配置，这里的配置是一个可以公网访问的地址，如果是产品上线的话肯定有公网地址，但是在开发过程中需要本地测试，总不能开发一点部署到服务器测试。这时候我们就需要从公网访问本地服务器。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/1.jpg&#34; alt=&#34;设置你的路由器，进行内网映射&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;这已经是设置好的，服务器端口是指公网地址的端口，就以80端口来好了，这样公网地址可以省略端口，内部服务器端口就是本地服务器端口，Java程序一般是8080这样的端口，IP地址就是本地服务器在局域网中的ip，协议选ALL，状态：生效。常用服务器端口可以不选。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/2.png&#34; alt=&#34;设置你的路由器，进行内网映射&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;然后启动本地服务器就可以通过路由器的公网IP访问本地服务了&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/3.jpg&#34; alt=&#34;设置你的路由器，进行内网映射&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/4.jpg&#34; alt=&#34;设置你的路由器，进行内网映射&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;但是我们不习惯使用IP地址访问，可以通过域名来访问，首先再到路由器中配置“动态DNS”：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/5.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;当然，得先注册一个动态域名，登录成功之后就可以通过域名访问本地应用服务器了&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/6.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>搞懂了七牛文件存储</title>
      <link>https://blog.hopefly.top/blogdetail/54662bf3e8183bcf964f88eb/</link>
      <pubDate>Fri, 14 Nov 2014 16:21:07 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/54662bf3e8183bcf964f88eb/</guid>
      <description>&lt;pre&gt;&lt;code&gt;由于工作没时间，博客搭建起来以后一直没有添加文件上传功能，瞬间感觉不完美了。这两天外包项目结束，要出项目组，在交接工作之余，用中午休息时间写好了文件上传功能，具体是图片上传。在本地测试好发布到BAE上，居然没法上传了，初步推断应该是服务器没有写权限，原来一直想试试百度云存储来做图片存储，但是翻看了文档发现暂不支持node.js上传，只能先上传好再引用链接，感觉好麻烦。&#xA;&#xA;由于一直在node中文社区混，发现用的是七牛存储，也想跟着大牛的步伐去试试，对开发文档进行两轮战斗，愣是没看懂，今天没事干，就从头到尾认认真真看了一遍，动手写了个测试程序，可以上传，激动万分，真想分享出来，但是测试程序还不完善，还没有把回调搞定，也没有完整的例子拿出来给大家看，等完全搞定了以后再写个教程卖弄一下。&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://qn-img.hopefly.top/FmVglKNoggGZd5y7hYMFg2iAMjeQ&#34; alt=&#34;&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>git常用命令</title>
      <link>https://blog.hopefly.top/blogdetail/54486c117b1470fa64bb911a/</link>
      <pubDate>Thu, 23 Oct 2014 02:46:41 +0000</pubDate>
      <guid>https://blog.hopefly.top/blogdetail/54486c117b1470fa64bb911a/</guid>
      <description>&lt;p&gt;&lt;strong&gt;查看、添加、提交、删除、找回，重置修改文件&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;git help &lt;!-- raw HTML omitted --&gt; # 显示command的help&lt;/p&gt;&#xA;&lt;p&gt;git show # 显示某次提交的内容 git show $id&lt;/p&gt;&#xA;&lt;p&gt;git co &amp;ndash; &lt;!-- raw HTML omitted --&gt; # 抛弃工作区修改&lt;/p&gt;&#xA;&lt;p&gt;git co . # 抛弃工作区修改&lt;/p&gt;&#xA;&lt;p&gt;git add &lt;!-- raw HTML omitted --&gt; # 将工作文件修改提交到本地暂存区&lt;/p&gt;&#xA;&lt;p&gt;git add . # 将所有修改过的工作文件提交暂存区&lt;/p&gt;&#xA;&lt;p&gt;git rm &lt;!-- raw HTML omitted --&gt; # 从版本库中删除文件&lt;/p&gt;&#xA;&lt;p&gt;git rm &lt;!-- raw HTML omitted --&gt; &amp;ndash;cached # 从版本库中删除文件，但不删除文件&lt;/p&gt;&#xA;&lt;p&gt;git reset &lt;!-- raw HTML omitted --&gt; # 从暂存区恢复到工作文件&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
