<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>运维笔记</title>
  <subtitle>一个领域如果不能做到Top,那就是一种伤害.</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://devops.osichina.net/"/>
  <updated>2018-04-19T14:45:48.131Z</updated>
  <id>https://devops.osichina.net/</id>
  
  <author>
    <name>明哥</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>关于LNMP 环境open_basedir restriction in effect报错问题</title>
    <link href="https://devops.osichina.net/2018/04/19/lnmpopen_basedir/"/>
    <id>https://devops.osichina.net/2018/04/19/lnmpopen_basedir/</id>
    <published>2018-04-19T14:45:12.859Z</published>
    <updated>2018-04-19T14:45:48.131Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="关于LNMP-环境open-basedir-restriction-in-effect报错问题"><a href="#关于LNMP-环境open-basedir-restriction-in-effect报错问题" class="headerlink" title="关于LNMP 环境open_basedir restriction in effect报错问题"></a>关于LNMP 环境open_basedir restriction in effect报错问题</h1><hr>
<h2 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h2><h3 id="nginx"><a href="#nginx" class="headerlink" title="nginx"></a>nginx</h3><figure class="highlight abnf"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">fastcgi_param PHP_ADMIN_VALUE <span class="string">"open_basedir=document_root/:/tmp/:/proc/"</span><span class="comment">;</span></div></pre></td></tr></table></figure>
<p>修改为<br><figure class="highlight nginx"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">fastcgi_param</span> PHP_ADMIN_VALUE <span class="string">"open_basedir=/data/log/walle/:<span class="variable">$document_root</span>/:/tmp/:/proc/"</span>;</div></pre></td></tr></table></figure></p>
<h3 id="php"><a href="#php" class="headerlink" title="php"></a>php</h3><p>打开注视添加你要访问的文件夹路径<br><figure class="highlight elixir"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">open_basedir = <span class="regexp">/data/log</span><span class="regexp">/walle/</span><span class="symbol">:/tmp/</span><span class="symbol">:/proc/</span></div></pre></td></tr></table></figure></p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;关于LNMP-环境open-basedir-restrictio
    
    </summary>
    
      <category term="运维归档" scheme="https://devops.osichina.net/categories/%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3/"/>
    
    
      <category term="lnmp" scheme="https://devops.osichina.net/tags/lnmp/"/>
    
  </entry>
  
  <entry>
    <title>加快ssh连接速度</title>
    <link href="https://devops.osichina.net/2018/04/19/%E5%8A%A0%E5%BF%ABssh%E8%BF%9E%E6%8E%A5%E9%80%9F%E5%BA%A6/"/>
    <id>https://devops.osichina.net/2018/04/19/加快ssh连接速度/</id>
    <published>2018-04-18T16:14:46.351Z</published>
    <updated>2018-04-18T16:15:09.321Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="加快ssh连接速度"><a href="#加快ssh连接速度" class="headerlink" title="加快ssh连接速度"></a>加快ssh连接速度</h1><hr>
<h2 id="客户端设置"><a href="#客户端设置" class="headerlink" title="客户端设置"></a>客户端设置</h2><ol>
<li><p>ssh客户端打开如下注释 /etc/ssh/ssh_config</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="string">Host</span> <span class="string">*</span></div><div class="line">        <span class="string">GSSAPIAuthentication</span> <span class="literal">no</span></div><div class="line">        <span class="string">GSSAPIDelegateCredentials</span> <span class="literal">no</span></div></pre></td></tr></table></figure>
</li>
<li><p>重启ssh服务</p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="regexp">/etc/i</span>nit.d<span class="regexp">/sshd restart</span></div></pre></td></tr></table></figure>
</li>
</ol>
<h2 id="服务端设置"><a href="#服务端设置" class="headerlink" title="服务端设置"></a>服务端设置</h2><ol>
<li>/etc/ssh/sshd_config<figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="string">UseDNS</span> <span class="literal">no</span></div><div class="line"><span class="string">GSSAPIAuthentication</span> <span class="literal">no</span></div></pre></td></tr></table></figure>
</li>
</ol>
<p>2.重启ssh<br><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">service sshd restart</span></div></pre></td></tr></table></figure></p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;加快ssh连接速度&quot;&gt;&lt;a href=&quot;#加快ssh连接速度&quot; 
    
    </summary>
    
      <category term="运维归档" scheme="https://devops.osichina.net/categories/%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3/"/>
    
    
      <category term="ssh" scheme="https://devops.osichina.net/tags/ssh/"/>
    
  </entry>
  
  <entry>
    <title>shell脚本结合zabbix玩转故障自愈</title>
    <link href="https://devops.osichina.net/2018/01/19/shell%E8%84%9A%E6%9C%AC%E7%BB%93%E5%90%88zabbix%E7%8E%A9%E8%BD%AC%E6%95%85%E9%9A%9C%E8%87%AA%E6%84%88/"/>
    <id>https://devops.osichina.net/2018/01/19/shell脚本结合zabbix玩转故障自愈/</id>
    <published>2018-01-18T16:27:06.000Z</published>
    <updated>2018-01-18T16:27:06.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="shell脚本结合zabbix玩转故障自愈"><a href="#shell脚本结合zabbix玩转故障自愈" class="headerlink" title="shell脚本结合zabbix玩转故障自愈"></a>shell脚本结合zabbix玩转故障自愈</h1><hr>
<blockquote>
<p>收到zabbix故障报警,匹配相应的规则触发不同的自愈机制.当然这个脚本功能不仅仅如此.</p>
</blockquote>
<p>[TOC]</p>
<h2 id="脚本作用"><a href="#脚本作用" class="headerlink" title="脚本作用"></a>脚本作用</h2><ul>
<li>利用zabbix实现故障自愈</li>
<li>http监控自愈</li>
<li>tcp端口监控自愈</li>
<li>微信/邮件消息通知</li>
<li>多方式远程批量执行</li>
<li>……</li>
</ul>
<h2 id="实现逻辑-Zabbix故障自愈"><a href="#实现逻辑-Zabbix故障自愈" class="headerlink" title="实现逻辑(Zabbix故障自愈)"></a>实现逻辑(Zabbix故障自愈)</h2><div id="flowchart-0" class="flow-chart"></div>

<h2 id="脚本内容"><a href="#脚本内容" class="headerlink" title="脚本内容"></a>脚本内容</h2><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">[root@<span class="keyword">blueking </span>policeRecover]<span class="comment"># tree -L 1</span></div><div class="line">.</div><div class="line">├── common.config       <span class="comment">#全局配置文件</span></div><div class="line">├── policeRecover.<span class="keyword">sh </span>   <span class="comment">#核心执行脚本</span></div><div class="line">├── rule.config         <span class="comment">#规则配置文件  </span></div><div class="line">└── temp                <span class="comment">#临时存储文件 </span></div><div class="line"><span class="number">1</span> <span class="keyword">directory, </span><span class="number">3</span> files</div></pre></td></tr></table></figure>
<h2 id="使用示例"><a href="#使用示例" class="headerlink" title="使用示例"></a>使用示例</h2><h3 id="zabbix添加告警自愈脚本和相应参数"><a href="#zabbix添加告警自愈脚本和相应参数" class="headerlink" title="zabbix添加告警自愈脚本和相应参数"></a>zabbix添加告警自愈脚本和相应参数</h3><h4 id="1-Actions设置"><a href="#1-Actions设置" class="headerlink" title="1. Actions设置"></a>1. Actions设置</h4><blockquote>
<p>对Actions进行特殊设置,Default subject / Default message ,消息内容是规则判断的主要依据。</p>
</blockquote>
<p>图1<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1515986777355.png" alt="Alt text"><br>图2<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1515986874756.png" alt="Alt text"><br>图3<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1515986918190.png" alt="Alt text"></p>
<ul>
<li><p>Default subject</p>
<figure class="highlight dust"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="xml"></span><span class="template-variable">&#123;EVENT.ID&#125;</span><span class="xml">_1#故障:</span><span class="template-variable">&#123;HOSTNAME1&#125;</span><span class="xml">:</span><span class="template-variable">&#123;TRIGGER.NAME&#125;</span><span class="xml"></span></div></pre></td></tr></table></figure>
</li>
<li><p>Default message</p>
<figure class="highlight coq"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">triggervalue|<span class="type">&#123;TRIGGER</span>.VALUE&#125;#hostname|<span class="type">&#123;HOSTNAME1</span>&#125;#ipaddress|<span class="type">&#123;IPADDRESS</span>&#125;#hostgroup|<span class="type">&#123;TRIGGER</span>.HOSTGROUP.NAME&#125;#triggernseverity|<span class="type">&#123;TRIGGER</span>.NSEVERITY&#125;#triggername|<span class="type">&#123;TRIGGER</span>.NAME&#125;#triggerkey|<span class="type">&#123;TRIGGER</span>.KEY1&#125;#triggeritems|<span class="type">&#123;ITEM</span>.NAME&#125;#itemvalue|<span class="type">&#123;ITEM</span>.VALUE&#125;#eventid|<span class="type">&#123;EVENT</span>.ID&#125;</div></pre></td></tr></table></figure>
</li>
</ul>
<p>Recovery operations</p>
<ul>
<li><p>Default subject</p>
<figure class="highlight dust"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="xml"></span><span class="template-variable">&#123;EVENT.ID&#125;</span><span class="xml">_0#已恢复:</span><span class="template-variable">&#123;HOSTNAME1&#125;</span><span class="xml">:</span><span class="template-variable">&#123;TRIGGER.NAME&#125;</span><span class="xml"></span></div></pre></td></tr></table></figure>
</li>
<li><p>Default message</p>
<figure class="highlight coq"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">triggervalue|<span class="type">&#123;TRIGGER</span>.VALUE&#125;#hostname|<span class="type">&#123;HOSTNAME1</span>&#125;#ipaddress|<span class="type">&#123;IPADDRESS</span>&#125;#hostgroup|<span class="type">&#123;TRIGGER</span>.HOSTGROUP.NAME&#125;#triggernseverity|<span class="type">&#123;TRIGGER</span>.NSEVERITY&#125;#triggername|<span class="type">&#123;TRIGGER</span>.NAME&#125;#triggerkey|<span class="type">&#123;TRIGGER</span>.KEY1&#125;#triggeritems|<span class="type">&#123;ITEM</span>.NAME&#125;#itemvalue|<span class="type">&#123;ITEM</span>.VALUE&#125;#eventid|<span class="type">&#123;EVENT</span>.ID&#125;</div></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="2-Media-types设置"><a href="#2-Media-types设置" class="headerlink" title="2. Media types设置"></a>2. Media types设置</h4><p><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1515987139203.png" alt="Alt text"></p>
<h4 id="3-Users-设置"><a href="#3-Users-设置" class="headerlink" title="3. Users 设置"></a>3. Users 设置</h4><blockquote>
<p>Users需要关联该报警自愈的媒介<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1515987538067.png" alt="Alt text"></p>
</blockquote>
<h4 id="4-上传脚本"><a href="#4-上传脚本" class="headerlink" title="4. 上传脚本"></a>4. 上传脚本</h4><blockquote>
<p>将policeRecover上传到Zabbix服务器的alertscripts目录,并修改为可执行权限</p>
</blockquote>
<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="selector-attr">[root@localhost policeRecover]</span># <span class="selector-tag">ls</span>   </div><div class="line"><span class="selector-tag">common</span><span class="selector-class">.config</span>  <span class="selector-tag">policeRecover</span><span class="selector-class">.sh</span>  <span class="selector-tag">rule</span><span class="selector-class">.config</span>  <span class="selector-tag">temp</span></div></pre></td></tr></table></figure>
<h3 id="磁盘空间不足-匹配规则配置后自动恢复"><a href="#磁盘空间不足-匹配规则配置后自动恢复" class="headerlink" title="磁盘空间不足,匹配规则配置后自动恢复"></a>磁盘空间不足,匹配规则配置后自动恢复</h3><h4 id="1-配置磁盘空间不足自愈规则-rule-config"><a href="#1-配置磁盘空间不足自愈规则-rule-config" class="headerlink" title="1. 配置磁盘空间不足自愈规则(rule.config)"></a>1. 配置磁盘空间不足自愈规则(rule.config)</h4><figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="string">serial:</span><span class="number">2</span>||<span class="string">env:</span>dev||<span class="string">isactive:</span><span class="number">1</span>||<span class="string">triggervalue:</span>&#123;=,<span class="number">1</span>&#125;||<span class="string">ipaddress:</span>&#123;like,<span class="number">192.168</span><span class="number">.3</span>%&#125;||<span class="string">triggername:</span>&#123;like,Free disk space is less than%&#125;||<span class="string">triggerkey:</span>&#123;=,vfs.fs.size[<span class="regexp">/var,pfree]&#125;||itemvalue:&#123;lt,20&#125;||cmd:echo '' &amp;&amp; echo 删除前/</span>var大小&amp;&amp; du -sh <span class="regexp">/var &amp;&amp; find  /</span>var<span class="regexp">/log/</span>logcenter<span class="regexp">/ -type f -mtime +10 -exec rm -f  &#123;&#125; \\; &amp;&amp;  echo 10天前的文件删除成功 &amp;&amp; echo 删除后/</span>var大小&amp;&amp; du -sh /var||<span class="string">ischeck:</span><span class="number">1</span>||<span class="string">returncode:</span><span class="number">0</span>||<span class="string">returnreqiure:</span>&#123;like,%成功%&#125;||<span class="string">returntimeout:</span><span class="number">60</span>||<span class="string">runlevel:</span><span class="number">5</span></div></pre></td></tr></table></figure>
<h4 id="2-自愈"><a href="#2-自愈" class="headerlink" title="2. 自愈"></a>2. 自愈</h4><ol>
<li><p>模拟触发报警<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516003846825.png" alt="Alt text"></p>
</li>
<li><p>zabbix收到报警<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516003919294.png" alt="Alt text"></p>
</li>
<li><p>触发自愈规则<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516003947260.png" alt="Alt text"></p>
</li>
<li><p>成功或失败发送微信或邮件消息<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516004208731.png" alt="Alt text"><br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516004059519.png" alt="Alt text"></p>
</li>
</ol>
<h3 id="应用端口不存在时-匹配规则配置后自动恢复"><a href="#应用端口不存在时-匹配规则配置后自动恢复" class="headerlink" title="应用端口不存在时,匹配规则配置后自动恢复"></a>应用端口不存在时,匹配规则配置后自动恢复</h3><h4 id="1-配置端口不存在自愈规则-rule-config"><a href="#1-配置端口不存在自愈规则-rule-config" class="headerlink" title="1. 配置端口不存在自愈规则(rule.config)"></a>1. 配置端口不存在自愈规则(rule.config)</h4><figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="string">serial:</span><span class="number">1</span>||<span class="string">env:</span>dev||<span class="string">isactive:</span><span class="number">1</span>||<span class="string">triggervalue:</span>&#123;=,<span class="number">1</span>&#125;||<span class="string">ipaddress:</span>&#123;=,<span class="number">192.168</span><span class="number">.3</span><span class="number">.85</span>&#125;||<span class="string">triggername:</span>&#123;like,<span class="number">8080</span> service is down on%&#125;||<span class="string">triggerkey:</span>&#123;=,net.tcp.port[,<span class="number">8080</span>]||<span class="string">itemvalue:</span>&#123;=,<span class="number">0</span>&#125;||<span class="string">cmd:</span><span class="regexp">/bin/</span>bash <span class="regexp">/usr/</span>local<span class="regexp">/tomcat/</span>bin/startup.sh  ||<span class="string">ischeck:</span><span class="number">1</span>||<span class="string">returncode:</span><span class="number">200</span>||<span class="string">returnreqiure:</span>&#123;like,%started%&#125;||<span class="string">returntimeout:</span><span class="number">60</span>||<span class="string">runlevel:</span><span class="number">1</span></div></pre></td></tr></table></figure>
<h4 id="2-自愈-1"><a href="#2-自愈-1" class="headerlink" title="2. 自愈"></a>2. 自愈</h4><ol>
<li>模拟端口不存在<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516005064690.png" alt="Alt text"></li>
</ol>
<p>2.触发报警和规则<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516006083542.png" alt="Alt text"></p>
<p>3.自愈成功<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516006154341.png" alt="Alt text"></p>
<p>4.失败的情况</p>
<blockquote>
<p>比如如果你的cmd配置错误<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516006234862.png" alt="Alt text"></p>
</blockquote>
<h3 id="接口返回异常时-匹配规则配置后自动恢复"><a href="#接口返回异常时-匹配规则配置后自动恢复" class="headerlink" title="接口返回异常时,匹配规则配置后自动恢复"></a>接口返回异常时,匹配规则配置后自动恢复</h3><h4 id="1-配置web监控-具体细节自行谷歌"><a href="#1-配置web监控-具体细节自行谷歌" class="headerlink" title="1. 配置web监控(具体细节自行谷歌)"></a>1. 配置web监控(具体细节自行谷歌)</h4><blockquote>
<p>监控url,校验返回码和require<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516006483161.png" alt="Alt text"></p>
</blockquote>
<h4 id="2-设置接口自愈规则"><a href="#2-设置接口自愈规则" class="headerlink" title="2. 设置接口自愈规则"></a>2. 设置接口自愈规则</h4><figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="string">serial:</span><span class="number">3</span>||<span class="string">env:</span>dev||<span class="string">isactive:</span><span class="number">1</span>||<span class="string">triggervalue:</span>&#123;=,<span class="number">1</span>&#125;||<span class="string">ipaddress:</span>&#123;=,<span class="number">192.168</span><span class="number">.3</span><span class="number">.102</span>&#125;||<span class="string">triggername:</span>&#123;like,首页<span class="number">200</span>监控%&#125;||<span class="string">triggerkey:</span>&#123;=,web.test.rspcode[<span class="number">3.102</span>首页,首页]||<span class="string">itemvalue:</span>&#123;=,<span class="number">404</span>&#125;||<span class="string">cmd:</span><span class="regexp">/etc/</span>init.d/nginx restart||<span class="string">ischeck:</span><span class="number">1</span>||<span class="string">returncode:</span><span class="number">200</span>||<span class="string">returnreqiure:</span>&#123;like,%success%&#125;||<span class="string">returntimeout:</span><span class="number">60</span></div></pre></td></tr></table></figure>
<h4 id="3-模拟网页404"><a href="#3-模拟网页404" class="headerlink" title="3. 模拟网页404"></a>3. 模拟网页404</h4><p>访问前<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516006598753.png" alt="Alt text"><br>模拟故障后<br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516006637038.png" alt="Alt text"></p>
<h4 id="4-触发报警和规则"><a href="#4-触发报警和规则" class="headerlink" title="4. 触发报警和规则"></a>4. 触发报警和规则</h4><p><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516006689434.png" alt="Alt text"></p>
<h4 id="5-自愈"><a href="#5-自愈" class="headerlink" title="5. 自愈"></a>5. 自愈</h4><p><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516009229515.png" alt="Alt text"></p>
<h3 id="自定义规则-执行相应的恢复操作"><a href="#自定义规则-执行相应的恢复操作" class="headerlink" title="自定义规则,执行相应的恢复操作"></a>自定义规则,执行相应的恢复操作</h3><blockquote>
<p>其他自定义规则,可以根据相应的返回KEY，做相应的自愈操作。<code>一切你想要自愈的操作都可以做到。</code><br>需要注意如果是salt-api/ansible等远程执行传参数的时候，如果传特殊符号需要转义，ansible也不支持管道等符号</p>
</blockquote>
<h2 id="功能说明"><a href="#功能说明" class="headerlink" title="功能说明"></a>功能说明</h2><h3 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h3><h4 id="全局配置文件-common-config"><a href="#全局配置文件-common-config" class="headerlink" title="全局配置文件:common.config"></a>全局配置文件:common.config</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#!/bin/bash</span></div><div class="line"><span class="comment">#基础配置文件</span></div><div class="line"><span class="comment">#1.0 规则配置相关</span></div><div class="line"><span class="comment">#skipRuleParams:规则配置中跳过校验的字段</span></div><div class="line"></div><div class="line"><span class="comment">#2.0 微信消息相关</span></div><div class="line"><span class="comment">#CropID:微信企业号CropID,后台可查</span></div><div class="line"><span class="comment">#Secret:微信企业号Secret,后台可查</span></div><div class="line"><span class="comment">#AppID:企业号中的应用id</span></div><div class="line"><span class="comment">#PartyID:企业号中的部门id,多个部门用‘|’分隔</span></div><div class="line"><span class="comment">#isSendAll:0(只发送给个人) 1(发送给部门所有人)</span></div><div class="line"><span class="comment">#sendUsers:部门成员id(微信号) 当isSendAll为0时发送给$&#123;sendUsers&#125;,多个用户用空格间隔</span></div><div class="line"></div><div class="line"><span class="comment">#3.0 发送邮件相关(telnet发送无需安装mutt等组件)</span></div><div class="line"><span class="comment">#smtp:邮件发送主机</span></div><div class="line"><span class="comment">#smtpDomain:邮件发送后缀域名,比如test@abc.com,则配置为abc.com</span></div><div class="line"><span class="comment">#from:邮件发送者</span></div><div class="line"><span class="comment">#usernameBase64:邮件用户名base64</span></div><div class="line"><span class="comment">#passwordBase64:邮件密码base64</span></div><div class="line"><span class="comment">#toEmail:发送给谁,多个收件人用空格间隔</span></div><div class="line"></div><div class="line"><span class="comment">#4.0 不同环境下的基础配置项</span></div><div class="line"><span class="comment">#*Conf为不同环境下的配置项目,规则配置中将会用到</span></div><div class="line"><span class="comment">#devConf开发环境配置</span></div><div class="line"><span class="comment">#testConf测试环境配置</span></div><div class="line"><span class="comment">#zzbConf准生产环境配置(预生产环境)</span></div><div class="line"><span class="comment">#comConf生产环境配置</span></div><div class="line"></div><div class="line"><span class="comment">#4.1 自愈远程执行方式一: 自定义api远程执行</span></div><div class="line"><span class="comment">#api:自定义api sync:是否同步(true或false默认异步) async:是否异步(true或false默认异步)  </span></div><div class="line"><span class="comment">#rex_env:执行环境(默认local,即本地环境)  auth_type:认证类型(可选:password,key,config)  、</span></div><div class="line"><span class="comment">#user:用户名  password:密码 salt_env:api的执行环境(默认saltapi-com,可选saltapi-dev)</span></div><div class="line"><span class="comment">#returncode:全局默认http返回码/bash执行返回码 returntimeout:全局默认http超时时间/bash连接超时时间</span></div><div class="line"></div><div class="line"><span class="comment">#4.2 自愈远程执行方式二: salt-api远程执行</span></div><div class="line"><span class="comment">#saltUrl:salt-api的url地址 saltUsername:salt-api的用户名 saltPassword:salt-api的密码 </span></div><div class="line"></div><div class="line"><span class="comment">#4.3 自愈远程执行方式三: ssh expect &amp;&amp; 自愈远程执行方式四: sshpass </span></div><div class="line"><span class="comment">#sshUsername:全局ssh用户名(如规则配置不存在取全局) sshPassword:全局ssh密码(如规则配置不存在取全局)</span></div><div class="line"></div><div class="line"><span class="comment">#4.4 自愈远程执行方式五: ssh免秘钥执行 &amp;&amp; 自愈远程执行方式六: ansible</span></div><div class="line"></div><div class="line"><span class="comment">#5.0 全局执行级别</span></div><div class="line"><span class="comment">#runlevel:当规则配置项不存在取全局默认执行方式</span></div><div class="line"><span class="comment">#runlevel:0(自定义api) 1(salt-api) 2(免秘钥ssh执行) 3(ssh expect函数执行) 4(ansible远程执行) 5(sshpass)</span></div></pre></td></tr></table></figure>
<h4 id="规则配置文件-rule-config"><a href="#规则配置文件-rule-config" class="headerlink" title="规则配置文件:rule.config"></a>规则配置文件:rule.config</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></div><div class="line"><span class="meta">#</span><span class="bash">规则库配置</span></div><div class="line"><span class="meta">#</span><span class="bash">一行代表1条规则配置,排除全局配置中配置的<span class="variable">$&#123;skipRuleParams&#125;</span>中要跳过校验的字段以外,其他字段都是必须校验的字段,以||为间隔</span></div><div class="line"><span class="meta"></span></div><div class="line">#<span class="bash">1.0 非规则库校验的字段</span></div><div class="line"><span class="meta">#</span><span class="bash">skipRuleParams</span></div><div class="line"><span class="meta">#</span><span class="bash">serial:序号(唯一) env:执行环境 dev:读取全局配置devConf <span class="built_in">test</span>:读取全局配置testConf  52zzb:读取全局配置zzbConf  com:读取全局配置comConf </span></div><div class="line"><span class="meta">#</span><span class="bash">isactive:0(不启用该条规则) 1(启用该条规则) </span></div><div class="line"><span class="meta">#</span><span class="bash">cmd:自愈执行命令   </span></div><div class="line"><span class="meta"></span></div><div class="line">#<span class="bash">1.1 自愈执行后校验返回结果</span></div><div class="line"><span class="meta">#</span><span class="bash">ischeck: 0(不校验返回结果) 1(校验返回结果)</span></div><div class="line"><span class="meta">#</span><span class="bash">returncode(http返回码/执行返回值) returnreqiure(返回内容判断) returntimeout(返回超时时间/连接超时时间,单位秒)</span></div><div class="line"><span class="meta"></span></div><div class="line">#<span class="bash">2.0 规则配置中远程执行方式</span></div><div class="line"><span class="meta">#</span><span class="bash">runlevel:0(自定义api) 1(salt-api) 2(免秘钥ssh执行) 3(ssh expect函数执行) 4(ansible远程执行) 5(sshpass) 不存在时:取全局的runlevel</span></div><div class="line"><span class="meta"></span></div><div class="line">#<span class="bash">3.0 规则库配置</span></div><div class="line"><span class="meta">#</span><span class="bash">除了skipRuleParams中排除的字段,其他字段为zabbix返回要校验的字段,可以为1个或多个字段(无限制,根据你的zabbix内容设置)</span></div><div class="line"><span class="meta">#</span><span class="bash">解释我使用到几个关键字段</span></div><div class="line"><span class="meta"></span></div><div class="line">#<span class="bash">3.1 举例</span></div><div class="line"><span class="meta">#</span><span class="bash">triggervalue:&#123;=,1&#125; 条件1: triggervalued=1时,也即故障报警时</span></div><div class="line"><span class="meta">#</span><span class="bash">ipaddress:&#123;=,192.168.3.102&#125; 条件2: 故障主机为192.168.3.102</span></div><div class="line"><span class="meta">#</span><span class="bash">triggername:&#123;like,Free disk space is less than%&#125; 条件3: 故障名称为Free disk space is less than开头时</span></div><div class="line"><span class="meta">#</span><span class="bash">triggerkey:&#123;=,vfs.fs.size[/var,pfree]&#125; 条件4: 故障报警的key,这里指的/var空间不足时</span></div><div class="line"><span class="meta">#</span><span class="bash">itemvalue:&#123;lt,20&#125; 条件5: 故障报警key的值,这里指的是/var的空间不足20%时</span></div><div class="line"><span class="meta">#</span><span class="bash">以上条件为并且条件,只有都成立时才会触发cmd自愈.也可以只有2个条件或者更多的条件比如条件4和条件2,看你的报警需求</span></div><div class="line"><span class="meta"></span></div><div class="line">#<span class="bash">3.2 规则库的规则格式</span></div><div class="line"><span class="meta">#</span><span class="bash">||zabbix设置的key:&#123;条件,预期值&#125;||</span></div><div class="line"><span class="meta"></span></div><div class="line">#<span class="bash">3.3 规则库的支持条件</span></div><div class="line"><span class="meta">#</span><span class="bash">数值比较(支持浮点数) gt:大于 lt:小于 ge:大于等于 le:小于等于 eq:等于</span></div><div class="line"><span class="meta">#</span><span class="bash">字符串相等 ＝</span></div><div class="line"><span class="meta">#</span><span class="bash">模糊匹配 string%: 以string开头    ％string: 以string结尾  ％string％: 中间包含string</span></div></pre></td></tr></table></figure>
<h3 id="日志"><a href="#日志" class="headerlink" title="日志"></a>日志</h3><p><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516259710984.png" alt="Alt text"><br><img src="https://gitee.com/lookingdreamer/policeRecover/raw/master/image/1516259836277.png" alt="Alt text"></p>
<h3 id="其他功能"><a href="#其他功能" class="headerlink" title="其他功能"></a>其他功能</h3><h4 id="告警收敛"><a href="#告警收敛" class="headerlink" title="告警收敛"></a>告警收敛</h4><blockquote>
<p>将收集到数据保存到redis或mongodb中,进行报警数据聚合和分析,分析出有价值的信息。后续在补充这个功能</p>
</blockquote>
<h4 id="脚本复用"><a href="#脚本复用" class="headerlink" title="脚本复用"></a>脚本复用</h4><h4 id="1-邮件消息发送"><a href="#1-邮件消息发送" class="headerlink" title="1. 邮件消息发送"></a>1. 邮件消息发送</h4><ol>
<li><p>邮件发送</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">sendMail <span class="string">"邮件的主体"</span> <span class="string">"邮件的内容"</span></div></pre></td></tr></table></figure>
</li>
<li><p>发送给某个传参过来的用户</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">toEmail=<span class="variable">$1</span></div><div class="line">sendMail <span class="string">"邮件的主体"</span> <span class="string">"邮件的内容"</span></div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="2-微信消息发送"><a href="#2-微信消息发送" class="headerlink" title="2. 微信消息发送"></a>2. 微信消息发送</h4><ol>
<li><p>微信消息</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">sendWeixin <span class="string">"微信消息"</span></div></pre></td></tr></table></figure>
</li>
<li><p>发送给某个传参过来的用户</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">sendUsers=<span class="variable">$1</span></div><div class="line">sendWeixin <span class="string">"微信消息"</span></div></pre></td></tr></table></figure>
</li>
<li><p>发送整个部门</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">isSendAll=0</div><div class="line">sendWeixin <span class="string">"微信消息"</span></div></pre></td></tr></table></figure>
</li>
<li><p>发送个某个部门</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">isSendAll=0</div><div class="line">PartyID=<span class="variable">$1</span></div><div class="line">sendWeixin <span class="string">"微信消息"</span></div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="3-远程执行"><a href="#3-远程执行" class="headerlink" title="3. 远程执行"></a>3. 远程执行</h4><ol>
<li><p>salt-API接口 </p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">getsaltToken <span class="string">"[saltUrl]"</span> <span class="string">"[saltUsername]"</span> <span class="string">"[saltPassword]"</span></div><div class="line">runsaltTask <span class="string">"[执行主机]"</span> <span class="string">"[执行命令]"</span> <span class="string">"[超时时间]"</span> <span class="string">"[临时文件]"</span> <span class="string">"[锁文件]"</span></div></pre></td></tr></table></figure>
</li>
<li><p>免秘钥ssh执行</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">keyLessRun  <span class="string">"[ssh用户名]"</span> <span class="string">"[执行主机]"</span> <span class="string">"[执行命令]"</span> <span class="string">"[超时时间]"</span> <span class="string">"[临时文件]"</span> <span class="string">"[锁文件]"</span></div></pre></td></tr></table></figure>
</li>
<li><p>[expect]ssh执行</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">sshExpectRun  <span class="string">"[ssh用户名]"</span> <span class="string">"[执行主机]"</span> <span class="string">"[执行命令]"</span> <span class="string">"[超时时间]"</span> <span class="string">"[临时文件]"</span> <span class="string">"[锁文件]"</span> <span class="string">"[ssh密码]"</span></div></pre></td></tr></table></figure>
</li>
<li><p>ansible远程执行</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">ansibleRun <span class="string">"[执行主机]"</span> <span class="string">"[执行命令]"</span> <span class="string">"[超时时间]"</span>  <span class="string">"[临时文件]"</span> <span class="string">"[锁文件]"</span></div></pre></td></tr></table></figure>
</li>
<li><p>sshpass远程执行</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># main "$1" "$2"</span></div><div class="line"><span class="built_in">source</span> <span class="variable">$&#123;commonConf&#125;</span></div><div class="line">sshPassRun  <span class="string">"[ssh用户名]"</span> <span class="string">"[执行主机]"</span> <span class="string">"[执行命令]"</span> <span class="string">"[超时时间]"</span> <span class="string">"[临时文件]"</span> <span class="string">"[锁文件]"</span> <span class="string">"[ssh密码]"</span></div></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="4-监控url返回码-不正常时重启应用"><a href="#4-监控url返回码-不正常时重启应用" class="headerlink" title="4. 监控url返回码,不正常时重启应用"></a>4. 监控url返回码,不正常时重启应用</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">code=$(curl -m 8 -o /dev/null -s -w  %&#123;http_code&#125; <span class="variable">$&#123;url&#125;</span>)</div><div class="line"><span class="keyword">if</span> [[  <span class="variable">$code</span> != <span class="string">"200"</span> ]];<span class="keyword">then</span></div><div class="line"><span class="comment">#执行上面的远程指令</span></div><div class="line"><span class="keyword">fi</span></div></pre></td></tr></table></figure>
<p><script src="https://devops.osichina.net/static/js/raphael.min.js"></script><script src="https://devops.osichina.net/static/js/flowchart.min.js"></script><textarea id="flowchart-0-code" style="display: none">zabbix_server=>start: zabbix服务端触发告警脚本
self_recover=>operation: zabbix服务端告警(自愈脚本)
analysis_alert_content=>operation: 分析告警内容以及参数
match_rule=>condition: 判断是否满足自愈规则
exit_action=>end: 退出操作
rule_cmd_run=>operation: 根据规则配置执行自愈操作
check_result=>condition: 根据规则配置校验自愈结果(是否成功)
run_cmd_fail=>end: 退出并触发微信和邮件报警
rule_center=>subroutine: 规则配置库
zabbix_server->self_recover->analysis_alert_content->rule_center->match_rule
match_rule(no)->exit_action
match_rule(yes)->rule_cmd_run->check_result
check_result(no)->run_cmd_fail</textarea><textarea id="flowchart-0-options" style="display: none">{"scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12}</textarea><script>  var code = document.getElementById("flowchart-0-code").value;  var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-0-options").value));  var diagram = flowchart.parse(code);  diagram.drawSVG("flowchart-0", options);</script></p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;shell脚本结合zabbix玩转故障自愈&quot;&gt;&lt;a href=&quot;
    
    </summary>
    
      <category term="运维归档" scheme="https://devops.osichina.net/categories/%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3/"/>
    
    
      <category term="zabbix自愈" scheme="https://devops.osichina.net/tags/zabbix%E8%87%AA%E6%84%88/"/>
    
      <category term="故障自愈" scheme="https://devops.osichina.net/tags/%E6%95%85%E9%9A%9C%E8%87%AA%E6%84%88/"/>
    
      <category term="多方式远程批量执行" scheme="https://devops.osichina.net/tags/%E5%A4%9A%E6%96%B9%E5%BC%8F%E8%BF%9C%E7%A8%8B%E6%89%B9%E9%87%8F%E6%89%A7%E8%A1%8C/"/>
    
  </entry>
  
  <entry>
    <title>mac添加路由</title>
    <link href="https://devops.osichina.net/2018/01/19/%E7%AC%AC3%E5%91%A8%20mac%E6%B7%BB%E5%8A%A0%E8%B7%AF%E7%94%B1/"/>
    <id>https://devops.osichina.net/2018/01/19/第3周 mac添加路由/</id>
    <published>2018-01-18T16:27:06.000Z</published>
    <updated>2018-01-18T16:27:06.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="mac添加路由"><a href="#mac添加路由" class="headerlink" title="mac添加路由"></a>mac添加路由</h1><h2 id="查看路由"><a href="#查看路由" class="headerlink" title="查看路由"></a>查看路由</h2><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">netstat -r</span></div></pre></td></tr></table></figure>
<h2 id="添加缺省路由"><a href="#添加缺省路由" class="headerlink" title="添加缺省路由"></a>添加缺省路由</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">route</span> <span class="selector-tag">-n</span> <span class="selector-tag">add</span> <span class="selector-tag">defalut</span>  10<span class="selector-class">.13</span><span class="selector-class">.31</span><span class="selector-class">.1</span></div></pre></td></tr></table></figure>
<h2 id="添加路由"><a href="#添加路由" class="headerlink" title="添加路由"></a>添加路由</h2><figure class="highlight lsl"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">route -n add   -net <span class="number">10.0</span><span class="number">.0</span><span class="number">.0</span>/<span class="number">8</span>  <span class="number">10.13</span><span class="number">.31</span><span class="number">.1</span></div></pre></td></tr></table></figure>
<h2 id="删除路由"><a href="#删除路由" class="headerlink" title="删除路由"></a>删除路由</h2><figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="selector-tag">route</span> <span class="selector-tag">-n</span> <span class="selector-tag">delete</span> <span class="selector-tag">defalut</span>  10<span class="selector-class">.13</span><span class="selector-class">.31</span><span class="selector-class">.1</span></div></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;mac添加路由&quot;&gt;&lt;a href=&quot;#mac添加路由&quot; clas
    
    </summary>
    
      <category term="运维归档" scheme="https://devops.osichina.net/categories/%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3/"/>
    
    
      <category term="mac添加路由" scheme="https://devops.osichina.net/tags/mac%E6%B7%BB%E5%8A%A0%E8%B7%AF%E7%94%B1/"/>
    
  </entry>
  
  <entry>
    <title>关于服务启动按钮页面的优化</title>
    <link href="https://devops.osichina.net/2018/01/19/%E7%AC%AC4%E5%91%A8%20%E5%85%B3%E4%BA%8E%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8%E6%8C%89%E9%92%AE%E9%A1%B5%E9%9D%A2%E7%9A%84%E4%BC%98%E5%8C%96/"/>
    <id>https://devops.osichina.net/2018/01/19/第4周 关于服务启动按钮页面的优化/</id>
    <published>2018-01-18T16:27:06.000Z</published>
    <updated>2018-01-18T16:27:06.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="关于服务启动按钮页面的优化"><a href="#关于服务启动按钮页面的优化" class="headerlink" title="关于服务启动按钮页面的优化"></a>关于服务启动按钮页面的优化</h1><hr>
<h2 id="原则"><a href="#原则" class="headerlink" title="原则"></a>原则</h2><blockquote>
<ol>
<li>同一个服务器只允许启动一个按钮,也就是只能触发一个启动/关闭/重启的功能。不同的服务器是可以同时异步触发的。</li>
<li>启动或关闭是异步进行的。</li>
<li>启动或关闭的时候，同一个服务器的上按钮变灰色，并且不能点击。</li>
</ol>
</blockquote>
<h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p><strong>由于妹子ui的模态框在数据传输存在bug,详情撮: <a href="http://amazeui.org/javascript/modal" rel="external nofollow noopener noreferrer" target="_blank">http://amazeui.org/javascript/modal</a></strong><br>所以在多个异步并发执行的时候出现各种Bug.</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">$(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</div><div class="line">  $(<span class="string">'#doc-modal-list'</span>).find(<span class="string">'.am-icon-close'</span>).add(<span class="string">'#doc-confirm-toggle'</span>).</div><div class="line">    on(<span class="string">'click'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</div><div class="line">      $(<span class="string">'#my-confirm'</span>).modal(&#123;</div><div class="line">        <span class="attr">relatedTarget</span>: <span class="keyword">this</span>,</div><div class="line">        <span class="attr">onConfirm</span>: <span class="function"><span class="keyword">function</span>(<span class="params">options</span>) </span>&#123;</div><div class="line">          <span class="keyword">var</span> $link = $(<span class="keyword">this</span>.relatedTarget).prev(<span class="string">'a'</span>);</div><div class="line">          <span class="keyword">var</span> msg = $link.length ? <span class="string">'你要删除的链接 ID 为 '</span> + $link.data(<span class="string">'id'</span>) :</div><div class="line">            <span class="string">'确定了，但不知道要整哪样'</span>;</div><div class="line">          alert(msg);</div><div class="line">        &#125;,</div><div class="line">        <span class="comment">// closeOnConfirm: false,</span></div><div class="line">        onCancel: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</div><div class="line">          alert(<span class="string">'算求，不弄了'</span>);</div><div class="line">        &#125;</div><div class="line">      &#125;);</div><div class="line">    &#125;);</div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<blockquote>
<p> 通过 relatedTarget 这个钩子获取数据，如上面的演示，以该元素为桥梁获取想要的数据（2.1 开始支持）；</p>
</blockquote>
<p><strong>最初代码的引用</strong><br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">'#my-confirm'</span>).modal(&#123;</div><div class="line">        <span class="attr">relatedTarget</span>: <span class="keyword">this</span>,</div><div class="line">        <span class="attr">onConfirm</span>: <span class="function"><span class="keyword">function</span>(<span class="params">options</span>) </span>&#123;</div><div class="line"></div><div class="line">            <span class="keyword">if</span> (start_store != <span class="literal">undefined</span>) &#123;</div><div class="line">              $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span> + start_store.alias + <span class="string">'] 正在启动,请等待启动完成或使用批量启动.'</span>);  </div><div class="line">              $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">              <span class="keyword">return</span>;</div><div class="line">            &#125;<span class="keyword">else</span>&#123;</div><div class="line">              store.set(<span class="string">'start_store'</span>, &#123; <span class="attr">code</span>: <span class="string">'1'</span>, <span class="attr">alias</span>: dename &#125;)  </div><div class="line">            &#125;;</div><div class="line"></div><div class="line">            my_this = <span class="keyword">this</span>.relatedTarget;</div><div class="line">            $.ajax(&#123;</div><div class="line">             <span class="attr">type</span>: <span class="string">"POST"</span>,</div><div class="line">             <span class="attr">async</span>:<span class="literal">true</span>,</div><div class="line">             <span class="attr">url</span>: <span class="string">"/api/service"</span>,</div><div class="line">             <span class="attr">cache</span>: <span class="literal">false</span>,</div><div class="line">             <span class="attr">data</span>: data,</div><div class="line">             <span class="attr">dataType</span>: <span class="string">"json"</span>,</div><div class="line">             <span class="attr">success</span>: <span class="function"><span class="keyword">function</span>(<span class="params">res</span>)</span>&#123;</div><div class="line">                <span class="keyword">var</span> alias =  res.data.data[<span class="number">0</span>].alias;             </div><div class="line">                <span class="keyword">var</span> code =  res.data.data[<span class="number">0</span>].code;             </div><div class="line">                <span class="keyword">var</span> reskey =  res.data.data[<span class="number">0</span>].key;             </div><div class="line">                <span class="keyword">var</span> msg =  res.data.data[<span class="number">0</span>].msg;             </div><div class="line">                <span class="keyword">var</span> resnetwork_ip =  res.data.data[<span class="number">0</span>].network_ip;             </div><div class="line">                <span class="built_in">console</span>.log(res);</div><div class="line"></div><div class="line">                <span class="keyword">if</span> ( code == <span class="number">1</span> ) &#123;</div><div class="line">                    $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+alias+<span class="string">'启动成功!'</span>);  </div><div class="line">                    $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">                    closeloading(my_this);</div><div class="line">                &#125;<span class="keyword">else</span>&#123;</div><div class="line">                    $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+alias+<span class="string">']启动失败,'</span>+msg+<span class="string">'!'</span>);  </div><div class="line">                    $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">                    closeloading(my_this);</div><div class="line">                &#125;</div><div class="line">                store.remove(<span class="string">'start_store'</span>);</div><div class="line">                closeloading(my_this);</div><div class="line">                </div><div class="line"></div><div class="line">                </div><div class="line"></div><div class="line">            &#125;,</div><div class="line">            <span class="attr">error</span>:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;     </div><div class="line">                $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+$(my_this).attr(<span class="string">"dename"</span>)+<span class="string">'] 请求失败,请联系管理员!'</span>);  </div><div class="line">                $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">                closeloading(my_this);</div><div class="line">                store.remove(<span class="string">'start_store'</span>);     </div><div class="line">            &#125; </div><div class="line">        &#125;);</div><div class="line"></div><div class="line">        &#125;,</div><div class="line"></div><div class="line">        <span class="attr">onCancel</span>: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</div><div class="line">          my_this = <span class="keyword">this</span>.relatedTarget; </div><div class="line">          closeloading(my_this);</div><div class="line">          <span class="comment">// var store = $.AMUI.store;</span></div><div class="line">          store.remove(<span class="string">'start_store'</span>);</div><div class="line">        &#125;</div><div class="line"></div><div class="line">  &#125;);</div></pre></td></tr></table></figure></p>
<p><strong>改进后代码的引用</strong><br><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">'#my-confirm'</span>).modal(&#123;</div><div class="line">       relatedTarget: <span class="keyword">this</span>,</div><div class="line">       onConfirm: function(options) &#123;</div><div class="line">           <span class="keyword">var</span> my_this ;</div><div class="line">           my_this = <span class="keyword">this</span>.relatedTarget;</div><div class="line">           <span class="keyword">if</span> (start_store != undefined) &#123;</div><div class="line">             $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span> + start_store.alias + <span class="string">'] 正在启动,请等待启动完成或使用批量启动.'</span>);  </div><div class="line">             $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">             closeloading(my_this);</div><div class="line">             <span class="keyword">return</span>;</div><div class="line">           &#125;<span class="keyword">else</span>&#123;</div><div class="line">             store.<span class="keyword">set</span>(<span class="string">'run_service_allow_one'</span>, &#123; code: <span class="string">'1'</span>, alias: dename &#125;)  </div><div class="line">           &#125;;</div><div class="line">           <span class="keyword">data</span> = store.<span class="keyword">get</span>(<span class="string">'data'</span>);</div><div class="line">           </div><div class="line">           $.ajax(&#123;</div><div class="line">            type: <span class="string">"POST"</span>,</div><div class="line">            async:<span class="literal">true</span>,</div><div class="line">            url: <span class="string">"/api/service"</span>,</div><div class="line">            cache: <span class="literal">false</span>,</div><div class="line">            <span class="keyword">data</span>: <span class="keyword">data</span>,</div><div class="line">            dataType: <span class="string">"json"</span>,</div><div class="line">            success: function(res)&#123;</div><div class="line">               console.log(<span class="string">'get res result:'</span>);</div><div class="line">               console.log(res);</div><div class="line">               <span class="comment">// </span></div><div class="line">               <span class="keyword">var</span> code =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].code; </div><div class="line">               console.log(code);</div><div class="line">               <span class="keyword">if</span> (code == <span class="number">10020</span>) &#123;</div><div class="line">                   $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].related_servername+<span class="string">']'</span>+res.msg + <span class="string">'&lt;br/&gt; 最后时间: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].updated_time + <span class="string">'&lt;br/&gt; 动作: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].action + <span class="string">' 操作人: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].operation );  </div><div class="line">                   $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">                   closeloading(my_this);</div><div class="line">               &#125; <span class="keyword">else</span> <span class="keyword">if</span> (code == <span class="number">10041</span>)&#123;                   </div><div class="line">                   $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].related_servername+<span class="string">']'</span>+res.msg + <span class="string">'&lt;br/&gt; 最后时间: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].updated_time + <span class="string">'&lt;br/&gt; 动作: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].action + <span class="string">' 操作人: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].operation );  </div><div class="line">                   $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">                   closeloading(my_this);</div><div class="line">               &#125;<span class="keyword">else</span> <span class="keyword">if</span> (code == <span class="number">10042</span>)&#123;</div><div class="line">                   $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].related_servername+<span class="string">']'</span>+res.msg + <span class="string">'&lt;br/&gt; 最后时间: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].updated_time + <span class="string">'&lt;br/&gt; 动作: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].action + <span class="string">' 操作人: '</span>+ res.get_status.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].operation );  </div><div class="line">                   $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">                   closeloading(my_this);                </div><div class="line">               &#125;<span class="keyword">else</span> <span class="keyword">if</span> (code == <span class="number">1</span> )&#123;</div><div class="line">                   <span class="keyword">var</span> alias =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].alias;           </div><div class="line">                   <span class="keyword">var</span> reskey =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].key;             </div><div class="line">                   <span class="keyword">var</span> msg =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].msg;             </div><div class="line">                   <span class="keyword">var</span> resnetwork_ip =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].network_ip;                                     </div><div class="line">                   $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+alias+<span class="string">'启动成功!'</span>);  </div><div class="line">                   $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">                   closeloading(my_this);</div><div class="line">               &#125;<span class="keyword">else</span>&#123;</div><div class="line">                   <span class="keyword">var</span> alias =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].alias;           </div><div class="line">                   <span class="keyword">var</span> reskey =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].key;             </div><div class="line">                   <span class="keyword">var</span> msg =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].msg;             </div><div class="line">                   <span class="keyword">var</span> resnetwork_ip =  res.<span class="keyword">data</span>.<span class="keyword">data</span>[<span class="number">0</span>].network_ip; </div><div class="line">                   console.log(my_this);                   </div><div class="line">                   $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+alias+<span class="string">']启动失败,'</span>+msg+<span class="string">'!'</span>);  </div><div class="line">                   $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">                   closeloading(my_this);                  </div><div class="line">               &#125;</div><div class="line"></div><div class="line"></div><div class="line">               store.remove(<span class="string">'run_service_allow_one'</span>);</div><div class="line">               closeloading(my_this);</div><div class="line">               </div><div class="line"></div><div class="line">               </div><div class="line"></div><div class="line">           &#125;,</div><div class="line">           error:function()&#123;     </div><div class="line">               $(<span class="string">"#msgtips"</span>).html(<span class="string">'[服务器名称:'</span>+$(my_this).attr(<span class="string">"dename"</span>)+<span class="string">'] 请求失败,请联系管理员!'</span>);  </div><div class="line">               $(<span class="string">'#my-alert'</span>).modal(<span class="string">'open'</span>);</div><div class="line">               closeloading(my_this);</div><div class="line">               store.remove(<span class="string">'run_service_allow_one'</span>);     </div><div class="line">           &#125; </div><div class="line">       &#125;);</div><div class="line"></div><div class="line">       &#125;,</div><div class="line"></div><div class="line">       onCancel: function() &#123;</div><div class="line">         <span class="keyword">var</span> my_this ;</div><div class="line">         my_this = <span class="keyword">this</span>.relatedTarget; </div><div class="line">         closeloading(my_this);</div><div class="line">         <span class="comment">// var store = $.AMUI.store;</span></div><div class="line">         store.remove(<span class="string">'run_service_allow_one'</span>);</div><div class="line">       &#125;</div><div class="line"></div><div class="line"> &#125;);</div></pre></td></tr></table></figure></p>
<blockquote>
<ul>
<li>我这边的主要的问题现象:   <blockquote>
<ol>
<li>同一个页面点击启动，再次点击启动或关闭，还是上一次的post传参。</li>
<li>正在启动中或者关闭中的那个提示在点击多次时后面不能正常返回。比如我同时点击了启动和关闭，然后页面显示启动中和关闭中，然后返回数据后，启动中按钮变回启动，但是关闭中一直没返回。</li>
</ol>
</blockquote>
</li>
</ul>
</blockquote>
<h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>针对以上的问题后面的代码已经解决，主要是妹子ui模态框传参的Bug问题，调用多次模态框模块框只会保存第一次运行时的数据。</p>
<blockquote>
<p><strong>第1个问题: </strong>  通过store存储传参，每点击一次覆盖前一次的参数。(可能存在的问题: 如果启用无缝浏览则无法传data参数，如果点击过快参数赋值就会错乱，但是这种情况应该很少，参数赋值那块也就微妙级别，人的手工基本不会达到那种地步) 还有种方法就是通过relatedTarget钩子重新获取数据。推荐这个方法。</p>
<p><strong>第2个问题:</strong>  其实使用了relatedTarget钩子，但变量初始化的时候存在问题，之前没有var 定义局部变量，导致后面点击有可能获取全局变量的数据，导致my_this对象串了。重新初始化变量就OK了。 </p>
</blockquote>
<p>上图:<br><img src="./1497499300390.png" alt="Alt text"></p>
<p><img src="./1497499360424.png" alt="Alt text"></p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;关于服务启动按钮页面的优化&quot;&gt;&lt;a href=&quot;#关于服务启动按
    
    </summary>
    
      <category term="运维归档" scheme="https://devops.osichina.net/categories/%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3/"/>
    
    
      <category term="服务控制" scheme="https://devops.osichina.net/tags/%E6%9C%8D%E5%8A%A1%E6%8E%A7%E5%88%B6/"/>
    
      <category term="启动构思" scheme="https://devops.osichina.net/tags/%E5%90%AF%E5%8A%A8%E6%9E%84%E6%80%9D/"/>
    
      <category term="思路优化" scheme="https://devops.osichina.net/tags/%E6%80%9D%E8%B7%AF%E4%BC%98%E5%8C%96/"/>
    
      <category term="前端" scheme="https://devops.osichina.net/tags/%E5%89%8D%E7%AB%AF/"/>
    
  </entry>
  
  <entry>
    <title>应用的日志分析、对比以及实践</title>
    <link href="https://devops.osichina.net/2018/01/19/%E7%AC%AC5%E5%91%A8%20%E5%BA%94%E7%94%A8%E7%9A%84%E6%97%A5%E5%BF%97%E5%88%86%E6%9E%90%E3%80%81%E5%AF%B9%E6%AF%94%E4%BB%A5%E5%8F%8A%E5%AE%9E%E8%B7%B5/"/>
    <id>https://devops.osichina.net/2018/01/19/第5周 应用的日志分析、对比以及实践/</id>
    <published>2018-01-18T16:27:06.000Z</published>
    <updated>2018-01-18T16:27:06.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="应用的日志分析、对比以及实践"><a href="#应用的日志分析、对比以及实践" class="headerlink" title="应用的日志分析、对比以及实践"></a>应用的日志分析、对比以及实践</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>随着业务量的增长，服务器的增长，同时应用日志的数量也是呈现几何的速度增长。大部分人的认为日志数据对业务来说只是开发人员排除故障的依据，除此以外对业务而言是没有任何的意义的。我相信，对很多人的认知来说日志也就那么点的作用。不可或缺，但是也是很鸡肋。需要它的时候，迫不及待，不需要它的时候弃之如敝履。</p>
</blockquote>
<h2 id="作用"><a href="#作用" class="headerlink" title="作用"></a>作用</h2><blockquote>
<ul>
<li>常见作用: 排问题，查日志（<code>点</code>）</li>
</ul>
<ol>
<li>日志记录代码的执行记录，记录异常信息，排查代码的隐藏bug</li>
<li>记录业务逻辑，查询业务上的问题或者追踪相关信息</li>
</ol>
<ul>
<li>非常见作用: 数据分析（<code>面</code>）</li>
</ul>
<ol>
<li>根据错误日志的错误处，统计错误率，针对性的对代码进行优化</li>
<li>根据时间轨迹，可以统计出业务的集中时间和接口调用次数等统计</li>
<li>统计用户业务轨迹</li>
<li>…….更多的数据价值待挖掘，比如从日志中统计用户类型、用户访问习惯、用户停留时间、用户的等待时间等等各个方面，针对性的优化应用，提升用户的访问体验。</li>
</ol>
</blockquote>
<h2 id="变化"><a href="#变化" class="headerlink" title="变化"></a>变化</h2><p>到目前为止，参照我们系统(<small> 某上市互联网保险中介 </small>)应用，就日志而言，我们经历了以下几个时间段的变化，也经历很多方面的尝试。就目前我们的应用日志系统经历了以下的变化:</p>
<p><div id="flowchart-0" class="flow-chart"></div></p>
<ul>
<li><p><strong>原生时代</strong></p>
<blockquote>
<p><strong>描述:</strong> 早期的终端原生时代，由于业务和服务器的规模不是很大，针对应用的日志并没有做相应的的处理和优化。都只是应用容器本身的日志处理，开发需要看日志就去对应的服务器上看相应的日志。比如tomcat下自由log4j下的catalina.out等等。</p>
<p><strong>特点:</strong> 方便，对开发相对友好，因为在自己的PC开发环境中，开发更加习惯在文本或者终端查看日志。但是在linux平台下查看应用日志，需要具体的一定的Linux日志命令的相关基础知识，如tail、awk等</p>
</blockquote>
</li>
<li><p><strong>nfs共享</strong></p>
<blockquote>
<p><strong>描述:</strong> 随着业务规模的增加，服务器的数量增长，应用日志的数量也在增加。通常一个业务还有7到8个集群节点的日志，这时候如果还是采用的原生时代的日志查看方式会显得的很费力。查一个日志可能要登陆10多个终端在日志当中去排除问题。所以在这时候的我们考虑将日志归集到一起，这样就避免了开多个服务器去看日志的问题。</p>
<p><strong>特点:</strong> 相对于原生时代来说，其实没有发生了什么变化。只是不需要登陆多个服务器，只登陆一台服务器就能看到所有服务器的日志。</p>
</blockquote>
</li>
<li><p><strong>splunk</strong></p>
<blockquote>
<p><strong>描述:</strong> 这是一款商业的日志系统，集合日志收集、处理、分析等一体的日志解决方案。当日志文件超过500M就要收费的。但就它的功能而言，各方面的表现都非常不错的。web可视化，日志异常，资源占用率等很不错。唯一的是，基于当时的业务情况并不适合在日志收集去投入额外的资产支出，所以后续就放弃了。</p>
<p><strong>特点:</strong>  采用CS结构，各方面的都比较优秀。</p>
</blockquote>
</li>
<li><p><strong>log.io日志系统</strong></p>
<blockquote>
<p><strong>描述:</strong> 这是一款开源的实时日志系统，它只实时显示日志，并不对日志做存储。也是C/S结构，采用node的语言编写而成。</p>
<p><strong>特点:</strong>  采用CS结构，小巧易于使用。</p>
</blockquote>
</li>
<li><p><strong>elk</strong></p>
<blockquote>
<p><strong>描述:</strong> 这是一款开源的集中式日志系统，也是目前很多互联网公司主推的开源日志系统。ELK 其实并不是一款软件，而是一整套解决方案，是三个软件产品的首字母缩写，Elasticsearch，Logstash 和 Kibana。从日志收集、聚合、全文搜索、展现等拥有一套完整的解决方案。社区和文档也比较完善，可以进行自定义二次开发。</p>
<p><strong>特点:</strong>  采用CS结构，功能强大。</p>
</blockquote>
</li>
<li><p><strong>flume</strong></p>
<blockquote>
<p><strong>描述:</strong> 这是一款开源的日志收集的解决方案，并不对日志进行分析，flume是一个高可用的，高可靠的，分布式的海量日志采集、聚合和传输的系统。通过与kafka等结合做日志解决方案。<br><strong>特点:</strong>  采用CS结构，可扩展性强，存储丰富比如HDFS. </p>
</blockquote>
</li>
<li><p><strong>自研平台</strong></p>
<blockquote>
<p><strong>描述:</strong> 综合业务等个方面的特点自定义的开发日志系统。<br><strong>特点:</strong>  自主性强、适合业务的可持续性扩展。</p>
</blockquote>
</li>
</ul>
<p><strong>使用对比</strong><br><img src="http://devops-1251049439.cosgz.myqcloud.com/1499073183511.png" alt="Alt text"></p>
<h2 id="调研"><a href="#调研" class="headerlink" title="调研"></a>调研</h2><p> <strong>前置环境:</strong></p>
<blockquote>
<p>服务器数量: 40 +<br>应用容器类型: tomcat/resin/php等<br>日志大小:  500M &gt; size &lt; 5G<br>环境: 集群环境</p>
</blockquote>
<p><strong>需求调研</strong></p>
<blockquote>
<ol>
<li>方便开发人员查询日志，排除故障</li>
<li>不占用系统资源，一般日志系统采用C/S结构，客户端的资源占用率必须保障在3%以下</li>
<li>扩展性强，易于进行二次开发</li>
</ol>
</blockquote>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>目前在行业内日志处理方案，有开源的，也有商业级别，也可以自行开发。至于你要选择什么解决方案，完全要依赖于你的业务需求和环境，如果你有更加高的要求的日志要求，且对费用没什么担心，商业版本的日志解决方案无疑是最佳的解决方案。如果你的资产投入有限，或者想自定义日志的系统，开源或者自研也是可以的。选择最合适业务，然后去调研、测试，来最贴近你的业务需求。</p>
<p><script src="https://devops.osichina.net/static/js/raphael.min.js"></script><script src="https://devops.osichina.net/static/js/flowchart.min.js"></script><textarea id="flowchart-0-code" style="display: none">st=>start: 原生时代
e=>end: 自研平台
op=>operation: syslog-ng
op1=>operation: nfs共享
op2=>operation: splunk
op3=>operation: log.io日志系统
op4=>operation: elk
op5=>operation: flume
st->op->op1->op2->op3->op4->op5->e</textarea><textarea id="flowchart-0-options" style="display: none">{"scale":1,"line-width":2,"line-length":50,"text-margin":10,"font-size":12}</textarea><script>  var code = document.getElementById("flowchart-0-code").value;  var options = JSON.parse(decodeURIComponent(document.getElementById("flowchart-0-options").value));  var diagram = flowchart.parse(code);  diagram.drawSVG("flowchart-0", options);</script></p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;应用的日志分析、对比以及实践&quot;&gt;&lt;a href=&quot;#应用的日志分
    
    </summary>
    
      <category term="运维归档" scheme="https://devops.osichina.net/categories/%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3/"/>
    
    
      <category term="日志系统对比和分析" scheme="https://devops.osichina.net/tags/%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F%E5%AF%B9%E6%AF%94%E5%92%8C%E5%88%86%E6%9E%90/"/>
    
  </entry>
  
  <entry>
    <title>windows自定义程序开机启动</title>
    <link href="https://devops.osichina.net/2017/06/18/%E7%AC%AC2%E5%91%A8%20windows%E8%87%AA%E5%AE%9A%E4%B9%89%E7%A8%8B%E5%BA%8F%E5%BC%80%E6%9C%BA%E5%90%AF%E5%8A%A8/"/>
    <id>https://devops.osichina.net/2017/06/18/第2周 windows自定义程序开机启动/</id>
    <published>2017-06-18T13:24:33.000Z</published>
    <updated>2018-01-18T16:27:06.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="windows自定义程序开机启动"><a href="#windows自定义程序开机启动" class="headerlink" title="windows自定义程序开机启动"></a>windows自定义程序开机启动</h1><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><blockquote>
<p>每次开机之后要手工启动各种服务，有一些程序是自带了添加服务项，添加到开机启动，有一些则没有。昨天刚装完机器，什么开机启动需要自己添加，所以整理了一下开机启动的相关技巧。</p>
</blockquote>
<h2 id="windows开启开机启动方法"><a href="#windows开启开机启动方法" class="headerlink" title="windows开启开机启动方法"></a>windows开启开机启动方法</h2><blockquote>
<ul>
<li>服务启动<br><small> 服务启动是电脑启动时，用户登陆之前启动，有系统服务程序控制。</small></li>
<li>启动项启动<br><small> 启动项是用户登陆之后启动的。</small></li>
</ul>
</blockquote>
<h2 id="服务启动"><a href="#服务启动" class="headerlink" title="服务启动"></a>服务启动</h2><h3 id="添加服务启动"><a href="#添加服务启动" class="headerlink" title="添加服务启动"></a>添加服务启动</h3><p><strong>启动example</strong></p>
<blockquote>
<p>sc create <code>服务名</code> binPath= <code>&quot;路径&quot;</code> start= auto type= share<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sc <span class="keyword">create</span> Frpc binPath= <span class="string">"C:/frpc/windows/start.bat"</span> <span class="keyword">start</span>= <span class="keyword">auto</span> <span class="keyword">type</span>= <span class="keyword">share</span></div></pre></td></tr></table></figure></p>
</blockquote>
<h2 id="cmd添加服务存在问题"><a href="#cmd添加服务存在问题" class="headerlink" title="cmd添加服务存在问题"></a>cmd添加服务存在问题</h2><blockquote>
<p>通过sc创建的服务在启动的报错: <code>服务没有响应控制功能</code><br>但是！不是所有程序都可以作为服务的方式运行，因为作为服务运行需要能返回运行情况等信息，所以有的程序添加后会出现以下提示：<br>Windows无法启动 XXX 服务（位于 本地计算机上）。错误1053:服务没有及时响应启动或者控制请求。<br><strong>解决方法:</strong><br>既然知道了原因，就有了解决办法，微软有一个srvany.exe可以解决此问题，首先创建一个服务，但是执行文件要选择srvany.exe，然后在另外的属性里面加入要执行的文件信息就可以了。（提前下载srvany.exe到C:\Windows目录下,不要放System32文件夹，因为64位系统会出现兼容性问题）<br>Srvany.exe下载地址 <a href="http://u.x2009.net/q" rel="external nofollow noopener noreferrer" target="_blank">http://u.x2009.net/q</a></p>
</blockquote>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">sc create ServiceName binPath= <span class="string">"C:\Windows\srvany.exe"</span> start= auto</div><div class="line"><span class="comment">#加入要执行的文件的信息</span></div><div class="line">reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName\Parameters /v Application /t REG_SZ /d <span class="string">"这里填入你要作为服务运行的程序地址比如c:\xxx.exe"</span> /f</div><div class="line">reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName\Parameters /v AppParameters /t REG_SZ /d <span class="string">"如果程序需要参数则填在这里，如果不需要，清空这段文字或者整行"</span> /f</div><div class="line">reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName\Parameters /v Application /t REG_SZ /d <span class="string">"这里填入程序运行时所在文件夹（作为环境变量），如果不填，则清除这段内容或者直接删除本行"</span> /f</div><div class="line">然后启动服务即可。(其中一条命令即可)</div></pre></td></tr></table></figure>
<figure class="highlight dos"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sc <span class="built_in">start</span> ServiceName</div><div class="line"><span class="built_in">net</span> <span class="built_in">start</span> ServiceName</div></pre></td></tr></table></figure>
<p>因为操作较为复杂，所以有人写了一款软件，叫SrvanyUI，集成了了srvany.exe，新建服务较为简单（打开软件，点增加服务，选自建服务即可达到相同效果）。<br>SrvanyUI下载地址 <a href="http://u.x2009.net/l" rel="external nofollow noopener noreferrer" target="_blank">http://u.x2009.net/l</a><br>注意:以上所有命令都需要管理员权限才能运行，如果是Windows 8/8.1/10，需要SYSTEM权限才行（在开始菜单里找到命令行提示符，右键里面有使用管理员身份运行）</p>
<h3 id="删除服务启动"><a href="#删除服务启动" class="headerlink" title="删除服务启动"></a>删除服务启动</h3><p><strong>删除example</strong></p>
<blockquote>
<p>sc delete <code>服务名</code><br><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sc <span class="keyword">delete</span> Frpc</div></pre></td></tr></table></figure></p>
</blockquote>
<h2 id="启动项启动"><a href="#启动项启动" class="headerlink" title="启动项启动"></a>启动项启动</h2><p>直接将启动文件丢在以下目录中: <code>C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup</code></p>
<h2 id="windows后台执行"><a href="#windows后台执行" class="headerlink" title="windows后台执行"></a>windows后台执行</h2><blockquote>
<p>有时候定制cmd的会一直显示console的终端，以下为定制后台执行的方法。<br>start.vbe:<br><figure class="highlight routeros"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="builtin-name">set</span> <span class="attribute">ws</span>=wscript.createobject("wscript.shell")</div><div class="line">ws.<span class="builtin-name">run</span> <span class="string">"C:/frpc/windows/start.bat /start"</span>,0</div></pre></td></tr></table></figure></p>
<p>注意如果开了360软件请将加入可信。</p>
</blockquote>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;windows自定义程序开机启动&quot;&gt;&lt;a href=&quot;#wind
    
    </summary>
    
      <category term="运维归档" scheme="https://devops.osichina.net/categories/%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3/"/>
    
    
      <category term="运维笔记" scheme="https://devops.osichina.net/tags/%E8%BF%90%E7%BB%B4%E7%AC%94%E8%AE%B0/"/>
    
      <category term="windows服务" scheme="https://devops.osichina.net/tags/windows%E6%9C%8D%E5%8A%A1/"/>
    
      <category term="开机启动" scheme="https://devops.osichina.net/tags/%E5%BC%80%E6%9C%BA%E5%90%AF%E5%8A%A8/"/>
    
  </entry>
  
  <entry>
    <title>运维归档的起始</title>
    <link href="https://devops.osichina.net/2017/06/09/%E7%AC%AC1%E5%91%A8%20%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3%E7%9A%84%E8%B5%B7%E5%A7%8B/"/>
    <id>https://devops.osichina.net/2017/06/09/第1周 运维归档的起始/</id>
    <published>2017-06-09T09:24:33.000Z</published>
    <updated>2018-01-18T16:27:06.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="第1周-运维归档的起始"><a href="#第1周-运维归档的起始" class="headerlink" title="第1周 运维归档的起始"></a>第1周 运维归档的起始</h1><h2 id="运维归档的前言"><a href="#运维归档的前言" class="headerlink" title="运维归档的前言"></a>运维归档的前言</h2><blockquote>
<p>很早之前就想对自己这几年的运维经验作为一个全面的总结，然后由于各种原因<code>(借口)</code>一直没有行动起来。最近才下定决心开始的运维总结和归纳之旅,其实之前也一直做笔记和归纳，看了下我的印象笔记和文档总结，不下于2000篇笔记和文档，精华性的文档总结预计在200篇左右。从14年开通了开源中国的博客，断断续续的写了90多篇博客文章，推荐博客也有上10篇。截止目前的访问量: <code>17万</code> </p>
</blockquote>
<h2 id="总结和归纳的意义"><a href="#总结和归纳的意义" class="headerlink" title="总结和归纳的意义"></a>总结和归纳的意义</h2><blockquote>
<ul>
<li>加深自己对知识的理解 </li>
<li>强迫症患者 <small>(在印象笔记 || 收藏的标签 || 收集的一些资料中,记录了很多的小技巧和知识点,但是这些点很凌乱,看起来的不是很规整,很想将这些知识点重整化为一个整体)</small></li>
<li>传道者 <small>不觉得的自己技术能力有多牛掰，但是还是希望能在运维知识的价值传播上做作出自己的一点贡献</small></li>
<li>开源精神<small>无处不在开源精神，分享快乐</small> </li>
</ul>
</blockquote>
<h2 id="就定一个小目标"><a href="#就定一个小目标" class="headerlink" title="就定一个小目标"></a>就定一个小目标</h2><ol>
<li>1周至少一篇总结和归纳</li>
<li>分享的内容不做限制，可以是技术、生活经验、工作总结、管理和沟通等方面</li>
<li>分享方式<ul>
<li><a href="https://devops.osichina.net">个人博客</a> <small><code>[首发]</code></small></li>
<li><a href="https://my.oschina.net/pwd/home" rel="external nofollow noopener noreferrer" target="_blank">开源博客</a>  </li>
<li><a href="https://devops.osichina.net">微信公众号</a>  <small>公众号还在紧急筹备当中…</small></li>
</ul>
</li>
</ol>
<h2 id="近期在做的事"><a href="#近期在做的事" class="headerlink" title="近期在做的事"></a>近期在做的事</h2><blockquote>
<p>从年初开始一直到现在一直在做运维平台化的工作,也即是devops的筹备和开展工作。<strong>为什么要做运维平台化？怎么开展运维平台化的工作？运维平台化的工作中遇到什么了什么样的问题？针对中小企业如何去推动运维平台化和价值化的发展？带着这些问题我后续会单独在一个篇幅中去介绍和分享</strong></p>
</blockquote>
<h2 id="开源项目"><a href="#开源项目" class="headerlink" title="开源项目"></a>开源项目</h2><blockquote>
<p><a href="http://git.oschina.net/lookingdreamer/RexDeploy_v1" rel="external nofollow noopener noreferrer" target="_blank">自动化发布系统</a><br><small>基于Rex开发的一个自动化发布平台，基于终端的发布版本。后来其实一直做了很多BUG改进和改版，但是一些原因一直没有发布，打算在7月底在放一个更全面的可视化的自动发布系统版本,敬请期待。</small></p>
</blockquote>
<h2 id="关于我"><a href="#关于我" class="headerlink" title="关于我"></a>关于我</h2><blockquote>
<ol>
<li>2012年大学毕业</li>
<li>2012-至今 某上市互联网保险中介  运维经理</li>
<li><strong>专长领域:</strong>  <code>脚本编程</code>、<code>开源工具党</code>、<code>自动化运维</code>、<code>自动化部署</code>、<code>运维价值化</code>、<code>全栈工程师</code></li>
<li><strong>经验简述:</strong> 早期参与IDC机房的建设，设计大数据的容灾系统，以及主导和规划IDC上公有云和金融云，从无到有开发了基于运维的自动化发布系统，目前致力于自动化运维和价值化运维的研究。</li>
</ol>
</blockquote>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;第1周-运维归档的起始&quot;&gt;&lt;a href=&quot;#第1周-运维归档的
    
    </summary>
    
      <category term="运维归档" scheme="https://devops.osichina.net/categories/%E8%BF%90%E7%BB%B4%E5%BD%92%E6%A1%A3/"/>
    
    
      <category term="运维笔记|运维价值|前言" scheme="https://devops.osichina.net/tags/%E8%BF%90%E7%BB%B4%E7%AC%94%E8%AE%B0-%E8%BF%90%E7%BB%B4%E4%BB%B7%E5%80%BC-%E5%89%8D%E8%A8%80/"/>
    
  </entry>
  
  <entry>
    <title>svn 钩子开启</title>
    <link href="https://devops.osichina.net/2017/04/24/1/"/>
    <id>https://devops.osichina.net/2017/04/24/1/</id>
    <published>2017-04-24T09:24:33.000Z</published>
    <updated>2017-06-08T13:53:24.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><p>svn 钩子开启</p>
<p>背景:<br>公司的Svn很多人在用，有不少人在作修改后不添加注释，所以需要强制用户填写注释。<br>操作：<br>1.<br>重命名svn主目录中hooks的pre-commit.tmpl文件为pre-commit，并添加可执行权限<br><figure class="highlight vim"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">mv <span class="keyword">pre</span>-commit.tmpl <span class="keyword">pre</span>-commit</div><div class="line">chmod <span class="keyword">u</span>+<span class="keyword">x</span> <span class="keyword">pre</span>-commit</div></pre></td></tr></table></figure></p>
<ol>
<li>编辑pre-commit文件</li>
</ol>
<!-- -->
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">export</span> LANG=<span class="string">"zh_CN.UTF-8"</span></div><div class="line">REPOS=<span class="string">"<span class="variable">$1</span>"</span></div><div class="line">TXN=<span class="string">"<span class="variable">$2</span>"</span></div><div class="line"></div><div class="line"><span class="comment"># Make sure that the log message contains some text.</span></div><div class="line">SVNLOOK=/usr/bin/svnlook</div><div class="line"><span class="comment">#$SVNLOOK log -t "$TXN" "$REPOS" | \</span></div><div class="line"><span class="comment"># grep "[a-zA-Z0-9]" &gt; /dev/null || exit 1</span></div><div class="line"></div><div class="line">commit_type=$(svnlook changed -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span>)</div><div class="line"><span class="comment">#以下后缀可以不填写注释</span></div><div class="line">except_list=<span class="string">".txt,.docx,.doc,.xls,.xlsx,.ppt,/"</span></div><div class="line">num=0</div><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> $(<span class="built_in">echo</span> -e <span class="string">"<span class="variable">$except_list</span>"</span> |sed <span class="string">"s/,/\n/g"</span>)</div><div class="line"><span class="keyword">do</span></div><div class="line">    sum=$(<span class="built_in">echo</span> -e <span class="string">"<span class="variable">$commit_type</span>"</span> |grep <span class="string">"<span class="variable">$i</span>$"</span> |wc -l)</div><div class="line">    <span class="keyword">if</span> <span class="built_in">test</span>[ <span class="variable">$sum</span> -ne 0 ];<span class="keyword">then</span></div><div class="line">        num=$(expr <span class="variable">$num</span> + 1 )</div><div class="line">    <span class="keyword">fi</span></div><div class="line"><span class="keyword">done</span></div><div class="line">total=$(<span class="built_in">echo</span> -e <span class="string">"<span class="variable">$commit_type</span>"</span> |wc -l)</div><div class="line"></div><div class="line"><span class="keyword">if</span> <span class="built_in">test</span>[ <span class="variable">$num</span> -eq <span class="variable">$total</span> ];<span class="keyword">then</span></div><div class="line">    <span class="built_in">exit</span> 0</div><div class="line"><span class="keyword">fi</span></div><div class="line"></div><div class="line"><span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span> &gt; /tmp/aaa.txt</div><div class="line"></div><div class="line"><span class="comment">#强制用户提交注释,注释格式要求:bug/task+数字(任务数字编号)+注释(大于10)</span></div><div class="line">TEMP_LENGTH=`<span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span>|sed <span class="string">'s/\s*$//g'</span>|sed <span class="string">'s/^\s*//g'</span>| wc --chars` <span class="comment"># 获取字符数量(包括换行符)</span></div><div class="line">TEMP_LINE=`<span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span>| wc --lines` <span class="comment"># 统计换行符</span></div><div class="line">LOGMSG_LENGTH=`expr <span class="variable">$TEMP_LENGTH</span> - <span class="variable">$TEMP_LINE</span>` <span class="comment"># 真实字符数量</span></div><div class="line">task=$( <span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span> |grep <span class="string">"^task\-[0-9]*[0-9]\-"</span> |wc -l )</div><div class="line">bug=$( <span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span> |grep <span class="string">"^bug\-[0-9]*[0-9]\-"</span> |wc -l )</div><div class="line">emrg=$( <span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span> |grep <span class="string">"^emrg\-[0-9]*[0-9]\-"</span> |wc -l )</div><div class="line">getlaststring=$(<span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span>|grep -o <span class="string">"^task\-[0-9]*[0-9]\-\|^bug\-[0-9]*[0-9]\-\|^emrg\-[0-9]*[0-9]\-"</span>)</div><div class="line">content=$(<span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span>|sed <span class="string">'s/\s*$//g'</span>|sed <span class="string">'s/^\s*//g'</span>)</div><div class="line"></div><div class="line"><span class="keyword">if</span> <span class="built_in">test</span>[ <span class="variable">$LOGMSG_LENGTH</span> -eq 0 ];<span class="keyword">then</span></div><div class="line">    <span class="built_in">echo</span> <span class="string">"【注释】<span class="variable">$content</span>"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">echo</span> <span class="string">"【注意】注释不能为空,请重新填写注释!!!"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">echo</span> <span class="string">"【格式】:bug/task/emrg-数字任务编号-注释(大于10)"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">exit</span> 1</div><div class="line"><span class="keyword">fi</span></div><div class="line"></div><div class="line"><span class="keyword">if</span> <span class="built_in">test</span>[ <span class="variable">$task</span> -eq 0 &amp;&amp; <span class="variable">$bug</span> -eq 0 &amp;&amp; <span class="variable">$emrg</span> -eq 0 ];<span class="keyword">then</span></div><div class="line">    <span class="built_in">echo</span> <span class="string">"【注释】<span class="variable">$content</span>"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">echo</span> <span class="string">"【注意】注释必须以bug或者task开头,后面加-和数字编号,请重新填写注释!!!"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">echo</span> <span class="string">"【格式】:bug/task/emrg-数字任务编号-注释(大于10)"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">exit</span> 1</div><div class="line"><span class="keyword">fi</span></div><div class="line"></div><div class="line">commemt=$(<span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span>|sed <span class="string">'s/\s*$//g'</span>|sed <span class="string">'s/^\s*//g'</span>|sed <span class="string">"s/^<span class="variable">$getlaststring</span>//g"</span>| wc --chars)</div><div class="line">commemt_line=$(<span class="variable">$SVNLOOK</span> <span class="built_in">log</span> -t <span class="string">"<span class="variable">$TXN</span>"</span> <span class="string">"<span class="variable">$REPOS</span>"</span> |sed <span class="string">"s/^<span class="variable">$getlaststring</span>//g"</span>|wc --lines)</div><div class="line">commemt_length=$( expr <span class="variable">$commemt</span> - <span class="variable">$commemt_line</span>)</div><div class="line"></div><div class="line"><span class="keyword">if</span> <span class="built_in">test</span> <span class="string">"<span class="variable">$commemt_length</span>"</span> -lt 10 ;</div><div class="line"><span class="keyword">then</span></div><div class="line">    <span class="built_in">echo</span> <span class="string">"【注释】<span class="variable">$content</span>"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">echo</span> <span class="string">"【注意】注释必须超过10个字符,请重新填写注释!!!"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">echo</span> <span class="string">"【格式】:bug/task/emrg-数字任务编号-注释(大于10)"</span> 1&gt;&amp;2</div><div class="line">    <span class="built_in">exit</span> 1</div><div class="line"><span class="keyword">fi</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="comment"># Check that the author of this commit has the rights to perform</span></div><div class="line"><span class="comment"># the commit on the files and directories being modified.</span></div><div class="line"><span class="comment">#commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1</span></div><div class="line"></div><div class="line"><span class="comment"># All checks passed, so allow the commit.</span></div><div class="line"><span class="built_in">exit</span></div></pre></td></tr></table></figure>
<p>一、问题</p>
<pre><code>* pre-commit等钩子有做一些检查，如果有问题就echo错误信息，但出错信息是中文的，svn客户端无法显示，提示如下
</code></pre><p>Error output could not be translated from the native locale to UTF-8.</p>
<p>我们尝试过以下方法，但都没有解决</p>
<ul>
<li><p>修改pre-commit的编码，修改LANG</p>
<p>  export LANG=zh_CN.UTF-8<br>  export LC_ALL=zh_CN.UTF-8</p>
</li>
<li><p>修改Apache的编码</p>
</li>
</ul>
<!-- -->
<pre><code>AddDefaultCharset UTF-8
</code></pre><ul>
<li>采用http发布，而不是https</li>
</ul>
<p>结论：网上的解决方案只对svn://这种直接用svnserve发布出来的仓库才有效</p>
<p>二、 解决方案</p>
<p>Subversion 1.8特性</p>
<p>SVNUseUTF8 On</p>
<p>它的作用就是使得Apache的mod_dav_svn模块，在和pre-commit等钩子通讯的时候，使用utf-8编码，可以参考mod_dav_svn</p>
<p>升级</p>
<p>我们系统是CentOS 6.2，比较简单，有个第三方，走了Subversion<br>1.8的rpm包，yum即可，主要是更新了2个rpm包</p>
<pre><code>* subversion-1.8.15-1.x86_64
* mod_dav_svn-1.8.15-1.x86_64
</code></pre><p>具体升级操作</p>
<pre><code>cat &gt; /etc/yum.repos.d/wandisco-svn.repo &lt;&lt;EOF

[WandiscoSVN]

name=Wandisco SVN Repo

baseurl=http://opensource.wandisco.com/centos/6/svn-1.8/RPMS/\$basearch/

enabled=1

gpgcheck=0

EOF



yum install subversion -y
</code></pre><p>修改httpd.conf并重启httpd</p>
<pre><code>&lt;IfModule mod_dav_fs.c&gt;

    # Location of the WebDAV lock database.

    DAVLockDB /var/lib/dav/lockdb

    SVNUseUTF8 On

&lt;/IfModule&gt;
</code></pre><p>/etc/init.d/httpd graceful</p>
<p>升级后的测试</p>
<p>需要做些测试，确保升级后不会有问题，测试列表如下</p>
<pre><code>* commit
* update
* log
* merge
* copy签出版本
</code></pre><p>注意问题:</p>
<p>服务器版本是1.8，如果客户端是1.6，则只能checkout，不能update，1.7没有问题，建议客户端至少1.8</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;p&gt;svn 钩子开启&lt;/p&gt;
&lt;p&gt;背景:&lt;br&gt;公司的Svn很多人在用，有不
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>nginx 反向代理问题小结</title>
    <link href="https://devops.osichina.net/2016/10/27/2/"/>
    <id>https://devops.osichina.net/2016/10/27/2/</id>
    <published>2016-10-27T04:16:15.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><p>nginx 反向代理问题小结</p>
<pre><code>location /Autops

{

proxy\_pass http://a.test.com;

}
</code></pre><p>① 循环跳转，nginx条件判断跳出</p>
<p>在nginx中配置好，死活都无法跳转。</p>
<p>通过F12查看,其实已经跳转过去了,但是接口在认证的地方循环在跳转。</p>
<p><img src="http://static.oschina.net/uploads/space/2016/1027/121711_NFbV_1452345.png" alt="">{width=”554”<br>height=”115”}</p>
<p>应该是登陆接口路由有问题，由于我请求的对方接口是直接访问，无需路由。<br>所以的添加条件判断，请求完接口之后,直接退出。(此处应该去检查登陆路由，由于时间关系，直接采取回避的方法。)</p>
<p>匹配到/Autops/api接口下的任何请求，请求完毕之后直接break,不往下请求。</p>
<pre><code>location /Autops/api/{

if (-e \$document\_root/Autops/api/dbuser/\$request\_uri) {

    rewrite \^/(.\*)\$ /Autops/api/dbuser/\$1 break;

     break;

}

}



location / {

    try\_files \$uri \$uri/  /Autops/web/index.php?\$args;

}
</code></pre><p>顺便了解下 try_files 的作用:<br> 按照顺序请求如上地址,如果不存在或匹配不到会访问最后一个参数。也即是改写参数。</p>
<p>② 请求跳转是不跳转非index文件</p>
<p>原服务器地址: <a href="http://oa.baoxian.in/Autops/api/dbuser/dbuser.php" rel="external nofollow noopener noreferrer" target="_blank">http://b.test.com/Autops/api/dbuser/dbuser.php</a></p>
<p>实际跳转的是:<a href="http://devops.52zzb.com/Autops/api/dbuser/dbuser.php" rel="external nofollow noopener noreferrer" target="_blank">http://a.test.com/Autops/api/dbuser/dbuser.php</a></p>
<p>实际的结果是 怎么都无法跳转<br>，但是实际的访问接口是可以访问到。通过查看access日志,根本没有跳转过去，当你不加文件的时候是可以正常跳转过去的，也就是</p>
<p>原服务器地址: <a href="http://oa.baoxian.in/Autops/api/dbuser/dbuser.php" rel="external nofollow noopener noreferrer" target="_blank">http://b.test.com/Autops/api/dbuser/</a></p>
<p>实际跳转的是:<a href="http://devops.52zzb.com/Autops/api/dbuser/dbuser.php" rel="external nofollow noopener noreferrer" target="_blank">http://a.test.com/Autops/api/dbuser/</a></p>
<p>可以正常跳转，也就是当你直接访问接口的文件，即使你加上了反向代理，也是不会跳转的，而是直接访问当前服务器的应用。(低级错误！！！！)</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;p&gt;nginx 反向代理问题小结&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;locatio
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>Perl与数据库DBI快速入门</title>
    <link href="https://devops.osichina.net/2016/08/15/3/"/>
    <id>https://devops.osichina.net/2016/08/15/3/</id>
    <published>2016-08-15T12:51:17.000Z</published>
    <updated>2017-06-08T13:53:24.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="Perl与数据库DBI快速入门"><a href="#Perl与数据库DBI快速入门" class="headerlink" title="Perl与数据库DBI快速入门"></a>Perl与数据库DBI快速入门</h1><p>上次的文章<a href="http://log4think.com/perl_fast_tutorial/" rel="external nofollow noopener noreferrer" target="_blank">Perl无废话入门指南</a>中，简单的介绍了Perl的开发环境。为了完成提到的任务，还需要做几个知识点。无论是写脚本还是做CGI，如何使用Perl来访问数据库就是很有用的一个知识。</p>
<p>各种语言和开发环境访问数据库有各种不同的方式，比如可以用C和数据库提供的API接口来进行访问，也可以用JDBC、ODBC、ADO等封装好的统一接口来进行访问。Perl访问数据库最常用的包是DBI，可以在<a href="http://www.cpan.org/" rel="external nofollow noopener noreferrer" target="_blank">www.cpan.org</a>找到。另外还需要安装对应数据库的驱动包，例如DBD::MySQL、DBD::Oracle、DBD::Sybase或者DBD::ODBC等。具体的安装方法请参考上期文章，在此就不赘述了。</p>
<p>下文以常见的MySQL为例，说说如何实现对数据库的操作。</p>
<h2 id="1-基本流程"><a href="#1-基本流程" class="headerlink" title="1 基本流程"></a>1 基本流程</h2><p>习惯在Windows下开发数据库、熟悉ADO、ADO.NET的朋友，一定对ADOConnection/ADODataSet/ADOTable等类耳熟能详。DBI的接口与之类似，但在操作方法上又有不同，对ADO熟悉的朋友不妨比较一下异同。一般来说，数据库操作由以下几个步骤组成一个常见的流程：</p>
<p>1． 建立一个数据库连接</p>
<p>2． 通过建立的数据库连接，执行SQL语句</p>
<p>3． 执行SQL后获取返回的数据集</p>
<p>4． 在数据集中对记录进行处理，一般是一个循环的过程</p>
<p>5． 处理完毕，关闭数据库连接，释放资源</p>
<p>下面是按照上述的流程，在Perl中访问MySQL的一段代码，以这段代码为例，详细说明DBI的使用方法。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#!/usr/bin/perl -w</span></div><div class="line"><span class="keyword">use</span> <span class="title">strict</span>;</div><div class="line"><span class="keyword">use</span> <span class="title">DBI</span>;</div><div class="line"></div><div class="line">my $dbh = DBI-&gt;connect(<span class="string">"DBI:mysql:test:192.168.1.2"</span>, <span class="string">'root'</span>, <span class="string">'password'</span>);</div><div class="line">my $sth = $dbh-&gt;prepare(<span class="string">"SELECT * FROM test1"</span>);</div><div class="line">$sth-&gt;execute();</div><div class="line"></div><div class="line"><span class="keyword">while</span> ( my @row = $sth-&gt;fetchrow_array() )</div><div class="line">&#123;</div><div class="line">       <span class="keyword">print</span> join(<span class="string">'\t'</span>, @row).<span class="string">"\n"</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line">$sth-&gt;finish();</div><div class="line">$dbh-&gt;disconnect();</div></pre></td></tr></table></figure>
<p>注意代码中的灰色部分就是要特别关注的数据库访问接口，这里展现的只是一部分，下面将会依次说明每一个步骤，以及其它的操作在Perl中是如何实现的。</p>
<h3 id="1-1-连接数据库"><a href="#1-1-连接数据库" class="headerlink" title="1.1 连接数据库"></a>1.1 连接数据库</h3><pre><code>my $dbh = DBI-&gt;connect(&quot;DBI:mysql:test:192.168.1.2&quot;, &apos;root&apos;, &apos;password&apos;);
</code></pre><p>调用DBI的方法<code>DBI-&gt;connect</code>来建立一个数据库的连接，如果连接成功则返回一个数据库连接句柄，之后执行SQL等操作都要把这个连接句柄作为一个操作参数。在connect调用中，首先要提供一个数据库连接串。这个连接串用冒号分为了几个部分，请看下表</p>
<p>  小节          说明</p>
<hr>
<p>  DBI           接口类型<br>  mysql         数据库类型<br>  test          数据库名称<br>  192.168.1.2   数据库主机地址</p>
<p>在前面例子中的连接串中，DBI表示这是DBI接口的一个连接串；mysql表示要连接的数据库是MySQL数据库（如果要连接Oracle数据库，这里则是oracle），不同的数据库有不同的连接串定义，可以参考DBI对应的访问驱动的说明；test指明了连接到数据库主机上的数据库名称；192.168.1.2就是MySQL服务器的IP地址。这里要注意的是，连接串中的数据库类型mysql必须小写。如果省略了主机名，则缺省为localhost。connect方法的后面两个参数是连接数据库主机的用户名和密码，这个可是不可缺少的<br>J</p>
<p>如果在连接过程中出现任何错误，则connect的返回值都会是undef（和C语言中的NULL是一回事）。这里为了简化而略去了错误检查，实际做项目的时候应当对这些错误和返回值的进行检查。</p>
<h3 id="1-2-执行SQL语句"><a href="#1-2-执行SQL语句" class="headerlink" title="1.2 执行SQL语句"></a>1.2 执行SQL语句</h3><pre><code>my $sth = $dbh-&gt;prepare(&quot;SELECT * FROM test1&quot;);
$sth-&gt;execute();

$dbh-&gt;do(“UPDATE test1 SET time=now()”);
</code></pre><p>连接上了数据库，获得了数据库连接句柄，就可以利用这个句柄来对数据库进行操作了。要执行一条SQL语句，为了提高性能，DBI分两个步骤来做。先把SQL语句通过prepare方法提交到数据库，数据库为该语句分配执行资源，之后调用execute方法通知数据库执行该SQL语句。注意prepare方法是通过数据库连接句柄调用的，如果成功则返回一个该SQL的句柄，之后通过该SQL语句句柄调用execute执行SQL。<br>一般来说execute执行的都是返回数据的语句（例如SELECT语句）。反之如果执行INSERT、UPDATE、DELETE、CREATE<br>TABLE等不需要返回数据的语句，则有一个更方便、快速的方法 <code>$dbh-&gt;do(SQL语句)</code>，可以省去prepare的步骤。do方法返回的是受该SQL影响的记录数量。</p>
<h4 id="1-2-1-技巧：对SQL进行排版"><a href="#1-2-1-技巧：对SQL进行排版" class="headerlink" title="1.2.1 技巧：对SQL进行排版"></a>1.2.1 技巧：对SQL进行排版</h4><p>常写大段SQL的朋友可能会对于SQL中的引号很头痛，每每都因为引号的问题搞的SQL语句乱成一团分辨不清。还记得上篇文章讲过的qq吗？这里正是它的好用处。由于qq中的字符串同双引号”<br>”内的字符串一样会对变量进行解释，同时qq还可以换行。因此使用它来对SQL进行排版是非常好的一个选择，例如像这样的一条SQL语句：</p>
<pre><code>my $res_operator = $dbhandle-&gt;prepare( qq{
       SELECT o_customerid, COUNT(*) AS totalMsgNum FROM mm4fcdrs
       WHERE (m_date&gt;&apos;$begindate&apos;) AND (m_date&lt;&apos;enddate&apos;) 
       GROUP BY o_customerid 
});
</code></pre><p>根本无需考虑引号的问题，可以和正常情况一样的写SQL，是不是方便了很多？</p>
<h4 id="1-2-2-通过SQL语句中的参数优化查询执行效率"><a href="#1-2-2-通过SQL语句中的参数优化查询执行效率" class="headerlink" title="1.2.2 通过SQL语句中的参数优化查询执行效率"></a>1.2.2 通过SQL语句中的参数优化查询执行效率</h4><p>在执行大量INSERT之类的语句的时候，反复向数据库服务器提交同样结构的一个SQL语句，在这种情况下可以利用prepare和SQL参数来优化执行效率：</p>
<p>1．先使用prepare提交一个SQL模板给数据库服务器，把其中值的部分用参数占位符代替。<br>2．使用prepare让服务器为该SQL准备了执行资源后，调用execute并在该方法中传入参数实际的值执行SQL。<br>3．之后可以反复调用execute，不需要服务器重新prepare</p>
<p>假设要执行这样的一个系列的SQL</p>
<pre><code>INSERT INTO test1 VALUES (NULL, ‘a’, ‘2005-04-01’)
... ...
INSERT INTO test1 VALUES (NULL, ‘z’, ‘2005-04-01’)
</code></pre><p>其中第二个字段的值是从a到z的字母。那么可以这样来优化执行效率：</p>
<pre><code>my $sth = $dbh-&gt;prepare( qq{
    INSERT INTO test1 VALUES (NULL, ?, ‘2005-04-01’)
} );

for my $value(&apos;a&apos;..&apos;z&apos;)  {
    $sth-&gt;execute($value);
}
</code></pre><p>其中的问号就是前面说的参数占位符了，它的意思就是告诉在准备执行资源的服务器：这个SQL的这个位置会有一个值，但是现在还不知道，等下执行的时候再告诉你。<br>prepare了之后，用一个循环产生a-z的字符给变量\$value，然后将\$value在execute方法中作为一个参数传入，服务器那里会自动用传入的值替换前面的\”?\”。需要提醒的是，传入的参数个数一定要和SQL中的占位符的数量一样。</p>
<h3 id="1-3-读取记录"><a href="#1-3-读取记录" class="headerlink" title="1.3 读取记录"></a>1.3 读取记录</h3><p>熟悉ADO的朋友一定知道里面有一个DataReader对象，DBI中读取数据的方法和它非常的相似。简单来说，就是单向、流式的读取数据，也就是每次只能向后读一条数据直到没有数据可以读取。</p>
<p>文章开头的例子中，用了 <code>$sth-&gt;fetchrow_array()</code> 方法来读取数据。其实DBI读取数据还有几种常见的方法，这几个方法是类似的，所不同的是返回记录的形式。</p>
<h4 id="1-3-1-fetchrow-array"><a href="#1-3-1-fetchrow-array" class="headerlink" title="1.3.1 fetchrow_array"></a>1.3.1 fetchrow_array</h4><p>返回一个由字段的值组成的数组。该数组的第1个元素就是当前记录第1个字段的值。</p>
<pre><code>while ( my @row = $sth-&gt;fetchrow_array() )  {
    print &quot;$row[0], $row[1], $row[2]\n&quot;;
}
</code></pre><p>或者这样，不过要注意字段对应的顺序</p>
<pre><code>while ( my ($id, $name, $time) = $sth-&gt;fetchrow_array() )  {
    print &quot;$id, $name, $time\n&quot;;
}
</code></pre><h4 id="1-3-2-fetchrow-arrayref"><a href="#1-3-2-fetchrow-arrayref" class="headerlink" title="1.3.2 fetchrow_arrayref"></a>1.3.2 fetchrow_arrayref</h4><p>返回由字段的值组成的数组的引用。同<code>fetchrow_array</code>的区别很明显，<code>fetchrow_arrayref</code>返回的数组的引用。</p>
<pre><code>while ( my $row_ref = $sth-&gt;fetchrow_arrayref() ) {
    for (my $i = 0; $i &lt; @{$row_ref}; $i++)       {
        print &quot;$row_ref-&gt;[$i]\t&quot;;
    }
    print &quot;\n&quot;;
}
</code></pre><p>这里要注意的是，如果要取字段的个数，需要把这个引用转成数组的形式获得<code>@{$row_ref}</code> 。获取数组元素的值的时候，因为\$row_ref是引用，因此需要使用<code>-&gt;</code>操作符。</p>
<h4 id="1-3-3-fetchrow-hashref"><a href="#1-3-3-fetchrow-hashref" class="headerlink" title="1.3.3 fetchrow_hashref"></a>1.3.3 fetchrow_hashref</h4><p>返回一个由”字段名－字段值”这样的”键－值”对组成的HASH表。关键的不同就是，只有这个方法可以通过一个字段名获得它的值，而不必关心这个字段是第几个字段。而前者只能依靠索引来访问值。不过缺点就是，效率要比前面两个差一些。</p>
<pre><code>while ( my $record = $sth-&gt;fetchrow_hashref() ) {
    for my $field( keys %{$record} ) {
        print &quot;$field: $record-&gt;{$field}\t&quot;;
    }
    print &quot;\n&quot;;
}
</code></pre><p>这里需要复习一下HASH表的操作方法。keys操作符获取HASH的键(key)的数组，<code>$record-&gt;{$field}</code>获得HASH表中\$field对应的值。注意这里同样是引用，因此要用<code>-&gt;</code>操作符。</p>
<p>使用上面三个方法可以基本解决问题了。此外，还有两个方法<code>fetchall_arrayref</code>和<code>selectall_arrayref</code>可以直接通过SQL一次性获取整个数据集，不过使用上稍微复杂一些，要涉及到<br>perl的scalar 操作符，这里就不赘述了。有兴趣的读者可以参考DBI的相关资料。</p>
<p>最后是收尾工作。</p>
<h3 id="1-4-结束一个SQL会话"><a href="#1-4-结束一个SQL会话" class="headerlink" title="1.4 结束一个SQL会话"></a>1.4 结束一个SQL会话</h3><pre><code>$sth-&gt;finish();
</code></pre><h3 id="1-5-断开数据库连接"><a href="#1-5-断开数据库连接" class="headerlink" title="1.5 断开数据库连接"></a>1.5 断开数据库连接</h3><pre><code>$dbh-&gt;disconnect();
</code></pre><p>很简单明了，就不赘述了。</p>
<p>Perl中利用DBI访问数据库的接口基本上就是这些了，还有一些高级的内容留给有兴趣的读者自己发掘研究了。可能有些读者会感觉没有ADO、ADO.NET操作起来方便，但是在脚本的环境下能够如此方便的操作数据库，比起用C接口来说已经方便很多了。也许在看完这片文章之后的不久，可以在cpan上发现你的Module和全世界的Perl程序员一起分享呢。</p>
<h2 id="2-参考资源"><a href="#2-参考资源" class="headerlink" title="2 参考资源"></a>2 参考资源</h2><ul>
<li>《Programming the Perl DBI》 O’Reily</li>
<li><a href="http://dbi.perl.org/" rel="external nofollow noopener noreferrer" target="_blank">DBI官方网站 http://dbi.perl.org/</a></li>
<li><a href="http://www.perl.com/pub/a/1999/10/DBI.html" rel="external nofollow noopener noreferrer" target="_blank">一个DBI编程的简短介绍</a></li>
</ul>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;Perl与数据库DBI快速入门&quot;&gt;&lt;a href=&quot;#Perl与
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>SVN分支的创建与合并</title>
    <link href="https://devops.osichina.net/2016/07/05/5/"/>
    <id>https://devops.osichina.net/2016/07/05/5/</id>
    <published>2016-07-05T03:24:01.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><p>#SVN分支的创建与合并\<br>标准的分支目录如下：\<br>  myproject/\<br>      trunk/ （主分支）\<br>      branches/ （分支）\<br>      tags/         (标记)\<br>现在的项目目录如下\<br>➜  zhangzhongbao tree -L 2\<br>.\<br>└── cm\<br>    ├── doc\<br>    ├── download\<br>    ├── out\<br>    ├── pom.xml\<br>    ├── src\<br>    └── target</p>
<p>6 directories, 1 file\<br>Tips<br>由于我的项目在创建的时候,并没有trunk,现在由于项目需要重新创建分支来进行版本控制.</p>
<p> 1.创建分支\<br> cd /Users/huanggaoming/Desktop/tmp/zhangzhongbao\<br> svn mkdir branches          (由于的不存在branches目录重新创建)\<br> svn mkdir branches/cm \<br> svn commit -m \”创建分支目录\”  \<br> svn copy <a href="https://10.211.55.3/svn/zhangzhongbao/cm" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/cm</a><br> <a href="https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716</a> -m<br>\”7月16日的版本\”<br> (创建分支,原则上尽量和cm平级,但是为了区分,我这里没有平级,版本+1了)\<br> svn update .\<br> ➜  zhangzhongbao tree -L 2\<br>.\<br>├── branches\<br>│   └── cm\<br>└── cm\<br>    ├── doc\<br>    ├── download\<br>    ├── out\<br>    ├── pom.xml\<br>    ├── src\<br>    └── target</p>
<p>8 directories, 1 file  </p>
<p>➜  zhangzhongbao tree -L 3 branches\<br>branches\<br>└── cm\<br>    └── v-20160716\<br>        ├── doc\<br>        ├── download\<br>        ├── out\<br>        ├── pom.xml\<br>        ├── src\<br>        └── target</p>
<p>7 directories, 1 file</p>
<p>Tips:需要注意的是Branch和Trunk使用同一套版本号，也就是说无论在Branch还是Trunk的提交都会引起主版本号的增加。这是因为svn<br>copy只支持同一个repository内的文件copy，并不支持跨repository的copy，所以新创建的Branch和Trunk都属于同一个repository。</p>
<p>2.合并分支\<br>在分支进行一系列的操作\<br>(1) 查看状态\<br>svn status （没有任何的本地修改）\<br>(2) 合并分支到主干\<br>cd /Users/huanggaoming/Desktop/tmp/zhangzhongbao/cm\<br>svn merge <a href="https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716</a><br> \<br>(svn merge <a href="https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716</a><br> -r35:HEAD) 将Branch的从版本35到当前版本的所有改动都合并到Trunk中\<br>(3) 提交保存\<br>svn commit -m \”合并v-20160716分支\” \<br>(4) 合并版本并将合并后的结果应用到现有的分支上 \<br>svn -r 148:149 merge <a href="https://10.211.55.3/svn/zhangzhongbao/cm" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/cm</a></p>
<p>-查找到分支版本\<br>cd /Users/huanggaoming/Desktop/tmp/zhangzhongbao/branches/cm/v-20160716\<br>svn log –stop-on-copy  (最后rid就是创建分支时的reversion)\<br>＝\<br>cd /Users/huanggaoming/Desktop/tmp/zhangzhongbao/cm \<br>svn log -q –stop-on-copy<br> <a href="https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716</a></p>
<p>-解决冲突\<br>svn st | grep \^C      # 查找合并时的冲突文件，手工解决冲突\<br>svn resolved filename # 告知svn冲突已解决\<br>svn commit -m \”\”      # 提交合并后的版本\<br>svn: Aborting commit: \’/path/resources/noc\’ remains in conflict\<br>\$ svn revert resources/noc\<br>Reverted \’resources/noc\’</p>
<p>3.查看分支\<br>svn mergeinfo<br> <a href="https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716\" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716\</a><br>➜  cm svn mergeinfo<br> <a href="https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716\" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716\</a><br>    youngest common ancestor\<br>    |         last full merge\<br>    |         |        tip of branch\<br>    |         |        |         repository path</p>
<pre><code>34        39       40\
|         |        |\
   --| |------------         branches/cm/v-20160716\
  /        \\\
 /          \\\
</code></pre><p>  ——-| |————         cm\<br>                       |\<br>                       WC</p>
<p>查看Branch中那些改动还未合并:\<br>svn mergeinfo<br> <a href="https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/branches/cm/v-20160716</a><br> –show-revs eligible</p>
<p>4.发布－tag管理(创建分支一样)\<br> cd /Users/huanggaoming/Desktop/tmp/zhangzhongbao\<br> svn mkdir tags      (由于的不存在tags目录重新创建)\<br> svn mkdir tags/cm \<br> svn commit -m \”创建tags目录\”  \<br> svn copy <a href="https://10.211.55.3/svn/zhangzhongbao/cm" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/cm</a><br> <a href="https://10.211.55.3/svn/zhangzhongbao/tags/cm/v-20160716" rel="external nofollow noopener noreferrer" target="_blank">https://10.211.55.3/svn/zhangzhongbao/tags/cm/v-20160716</a> -m<br>\”7月16日的版本\”<br> (创建tag,不允许开发在上面进行任何的修改)\<br> svn update .</p>
<p>➜  zhangzhongbao tree -L 2\<br>.\<br>├── branches\<br>│   └── cm\<br>├── cm\<br>│   ├── doc\<br>│   ├── download\<br>│   ├── out\<br>│   ├── pom.xml\<br>│   ├── src\<br>│   └── target\<br>└── tags\<br>    └── cm</p>
<p>10 directories, 1 file</p>
<p>➜  zhangzhongbao tree -L 2 tags/cm\<br>tags/cm\<br>└── v-20160716\<br>    ├── doc\<br>    ├── download\<br>    ├── out\<br>    ├── pom.xml\<br>    ├── src\<br>    └── target</p>
<p>6 directories, 1 file\<br>5.</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;p&gt;#SVN分支的创建与合并\&lt;br&gt;标准的分支目录如下：\&lt;br&gt;  myp
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>PHP超时处理全面总结</title>
    <link href="https://devops.osichina.net/2016/06/08/6/"/>
    <id>https://devops.osichina.net/2016/06/08/6/</id>
    <published>2016-06-08T07:00:59.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p>在PHP开发中工作里非常多使用到超时处理到超时的场合，我说几个场景：</p>
<ol>
<li><p>异步获取数据如果某个后端数据源获取不成功则跳过，不影响整个页面展现</p>
</li>
<li><p>为了保证Web服务器不会因为当个页面处理性能差而导致无法访问其他页面，则会对某些页面操作设置</p>
</li>
<li><p>对于某些上传或者不确定处理时间的场合，则需要对整个流程中所有超时设置为无限，否则任何一个环节设置不当，都会导致莫名执行中断</p>
</li>
<li><p>多个后端模块（MySQL、Memcached、HTTP接口），为了防止单个接口性能太差，导致整个前面获取数据太缓慢，影响页面打开速度，引起雪崩</p>
</li>
<li><p>。。。很多需要超时的场合</p>
</li>
</ol>
<p>这些地方都需要考虑超时的设定，但是PHP中的超时都是分门别类，各个处理方式和策略都不同，为了系统的描述，我总结了PHP中常用的超时处理的总结。</p>
<h2 id="Web服务器超时处理"><a href="#Web服务器超时处理" class="headerlink" title="Web服务器超时处理"></a>Web服务器超时处理</h2><h3 id="Apache"><a href="#Apache" class="headerlink" title="Apache"></a>Apache</h3><p>一般在性能很高的情况下，缺省所有超时配置都是30秒，但是在上传文件，或者网络速度很慢的情况下，那么可能触发超时操作。</p>
<p>目前apachefastcgiphp-fpm模式下有三个超时设置：</p>
<p>fastcgi超时设置：</p>
<p>修改httpd.conf的fastcgi连接配置，类似如下：</p>
<pre><code>&lt;IfModulemod_fastcgi.c&gt;FastCgiExternalServer/home/forum/apache/apache_php/cgi-bin/php-cgi-socket/home/forum/php5/etc/php-fpm.sock
ScriptAlias/fcgi-bin/”/home/forum/apache/apache_php/cgi-bin/”

AddHandlerphp-fastcgi.php

Actionphp-fastcgi/fcgi-bin/php-cgi

AddTypeapplication/x-httpd-php.php

&lt;/IfModule&gt;
</code></pre><p>缺省配置是30s，如果需要定制自己的配置，需要修改配置，比如修改为100秒：(修改后重启apache)：</p>
<pre><code>&lt;IfModulemod_fastcgi.c&gt;
FastCgiExternalServer/home/forum/apache/apache_php/cgi-bin/php-cgi-socket/home/forum/php5/etc/php-fpm.sock-idle-timeout100

ScriptAlias/fcgi-bin/”/home/forum/apache/apache_php/cgi-bin/”

AddHandlerphp-fastcgi.php

Actionphp-fastcgi/fcgi-bin/php-cgi

AddTypeapplication/x-httpd-php.php

&lt;/IfModule&gt;
</code></pre><p>如果超时会返回500错误，断开跟后端php服务的连接，同时记录一条apache错误日志：</p>
<pre><code>[ThuJan2718:30:152011][error][client10.81.41.110]FastCGI:commwithserver”/home/forum/apache/apache_php/cgi-bin/php-cgi”aborted:idletimeout(30sec)

[ThuJan2718:30:152011][error][client10.81.41.110]FastCGI:incompleteheaders(0bytes)receivedfromserver”/home/forum/apache/apache_php/cgi-bin/php-cgi”
</code></pre><p>其他fastcgi配置参数说明：</p>
<pre><code>IdleTimeout发呆时限ProcessLifeTime一个进程的最长生命周期，过期之后无条件kill
MaxProcessCount最大进程个数
DefaultMinClassProcessCount每个程序启动的最小进程个数
DefaultMaxClassProcessCount每个程序启动的最大进程个数
IPCConnectTimeout程序响应超时时间
IPCCommTimeout与程序通讯的最长时间，上面的错误有可能就是这个值设置过小造成的
MaxRequestsPerProcess每个进程最多完成处理个数，达成后自杀
</code></pre><h3 id="Lighttpd"><a href="#Lighttpd" class="headerlink" title="Lighttpd"></a>Lighttpd</h3><p>配置：lighttpd.conf</p>
<p>Lighttpd配置中，关于超时的参数有如下几个（篇幅考虑，只写读超时，写超时参数同理）：</p>
<p>主要涉及选项：</p>
<pre><code>server.max-keep-alive-idle=5
server.max-read-idle=60
server.read-timeout=0
server.max-connection-idle=360

————————————————–

#每次keep-alive的最大请求数,默认值是16

server.max-keep-alive-requests=100

#keep-alive的最长等待时间,单位是秒，默认值是5

server.max-keep-alive-idle=1200

#lighttpd的work子进程数，默认值是0，单进程运行

server.max-worker=2

#限制用户在发送请求的过程中，最大的中间停顿时间(单位是秒)，

#如果用户在发送请求的过程中(没发完请求)，中间停顿的时间太长，lighttpd会主动断开连接

#默认值是60(秒)

server.max-read-idle=1200

#限制用户在接收应答的过程中，最大的中间停顿时间(单位是秒)，

#如果用户在接收应答的过程中(没接完)，中间停顿的时间太长，lighttpd会主动断开连接

#默认值是360(秒)

server.max-write-idle=12000

#读客户端请求的超时限制，单位是秒,配为0表示不作限制

#设置小于max-read-idle时，read-timeout生效

server.read-timeout=0

#写应答页面给客户端的超时限制，单位是秒，配为0表示不作限制

#设置小于max-write-idle时，write-timeout生效

server.write-timeout=0

#请求的处理时间上限，如果用了mod_proxy_core，那就是和后端的交互时间限制,单位是秒

server.max-connection-idle=1200

————————————————–
</code></pre><p>说明：</p>
<p>对于一个keep-alive连接上的连续请求，发送第一个请求内容的最大间隔由参数max-read-idle决定，从第二个请求起，发送请求内容的最大间隔由参数max-keep-alive-idle决定。请求间的间隔超时也由max-keep-alive-idle决定。发送请求内容的总时间超时由参数read-timeout决定。Lighttpd与后端交互数据的超时由max-connection-idle决定。</p>
<p>延伸阅读：</p>
<p><a href="http://www.snooda.com/read/244" rel="external nofollow noopener noreferrer" target="_blank">http://www.snooda.com/read/244</a></p>
<h3 id="Nginx"><a href="#Nginx" class="headerlink" title="Nginx"></a>Nginx</h3><p>配置：nginx.conf</p>
<pre><code>http{
#Fastcgi:(针对后端的fastcgi生效,fastcgi不属于proxy模式)

fastcgi_connect_timeout5;#连接超时

fastcgi_send_timeout10; #写超时

fastcgi_read_timeout10;#读取超时

#Proxy:(针对proxy/upstreams的生效)

proxy_connect_timeout15s;#连接超时

proxy_read_timeout24s;#读超时

proxy_send_timeout10s; #写超时

}
</code></pre><p>说明：</p>
<p>Nginx<br>的超时设置倒是非常清晰容易理解，上面超时针对不同工作模式，但是因为超时带来的问题是非常多的。</p>
<p>延伸阅读：</p>
<p><a href="http://hi.baidu.com/pibuchou/blog/item/a1e330dd71fb8a5995ee3753.html" rel="external nofollow noopener noreferrer" target="_blank">http://hi.baidu.com/pibuchou/blog/item/a1e330dd71fb8a5995ee3753.html</a> \<br><a href="http://hi.baidu.com/pibuchou/blog/item/7cbccff0a3b77dc60b46e024.html" rel="external nofollow noopener noreferrer" target="_blank">http://hi.baidu.com/pibuchou/blog/item/7cbccff0a3b77dc60b46e024.html</a> \<br><a href="http://hi.baidu.com/pibuchou/blog/item/10a549818f7e4c9df703a626.html" rel="external nofollow noopener noreferrer" target="_blank">http://hi.baidu.com/pibuchou/blog/item/10a549818f7e4c9df703a626.html</a> \<br><a href="http://www.apoyl.com/?p=466" rel="external nofollow noopener noreferrer" target="_blank">http://www.apoyl.com/?p=466</a></p>
<h2 id="PHP本身超时处理"><a href="#PHP本身超时处理" class="headerlink" title="PHP本身超时处理"></a>PHP本身超时处理</h2><h3 id="PHP-fpm"><a href="#PHP-fpm" class="headerlink" title="PHP-fpm"></a>PHP-fpm</h3><p>配置：php-fpm.conf</p>
<pre><code>&lt;?xmlversion=”1.0″?&gt;
&lt;configuration&gt;

//…

Setsthelimitonthenumberofsimultaneousrequeststhatwillbeserved.

EquivalenttoApacheMaxClientsdirective.

EquivalenttoPHP_FCGI_CHILDRENenvironmentinoriginalphp.fcgi

Usedwithanypm_style.

#php-cgi的进程数量

&lt;valuename=”max_children”&gt;128&lt;/value&gt;

Thetimeout(inseconds)forservingasinglerequestafterwhichtheworkerprocesswillbeterminated

Shouldbeusedwhen’max_execution_time’inioptiondoesnotstopscriptexecutionforsomereason

’0s’means’off’

#php-fpm 请求执行超时时间，0s为永不超时，否则设置一个 Ns 为超时的秒数

&lt;valuename=”request_terminate_timeout”&gt;0s&lt;/value&gt;

Thetimeout(inseconds)forservingofsinglerequestafterwhichaphpbacktracewillbedumpedtoslow.logfile

’0s’means’off’

&lt;valuename=”request_slowlog_timeout”&gt;0s&lt;/value&gt;

&lt;/configuration&gt;
</code></pre><p>说明：</p>
<p>在php.ini中，有一个参数max_execution_time可以设置PHP脚本的最大执行时间，但是，在php-cgi(php-fpm)中，该参数不会起效。真正能够控制PHP脚本最大执行时：</p>
<pre><code>&lt;valuename=”request_terminate_timeout”&gt;0s&lt;/value&gt;
</code></pre><p>就是说如果是使用mod_php5.so的模式运行max_execution_time是会生效的，但是如果是php-fpm模式中运行时不生效的。</p>
<p>延伸阅读：</p>
<p><a href="http://blog.s135.com/file_get_contents/" rel="external nofollow noopener noreferrer" target="_blank">http://blog.s135.com/file_get_contents/</a></p>
<h3 id="PHP"><a href="#PHP" class="headerlink" title="PHP"></a>PHP</h3><p>配置：php.ini</p>
<p>选项：</p>
<pre><code>max_execution_time=30
</code></pre><p>或者在代码里设置：</p>
<pre><code>ini_set(“max_execution_time”,30);

set_time_limit(30);
</code></pre><p>说明：</p>
<p>对当前会话生效，比如设置0一直不超时，但是如果php的safe_mode打开了，这些设置都会不生效。</p>
<p>效果一样，但是具体内容需要参考php-fpm部分内容，如果php-fpm中设置了request_terminate_timeout的话，那么max_execution_time就不生效。</p>
<h2 id="后端-amp-接口访问超时"><a href="#后端-amp-接口访问超时" class="headerlink" title="后端&amp;接口访问超时"></a>后端&amp;接口访问超时</h2><h2 id="HTTP访问"><a href="#HTTP访问" class="headerlink" title="HTTP访问"></a>HTTP访问</h2><p>一般我们访问HTTP方式很多，主要是：curl,socket,file_get_contents()等方法。</p>
<p>如果碰到对方服务器一直没有响应的时候，我们就悲剧了，很容易把整个服务器搞死，所以在访问http的时候也需要考虑超时的问题。</p>
<h3 id="CURL-访问HTTP"><a href="#CURL-访问HTTP" class="headerlink" title="CURL 访问HTTP"></a>CURL 访问HTTP</h3><p>CURL<br>是我们常用的一种比较靠谱的访问HTTP协议接口的lib库，性能高，还有一些并发支持的功能等。</p>
<p>CURL:</p>
<pre><code>curl_setopt($ch,opt)可以设置一些超时的设置，主要包括：

*(重要)CURLOPT_TIMEOUT设置cURL允许执行的最长秒数。

*(重要)CURLOPT_TIMEOUT_MS设置cURL允许执行的最长毫秒数。(在cURL7.16.2中被加入。从PHP5.2.3起可使用。)

CURLOPT_CONNECTTIMEOUT在发起连接前等待的时间，如果设置为0，则无限等待。

CURLOPT_CONNECTTIMEOUT_MS尝试连接等待的时间，以毫秒为单位。如果设置为0，则无限等待。在cURL7.16.2中被加入。从PHP5.2.3开始可用。

CURLOPT_DNS_CACHE_TIMEOUT设置在内存中保存DNS信息的时间，默认为120秒。
</code></pre><p>curl普通秒级超时：</p>
<pre><code>$ch=curl_init();

curl_setopt($ch,CURLOPT_URL,$url);

curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

curl_setopt($ch,CURLOPT_TIMEOUT,60);//只需要设置一个秒的数量就可以

curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);

curl_setopt($ch,CURLOPT_USERAGENT,$defined_vars[&apos;HTTP_USER_AGENT&apos;]);
</code></pre><p>curl普通秒级超时使用：</p>
<pre><code>curl_setopt($ch,CURLOPT_TIMEOUT,60);

curl如果需要进行毫秒超时，需要增加：

curl_easy_setopt(curl,CURLOPT_NOSIGNAL,1L);
</code></pre><p>或者是：</p>
<pre><code>curl_setopt($ch,CURLOPT_NOSIGNAL,true);是可以支持毫秒级别超时设置的
</code></pre><p>curl一个毫秒级超时的例子：</p>
<pre><code>&lt;?php
if(!isset($_GET[&apos;foo&apos;])){

//Client

$ch=curl_init(‘http://example.com/’);

curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);

curl_setopt($ch,CURLOPT_NOSIGNAL,1);//注意，毫秒超时一定要设置这个

curl_setopt($ch,CURLOPT_TIMEOUT_MS,200);//超时毫秒，cURL7.16.2中被加入。从PHP5.2.3起可使用

$data=curl_exec($ch);

$curl_errno=curl_errno($ch);

$curl_error=curl_error($ch);

curl_close($ch);

if($curl_errno&gt;0){

echo”cURLError($curl_errno):$curl_errorn”;

}else{

echo”Datareceived:$datan”;

}

}else{

//Server

sleep(10);

echo”Done.”;

}

?&gt;
</code></pre><p>其他一些技巧：</p>
<ol>
<li><p>按照经验总结是：cURL版本&gt;=libcurl/7.21.0版本，毫秒级超时是一定生效的，切记。</p>
</li>
<li><p>curl_multi的毫秒级超时也有问题。。单次访问是支持ms级超时的，curl_multi并行调多个会不准</p>
</li>
</ol>
<h3 id="流处理方式访问HTTP"><a href="#流处理方式访问HTTP" class="headerlink" title="流处理方式访问HTTP"></a>流处理方式访问HTTP</h3><p>除了curl，我们还经常自己使用fsockopen、或者是file操作函数来进行HTTP协议的处理，所以，我们对这块的超时处理也是必须的。</p>
<p>一般连接超时可以直接设置，但是流读取超时需要单独处理。</p>
<p>自己写代码处理:</p>
<pre><code>$tmCurrent=gettimeofday();

$intUSGone=($tmCurrent[&apos;sec&apos;]-$tmStart[&apos;sec&apos;])*1000000

+($tmCurrent[&apos;usec&apos;]-$tmStart[&apos;usec&apos;]);

if($intUSGone&gt;$this-&gt;_intReadTimeoutUS){

returnfalse;

}
</code></pre><p>或者使用内置流处理函数stream_set_timeout()和stream_get_meta_data()处理：</p>
<pre><code>&lt;?php//Timeoutinseconds
$timeout=5;

$fp=fsockopen(“example.com”,80,$errno,$errstr,$timeout);

if($fp){

fwrite($fp,”GET/HTTP/1.0rn”);

fwrite($fp,”Host:example.comrn”);

fwrite($fp,”Connection:Closernrn”);

stream_set_blocking($fp,true);//重要，设置为非阻塞模式

stream_set_timeout($fp,$timeout);//设置超时

$info=stream_get_meta_data($fp);

while((!feof($fp))&amp;&amp;(!$info[&apos;timed_out&apos;])){

$data.=fgets($fp,4096);

$info=stream_get_meta_data($fp);

ob_flush;

flush();

}

if($info[&apos;timed_out&apos;]){

echo”ConnectionTimedOut!”;

}else{

echo$data;

}

}
</code></pre><p>file_get_contents超时：</p>
<pre><code>&lt;?php$timeout=array(
‘http’=&gt;array(

‘timeout’=&gt;5//设置一个超时时间，单位为秒

)

);

$ctx=stream_context_create($timeout);

$text=file_get_contents(“http://example.com/”,0,$ctx);

?&gt;
</code></pre><p>fopen超时：</p>
<pre><code>&lt;?php$timeout=array(
‘http’=&gt;array(

‘timeout’=&gt;5//设置一个超时时间，单位为秒

)

);

$ctx=stream_context_create($timeout);

if($fp=fopen(“http://example.com/”,”r”,false,$ctx)){

while($c=fread($fp,8192)){

echo$c;

}

fclose($fp);

}

?&gt;
</code></pre><h2 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h2><p>php中的mysql客户端都没有设置超时的选项，mysqli和mysql都没有，但是libmysql是提供超时选项的，只是我们在php中隐藏了而已。</p>
<p>那么如何在PHP中使用这个操作捏，就需要我们自己定义一些MySQL操作常量，主要涉及的常量有：</p>
<pre><code>MYSQL_OPT_READ_TIMEOUT=11;

MYSQL_OPT_WRITE_TIMEOUT=12;
</code></pre><p>这两个，定义以后，可以使用options设置相应的值。</p>
<p>不过有个注意点，mysql内部实现：</p>
<ol>
<li><p>超时设置单位为秒，最少配置1秒</p>
</li>
<li><p>但mysql底层的read会重试两次，所以实际会是3秒</p>
</li>
</ol>
<p>重试两次+　自身一次=3倍超时时间，那么就是说最少超时时间是3秒，不会低于这个值，对于大部分应用来说可以接受，但是对于小部分应用需要优化。</p>
<p>查看一个设置访问mysql超时的php实例：</p>
<pre><code>&lt;?php//自己定义读写超时常量
if(!defined(‘MYSQL_OPT_READ_TIMEOUT’)){

define(‘MYSQL_OPT_READ_TIMEOUT’,11);

}

if(!defined(‘MYSQL_OPT_WRITE_TIMEOUT’)){

define(‘MYSQL_OPT_WRITE_TIMEOUT’,12);

}

//设置超时

$mysqli=mysqli_init();

$mysqli-&gt;options(MYSQL_OPT_READ_TIMEOUT,3);

$mysqli-&gt;options(MYSQL_OPT_WRITE_TIMEOUT,1);

//连接数据库

$mysqli-&gt;real_connect(“localhost”,”root”,”root”,”test”);

if(mysqli_connect_errno()){

printf(“Connectfailed:%s/n”,mysqli_connect_error());

exit();

}

//执行查询sleep1秒不超时

printf(“Hostinformation:%s/n”,$mysqli-&gt;host_info);

if(!($res=$mysqli-&gt;query(‘selectsleep(1)’))){

echo”query1error:”.$mysqli-&gt;error.”/n”;

}else{

echo”Query1:querysuccess/n”;

}

//执行查询sleep9秒会超时

if(!($res=$mysqli-&gt;query(‘selectsleep(9)’))){

echo”query2error:”.$mysqli-&gt;error.”/n”;

}else{

echo”Query2:querysuccess/n”;

}

$mysqli-&gt;close();

echo”closemysqlconnection/n”;

?&gt;
</code></pre><p>延伸阅读：</p>
<p><a href="http://blog.csdn.net/heiyeshuwu/article/details/5869813" rel="external nofollow noopener noreferrer" target="_blank">http://blog.csdn.net/heiyeshuwu/article/details/5869813</a></p>
<h2 id="Memcached"><a href="#Memcached" class="headerlink" title="Memcached"></a>Memcached</h2><h3 id="PHP扩展"><a href="#PHP扩展" class="headerlink" title="PHP扩展"></a>PHP扩展</h3><p>php_memcache客户端：</p>
<p>连接超时：<code>boolMemcache::connect(string$host[,int$port[,int$timeout]])</code></p>
<p>在get和set的时候，都没有明确的超时设置参数。</p>
<p>libmemcached客户端：在php接口没有明显的超时参数。</p>
<p>说明：所以说，在PHP中访问Memcached是存在很多问题的，需要自己hack部分操作，或者是参考网上补丁。</p>
<h3 id="C-amp-C-访问Memcached"><a href="#C-amp-C-访问Memcached" class="headerlink" title="C&amp;C++访问Memcached"></a>C&amp;C++访问Memcached</h3><p>客户端：libmemcached客户端</p>
<p>说明：memcache超时配置可以配置小点，比如5，10个毫秒已经够用了，超过这个时间还不如从数据库查询。</p>
<p>下面是一个连接和读取set数据的超时的C++示例：</p>
<pre><code>//创建连接超时（连接到Memcached）
memcached_st*MemCacheProxy::_create_handle()

{

memcached_st*mmc=NULL;

memcached_return_tprc;

if(_mpool!=NULL){//getfrompool

mmc=memcached_pool_pop(_mpool,false,&amp;prc);

if(mmc==NULL){

__LOG_WARNING__(“MemCacheProxy”,”gethandlefrompoolerror[%d]“,(int)prc);

}

returnmmc;

}

memcached_st*handle=memcached_create(NULL);

if(handle==NULL){

__LOG_WARNING__(“MemCacheProxy”,”create_handleerror”);

returnNULL;

}

//设置连接/读取超时

memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_HASH,MEMCACHED_HASH_DEFAULT);

memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_NO_BLOCK,_noblock);//参数MEMCACHED_BEHAVIOR_NO_BLOCK为1使超时配置生效，不设置超时会不生效，关键时候会悲剧的，容易引起雪崩

memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT,_connect_timeout);//连接超时

memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_RCV_TIMEOUT,_read_timeout);//读超时

memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_SND_TIMEOUT,_send_timeout);//写超时

memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_POLL_TIMEOUT,_poll_timeout);

//设置一致hash

//memcached_behavior_set_distribution(handle,MEMCACHED_DISTRIBUTION_CONSISTENT);

memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_DISTRIBUTION,MEMCACHED_DISTRIBUTION_CONSISTENT);

memcached_returnrc;

for(uinti=0;i&lt;_server_count;i++){

rc=memcached_server_add(handle,_ips[i],_ports[i]);

if(MEMCACHED_SUCCESS!=rc){

__LOG_WARNING__(“MemCacheProxy”,”addserver[%s:%d]failed.”,_ips[i],_ports[i]);

}

}

_mpool=memcached_pool_create(handle,_min_connect,_max_connect);

if(_mpool==NULL){

__LOG_WARNING__(“MemCacheProxy”,”create_poolerror”);

returnNULL;

}

mmc=memcached_pool_pop(_mpool,false,&amp;prc);

if(mmc==NULL){

__LOG_WARNING__(“MyMemCacheProxy”,”gethandlefrompoolerror[%d]“,(int)prc);

}

//__LOG_DEBUG__(“MemCacheProxy”,”gethandle[%p]“,handle);

returnmmc;

}

//设置一个key超时（set一个数据到memcached）

boolMemCacheProxy::_add(memcached_st*handle,unsignedint*key,constchar*value,intlen,unsignedinttimeout)

{

memcached_returnrc;

chartmp[1024];

snprintf(tmp,sizeof(tmp),”%u#%u”,key[0],key[1]);

//有个timeout值

rc=memcached_set(handle,tmp,strlen(tmp),(char*)value,len,timeout,0);

if(MEMCACHED_SUCCESS!=rc){

returnfalse;

}

returntrue;

}

//Memcache读取数据超时(没有设置)
</code></pre><p>libmemcahed源码中接口定义：</p>
<pre><code>LIBMEMCACHED_APIchar*memcached_get(memcached_st*ptr,constchar*key,size_tkey_length,size_t*value_length,uint32_t*flags,memcached_return_t*error);

LIBMEMCACHED_APImemcached_return_tmemcached_mget(memcached_st*ptr,constchar*const*keys,constsize_t*key_length,size_tnumber_of_keys);
</code></pre><p>从接口中可以看出在读取数据的时候，是没有超时设置的。</p>
<p>延伸阅读：</p>
<p><a href="http://hi.baidu.com/chinauser/item/b30af90b23335dde73e67608" rel="external nofollow noopener noreferrer" target="_blank">http://hi.baidu.com/chinauser/item/b30af90b23335dde73e67608</a> \<br><a href="http://libmemcached.org/libMemcached.html" rel="external nofollow noopener noreferrer" target="_blank">http://libmemcached.org/libMemcached.html</a></p>
<h2 id="如何实现超时"><a href="#如何实现超时" class="headerlink" title="如何实现超时"></a>如何实现超时</h2><p>程序中需要有超时这种功能，比如你单独访问一个后端Socket模块，Socket模块不属于我们上面描述的任何一种的时候，它的协议也是私有的，那么这个时候可能需要自己去实现一些超时处理策略，这个时候就需要一些处理代码了。</p>
<h3 id="PHP中超时实现"><a href="#PHP中超时实现" class="headerlink" title="PHP中超时实现"></a>PHP中超时实现</h3><p>一、初级：最简单的超时实现 （秒级超时）</p>
<p>思路很简单：链接一个后端，然后设置为非阻塞模式，如果没有连接上就一直循环，判断当前时间和超时时间之间的差异。</p>
<p>phpsocket中实现原始的超时：(每次循环都当前时间去减，性能会很差，cpu占用会较高)</p>
<pre><code>&lt;?$host=”127.0.0.1″;
$port=”80″;

$timeout=15;//timeoutinseconds

$socket=socket_create(AF_INET,SOCK_STREAM,SOL_TCP)

ordie(“Unabletocreatesocketn”);

socket_set_nonblock($socket) //务必设置为阻塞模式

ordie(“Unabletosetnonblockonsocketn”);

$time=time();

//循环的时候每次都减去相应值

while(!@socket_connect($socket,$host,$port))//如果没有连接上就一直死循环

{

$err=socket_last_error($socket);

if($err==115||$err==114)

{

if((time()-$time)&gt;=$timeout)//每次都需要去判断一下是否超时了

{

socket_close($socket);

die(“Connectiontimedout.n”);

}

sleep(1);

continue;

}

die(socket_strerror($err).”n”);

}

socket_set_block($this-&gt;socket)//还原阻塞模式

ordie(“Unabletosetblockonsocketn”);

?&gt;
</code></pre><p>二、升级：使用PHP自带异步IO去实现（毫秒级超时）</p>
<p>说明：</p>
<p>异步IO：异步IO的概念和同步IO相对。当一个异步过程调用发出后，调用者不能立刻得到结果。实际处理这个调用的部件在完成后，通过状态、通知和回调来通知调用者。异步IO将比特分成小组进行传送，小组可以是8位的1个字符或更长。发送方可以在任何时刻发送这些比特组，而接收方从不知道它们会在什么时候到达。</p>
<p>多路复用：复用模型是对多个IO操作进行检测，返回可操作集合，这样就可以对其进行操作了。这样就避免了阻塞IO不能随时处理各个IO和非阻塞占用系统资源的确定。</p>
<p>使用socket_select()实现超时</p>
<pre><code>socket_select(…,floor($timeout),ceil($timeout*1000000));
</code></pre><p>select的特点：能够设置到微秒级别的超时！</p>
<p>使用socket_select()的超时代码（需要了解一些异步IO编程的知识去理解）</p>
<p>编程 调用类 编程</p>
<pre><code>&lt;?php

$server=newServer;

$client=newClient;

for(;;){

foreach($select-&gt;can_read(0)as$socket){

if($socket==$client-&gt;socket){

//NewClientSocket

$select-&gt;add(socket_accept($client-&gt;socket));

}

else{

//there’ssomethingtoreadon$socket

}

}

}

?&gt;
</code></pre><p>编程 异步多路复用IO &amp; 超时连接处理类 编程</p>
<pre><code>&lt;?php

classselect{

var$sockets;

functionselect($sockets){

$this-&gt;sockets=array();

foreach($socketsas$socket){

$this-&gt;add($socket);

}

}

functionadd($add_socket){

array_push($this-&gt;sockets,$add_socket);

}

functionremove($remove_socket){

$sockets=array();

foreach($this-&gt;socketsas$socket){

if($remove_socket!=$socket)

$sockets[]=$socket;

}

$this-&gt;sockets=$sockets;

}

functioncan_read($timeout){

$read=$this-&gt;sockets;

socket_select($read,$write=NULL,$except=NULL,$timeout);

return$read;

}

functioncan_write($timeout){

$write=$this-&gt;sockets;

socket_select($read=NULL,$write,$except=NULL,$timeout);

return$write;

}

}

?&gt;
</code></pre><h3 id="C-amp-C-中超时实现"><a href="#C-amp-C-中超时实现" class="headerlink" title="C&amp;C++中超时实现"></a>C&amp;C++中超时实现</h3><p>一般在LinuxC/C++中，可以使用：alarm()设置定时器的方式实现秒级超时，或者：select()、poll()、epoll()之类的异步复用IO实现毫秒级超时。也可以使用二次封装的异步io库（libevent,libev）也能实现。</p>
<p>一、使用alarm中用信号实现超时 （秒级超时）</p>
<p>说明：Linux内核connect超时通常为75秒，我们可以设置更小的时间如10秒来提前从connect中返回。这里用使用信号处理机制，调用alarm，超时后产生SIGALRM信号（也可使用select实现）</p>
<p>用alarym秒级实现　connect设置超时代码示例：</p>
<p>全选复制放进笔记</p>
<p><code>//信号处理函数staticvoidconnect_alarm(intsigno) { debug_printf(“SignalHandler”); return; } //alarm超时连接实现 staticvoidconn_alarm() { Sigfunc*sigfunc;//现有信号处理函数 sigfunc=signal(SIGALRM,connect_alarm);//建立信号处理函数connect_alarm,(如果有)保存现有的信号处理函数 inttimeout=5; //设置闹钟 if(alarm(timeout)!=0){ //…闹钟已经设置处理 } //进行连接操作 if(connect(m_Socket,(structsockaddr*)&amp;addr,sizeof(addr))&lt;0){ if(errno==EINTR){//如果错误号设置为EINTR，说明超时中断了 debug_printf(“Timeout”);</code></p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h2 id=&quot;概述&quot;&gt;&lt;a href=&quot;#概述&quot; class=&quot;headerl
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>图解HTTPS协议加密解密全过程</title>
    <link href="https://devops.osichina.net/2016/05/03/7/"/>
    <id>https://devops.osichina.net/2016/05/03/7/</id>
    <published>2016-05-03T10:12:00.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><p>　　我们都知道HTTPS能够加密信息，以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。</p>
<p>　　<strong>HTTPS简介</strong></p>
<p>　　HTTPS其实是有两部分组成：HTTP + SSL /<br>TLS，也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过TLS进行加密，所以传输的数据都是加密后的数据。具体是如何进行加密，解密，验证的，且看下图。</p>
<p><img src="http://static.oschina.net/uploads/img/201605/03181202_aHwm.png" alt="">　　<strong>1.<br>客户端发起HTTPS请求</strong></p>
<p>　　这个没什么好说的，就是用户在浏览器里输入一个https网址，然后连接到server的443端口。</p>
<p>　　<strong>2. 服务端的配置</strong></p>
<p>　　采用HTTPS协议的服务器必须要有一套数字证书，可以自己制作，也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过，才可以继续访问，而使用受信任的公司申请的证书则不会弹出提示页面(startssl就是个不错的选择，有1年的免费服务)。这套证书其实就是一对公钥和私钥。如果对公钥和私钥不太理解，可以想象成一把钥匙和一个锁头，只是全世界只有你一个人有这把钥匙，你可以把锁头给别人，别人可以用这个锁把重要的东西锁起来，然后发给你，因为只有你一个人有这把钥匙，所以只有你才能看到被这把锁锁起来的东西。</p>
<p>　　<strong>3. 传送证书</strong></p>
<p>　　这个证书其实就是公钥，只是包含了很多信息，如证书的颁发机构，过期时间等等。</p>
<p>　　<strong>4. 客户端解析证书</strong></p>
<p>　　这部分工作是有客户端的TLS来完成的，首先会验证公钥是否有效，比如颁发机构，过期时间等等，如果发现异常，则会弹出一个警告框，提示证书存在问题。如果证书没有问题，那么就生成一个随机值。然后用证书对该随机值进行加密。就好像上面说的，把随机值用锁头锁起来，这样除非有钥匙，不然看不到被锁住的内容。</p>
<p>　　<strong>5. 传送加密信息</strong></p>
<p>　　这部分传送的是用证书加密后的随机值，目的就是让服务端得到这个随机值，以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了。</p>
<p>　　<strong>6. 服务段解密信息</strong></p>
<p>　　服务端用私钥解密后，得到了客户端传过来的随机值(私钥)，然后把内容通过该值进行对称加密。所谓对称加密就是，将信息和私钥通过某种算法混合在一起，这样除非知道私钥，不然无法获取内容，而正好客户端和服务端都知道这个私钥，所以只要加密算法够彪悍，私钥够复杂，数据就够安全。</p>
<p>　　<strong>7. 传输加密后的信息</strong></p>
<p>　　这部分信息是服务段用私钥加密后的信息，可以在客户端被还原。</p>
<p>　　<strong>8. 客户端解密信息</strong></p>
<p>　　客户端用之前生成的私钥解密服务段传过来的信息，于是获取了解密后的内容。整个过程第三方即使监听到了数据，也束手无策。</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;p&gt;　　我们都知道HTTPS能够加密信息，以免敏感信息被第三方获取。所以很多银
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>bash基础</title>
    <link href="https://devops.osichina.net/2016/05/03/8/"/>
    <id>https://devops.osichina.net/2016/05/03/8/</id>
    <published>2016-05-03T09:53:43.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><p><a href="https://my.oschina.net/pwd/blog/669207" rel="external nofollow noopener noreferrer" target="_blank">https://my.oschina.net/pwd/blog/669207</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;p&gt;&lt;a href=&quot;https://my.oschina.net/pwd/b
    
    </summary>
    
      <category term="HTML相关" scheme="https://devops.osichina.net/categories/HTML%E7%9B%B8%E5%85%B3/"/>
    
    
      <category term="HTML相关" scheme="https://devops.osichina.net/tags/HTML%E7%9B%B8%E5%85%B3/"/>
    
  </entry>
  
  <entry>
    <title>CentOS 7 下使用 iptables</title>
    <link href="https://devops.osichina.net/2016/04/21/9/"/>
    <id>https://devops.osichina.net/2016/04/21/9/</id>
    <published>2016-04-21T07:16:58.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><p>系统升级到CentOS<br>7后总感觉<a href="https://en.wikipedia.org/wiki/iptables" rel="external nofollow noopener noreferrer" target="_blank">iptables</a>怪怪的,比如不管怎么保存重启后都被初始化一下,即便我最后发大绝招启动时候加命令:\<br>首先<strong>iptables-save &gt; /etc/iptables.rules</strong>保存当前状态。\<br>然后再在/etc/rc.local中强制加上</p>
<p>[/etc/rc.local]</p>
<p> \</p>
<p>+———————————–+———————————–+<br>|                              |                              |<br>|                                   |                                   |<br>| \                                 | <code>iptables-restore</code>                |<br>|                                   | <code>/etc/iptables``.rules</code>           |<br>|                             |                                   |<br>|                                   |                             |<br>+———————————–+———————————–+</p>
<p>重启后虽然规则生效但仔细看规则还是一些被莫名添加的额外的内容，让人很是不爽。\</p>
<p>仔细一google,发现问题之所在了。<a href="https://en.wikipedia.org/wiki/RedHat" rel="external nofollow noopener noreferrer" target="_blank">RedHat</a>在7中更改了系统软件，不再使用iptables作为系统的防火墙，而是使用了<a href="https://en.wikipedia.org/wiki/FirewallD" rel="external nofollow noopener noreferrer" target="_blank">FirewallD</a>,但是为了兼容过去的命令也可以使用iptables来设置防护规则，但启动的时候自搞了一套。</p>
<p>解决方法也很简单。</p>
<p>首先，可以考虑follow官方的想法转用FirewallD。其实查看一些<a href="https://argcv.com/articles/3167.c#rel_4" rel="external nofollow noopener noreferrer" target="_blank">官方文档</a>也能用。\<br>但是，个人觉得若没有显著的提升也可以继续使用原来的iptables。若打算继续使用iptables,<br>可以继续做如下:</p>
<p>备份当前规则</p>
<p>+———————————–+———————————–+<br>|                              |                              |<br>|                                   |                                   |<br>| 1                                 |                              |<br>|                                   |                                   |<br>|                             |                              |<br>|                                   |                                   |<br>|                                   | <code>iptables-save &gt; iptables.rules</code>  |<br>|                                   |                                   |<br>|                                   |                             |<br>|                                   |                                   |<br>|                                   |                             |<br>|                                   |                                   |<br>|                                   |                             |<br>+———————————–+———————————–+</p>
<p>[禁用FireWallD,安装&amp;启用iptables-services]</p>
<p>[systemctl stop firewalld]</p>
<p>[systemctl mask firewalld]</p>
<p>[[yum<br>install ][iptables-services<br>-y ]</p>
<p>[systemctl<br>enable ]</p>
<p>+———————————–+———————————–+<br>|                              |                              |<br>|                                   |                                   |<br>|                                   | \                                 |<br>|                                   |                                   |<br>|                             |                             |<br>+———————————–+———————————–+</p>
<p>这时候检查iptables发现规则被清空了</p>
<p>+———————————–+———————————–+<br>|                              |                              |<br>|                                   |                                   |<br>| 1                                 |                              |<br>|                                   |                                   |<br>|                             | <code>iptables -L -x -n</code>               |<br>|                                   |                                   |<br>|                                   |                             |<br>|                                   |                                   |<br>|                                   |                             |<br>+———————————–+———————————–+</p>
<p>将备份的规则还原</p>
<p>+———————————–+———————————–+<br>|                              |                              |<br>|                                   |                                   |<br>| 1                                 |                              |<br>|                                   |                                   |<br>|                             | <code>iptables-restore iptables.rules</code> |<br>|                                   |                                   |<br>|                                   |                             |<br>|                                   |                                   |<br>|                                   |                             |<br>+———————————–+———————————–+</p>
<p>保存当前规则</p>
<p>+———————————–+———————————–+<br>|                              |                              |<br>|                                   |                                   |<br>| 1                                 |                              |<br>|                                   |                                   |<br>|                             | <code>/usr/libexec/iptables/iptables`` |
|                                   | .init save</code>                       |<br>|                                   |                                   |<br>|                                   |                             |<br>|                                   |                                   |<br>|                                   |                             |<br>+———————————–+———————————–+</p>
<p>若使用minimize版本的安装，可能会出现提示</p>
<blockquote>
<p>iptables: Saving firewall rules to /etc/sysconfig/iptables:<br>/etc/init.d/iptables: line 274: restorecon: command not found</p>
</blockquote>
<p>这是因为selinux没有安装的缘故，缺少一个组件。安装policycoreutils即可。</p>
<p>+———————————–+———————————–+<br>|                              |                              |<br>|                                   |                                   |<br>| 1                                 |                              |<br>|                                   |                                   |<br>|                             | <code>yum</code> <code>install</code>                   |<br>|                                   | <code>policycoreutils -y</code>              |<br>|                                   |                                   |<br>|                                   |                             |<br>|                                   |                                   |<br>|                                   |                             |<br>+———————————–+———————————–+</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;p&gt;系统升级到CentOS&lt;br&gt;7后总感觉&lt;a href=&quot;https://
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>PHP JSON使用实例</title>
    <link href="https://devops.osichina.net/2016/02/24/10/"/>
    <id>https://devops.osichina.net/2016/02/24/10/</id>
    <published>2016-02-24T02:40:43.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><p>一、json_encode()<br>该函数主要用来将数组和对象，转换为json格式。先看一个数组转换的例子：<br><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">　　$arr = <span class="keyword">array</span> (<span class="string">'a'</span>=&gt;<span class="number">1</span>,<span class="string">'b'</span>=&gt;<span class="number">2</span>,<span class="string">'c'</span>=&gt;<span class="number">3</span>,<span class="string">'d'</span>=&gt;<span class="number">4</span>,<span class="string">'e'</span>=&gt;<span class="number">5</span>);</div><div class="line"></div><div class="line">　　<span class="keyword">echo</span> json_encode($arr);</div></pre></td></tr></table></figure></p>
<p>结果为</p>
<p>　　{“a”:1,”b”:2,”c”:3,”d”:4,”e”:5}</p>
<p>再看一个对象转换的例子：<br><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　$obj-&gt;body           = <span class="string">'another post'</span>;</div><div class="line"></div><div class="line">　　$obj-&gt;id             = <span class="number">21</span>;</div><div class="line"></div><div class="line">　　$obj-&gt;approved       = <span class="keyword">true</span>;</div><div class="line"></div><div class="line">　　$obj-&gt;favorite_count = <span class="number">1</span>;</div><div class="line"></div><div class="line">　　$obj-&gt;status         = <span class="keyword">NULL</span>;</div><div class="line"></div><div class="line">　　<span class="keyword">echo</span> json_encode($obj);</div></pre></td></tr></table></figure></p>
<p>结果为<br><figure class="highlight json"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　&#123;</div><div class="line">　　　　<span class="attr">"body"</span>:<span class="string">"another post"</span>,</div><div class="line"></div><div class="line">　　　　<span class="attr">"id"</span>:<span class="number">21</span>,</div><div class="line"></div><div class="line">　　　　<span class="attr">"approved"</span>:<span class="literal">true</span>,</div><div class="line"></div><div class="line">　　　　<span class="attr">"favorite_count"</span>:<span class="number">1</span>,</div><div class="line"></div><div class="line">　　　　<span class="attr">"status"</span>:<span class="literal">null</span></div><div class="line">　　&#125;</div></pre></td></tr></table></figure></p>
<p>由于json只接受utf-8编码的字符，所以json_encode()的参数必须是utf-8编码，否则会得到空字符或者null。当中文使用GB2312编码，或者外文使用ISO-8859-1编码的时候，这一点要特别注意。<br>二、索引数组和关联数组<br>PHP支持两种数组，一种是只保存”值”（value）的索引数组（indexed array），另一种是保存”名值对”（name/value）的关联数组（associative array）。<br>由于javascript不支持关联数组，所以json_encode()只将索引数组（indexed array）转为数组格式，而将关联数组（associative array）转为对象格式。<br>比如，现在有一个索引数组<br><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　$arr = <span class="keyword">Array</span>(<span class="string">'one'</span>, <span class="string">'two'</span>, <span class="string">'three'</span>);</div><div class="line"></div><div class="line">　　<span class="keyword">echo</span> json_encode($arr);</div></pre></td></tr></table></figure></p>
<p>结果为：<br><figure class="highlight json"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　[<span class="string">"one"</span>,<span class="string">"two"</span>,<span class="string">"three"</span>]</div></pre></td></tr></table></figure></p>
<p>如果将它改为关联数组：<br><figure class="highlight http"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"></div><div class="line"><span class="php">　　$arr = <span class="keyword">Array</span>(<span class="string">'1'</span>=&gt;<span class="string">'one'</span>, <span class="string">'2'</span>=&gt;<span class="string">'two'</span>, <span class="string">'3'</span>=&gt;<span class="string">'three'</span>);</span></div><div class="line"></div><div class="line">　　<span class="keyword">echo</span> json_encode($arr);</div></pre></td></tr></table></figure></p>
<p>结果就变了：<br><figure class="highlight json"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　&#123;<span class="attr">"1"</span>:<span class="string">"one"</span>,<span class="attr">"2"</span>:<span class="string">"two"</span>,<span class="attr">"3"</span>:<span class="string">"three"</span>&#125;</div></pre></td></tr></table></figure></p>
<p>注意，数据格式从”[]”（数组）变成了”{}”（对象）。<br>如果你需要将”索引数组”强制转化成”对象”，可以这样写<br><figure class="highlight lisp"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">　　json_encode( (<span class="name">object</span>)$arr )<span class="comment">;</span></div></pre></td></tr></table></figure></p>
<p>或者<br><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　<span class="keyword">json_encode </span>( $arr, <span class="keyword">JSON_FORCE_OBJECT </span>)<span class="comment">;</span></div></pre></td></tr></table></figure></p>
<p>三、类（class）的转换<br>下面是一个PHP的类：<br><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">　　<span class="class"><span class="keyword">class</span> <span class="title">Foo</span> </span>&#123;</div><div class="line"></div><div class="line">　　　　<span class="keyword">const</span>     ERROR_CODE = <span class="string">'404'</span>;</div><div class="line"></div><div class="line">　　　　<span class="keyword">public</span>    $public_ex = <span class="string">'this is public'</span>;</div><div class="line"></div><div class="line">　　　　<span class="keyword">private</span>   $private_ex = <span class="string">'this is private!'</span>;</div><div class="line"></div><div class="line">　　　　<span class="keyword">protected</span> $protected_ex = <span class="string">'this should be protected'</span>; </div><div class="line"></div><div class="line">　　　　<span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getErrorCode</span><span class="params">()</span> </span>&#123;</div><div class="line"></div><div class="line">　　　　　　<span class="keyword">return</span> <span class="keyword">self</span>::ERROR_CODE;</div><div class="line"></div><div class="line">　　　　&#125;</div><div class="line"></div><div class="line">　　&#125;</div></pre></td></tr></table></figure></p>
<p>现在，对这个类的实例进行json转换：<br><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　$foo = <span class="keyword">new</span> Foo;</div><div class="line"></div><div class="line">　　$foo_json = json_encode($foo);</div><div class="line"></div><div class="line">　　<span class="keyword">echo</span> $foo_json;</div></pre></td></tr></table></figure></p>
<p>输出结果是</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">　　&#123;<span class="attr">"public_ex"</span>:<span class="string">"this is public"</span>&#125;</div></pre></td></tr></table></figure>
<p>可以看到，除了公开变量（public），其他东西（常量、私有变量、方法等等）都遗失了。<br>四、json_decode()<br>该函数用于将json文本转换为相应的PHP数据结构。下面是一个例子：<br><figure class="highlight elixir"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　<span class="variable">$json</span> = <span class="string">'&#123;"foo": 12345&#125;'</span>;</div><div class="line"></div><div class="line">　　<span class="variable">$obj</span> = json_decode(<span class="variable">$json</span>);</div><div class="line"></div><div class="line">　　print <span class="variable">$obj</span>-&gt;&#123;<span class="string">'foo'</span>&#125;; <span class="regexp">//</span> <span class="number">12345</span></div></pre></td></tr></table></figure></p>
<p>通常情况下，json_decode()总是返回一个PHP对象，而不是数组。比如：<br><figure class="highlight cos"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　<span class="built_in">$json</span> = '&#123;<span class="string">"a"</span>:<span class="number">1</span>,<span class="string">"b"</span>:<span class="number">2</span>,<span class="string">"c"</span>:<span class="number">3</span>,<span class="string">"d"</span>:<span class="number">4</span>,<span class="string">"e"</span>:<span class="number">5</span>&#125;'<span class="comment">;</span></div><div class="line"></div><div class="line">　　var_dump(json_decode(<span class="built_in">$json</span>))<span class="comment">;</span></div></pre></td></tr></table></figure></p>
<p>结果就是生成一个PHP对象：<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　<span class="keyword">object</span>(stdClass)<span class="meta">#1 (5) &#123;</span></div><div class="line"></div><div class="line">　　　　[<span class="meta"><span class="meta-string">"a"</span></span>] =&gt; <span class="keyword">int</span>(<span class="number">1</span>)</div><div class="line">　　　　[<span class="meta"><span class="meta-string">"b"</span></span>] =&gt; <span class="keyword">int</span>(<span class="number">2</span>)</div><div class="line">　　　　[<span class="meta"><span class="meta-string">"c"</span></span>] =&gt; <span class="keyword">int</span>(<span class="number">3</span>)</div><div class="line">　　　　[<span class="meta"><span class="meta-string">"d"</span></span>] =&gt; <span class="keyword">int</span>(<span class="number">4</span>)</div><div class="line">　　　　[<span class="meta"><span class="meta-string">"e"</span></span>] =&gt; <span class="keyword">int</span>(<span class="number">5</span>)</div><div class="line"></div><div class="line">　　&#125;</div></pre></td></tr></table></figure></p>
<p>如果想要强制生成PHP关联数组，json_decode()需要加一个参数true：<br><figure class="highlight cos"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　<span class="built_in">$json</span> = '&#123;<span class="string">"a"</span>:<span class="number">1</span>,<span class="string">"b"</span>:<span class="number">2</span>,<span class="string">"c"</span>:<span class="number">3</span>,<span class="string">"d"</span>:<span class="number">4</span>,<span class="string">"e"</span>:<span class="number">5</span>&#125;'<span class="comment">;</span></div><div class="line"></div><div class="line">　　var_dump(json_decode(<span class="built_in">$json</span>,true))<span class="comment">;</span></div></pre></td></tr></table></figure></p>
<p>结果就生成了一个关联数组：<br><figure class="highlight ocaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">　　<span class="built_in">array</span>(<span class="number">5</span>) &#123;</div><div class="line"></div><div class="line">　　 　　[<span class="string">"a"</span>] =&gt; <span class="built_in">int</span>(<span class="number">1</span>)</div><div class="line">　　 　　[<span class="string">"b"</span>] =&gt; <span class="built_in">int</span>(<span class="number">2</span>)</div><div class="line">　　 　　[<span class="string">"c"</span>] =&gt; <span class="built_in">int</span>(<span class="number">3</span>)</div><div class="line">　　 　　[<span class="string">"d"</span>] =&gt; <span class="built_in">int</span>(<span class="number">4</span>)</div><div class="line">　　 　　[<span class="string">"e"</span>] =&gt; <span class="built_in">int</span>(<span class="number">5</span>)</div><div class="line"></div><div class="line">　　&#125;</div></pre></td></tr></table></figure></p>
<p>五、json_decode()的常见错误<br>下面三种json写法都是错的，你能看出错在哪里吗？<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="meta"></span></div><div class="line">　　$<span class="bash">bad_json = <span class="string">"&#123; 'bar': 'baz' &#125;"</span>;</span></div><div class="line"><span class="meta"></span></div><div class="line">　　$<span class="bash">bad_json = <span class="string">'&#123; bar: "baz" &#125;'</span>;</span></div><div class="line"><span class="meta"></span></div><div class="line">　　$<span class="bash">bad_json = <span class="string">'&#123; "bar": "baz", &#125;'</span>;</span></div></pre></td></tr></table></figure></p>
<p>对这三个字符串执行json_decode()都将返回null，并且报错。<br>第一个的错误是，json的分隔符（delimiter）只允许使用双引号，不能使用单引号。第二个的错误是，json名值对的”名”（冒号左边的部分），任何情况下都必须使用双引号。第三个的错误是，最后一个值之后不能添加逗号（trailing comma）。</p>
<p>另外，json只能用来表示对象（object）和数组（array），如果对一个字符串或数值使用json_decode()，将会返回null。</p>
<figure class="highlight lisp"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">　　var_dump(<span class="name">json_decode</span>(<span class="string">"Hello World"</span>))<span class="comment">; //null</span></div></pre></td></tr></table></figure>
<p>　　</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;p&gt;一、json_encode()&lt;br&gt;该函数主要用来将数组和对象，转换为j
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>关于的运维平台化和价值化的思考</title>
    <link href="https://devops.osichina.net/2016/02/17/11/"/>
    <id>https://devops.osichina.net/2016/02/17/11/</id>
    <published>2016-02-17T08:47:50.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><p>[<em>*</em>[运维是什么？]</p>
<p>[<br> [运维是什么？经常有人询问，运维到底是一个什么样的角色？做什么的？什么是运维？]</p>
<p>[<br> 不知道身为运维同行的你们会怎么回答这个问题，借用百度百科的关于运维的定义。[运维，这里指互联网运维，通常属于技术部门，与研发、测试、系统管理同为互联网产品技术支撑的4大部门，这个划分在国内和国外以及大小公司间都会多少有一些不同。一般来讲国内的互联网运维负责软件测试交付后的发布和管理，其核心目标是将交付的业务软件和硬件基础设施高效合理的整合，转换为可持续提供高质量服务的产品，同时最大限度降低服务运行的成本，保障服务运行的安全。]</p>
<p>[<br> 在大部分／开发／测试／运营等部门的眼里，运维就是一个负责发布和部署部门，当然不同规模的公司，运维团地规模以及需求和侧重点都不一样，有的公司甚至都没有开设运维工程师的这一职位，由开发人员自主的承担运维的角色。在业务规模达到一定的时候，运维一定在其中担任不可或缺的重要角色。在互联网的产品体系当中，运维的角色在很多的情况下并不是很清晰明了，甚至有很多的运维工程师都不清楚自己所处的运维的定位到底是什么？]</p>
<p>[<br> 运维在互联网产品的技术支撑体系中所扮演的角色并不是那么清晰，从产品的需求设计到开发，到测试，再到上线运营的过程当中。比如开发，在整个产品形态当中，开发的角色非常的清晰，就是根据需求和设计开发相对应的功能，比如测试，根据产品的需求和设计，测试相对应的功能点。而运维在整个的产品的体系当中，它所处的角色到底又是什么呢？上线部署？线上维护？版本管理？]</p>
<p>[<br>在整个的技术支撑体系过程当中，运维一直在”打辅助“的角色当中，可能大家对运维的最深刻的认识就是当服务故障了，大家第一时间想到的就是运维。可是你又真正的认识到自己是有多重要么？在我看来，运维、测试、运营支持就是为产品服务的技术支持团队，每一个角色都至关重要，缺一不可。那么，作为反过来回答运维是什么，<strong>运维就是解决用户痛点，提升用户体验的技术支持部门。</strong>用户这里不是单单是指使用我们产品的用户，也同时是指运营、运维、测试等服务对象。为了用户体验，我们需要构建安全、监控、报警等多个维度的体系。]</p>
<p>[\<br>]</p>
<p>[<strong><em>[运维的划分是怎样的？]</em></strong><br>]</p>
<p>[<br> 在一般的情况下，运维会划分几个维度,[运维团队可以划分为：应用运维、系统运维、运维开发和监控运维，可能还会包含DBA团队和安全团队。]</p>
<ul>
<li><p>[应用运维：负责支持线上业务，各自会负责对应的业务线，主要职能是保证线上业务稳定性和同开发共同支撑对应业务，以及线上服务管理和持续优化。]</p>
</li>
<li><p>[运维开发：帮助运维提升工作效率，开发方便快捷的工具，实现运维平台化自动化。]</p>
</li>
<li><p>[系统运维：负责操作系统定制和优化，IDC管理和机器交付，以及跳板机和账号信息管理。]</p>
</li>
<li><p>[监控运维：负责发现故障，并第一时间通知相关人员，及时处理简单故障和启动降级方案等。]</p>
</li>
</ul>
<p>[<strong><em>[运维的平台化和价值化]</em></strong><br>]</p>
<p>[<strong><em>   
 </em></strong>我自己的理解，运维做过的事情很多。部署、发布、监控、安全、开发工具集……，大大小小做了的事情很多，请问，付出了那么多，做了那么多事，你老板知道么？直接的价值产出在哪里？说句很实在的话就是老板根本不懂什么安装、部署、监控、什么LVS、什么高可用，什么高并发……<br>老板又问，又要买服务器，”上个月不是刚刚花了200多万购买了一批服务器到机房么“，等等。你需要将你所做的事情升华出来，当然你一定有一定的价值真正产出。说了这么多，举个例子，为了提升运营人员的工作效率，运维开发了各种小巧的小工具，原来需要半天才能出来的数据，运维开发出工具，几分钟就出来了运营人员需要的数据，这就是的效率的提升。]</p>
<p>[\<br>]</p>
<p>[<strong><em>[那么运维平台化和价值化的维度在在哪儿呢?]</em></strong><br>]</p>
<p>[<strong><em>[\<br>]</em></strong><br>]</p>
<p><img src="http://static.oschina.net/uploads/space/2016/0217/164729_ToB8_1452345.png" alt="">\</p>
<p>[<img src="http://static.oschina.net/uploads/space/2016/0217/164741_F6Zq_1452345.png" alt="">\<br>]</p>
<p>[后续在分享运维平台化的具体实现方式~ ]</p>
<p>[谢谢]</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;p&gt;[&lt;em&gt;*&lt;/em&gt;[运维是什么？]&lt;/p&gt;
&lt;p&gt;[&lt;br&gt; [运维是
    
    </summary>
    
      <category term="工作日志" scheme="https://devops.osichina.net/categories/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
    
      <category term="工作日志" scheme="https://devops.osichina.net/tags/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/"/>
    
  </entry>
  
  <entry>
    <title>Mac wifi 自动控制脚本</title>
    <link href="https://devops.osichina.net/2016/01/22/12/"/>
    <id>https://devops.osichina.net/2016/01/22/12/</id>
    <published>2016-01-22T13:30:07.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#!/bin/bash</span></div><div class="line"><span class="comment">#author: 黄高明</span></div><div class="line"><span class="comment">#date: 2016-01-22</span></div><div class="line"><span class="comment">#qq: 530035210</span></div><div class="line"><span class="comment">#blog: http://my.oschina.net/pwd/blog </span></div><div class="line"><span class="comment">#控制mac wifi脚本   </span></div><div class="line">logdir=/data/<span class="built_in">log</span>/shell          <span class="comment">#日志路径</span></div><div class="line"><span class="built_in">log</span>=<span class="variable">$logdir</span>/log.log            <span class="comment">#日志文件 </span></div><div class="line">is_font=1                <span class="comment">#终端是否打印日志: 1打印 0不打印 </span></div><div class="line">is_log=0                 <span class="comment">#是否记录日志: 1记录 0不记录</span></div><div class="line">ssid=<span class="string">"Raincy"</span></div><div class="line">ssid_passwd=<span class="string">"aa123456"</span></div><div class="line">ip_info=<span class="string">"192.168.0.120 255.255.255.0 192.168.0.1"</span></div><div class="line">dnsgroup=<span class="string">"25.25.25.1 223.5.5.5"</span></div><div class="line">device=<span class="string">"Wi-Fi"</span>  </div><div class="line"><span class="function"><span class="title">datef</span></span>()&#123;</div><div class="line">date <span class="string">"+%Y-%m-%d %H:%M:%S"</span></div><div class="line">&#125;</div><div class="line">    </div><div class="line"><span class="function"><span class="title">print_log</span></span>()&#123;</div><div class="line"><span class="keyword">if</span> [[ <span class="variable">$is_log</span> -eq 1  ]];<span class="keyword">then</span></div><div class="line">[[ -d <span class="variable">$logdir</span> ]] || mkdir -p <span class="variable">$logdir</span></div><div class="line"><span class="built_in">echo</span> <span class="string">"[ <span class="variable">$(datef)</span> ] <span class="variable">$1</span>"</span> &gt;&gt; <span class="variable">$log</span></div><div class="line"><span class="keyword">fi</span></div><div class="line"><span class="keyword">if</span> [[ <span class="variable">$is_font</span> -eq 1  ]];<span class="keyword">then</span></div><div class="line"><span class="built_in">echo</span> <span class="string">"[ <span class="variable">$(datef)</span> ] <span class="variable">$1</span>"</span></div><div class="line"><span class="keyword">fi</span></div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="title">wifi_action</span></span>()&#123;</div><div class="line"><span class="keyword">case</span> <span class="variable">$1</span> <span class="keyword">in</span> </div><div class="line"></div><div class="line">list)</div><div class="line">/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport scan</div><div class="line"></div><div class="line">;;</div><div class="line">start)</div><div class="line">networksetup -setairportpower en0 on</div><div class="line"></div><div class="line">;;</div><div class="line">stop)</div><div class="line">networksetup -setairportpower en0 off</div><div class="line"></div><div class="line">;;</div><div class="line">connect)</div><div class="line"><span class="keyword">if</span> [[ <span class="string">"<span class="variable">$ssid</span>"</span> == <span class="string">""</span> &amp;&amp; <span class="string">"<span class="variable">$ssid_passwd</span>"</span> == <span class="string">""</span> ]];<span class="keyword">then</span></div><div class="line">networksetup -setairportnetwork en0 <span class="variable">$ssid</span> <span class="variable">$ssid_passwd</span></div><div class="line"><span class="keyword">else</span></div><div class="line">print_log  <span class="string">"ssid or password 为空."</span></div><div class="line"><span class="keyword">fi</span></div><div class="line"></div><div class="line">;;</div><div class="line"><span class="built_in">set</span>-statics-ip)</div><div class="line">networksetup -setmanual <span class="string">"<span class="variable">$device</span>"</span> <span class="variable">$ip_info</span></div><div class="line"></div><div class="line">;;</div><div class="line"><span class="built_in">set</span>-dhcp-ip)</div><div class="line"> ipconfig <span class="built_in">set</span> en0 DHCP</div><div class="line"></div><div class="line">;;</div><div class="line">list-devices)</div><div class="line">networksetup -listallnetworkservices</div><div class="line">;;</div><div class="line"><span class="built_in">set</span>-dns)</div><div class="line">networksetup -setdnsservers <span class="string">"<span class="variable">$device</span>"</span>  <span class="variable">$dnsgroup</span></div><div class="line">dscacheutil -flushcache </div><div class="line">;;</div><div class="line">*)</div><div class="line"><span class="built_in">echo</span> <span class="string">"usage: wifi.sh list| start| stop| connect| set-statics-ip| set-dhcp-ip| list-devices| set-dns"</span></div><div class="line"></div><div class="line">;;</div><div class="line"><span class="keyword">esac</span></div><div class="line">&#125;</div><div class="line">wifi_action <span class="string">"<span class="variable">$1</span>"</span></div></pre></td></tr></table></figure>
<p>root权限下：</p>
<p>usage: wifi.sh list:查看Wi-Fi列表| start 启动| stop关闭|<br>connect连接某个ssid| set-statics-ip设置静态ip| set-dhcp-ip设置动态IP|<br>list-devices查看网络设备| set-dns设置dns</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;t
    
    </summary>
    
      <category term="MAC小技巧" scheme="https://devops.osichina.net/categories/MAC%E5%B0%8F%E6%8A%80%E5%B7%A7/"/>
    
    
      <category term="MAC小技巧" scheme="https://devops.osichina.net/tags/MAC%E5%B0%8F%E6%8A%80%E5%B7%A7/"/>
    
  </entry>
  
  <entry>
    <title>让Mac OS X的终端多姿多彩</title>
    <link href="https://devops.osichina.net/2016/01/22/13/"/>
    <id>https://devops.osichina.net/2016/01/22/13/</id>
    <published>2016-01-22T12:12:05.000Z</published>
    <updated>2017-06-07T13:53:53.000Z</updated>
    
    <content type="html"><![CDATA[<script src="/assets/js/DPlayer.min.js"> </script><script src="/assets/js/APlayer.min.js"> </script><h1 id="让Mac-OS-X的终端多姿多彩"><a href="#让Mac-OS-X的终端多姿多彩" class="headerlink" title="让Mac OS X的终端多姿多彩"></a>让Mac OS X的终端多姿多彩</h1><p>FEB 27TH, 2012</p>
<p>与Linux相比，Mac OS<br>X的终端总是欠缺些什么。对了，是色彩，Linux的ls命令使用不同颜色区分各种文件类型，Vim编辑器也支持语法高亮，而Mac终端却总是以黑白示人。其实，只要稍微做一些工作，Mac的终端同样可以多姿多彩，请往下看。</p>
<h2 id="彩色化ls的输出"><a href="#彩色化ls的输出" class="headerlink" title="彩色化ls的输出"></a>彩色化ls的输出</h2><p>Mac中BSD的ls命令可以使用<code>-G</code>参数彩色化输出的文件列表，需要配置LSCOLORS环境变量定义颜色，具体配置方法可以输入<code>man ls</code>查看。</p>
<p>不过，我推荐安装Linux使用的GNU Coreutils替换Mac的ls命令，因为：</p>
<ul>
<li><p>Coreutils提供了配置工具，定义颜色代码更加方便；</p>
</li>
<li><p>Coreutils包含的不仅仅是ls，同时作为Linux用户，我更习惯于使用GNU的各种shell工具。</p>
</li>
</ul>
<p>Coreutils的安装与配置方法如下：</p>
<ol>
<li><p>通过<a href="http://linfan.info/blog/2012/02/25/homebrew-installation-and-usage/" rel="external nofollow noopener noreferrer" target="_blank">Homebrew</a>安装Coreutils\<br><code>brew install xz coreutils</code>\<br>注：Coreutils并不依赖于xz，但它的源码是用xz格式压缩的，安装xz才能解压。</p>
</li>
<li><p>生成颜色定义文件\<br><code>gdircolors --print-database &gt; ~/.dir_colors</code></p>
</li>
<li><p>在<code>~/.bash_profile</code>配置文件中加入以下代码</p>
</li>
<li><p>\</p>
</li>
</ol>
<p>[[if<br>]brew<br>list | grep coreutils &gt; /dev/null ;<br>[then][[<br> ]</p>
<p>[[PATH][\”\$(brew<br>–prefix<br>coreutils)/libexec/gnubin:\$PATH\”][<br> ]</p>
<p>[[alias<br>][\’ls<br>-F –show-control-chars<br>–color=auto\’][<br> ]</p>
<p>[[eval]<br>[`]gdircolors<br>-b<br>[\$HOME]</p>
<p>[[fi]</p>
<p>gdircolor的作用就是设置ls命令使用的环境变量LS_COLORS（BSD是LSCOLORS），我们可以修改~/.dir_colors自定义文件的颜色，此文件中的注释已经包含各种颜色取值的说明。</p>
<p>看看默认颜色的显示效果。</p>
<h2 id="grep高亮显示关键字"><a href="#grep高亮显示关键字" class="headerlink" title="grep高亮显示关键字"></a>grep高亮显示关键字</h2><p>这个很简单，加上<code>--color</code>参数就可以了，为了使用方便，可以在<code>~/.bash_profile</code>配置文件中加上alias定义。</p>
<p>[[[[alias<br>][\’grep<br>–color\’]</p>
<p>[[[[alias<br>][\’egrep<br>–color\’]</p>
<p>[[[[alias<br>][\’fgrep<br>–color\’]</p>
<h2 id="Vim语法高亮"><a href="#Vim语法高亮" class="headerlink" title="Vim语法高亮"></a>Vim语法高亮</h2><p>在Vim中输入命令<code>:syntax on</code>激活语法高亮，若需要Vim启动时自动激活，在<code>~/.vimrc</code>中添加一行<code>syntax on</code>即可。</p>
]]></content>
    
    <summary type="html">
    
      &lt;script src=&quot;/assets/js/DPlayer.min.js&quot;&gt; &lt;/script&gt;&lt;script src=&quot;/assets/js/APlayer.min.js&quot;&gt; &lt;/script&gt;&lt;h1 id=&quot;让Mac-OS-X的终端多姿多彩&quot;&gt;&lt;a href=&quot;#让Mac
    
    </summary>
    
      <category term="MAC小技巧" scheme="https://devops.osichina.net/categories/MAC%E5%B0%8F%E6%8A%80%E5%B7%A7/"/>
    
    
      <category term="MAC小技巧" scheme="https://devops.osichina.net/tags/MAC%E5%B0%8F%E6%8A%80%E5%B7%A7/"/>
    
  </entry>
  
</feed>
