<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Victory&#39;s Blog</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://yoursite.com/"/>
  <updated>2023-03-06T14:39:46.916Z</updated>
  <id>http://yoursite.com/</id>
  
  <author>
    <name>Victory</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>My Resume</title>
    <link href="http://yoursite.com/2023/03/01/MyResume/"/>
    <id>http://yoursite.com/2023/03/01/MyResume/</id>
    <published>2023-02-28T16:43:39.857Z</published>
    <updated>2023-03-06T14:39:46.916Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Python程序员-李志威"><a href="#Python程序员-李志威" class="headerlink" title="Python程序员-李志威"></a>Python程序员-李志威</h1><hr><h1 id="联系方式"><a href="#联系方式" class="headerlink" title="联系方式"></a>联系方式</h1><ul><li>手机 ：136-9334-7696</li><li>Email：<a href="mailto:lzw9560@163.com" target="_blank" rel="noopener">lzw9560@163.com</a> </li><li>微信号：329396703</li><li>Github:  <a href="https://github.com/lzw9560" target="_blank" rel="noopener">https://github.com/lzw9560</a></li><li>Blog: <a href="https://lzw9560.github.io" target="_blank" rel="noopener">https://lzw9560.github.io</a></li></ul><a id="more"></a><hr><h1 id="个人信息"><a href="#个人信息" class="headerlink" title="个人信息"></a>个人信息</h1><ul><li>男 1990 </li><li>本科/计算机科学与技术 </li><li>工作年限：9年</li><li>期望职位：后台开发工程师</li><li>期望薪资：面议</li><li>期望城市：杭州</li></ul><hr><h1 id="工作经历"><a href="#工作经历" class="headerlink" title="工作经历"></a>工作经历</h1><h2 id="北京原语科技-（-2022年1月-至今-）"><a href="#北京原语科技-（-2022年1月-至今-）" class="headerlink" title="北京原语科技 （ 2022年1月 ~ 至今 ）"></a>北京原语科技 （ 2022年1月 ~ 至今 ）</h2><h3 id="后台开发工程师"><a href="#后台开发工程师" class="headerlink" title="后台开发工程师"></a>后台开发工程师</h3><h4 id="简介："><a href="#简介：" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>PrimiHub是原语科技基于多方安全计算、联邦学习、同态加密、可信计算等技术自主研发的分布式隐私计算平台。（平台涵盖隐私求交、联合建模、联合统计、匿踪查询、数据资源管理、算法容器管理、异构平台互联互通等，基于自研、开放隐私计算框架，打造适配全业务场景且兼容性能、安全性、高效的隐私计算平台。）</p><h4 id="岗位描述："><a href="#岗位描述：" class="headerlink" title="岗位描述："></a><strong>岗位描述</strong>：</h4><ul><li>联邦学习平台开发，GitHub开源代码贡献，文档更新</li><li>PrimiHub企业版定制功能开发</li><li>PrimiHub Python SDK Client 开发，通过gRPC向平台提交任务</li><li>Python SDK 编写，或使用Python对C++底层库进行二次封装</li><li>高性能APSI数据组件开发，支持无限制数据分箱，分布式数据预处理</li><li>PrimiHub平台算法集成，调试</li><li>协助解决平台使用中遇到的其他问题</li></ul><h2 id="中国广视索福瑞媒介研究有限责任公司-（-2019年4月-2021年12月-）"><a href="#中国广视索福瑞媒介研究有限责任公司-（-2019年4月-2021年12月-）" class="headerlink" title="中国广视索福瑞媒介研究有限责任公司 （ 2019年4月 ~ 2021年12月 ）"></a>中国广视索福瑞媒介研究有限责任公司 （ 2019年4月 ~ 2021年12月 ）</h2><h3 id="媒介受众调查与研究"><a href="#媒介受众调查与研究" class="headerlink" title="媒介受众调查与研究"></a>媒介受众调查与研究</h3><h4 id="简介：-1"><a href="#简介：-1" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>中国广视索福瑞媒介研究(CSM)是央视市场研究(CTR)与Kantar Media集团等共同建立的中外合作企业，自1997年12月4日成立以来，基于国际科学的技术理念和对国内市场的深入了解，开展电视收视率调查、广播收听率调查、体育与媒介研究和新媒体研究等多项研究业务，为中国大陆地区和香港传媒行业提供可靠的、不间断的视听率调查及深度研究服务。</p><h4 id="描述："><a href="#描述：" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>负责后端API后端架构设计</li><li>负责服务器运维，故障排查，保障服务器稳定运行</li><li>负责团队建设，基础设施平台搭建（GitLab, Docker私有仓库, Airflow, Zabbix …）</li><li>自动化构建CI脚本编写，运维脚本编写</li><li>编写 <strong>dockerfile</strong> / <strong>docker-compose</strong> 脚本</li><li>使用 <strong>Golang</strong> Web框架 <strong>Beego</strong> 开发电视广告二维码导流系统</li><li>使用 <strong>FastAPI</strong> 开发音视频分析管理系统,总台专区舆情报告系统等多个项目</li><li>使用 <strong>Django REST framework</strong> 开发融合媒体数据云平台，包含媒体收视数据可视化，榜单，词云，热点，微信小程序等等</li><li>使用 <strong>Django REST framework</strong> 开发电视广告收视分析系统(直播, 开机,  OTT,  IPTV),集成<strong>Celery</strong>异步任务框架</li><li>在 <strong>Windows</strong> 平台下开发电视台数据分析报告，<strong>RPC</strong> 服务框架搭建，核心代码编写</li><li>使用 <strong>Filebeat</strong> 收集日志到 <strong>Elasticsearch</strong></li></ul><h2 id="企鹅创新（北京）科技有限公司-（-2018年5月-2019年4月-）"><a href="#企鹅创新（北京）科技有限公司-（-2018年5月-2019年4月-）" class="headerlink" title="企鹅创新（北京）科技有限公司 （ 2018年5月 ~ 2019年4月 ）"></a>企鹅创新（北京）科技有限公司 （ 2018年5月 ~ 2019年4月 ）</h2><h3 id="智能家居产品"><a href="#智能家居产品" class="headerlink" title="智能家居产品"></a>智能家居产品</h3><h4 id="简介：-2"><a href="#简介：-2" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>PENGUINS INNOVATE，由一群90后年轻人创立的企鹅创新，今年9月全新发布了室内机器人rabbit。rabbit各项功能都基于强大的机器视觉识别算法，即使在没有指令的情况下，也能根据使用者的行为自主研判，在朝夕相处中逐渐了解并适应用户的生活习惯。</p><h4 id="描述：-1"><a href="#描述：-1" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>项目架构采用前后分离，主要负责后台应用框架搭建，应用服务器后台API重构设计实现，使用 <strong>Django REST framework</strong> ，<strong>Tonado</strong>，<strong>Celery</strong>。</li><li>负责后台应用服务器搭建维护，自动化构建采用 <strong>GitLab CI + Docker + Fabric</strong> 实现。</li><li>采用 <strong>Ucloud SDK</strong>  + <strong>Aliyun SDK</strong>  实现了视屏直播、录制、存储等多媒体功能。</li><li>集成了对IOS平台，Android平台（国内外）消息推送服务。</li><li>完成了后台服务语言本地/国际化。</li><li>设计实现了硬件设备远程升级服务。</li><li>采用 <strong>Fluentd</strong> 轻量级日志框架收集设备活动日志,为机器学习以及用户行为分析准备数据样本。</li><li>使用 <strong>TensorFlow</strong> 对用户手势模型进行训练。</li></ul><h2 id="架标科技有限公司-（-2016年9月-2018年5月-）"><a href="#架标科技有限公司-（-2016年9月-2018年5月-）" class="headerlink" title="架标科技有限公司 （ 2016年9月 ~ 2018年5月 ）"></a>架标科技有限公司 （ 2016年9月 ~ 2018年5月 ）</h2><h3 id="基于电子价签扩展应用系统"><a href="#基于电子价签扩展应用系统" class="headerlink" title="基于电子价签扩展应用系统"></a>基于电子价签扩展应用系统</h3><h4 id="简介：-3"><a href="#简介：-3" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>基于新零售的概念，项目以电子价签为切入点，替换了纸质标签，节省超市成本的同时为用户提供有别于传统超市的购物体验，能够实时显示商品价格信息，做到线上线下同步，同时可以做到商品定位导航，货架管理，商品陈列管理，同时还有基于电子标签蓝牙和NFC的互动，提升了用户在线下商超购物乐趣，通过线上加线下的方式，收集用户购物行为习惯，实现流量变现，提升用户粘合度。应用系统后台基于 <strong>Flask-RESTful</strong> 和  <strong>Django REST framework</strong>  技术实现，分为移动APP用户端，超市端管理，后台商品管理，电子价签管理，等多个模块。</p><h4 id="描述：-2"><a href="#描述：-2" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>项目架构采用前后分离，主要负责后台应用框架搭建，API设计实现。</li><li>项目中涉及相对比较复杂的权限管理控制，设计实现了 <strong>RBAC（Resource-Based Access Contro）</strong> 基于资源的权限控制模型Flask插件。</li><li>优化了数据同步脚本，提升了运行效率，数据库读写采用批量提交回滚，涉及到csv文件读写，使用 <strong>Python yield</strong> 实现，10w条商品数据处理大约需要600多秒。</li><li>负责搭建自动化持续构建集成 <strong>GitLab CI</strong>持续构建工具。</li><li>负责服务器代码部署，使用 <strong>uWSGI + Nginx/supervisor + gunicorn + Nginx</strong>。</li><li>采用 <strong>Django Celery</strong> 执行后台异步任务、定时任务。</li><li>涉及室外定位采用地理相关使用 <strong>PostGIS GeoDjango</strong> ，坐标计算，距离计算。</li><li>使用 <strong>Elasticsearch</strong> + 中文分词插件，完成商品搜索匹配。</li></ul><h2 id="搜狐公司-网络运营部-（-2016年3月-2016年9月-）"><a href="#搜狐公司-网络运营部-（-2016年3月-2016年9月-）" class="headerlink" title="搜狐公司-网络运营部 （ 2016年3月 ~ 2016年9月 ）"></a>搜狐公司-网络运营部 （ 2016年3月 ~ 2016年9月 ）</h2><h3 id="自动化构建部署发布模块-用户验收测试框"><a href="#自动化构建部署发布模块-用户验收测试框" class="headerlink" title="自动化构建部署发布模块-用户验收测试框"></a>自动化构建部署发布模块-用户验收测试框</h3><h4 id="简介：-4"><a href="#简介：-4" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>该项目属于公司内部运维平台自动化构建部署框架的一部分，用于自动化用户验收测试框架，需要在Linux下准备测试环境，然后在Windows下实现具体测试用例，为了避免环境干扰和测试用例解耦合，针对用例在Linux虚拟机上准备单独的LXC测试环境，环境部分分为测试环境准备，测试环境初始化，测试环境还原；测试框架部分主要是测试用例的分发规则和具体测试用例，最后结合Jenkins集成框架，实现了自动化构建，部署，发布功能。</p><h4 id="描述：-3"><a href="#描述：-3" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>测试框架使用 <strong>Selenuim + PyUnit</strong> 的方式进行用例编写自动化测试框架。</li><li>针对自动化运维平台，覆盖不同使用场景，不同使用流程的测试用例编写。</li><li>Windows下自动化测试框架设计开发。</li><li>Linux下运维脚本开发，编写自动化脚本准备测试LXC虚拟环境。</li><li>编写Shell脚本，对测试数据库数据进行更新恢复，数据还原。</li></ul><h2 id="北京文思海辉技术有限公司-（-2013年6月-2016年3月-）"><a href="#北京文思海辉技术有限公司-（-2013年6月-2016年3月-）" class="headerlink" title="北京文思海辉技术有限公司  （ 2013年6月 ~ 2016年3月 ）"></a>北京文思海辉技术有限公司  （ 2013年6月 ~ 2016年3月 ）</h2><h3 id="轨道电路虚拟仿真分析平台系统"><a href="#轨道电路虚拟仿真分析平台系统" class="headerlink" title="轨道电路虚拟仿真分析平台系统"></a>轨道电路虚拟仿真分析平台系统</h3><h4 id="简介：-5"><a href="#简介：-5" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>轨道电路虚拟仿真分析软件是轨道电路专项实验室的重要组成部分，需实现轨道电路的仿真计算、结果分析和数据管理功能，支撑轨道电路的技术方案论证、系统/设备结构调整论证、传输极限条件测试、元器件故障安全测试、调整表计算和管理、现场故障仿真分析等工作，为轨道电路的研发、优化、测试、应用、集成、售后提供服务。轨道电路虚拟仿真分析软件为系统研发阶段的仿真环境，提供轨道电路的仿真计算功能和数据管理功能。</p><h4 id="描述：-4"><a href="#描述：-4" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>用户需求分析，数据库模型设计，功能模块实现，代码编写以及优化</li><li>服务器端脚本程序编写</li><li>调用MatLab进行科学计算，结果存储</li><li>使用Django模板渲染计算结果</li></ul><!-- ## 启动力咨询有限责任公司  （ 2013年6月 ~ 2015年3月 ）### 院校学生信息管理应用 #### 简介：该应用基于Django框架开发，是一款打通微信接口的轻APP，通过微信访问，实现轻松管理学生信息，并对学生学习阶段进行跟踪测试，该web分为后台管理端（提供管理员对学生信息进行管理），和用户端（学生查看个人信息以及进行阶段测试等），实现了通过移动端方便的进行学生同院校之间的信息交互，该web应用有很强的拓展性和可移植性。#### **描述**：- 需求分析，数据库模型设计，功能模块实现，代码编写以及优化。- 在这个项目中开始接触Python，感觉太好用了，语法简单，代码排版也很美观，很大的提升了开发速度，根本停不下来了。### 电子招投标系统基础设施平台#### 简介：本系统是一款基础设施类项目，以网络技术为基础, 招标、投标、评标、合同等业务全过程实现数字化、网络化、高度集成化的系统,该系统实现了基本的业务功能要求,同时也考虑了系统的性能及安全性问题,并提出了相应的安全控制措施。安全性和可靠性是本系统的根本问题，本系统具有操作简单、用户界面友好的特点,为招投标业务实现电子化管理的应用奠定了基础,对提高招投标业务管理水平具有重要的现实意义。项目主要针对节点之间通信做安全保障，将节点之间通信的数据不定时的更新密钥，节点接受数据之后调用系统提供的接口通过本系统进行加密，进行安全传输。#### 描述：- 使用C++编写Linux密钥管理客户端模块，实现应用节点和应用节点之间的身份认证- 通过调用报文处理函数API，对服务端收到的相应节点请求进行处理，实现密钥的协商，校验，查看和注销，对密钥进行生命周期管理- 服务器从数据库读取应用节点的密钥信息，保存在共享内存以便实现高速访问，调用共享内存相关操作组件对共享内存进行读写操作- 通过对共享内存的操作来管理密钥信息，在开发过程中解决了因为指针类型转换导致读取内存因为指针偏移步长导致的程序段错误的问题- 使用ASN.l（抽象语法标记语言）处理报文，对传输信息进行编码，解码处理,该标准提供的TLV格式描述了对象的结构，并不关心具体数据的实现，简单易用，清晰明了，参与报文格式的设计，对报文数据进行表示、编码、传输和解码- 分别在Windows和Linux下平台将函数功能实现的部分接口进行封装，实现跨平台使用，导出成供Windows/Linux程序调用的动态库，提供系统外联接口，供前置机上层应用调用 --><hr><h1 id="技能清单"><a href="#技能清单" class="headerlink" title="技能清单"></a>技能清单</h1><ul><li>Linux：<strong>Linux命令/Shell脚本/Nginx</strong></li><li>数据库：<strong>MySQL/PostgreSQL/Oracle/SQLite/SQL Server/Redis</strong></li><li>Web框架：<strong>Django/Flask/Tonado</strong></li><li>任务队列：<strong>Celery</strong></li><li>API调试：<strong>Postman/Charles/Fiddler</strong></li><li>持续构建：<strong>GitLAB CI</strong></li><li>版本管理：<strong>Git/SourceTree</strong></li><li>文档：<strong>Markdown</strong> / <strong>YAML</strong> / <strong>ReStructuredText</strong></li><li>单元测试：<strong>Unittest</strong></li><li>科学上网：自带翻墙技能</li><li>其他：Websocket/MQTT/TensorFlow</li></ul><h1 id="自我评价"><a href="#自我评价" class="headerlink" title="自我评价"></a>自我评价</h1><ul><li>热爱工作，热爱生活，善于充实自我</li><li>具有良好的文档编写能力，能按要求完成项目所需文档的编写</li><li>具有良好的团队合作精神，工作责任心强，能承受一定的工作压力</li><li>工作认真，有较强的责任心，具备良好的团队精神</li><li>有很强的学习能力，态度端正，强烈的求知欲</li></ul><h1 id="资格证书"><a href="#资格证书" class="headerlink" title="资格证书"></a>资格证书</h1><ul><li>PMP项目管理认证</li></ul><h1 id="参与开源项目"><a href="#参与开源项目" class="headerlink" title="参与开源项目"></a>参与开源项目</h1><ul><li><a href="https://github.com/primihub/primihub" target="_blank" rel="noopener">https://github.com/primihub/primihub</a></li><li><a href="https://github.com/lzw9560/pyapsi" target="_blank" rel="noopener">https://github.com/lzw9560/pyapsi</a></li></ul><hr><h1 id="致谢"><a href="#致谢" class="headerlink" title="致谢"></a>致谢</h1><p>感谢您花时间阅读我的简历，期待能有机会和您共事。</p>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;Python程序员-李志威&quot;&gt;&lt;a href=&quot;#Python程序员-李志威&quot; class=&quot;headerlink&quot; title=&quot;Python程序员-李志威&quot;&gt;&lt;/a&gt;Python程序员-李志威&lt;/h1&gt;&lt;hr&gt;
&lt;h1 id=&quot;联系方式&quot;&gt;&lt;a href=&quot;#联系方式&quot; class=&quot;headerlink&quot; title=&quot;联系方式&quot;&gt;&lt;/a&gt;联系方式&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;手机 ：136-9334-7696&lt;/li&gt;
&lt;li&gt;Email：&lt;a href=&quot;mailto:lzw9560@163.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;lzw9560@163.com&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;微信号：329396703&lt;/li&gt;
&lt;li&gt;Github:  &lt;a href=&quot;https://github.com/lzw9560&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/lzw9560&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Blog: &lt;a href=&quot;https://lzw9560.github.io&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://lzw9560.github.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
      <category term="My Resume" scheme="http://yoursite.com/tags/My-Resume/"/>
    
  </entry>
  
  <entry>
    <title>TDD</title>
    <link href="http://yoursite.com/2020/03/14/Development/tdd/"/>
    <id>http://yoursite.com/2020/03/14/Development/tdd/</id>
    <published>2020-03-13T16:00:00.000Z</published>
    <updated>2020-03-14T07:04:54.522Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Summary"><a href="#Summary" class="headerlink" title="Summary"></a>Summary</h1><p>测试驱动开发（Test-Driven-Development） 简称：TDD</p><a id="more"></a><h1 id="Process"><a href="#Process" class="headerlink" title="Process"></a>Process</h1><pre><code>- 编写 TODO List- 编写测试用例test case- 运行不通过的测试 test RED- 编写对应的功能代码 code- 测试通过 test pass GREEN- 重构 REDACTOR</code></pre><h1 id="Principle"><a href="#Principle" class="headerlink" title="Principle"></a>Principle</h1><pre><code>- 隔离测试- 一顶帽子- 测试列表- 测试驱动     &gt; 完成某个功能函数，首先编写测试代码，考虑如何使用，如何测试；然后在对其进行设计编码。- 先写断言- 可测试性    &gt; 高内聚，接口依赖- 及时重构- 小步前进    &gt; 极限编程</code></pre><h1 id="Trap"><a href="#Trap" class="headerlink" title="Trap"></a>Trap</h1><pre><code>* 忘记运行测试* 一次编写太多测试* 编写太大或者粗粒度的测试* 编写过于琐碎的测试，省略断言* 为琐碎的代码编写测试* 项目中部分使用TDD* 测试集合维护不力-运行时间过长* 废弃的测试集合</code></pre><h1 id="Scope"><a href="#Scope" class="headerlink" title="Scope"></a>Scope</h1><pre><code>测试驱动开发强调的不是负担，而是应该帮助我们减轻工作量的方法。取决于个人的经验，功能复杂，核心功能的代码就应该编写更全面、细致的测试用例，一般的测试流程即可。测试范围没有静态的标准，同时也应该可以随着时间改变。对于开始没有编写足够的测试的功能代码，根据bug补全即可。</code></pre><h1 id="How"><a href="#How" class="headerlink" title="How"></a>How</h1><pre><code>测试用例的编写使用传统的测试技术即可。</code></pre><h1 id="Tips"><a href="#Tips" class="headerlink" title="Tips"></a>Tips</h1><pre><code>以最初的开发工作量的适度增加为代价，达到最终的缺陷率降低，并且有助于减少后期工作量；TDD 有助于提高代码质量，高内聚和耦合度。谨防过渡设计。</code></pre><p><a href="https://www.amazon.com/gp/product/0321146530/ref=as_li_ss_tl?ie=UTF8&amp;linkCode=sl1&amp;tag=&amp;linkId=6d76ed79b7f498d7930b370ad4c059ac," title="测试驱动开发" target="_blank" rel="noopener">测试驱动开发</a>，肯特·贝克（Kent Beck）</p>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;Summary&quot;&gt;&lt;a href=&quot;#Summary&quot; class=&quot;headerlink&quot; title=&quot;Summary&quot;&gt;&lt;/a&gt;Summary&lt;/h1&gt;&lt;p&gt;测试驱动开发（Test-Driven-Development） 简称：TDD&lt;/p&gt;
    
    </summary>
    
      <category term="Development" scheme="http://yoursite.com/categories/Development/"/>
    
    
      <category term="Development" scheme="http://yoursite.com/tags/Development/"/>
    
  </entry>
  
  <entry>
    <title>Python 策略模式（灵活调用个不同平台直播SDK）</title>
    <link href="http://yoursite.com/2019/03/13/code/Python/Python-%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8F/"/>
    <id>http://yoursite.com/2019/03/13/code/Python/Python-策略模式/</id>
    <published>2019-03-12T16:00:00.000Z</published>
    <updated>2019-03-13T15:52:07.128Z</updated>
    
    <content type="html"><![CDATA[<h4 id="Python策略模式（灵活调用个不同平台直播SDK）"><a href="#Python策略模式（灵活调用个不同平台直播SDK）" class="headerlink" title="Python策略模式（灵活调用个不同平台直播SDK）"></a>Python策略模式（灵活调用个不同平台直播SDK）</h4><a id="more"></a><p><img src="https://i.loli.net/2019/03/13/5c89258069896.png" alt="Main.png"></p><h2 id="说明："><a href="#说明：" class="headerlink" title="说明："></a>说明：</h2><p>使用策略模式封装了不同直播平台的SDK。</p><blockquote><p>代码目录结构：</p><p>├── <strong>init</strong>.py<br>├── context.py<br>├── live.py<br>├── live_aliyun.py<br>├── live_aliyun_edge.py<br>└── live_ucloud.py</p></blockquote><h3 id="context-py"><a href="#context-py" class="headerlink" title="context.py"></a>context.py</h3><blockquote><p>环境类</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Created by lizhiwei at 2018/12/17</span></span><br><span class="line"><span class="keyword">import</span> logging</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> .live_aliyun <span class="keyword">import</span> LiveAliyun</span><br><span class="line"><span class="keyword">from</span> .live_aliyun_edge <span class="keyword">import</span> LiveAliyunEdge</span><br><span class="line"><span class="keyword">from</span> .live_ucloud <span class="keyword">import</span> LiveUcloud</span><br><span class="line"></span><br><span class="line">logger = logging.getLogger(<span class="string">'debug'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LiveContext</span><span class="params">(object)</span>:</span></span><br><span class="line">    LIVE_PLATFORM = &#123;</span><br><span class="line">        <span class="string">"aliyun"</span>: LiveAliyun,</span><br><span class="line">        <span class="string">"ucloud"</span>: LiveUcloud,</span><br><span class="line">        <span class="string">'aliyun_edge'</span>: LiveAliyunEdge</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, platform=<span class="string">""</span>, channel=<span class="string">""</span>)</span>:</span></span><br><span class="line">        <span class="string">"""Constructor"""</span></span><br><span class="line">        self._platform = platform.lower()</span><br><span class="line">        self._channel = channel</span><br><span class="line"></span><br><span class="line">        self._live = self.LIVE_PLATFORM[self._platform](channel)</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">channel</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The channel property - the getter</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">return</span> self._channel</span><br><span class="line"></span><br><span class="line"><span class="meta">    @channel.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">channel</span><span class="params">(self, value)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The setter of the channel property</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        self._channel = value</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">platform</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The platform property - the getter</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">return</span> self._platform</span><br><span class="line"></span><br><span class="line"><span class="meta">    @platform.setter</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">platform</span><span class="params">(self, value)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The setter of the platform property</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        self._platform = value</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">pusher</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The pusher property - the getter</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">return</span> self._live.get_pusher()</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">rtmp_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The rtmp player property - the getter</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">return</span> self._live.get_rtmp_player()</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">hls_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The hls player property - the getter</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">return</span> self._live.get_hls_player()</span><br><span class="line"></span><br><span class="line"><span class="meta">    @property</span></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">players</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The players property - the getter</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">return</span> self._live.get_players()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">record_pusher</span><span class="params">(self, record_id)</span>:</span></span><br><span class="line">        <span class="string">"""</span></span><br><span class="line"><span class="string">        The record_pusher</span></span><br><span class="line"><span class="string">        """</span></span><br><span class="line">        <span class="keyword">return</span> self._live.get_record_pusher(record_id=record_id)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_obj_url</span><span class="params">(self, name, expires=<span class="number">3600</span>)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._live.get_obj_url(name, expires)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">put_stream_file</span><span class="params">(self, local, target, mime_type=<span class="string">'image/jpeg'</span>)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._live.put_stream_file(local=local, target=target, mime_type=mime_type)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">upload_file</span><span class="params">(self, local, target, mime_type=<span class="string">'image/jpeg'</span>)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> self._live.upload_file(local, target)</span><br></pre></td></tr></table></figure><h3 id="live-py"><a href="#live-py" class="headerlink" title="live.py"></a>live.py</h3><blockquote><p>抽象策略类</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">#!/usr/bin/env python</span><br><span class="line"># -*- coding: utf-8 -*-</span><br><span class="line"></span><br><span class="line"># Created by lizhiwei at 2018/12/17</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">class Live(object):</span><br><span class="line">    &quot;&quot;&quot;Live stragegy.&quot;&quot;&quot;</span><br><span class="line"></span><br><span class="line">    def __init__(self, channel):</span><br><span class="line">        self.channel = channel</span><br><span class="line"></span><br><span class="line">    def get_pusher(self):</span><br><span class="line">        raise NotImplementedError()</span><br><span class="line"></span><br><span class="line">    def get_rtmp_player(self):</span><br><span class="line">        raise NotImplementedError()</span><br><span class="line"></span><br><span class="line">    def get_record_pusher(self, record_id):</span><br><span class="line">        raise NotImplementedError()</span><br><span class="line"></span><br><span class="line">    def get_hls_player(self):</span><br><span class="line">        raise NotImplementedError()</span><br><span class="line"></span><br><span class="line">    def get_flv_player(self):</span><br><span class="line">        raise NotImplementedError()</span><br><span class="line"></span><br><span class="line">    def get_players(self):</span><br><span class="line">        raise NotImplementedError()</span><br><span class="line"></span><br><span class="line">    def get_obj_url(self, name, expries):</span><br><span class="line">        raise NotImplementedError()</span><br><span class="line"></span><br><span class="line">    def put_stream_file(self, local, target, mime_type):</span><br><span class="line">        raise NotImplementedError()</span><br><span class="line"></span><br><span class="line">    def upload_file(self, local, target):</span><br><span class="line">        raise NotImplementedError()</span><br></pre></td></tr></table></figure><h3 id="live-aliyun-py"><a href="#live-aliyun-py" class="headerlink" title="live_aliyun.py"></a>live_aliyun.py</h3><blockquote><p>阿里云直播</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Created by lizhiwei at 2018/12/17</span></span><br><span class="line"><span class="keyword">import</span> logging</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> django.conf <span class="keyword">import</span> settings</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> utils <span class="keyword">import</span> oss_util</span><br><span class="line"><span class="keyword">from</span> utils.aliyun_auth <span class="keyword">import</span> add_a_auth</span><br><span class="line"><span class="keyword">from</span> .live <span class="keyword">import</span> Live</span><br><span class="line"></span><br><span class="line">logger = logging.getLogger(<span class="string">'debug'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LiveAliyun</span><span class="params">(Live)</span>:</span></span><br><span class="line">    <span class="string">"""Live Aliyun stragegy.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    参考：http://www.voidcn.com/article/p-yrdycvtt-bpk.html</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line"></span><br><span class="line">    ak_id = settings.ALIYUN_AK_ID</span><br><span class="line">    ak_secret = settings.ALIYUN_AK_SECRET</span><br><span class="line">    centre_live_domain = settings.ALIYUN_CENTRE_LIVE_DOMAIN</span><br><span class="line">    live_record_oss_bucket = settings.ALIYUN_CENTRE_LIVE_RECORD_OSS_BUCKET</span><br><span class="line">    live_record_region = settings.ALIYUN_CENTRE_LIVE_RECORD_REGION</span><br><span class="line">    app_name = settings.ALIYUN_CENTRE_LIVE_APPNAME</span><br><span class="line">    a_auth_key = settings.ALIYUN_CENTRE_A_AUTH_KEY</span><br><span class="line">    auth_exp = settings.ALIYUN_AUTH_EXP</span><br><span class="line">    oss_auth_exp = settings.ALIYUN_OSS_URL_EXPRIES</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, channel)</span>:</span></span><br><span class="line">        super(LiveAliyun, self).__init__(channel=channel)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_pusher</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">'''</span></span><br><span class="line"><span class="string">        中心推流：</span></span><br><span class="line"><span class="string">        完整的推流地址，形如：rtmp://video-center.alivecdn.com/&#123;AppName&#125;/&#123;StreamName&#125;?vhost=&#123;yourdomain&#125;</span></span><br><span class="line"><span class="string">        eg.</span></span><br><span class="line"><span class="string">        rtmp://video-center.alivecdn.com/ra/raa?vhost=live.rabbitslive.com&amp;auth_key=1545213384-0-0-ad382da6a9c36ce34c06a0c538d5f244</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        边缘推流：</span></span><br><span class="line"><span class="string">        rtmp://live.overseas.rabbitslive.com/rest/123?auth_key=1545716465-0-0-a7541fe9b19ddf594044b5ee6483f533</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        '''</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 中心推流</span></span><br><span class="line">        url = <span class="string">"rtmp://video-center.alivecdn.com/&#123;AppName&#125;/&#123;StreamName&#125;?vhost=&#123;LiveDomain&#125;"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.centre_live_domain,</span><br><span class="line">        )</span><br><span class="line">        logger.debug(<span class="string">"pusher url: %s"</span> % url)</span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_rtmp_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"rtmp://&#123;LiveDomain&#125;/&#123;AppName&#125;/&#123;StreamName&#125;?"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.centre_live_domain,</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_hls_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"http://&#123;LiveDomain&#125;/&#123;AppName&#125;/&#123;StreamName&#125;.m3u8"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.centre_live_domain,</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_flv_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"http://&#123;LiveDomain&#125;/&#123;AppName&#125;/&#123;StreamName&#125;.flv"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.centre_live_domain,</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_players</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="string">"rtmp"</span>: self.get_rtmp_player(),</span><br><span class="line">            <span class="string">"flv"</span>: self.get_flv_player(),</span><br><span class="line">            <span class="string">"hls"</span>: self.get_hls_player(),</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_record_pusher</span><span class="params">(self, record_id)</span>:</span></span><br><span class="line">        url = <span class="string">"rtmp://video-center.alivecdn.com/record_&#123;AppName&#125;/&#123;StreamName&#125;_&#123;record_id&#125;?vhost=&#123;LiveDomain&#125;"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.centre_live_domain,</span><br><span class="line">            record_id=record_id</span><br><span class="line">        )</span><br><span class="line">        logger.debug(<span class="string">"pusher url: %s"</span> % url)</span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_obj_url</span><span class="params">(self, name, expries)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> oss_util.get_obj_url(</span><br><span class="line">            access_key_id=self.ak_id,</span><br><span class="line">            access_key_secret=self.ak_secret,</span><br><span class="line">            region=self.live_record_region,</span><br><span class="line">            name=name,</span><br><span class="line">            bucket_name=self.live_record_oss_bucket,</span><br><span class="line">            expires=int(self.oss_auth_exp)</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">put_stream_file</span><span class="params">(self, local, target, mime_type)</span>:</span></span><br><span class="line">        logger.debug(<span class="string">'input: %s'</span> % local)</span><br><span class="line">        logger.debug(<span class="string">'target: %s'</span> % target)</span><br><span class="line">        oss_util.put_obj(</span><br><span class="line">            access_key_id=self.ak_id,</span><br><span class="line">            access_key_secret=self.ak_secret,</span><br><span class="line">            region=self.live_record_region,</span><br><span class="line">            bucket_name=self.live_record_oss_bucket,</span><br><span class="line">            input=local,</span><br><span class="line">            target=target</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">upload_file</span><span class="params">(self, local, target)</span>:</span></span><br><span class="line">        oss_util.put_obj_from_file(</span><br><span class="line">            access_key_id=self.ak_id,</span><br><span class="line">            access_key_secret=self.ak_secret,</span><br><span class="line">            region=self.live_record_region,</span><br><span class="line">            bucket_name=self.live_record_oss_bucket,</span><br><span class="line">            local_file=local,</span><br><span class="line">            target=target</span><br><span class="line">        )</span><br><span class="line">        <span class="keyword">import</span> os</span><br><span class="line">        os.remove(local)</span><br></pre></td></tr></table></figure><h3 id="live-aliyun-edge-py"><a href="#live-aliyun-edge-py" class="headerlink" title="live_aliyun_edge.py"></a>live_aliyun_edge.py</h3><blockquote><p>阿里云边缘推流（适用于海外地区）</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Created by lizhiwei at 2018/12/17</span></span><br><span class="line"><span class="keyword">import</span> logging</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> django.conf <span class="keyword">import</span> settings</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> utils <span class="keyword">import</span> oss_util</span><br><span class="line"><span class="keyword">from</span> utils.aliyun_auth <span class="keyword">import</span> add_a_auth</span><br><span class="line"><span class="keyword">from</span> .live <span class="keyword">import</span> Live</span><br><span class="line"></span><br><span class="line">logger = logging.getLogger(<span class="string">'debug'</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LiveAliyunEdge</span><span class="params">(Live)</span>:</span></span><br><span class="line">    <span class="string">"""Live Aliyun stragegy.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    参考：http://www.voidcn.com/article/p-yrdycvtt-bpk.html</span></span><br><span class="line"><span class="string">    """</span></span><br><span class="line"></span><br><span class="line">    ak_id = settings.ALIYUN_AK_ID</span><br><span class="line">    ak_secret = settings.ALIYUN_AK_SECRET</span><br><span class="line">    push_domain = settings.ALIYUN_EDGE_LIVE_PUSH_DOMAIN</span><br><span class="line">    play_domain = settings.ALIYUN_EDGE_LIVE_PLAY_DOMAIN</span><br><span class="line">    live_record_oss_bucket = settings.ALIYUN_EDGE_LIVE_RECORD_OSS_BUCKET</span><br><span class="line">    live_record_region = settings.ALIYUN_EDGE_LIVE_RECORD_REGION</span><br><span class="line">    app_name = settings.ALIYUN_EDGE_LIVE_APPNAME</span><br><span class="line">    a_auth_key = settings.ALIYUN_EDGE_A_AUTH_KEY</span><br><span class="line">    auth_exp = settings.ALIYUN_AUTH_EXP</span><br><span class="line">    oss_auth_exp = settings.ALIYUN_OSS_URL_EXPRIES</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, channel)</span>:</span></span><br><span class="line">        super(LiveAliyunEdge, self).__init__(channel=channel)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_pusher</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="string">'''</span></span><br><span class="line"><span class="string">        中心推流：</span></span><br><span class="line"><span class="string">        完整的推流地址，形如：rtmp://video-center.alivecdn.com/&#123;AppName&#125;/&#123;StreamName&#125;?vhost=&#123;yourdomain&#125;</span></span><br><span class="line"><span class="string">        eg.</span></span><br><span class="line"><span class="string">        rtmp://video-center.alivecdn.com/ra/raa?vhost=live.rabbitslive.com&amp;auth_key=1545213384-0-0-ad382da6a9c36ce34c06a0c538d5f244</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        边缘推流：</span></span><br><span class="line"><span class="string">        rtmp://live.overseas.rabbitslive.com/rest/123?auth_key=1545716465-0-0-a7541fe9b19ddf594044b5ee6483f533</span></span><br><span class="line"><span class="string">        :return:</span></span><br><span class="line"><span class="string">        '''</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 边缘</span></span><br><span class="line">        url = <span class="string">"rtmp://&#123;LiveDomain&#125;/&#123;AppName&#125;/&#123;StreamName&#125;"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.push_domain,</span><br><span class="line">        )</span><br><span class="line">        logger.debug(<span class="string">"pusher url: %s"</span> % url)</span><br><span class="line">        <span class="comment"># return url</span></span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_rtmp_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"rtmp://&#123;LiveDomain&#125;/&#123;AppName&#125;/&#123;StreamName&#125;"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.play_domain,</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_hls_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"http://&#123;LiveDomain&#125;/&#123;AppName&#125;/&#123;StreamName&#125;.m3u8"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.play_domain,</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_flv_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"http://&#123;LiveDomain&#125;/&#123;AppName&#125;/&#123;StreamName&#125;.flv"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.play_domain,</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_players</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="string">"rtmp"</span>: self.get_rtmp_player(),</span><br><span class="line">            <span class="string">"flv"</span>: self.get_flv_player(),</span><br><span class="line">            <span class="string">"hls"</span>: self.get_hls_player(),</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_record_pusher</span><span class="params">(self, record_id)</span>:</span></span><br><span class="line">        <span class="comment"># edge</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># live</span></span><br><span class="line">        <span class="comment"># url = "rtmp://&#123;LiveDomain&#125;/&#123;AppName&#125;/&#123;StreamName&#125;".format(</span></span><br><span class="line">        <span class="comment">#     AppName=self.app_name,</span></span><br><span class="line">        <span class="comment">#     StreamName=self.channel,</span></span><br><span class="line">        <span class="comment">#     LiveDomain=self.push_domain,</span></span><br><span class="line">        <span class="comment"># )</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># record</span></span><br><span class="line">        <span class="comment"># url = "rtmp://&#123;LiveDomain&#125;/record_&#123;AppName&#125;/&#123;StreamName&#125;_&#123;record_id&#125;".format(</span></span><br><span class="line">        <span class="comment">#</span></span><br><span class="line">        <span class="comment">#     AppName=self.app_name,</span></span><br><span class="line">        <span class="comment">#     StreamName=self.channel,</span></span><br><span class="line">        <span class="comment">#     LiveDomain=self.push_domain,</span></span><br><span class="line">        <span class="comment">#     record_id=record_id</span></span><br><span class="line">        <span class="comment"># )</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># rtmp://video-center-jp.alivecdn.com/AppName/StreamName?vhost=live.overseas.publish.rabbitslive.com</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 日本节点使用中心推流进行录制</span></span><br><span class="line">        url = <span class="string">"rtmp://video-center-jp.alivecdn.com/record_&#123;AppName&#125;/&#123;StreamName&#125;_&#123;record_id&#125;?vhost=&#123;LiveDomain&#125;"</span>.format(</span><br><span class="line">            AppName=self.app_name,</span><br><span class="line">            StreamName=self.channel,</span><br><span class="line">            LiveDomain=self.play_domain,</span><br><span class="line">            record_id=record_id</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="comment"># TODO 日本节点录制失败，暂时使用国内节点进行录制</span></span><br><span class="line">        <span class="comment"># url = "rtmp://video-center.alivecdn.com/record_&#123;AppName&#125;/&#123;StreamName&#125;_&#123;record_id&#125;?vhost=live.rabbitslive.com".format(</span></span><br><span class="line">        <span class="comment">#     AppName=self.app_name,</span></span><br><span class="line">        <span class="comment">#     StreamName=self.channel,</span></span><br><span class="line">        <span class="comment">#     # LiveDomain=self.centre_live_domain,</span></span><br><span class="line">        <span class="comment">#     record_id=record_id</span></span><br><span class="line">        <span class="comment"># )</span></span><br><span class="line">        <span class="comment"># logger.debug("pusher url: %s" % url)</span></span><br><span class="line">        <span class="comment"># # return url</span></span><br><span class="line">        <span class="comment">#</span></span><br><span class="line">        <span class="comment"># return add_a_auth(uri=url, key="a8f5rl2TCUXCmoPL", exp=self.auth_exp)</span></span><br><span class="line">        <span class="keyword">return</span> add_a_auth(uri=url, key=self.a_auth_key, exp=self.auth_exp)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_obj_url</span><span class="params">(self, name, expries)</span>:</span></span><br><span class="line">        url = oss_util.get_obj_url(</span><br><span class="line">            access_key_id=self.ak_id,</span><br><span class="line">            access_key_secret=self.ak_secret,</span><br><span class="line">            region=self.live_record_region,</span><br><span class="line">            name=name,</span><br><span class="line">            bucket_name=self.live_record_oss_bucket,</span><br><span class="line">            expires=int(self.oss_auth_exp)</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        <span class="comment"># logger.debug('obj url: %s' % url)</span></span><br><span class="line">        <span class="keyword">return</span> url</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">put_stream_file</span><span class="params">(self, local, target, mime_type)</span>:</span></span><br><span class="line">        logger.debug(<span class="string">'input: %s'</span> % local)</span><br><span class="line">        logger.debug(<span class="string">'target: %s'</span> % target)</span><br><span class="line">        oss_util.put_obj(</span><br><span class="line">            access_key_id=self.ak_id,</span><br><span class="line">            access_key_secret=self.ak_secret,</span><br><span class="line">            region=self.live_record_region,</span><br><span class="line">            bucket_name=self.live_record_oss_bucket,</span><br><span class="line">            input=local,</span><br><span class="line">            target=target</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">upload_file</span><span class="params">(self, local, target)</span>:</span></span><br><span class="line">        oss_util.put_obj_from_file(</span><br><span class="line">            access_key_id=self.ak_id,</span><br><span class="line">            access_key_secret=self.ak_secret,</span><br><span class="line">            region=self.live_record_region,</span><br><span class="line">            bucket_name=self.live_record_oss_bucket,</span><br><span class="line">            local_file=local,</span><br><span class="line">            target=target</span><br><span class="line">        )</span><br><span class="line">        <span class="keyword">import</span> os</span><br><span class="line">        os.remove(local)</span><br></pre></td></tr></table></figure><h3 id="live-ucloud-py"><a href="#live-ucloud-py" class="headerlink" title="live_ucloud.py"></a>live_ucloud.py</h3><blockquote><p>Ucloud直播</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Created by lizhiwei at 2018/12/17</span></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> django.conf <span class="keyword">import</span> settings</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> utils.ucloud_util <span class="keyword">import</span> auth_key, private_download_url, put_stream_file, post_upload_file</span><br><span class="line"><span class="keyword">from</span> .live <span class="keyword">import</span> Live</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LiveUcloud</span><span class="params">(Live)</span>:</span></span><br><span class="line">    <span class="string">"""Live Ucloud stragegy."""</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, channel)</span>:</span></span><br><span class="line">        super(LiveUcloud, self).__init__(channel=channel)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> ﬁ<span class="title">get_pusher</span><span class="params">(self)</span>:</span></span><br><span class="line">        timestamp = int(time.time())</span><br><span class="line">        url = <span class="string">"rtmp://&#123;0&#125;/&#123;1&#125;/&#123;2&#125;"</span>.format(</span><br><span class="line">            settings.PUSH_DOMAIN,</span><br><span class="line">            settings.ACCESS_POINT,</span><br><span class="line">            self.channel, timestamp)</span><br><span class="line">        <span class="keyword">return</span> url</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_rtmp_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"rtmp://&#123;0&#125;/&#123;1&#125;/&#123;2&#125;"</span>.format(</span><br><span class="line">            settings.LIVE_DOMAIN,</span><br><span class="line">            settings.ACCESS_POINT,</span><br><span class="line">            self.channel)</span><br><span class="line">        <span class="keyword">return</span> auth_key(url, settings.LIVE_KEY)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_record_pusher</span><span class="params">(self, record_id)</span>:</span></span><br><span class="line">        timestamp = int(time.time())</span><br><span class="line">        url = <span class="string">"rtmp://&#123;0&#125;/&#123;1&#125;/&#123;2&#125;?record=true&amp;filename=&#123;1&#125;_&#123;2&#125;_&#123;3&#125;"</span>.format(</span><br><span class="line">            settings.PUSH_DOMAIN,</span><br><span class="line">            settings.ACCESS_POINT,</span><br><span class="line">            self.channel,</span><br><span class="line">            record_id,</span><br><span class="line">            timestamp)</span><br><span class="line">        <span class="keyword">return</span> url</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_hls_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"http://&#123;0&#125;/&#123;1&#125;/&#123;2&#125;/playlist.m3u8"</span>.format(</span><br><span class="line">            settings.HLS_DOMAIN,</span><br><span class="line">            settings.ACCESS_POINT,</span><br><span class="line">            self.channel)</span><br><span class="line">        <span class="keyword">return</span> auth_key(url, settings.LIVE_KEY)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_flv_player</span><span class="params">(self)</span>:</span></span><br><span class="line">        url = <span class="string">"http://&#123;0&#125;/&#123;1&#125;/&#123;2&#125;/playlist.flv"</span>.format(</span><br><span class="line">            settings.HLS_DOMAIN,</span><br><span class="line">            settings.ACCESS_POINT,</span><br><span class="line">            self.channel)</span><br><span class="line">        <span class="keyword">return</span> auth_key(url, settings.LIVE_KEY)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_players</span><span class="params">(self)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> &#123;</span><br><span class="line">            <span class="string">"rtmp"</span>: self.get_rtmp_player(),</span><br><span class="line">            <span class="string">"flv"</span>: self.get_flv_player(),</span><br><span class="line">            <span class="string">"hls"</span>: self.get_hls_player(),</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_obj_url</span><span class="params">(self, name, expries=<span class="number">3600</span>)</span>:</span></span><br><span class="line">        _, photo_url = private_download_url(settings.UCLOUD_PUB_KEY, settings.UCLOUD_PRIV_KEY,</span><br><span class="line">                                            settings.UCLOUD_BUCKET_DOMAIN,</span><br><span class="line">                                            name)</span><br><span class="line">        <span class="keyword">if</span> <span class="number">200</span> == _:</span><br><span class="line">            <span class="keyword">return</span> photo_url</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">put_stream_file</span><span class="params">(self, local, target, mime_type)</span>:</span></span><br><span class="line">        <span class="keyword">return</span> put_stream_file(</span><br><span class="line">            settings.UCLOUD_PUB_KEY, settings.UCLOUD_PRIV_KEY,</span><br><span class="line">            settings.UCLOUD_BUCKET_DOMAIN,</span><br><span class="line">            key=target,</span><br><span class="line">            stream=local,</span><br><span class="line">            mime_type=mime_type</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">upload_file</span><span class="params">(self, local, target)</span>:</span></span><br><span class="line">        resp_status = post_upload_file(</span><br><span class="line">            settings.UCLOUD_PUB_KEY, settings.UCLOUD_PRIV_KEY,</span><br><span class="line">            settings.UCLOUD_BUCKET_DOMAIN,</span><br><span class="line">            key=target,</span><br><span class="line">            local_file=local</span><br><span class="line">        )</span><br><span class="line">        <span class="keyword">if</span> resp_status:</span><br><span class="line">            <span class="keyword">import</span> os</span><br><span class="line">            os.remove(local)</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;Python策略模式（灵活调用个不同平台直播SDK）&quot;&gt;&lt;a href=&quot;#Python策略模式（灵活调用个不同平台直播SDK）&quot; class=&quot;headerlink&quot; title=&quot;Python策略模式（灵活调用个不同平台直播SDK）&quot;&gt;&lt;/a&gt;Python策略模式（灵活调用个不同平台直播SDK）&lt;/h4&gt;
    
    </summary>
    
      <category term="Python" scheme="http://yoursite.com/categories/Python/"/>
    
    
      <category term="Python" scheme="http://yoursite.com/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>My Resume</title>
    <link href="http://yoursite.com/2019/02/18/resume/resume/"/>
    <id>http://yoursite.com/2019/02/18/resume/resume/</id>
    <published>2019-02-18T08:21:41.794Z</published>
    <updated>2023-02-28T16:28:18.278Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Python程序员-李志威"><a href="#Python程序员-李志威" class="headerlink" title="Python程序员-李志威"></a>Python程序员-李志威</h1><hr><h1 id="联系方式"><a href="#联系方式" class="headerlink" title="联系方式"></a>联系方式</h1><ul><li>手机 ：136-9334-7696</li><li>Email：<a href="mailto:lzw9560@163.com" target="_blank" rel="noopener">lzw9560@163.com</a> </li><li>微信号：329396703</li><li>Github:  <a href="https://github.com/lzw9560" target="_blank" rel="noopener">https://github.com/lzw9560</a></li><li>Blog: <a href="https://lzw9560.github.io" target="_blank" rel="noopener">https://lzw9560.github.io</a></li></ul><a id="more"></a><hr><h1 id="个人信息"><a href="#个人信息" class="headerlink" title="个人信息"></a>个人信息</h1><ul><li>男 1990 </li><li>专科/计算机以及电子自动化 </li><li>工作年限：9年</li><li>期望职位：后台开发工程师</li><li>期望薪资：面议</li><li>期望城市：杭州</li></ul><hr><h1 id="工作经历"><a href="#工作经历" class="headerlink" title="工作经历"></a>工作经历</h1><h2 id="北京原语科技-（-2022年1月-至今-）"><a href="#北京原语科技-（-2022年1月-至今-）" class="headerlink" title="北京原语科技 （ 2022年1月 ~ 至今 ）"></a>北京原语科技 （ 2022年1月 ~ 至今 ）</h2><h3 id="后台开发工程师"><a href="#后台开发工程师" class="headerlink" title="后台开发工程师"></a>后台开发工程师</h3><h4 id="简介："><a href="#简介：" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>PrimiHub是原语科技基于多方安全计算、联邦学习、同态加密、可信计算等技术自主研发的分布式隐私计算平台。（平台涵盖隐私求交、联合建模、联合统计、匿踪查询、数据资源管理、算法容器管理、异构平台互联互通等，基于自研、开放隐私计算框架，打造适配全业务场景且兼容性能、安全性、高效的隐私计算平台。）</p><h4 id="岗位描述："><a href="#岗位描述：" class="headerlink" title="岗位描述："></a><strong>岗位描述</strong>：</h4><ul><li>联邦学习平台开发，GitHub开源代码贡献，文档更新</li><li>PrimiHub企业版定制功能开发</li><li>PrimiHub Python SDK Client 开发，通过gRPC向平台提交任务</li><li>Python SDK 编写，或使用Python对C++底层库进行二次封装</li><li>高性能APSI数据组件开发，支持无限制数据分箱，分布式数据预处理</li><li>PrimiHub平台算法集成，调试</li><li>协助解决平台使用中遇到的其他问题</li></ul><h2 id="中国广视索福瑞媒介研究有限责任公司-（-2019年4月-至今-）"><a href="#中国广视索福瑞媒介研究有限责任公司-（-2019年4月-至今-）" class="headerlink" title="中国广视索福瑞媒介研究有限责任公司 （ 2019年4月 ~ 至今 ）"></a>中国广视索福瑞媒介研究有限责任公司 （ 2019年4月 ~ 至今 ）</h2><h3 id="媒介受众调查与研究"><a href="#媒介受众调查与研究" class="headerlink" title="媒介受众调查与研究"></a>媒介受众调查与研究</h3><h4 id="简介：-1"><a href="#简介：-1" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>中国广视索福瑞媒介研究(CSM)是央视市场研究(CTR)与Kantar Media集团等共同建立的中外合作企业，自1997年12月4日成立以来，基于国际科学的技术理念和对国内市场的深入了解，开展电视收视率调查、广播收听率调查、体育与媒介研究和新媒体研究等多项研究业务，为中国大陆地区和香港传媒行业提供可靠的、不间断的视听率调查及深度研究服务。</p><h4 id="描述："><a href="#描述：" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>负责后端API后端架构设计</li><li>负责服务器运维，故障排查，保障服务器稳定运行</li><li>负责团队建设，基础设施平台搭建（GitLab, Docker私有仓库, Airflow, Zabbix …）</li><li>自动化构建CI脚本编写，运维脚本编写</li><li>编写 <strong>dockerfile</strong> / <strong>docker-compose</strong> 脚本</li><li>使用 <strong>Golang</strong> Web框架 <strong>Beego</strong> 开发电视广告二维码导流系统</li><li>使用 <strong>FastAPI</strong> 开发音视频分析管理系统,总台专区舆情报告系统等多个项目</li><li>使用 <strong>Django REST framework</strong> 开发融合媒体数据云平台，包含媒体收视数据可视化，榜单，词云，热点，微信小程序等等</li><li>使用 <strong>Django REST framework</strong> 开发电视广告收视分析系统(直播, 开机,  OTT,  IPTV),集成<strong>Celery</strong>异步任务框架</li><li>在 <strong>Windows</strong> 平台下开发电视台数据分析报告，<strong>RPC</strong> 服务框架搭建，核心代码编写</li><li>使用 <strong>Filebeat</strong> 收集日志到 <strong>Elasticsearch</strong></li></ul><h2 id="企鹅创新（北京）科技有限公司-（-2018年5月-2019年4月-）"><a href="#企鹅创新（北京）科技有限公司-（-2018年5月-2019年4月-）" class="headerlink" title="企鹅创新（北京）科技有限公司 （ 2018年5月 ~ 2019年4月 ）"></a>企鹅创新（北京）科技有限公司 （ 2018年5月 ~ 2019年4月 ）</h2><h3 id="智能家居产品"><a href="#智能家居产品" class="headerlink" title="智能家居产品"></a>智能家居产品</h3><h4 id="简介：-2"><a href="#简介：-2" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>PENGUINS INNOVATE，由一群90后年轻人创立的企鹅创新，今年9月全新发布了室内机器人rabbit。rabbit各项功能都基于强大的机器视觉识别算法，即使在没有指令的情况下，也能根据使用者的行为自主研判，在朝夕相处中逐渐了解并适应用户的生活习惯。</p><h4 id="描述：-1"><a href="#描述：-1" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>项目架构采用前后分离，主要负责后台应用框架搭建，应用服务器后台API重构设计实现，使用 <strong>Django REST framework</strong> ，<strong>Tonado</strong>，<strong>Celery</strong>。</li><li>负责后台应用服务器搭建维护，自动化构建采用 <strong>GitLab CI + Docker + Fabric</strong> 实现。</li><li>采用 <strong>Ucloud SDK</strong>  + <strong>Aliyun SDK</strong>  实现了视屏直播、录制、存储等多媒体功能。</li><li>集成了对IOS平台，Android平台（国内外）消息推送服务。</li><li>完成了后台服务语言本地/国际化。</li><li>设计实现了硬件设备远程升级服务。</li><li>采用 <strong>Fluentd</strong> 轻量级日志框架收集设备活动日志,为机器学习以及用户行为分析准备数据样本。</li><li>使用 <strong>TensorFlow</strong> 对用户手势模型进行训练。</li></ul><h2 id="架标科技有限公司-（-2016年9月-2018年5月-）"><a href="#架标科技有限公司-（-2016年9月-2018年5月-）" class="headerlink" title="架标科技有限公司 （ 2016年9月 ~ 2018年5月 ）"></a>架标科技有限公司 （ 2016年9月 ~ 2018年5月 ）</h2><h3 id="基于电子价签扩展应用系统"><a href="#基于电子价签扩展应用系统" class="headerlink" title="基于电子价签扩展应用系统"></a>基于电子价签扩展应用系统</h3><h4 id="简介：-3"><a href="#简介：-3" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>基于新零售的概念，项目以电子价签为切入点，替换了纸质标签，节省超市成本的同时为用户提供有别于传统超市的购物体验，能够实时显示商品价格信息，做到线上线下同步，同时可以做到商品定位导航，货架管理，商品陈列管理，同时还有基于电子标签蓝牙和NFC的互动，提升了用户在线下商超购物乐趣，通过线上加线下的方式，收集用户购物行为习惯，实现流量变现，提升用户粘合度。应用系统后台基于 <strong>Flask-RESTful</strong> 和  <strong>Django REST framework</strong>  技术实现，分为移动APP用户端，超市端管理，后台商品管理，电子价签管理，等多个模块。</p><h4 id="描述：-2"><a href="#描述：-2" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>项目架构采用前后分离，主要负责后台应用框架搭建，API设计实现。</li><li>项目中涉及相对比较复杂的权限管理控制，设计实现了 <strong>RBAC（Resource-Based Access Contro）</strong> 基于资源的权限控制模型Flask插件。</li><li>优化了数据同步脚本，提升了运行效率，数据库读写采用批量提交回滚，涉及到csv文件读写，使用 <strong>Python yield</strong> 实现，10w条商品数据处理大约需要600多秒。</li><li>负责搭建自动化持续构建集成 <strong>GitLab CI</strong>持续构建工具。</li><li>负责服务器代码部署，使用 <strong>uWSGI + Nginx/supervisor + gunicorn + Nginx</strong>。</li><li>采用 <strong>Django Celery</strong> 执行后台异步任务、定时任务。</li><li>涉及室外定位采用地理相关使用 <strong>PostGIS GeoDjango</strong> ，坐标计算，距离计算。</li><li>使用 <strong>Elasticsearch</strong> + 中文分词插件，完成商品搜索匹配。</li></ul><h2 id="搜狐公司-网络运营部-（-2016年3月-2016年9月-）"><a href="#搜狐公司-网络运营部-（-2016年3月-2016年9月-）" class="headerlink" title="搜狐公司-网络运营部 （ 2016年3月 ~ 2016年9月 ）"></a>搜狐公司-网络运营部 （ 2016年3月 ~ 2016年9月 ）</h2><h3 id="自动化构建部署发布模块-用户验收测试框"><a href="#自动化构建部署发布模块-用户验收测试框" class="headerlink" title="自动化构建部署发布模块-用户验收测试框"></a>自动化构建部署发布模块-用户验收测试框</h3><h4 id="简介：-4"><a href="#简介：-4" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>该项目属于公司内部运维平台自动化构建部署框架的一部分，用于自动化用户验收测试框架，需要在Linux下准备测试环境，然后在Windows下实现具体测试用例，为了避免环境干扰和测试用例解耦合，针对用例在Linux虚拟机上准备单独的LXC测试环境，环境部分分为测试环境准备，测试环境初始化，测试环境还原；测试框架部分主要是测试用例的分发规则和具体测试用例，最后结合Jenkins集成框架，实现了自动化构建，部署，发布功能。</p><h4 id="描述：-3"><a href="#描述：-3" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>测试框架使用 <strong>Selenuim + PyUnit</strong> 的方式进行用例编写自动化测试框架。</li><li>针对自动化运维平台，覆盖不同使用场景，不同使用流程的测试用例编写。</li><li>Windows下自动化测试框架设计开发。</li><li>Linux下运维脚本开发，编写自动化脚本准备测试LXC虚拟环境。</li><li>编写Shell脚本，对测试数据库数据进行更新恢复，数据还原。</li></ul><h2 id="北京文思海辉技术有限公司-（-2013年6月-2016年3月-）"><a href="#北京文思海辉技术有限公司-（-2013年6月-2016年3月-）" class="headerlink" title="北京文思海辉技术有限公司  （ 2013年6月 ~ 2016年3月 ）"></a>北京文思海辉技术有限公司  （ 2013年6月 ~ 2016年3月 ）</h2><h3 id="轨道电路虚拟仿真分析平台系统"><a href="#轨道电路虚拟仿真分析平台系统" class="headerlink" title="轨道电路虚拟仿真分析平台系统"></a>轨道电路虚拟仿真分析平台系统</h3><h4 id="简介：-5"><a href="#简介：-5" class="headerlink" title="简介："></a><strong>简介</strong>：</h4><p>轨道电路虚拟仿真分析软件是轨道电路专项实验室的重要组成部分，需实现轨道电路的仿真计算、结果分析和数据管理功能，支撑轨道电路的技术方案论证、系统/设备结构调整论证、传输极限条件测试、元器件故障安全测试、调整表计算和管理、现场故障仿真分析等工作，为轨道电路的研发、优化、测试、应用、集成、售后提供服务。轨道电路虚拟仿真分析软件为系统研发阶段的仿真环境，提供轨道电路的仿真计算功能和数据管理功能。</p><h4 id="描述：-4"><a href="#描述：-4" class="headerlink" title="描述："></a><strong>描述</strong>：</h4><ul><li>用户需求分析，数据库模型设计，功能模块实现，代码编写以及优化</li><li>服务器端脚本程序编写</li><li>调用MatLab进行科学计算，结果存储</li><li>使用Django模板渲染计算结果</li></ul><!-- ## 启动力咨询有限责任公司  （ 2013年6月 ~ 2015年3月 ）### 院校学生信息管理应用 #### 简介：该应用基于Django框架开发，是一款打通微信接口的轻APP，通过微信访问，实现轻松管理学生信息，并对学生学习阶段进行跟踪测试，该web分为后台管理端（提供管理员对学生信息进行管理），和用户端（学生查看个人信息以及进行阶段测试等），实现了通过移动端方便的进行学生同院校之间的信息交互，该web应用有很强的拓展性和可移植性。#### **描述**：- 需求分析，数据库模型设计，功能模块实现，代码编写以及优化。- 在这个项目中开始接触Python，感觉太好用了，语法简单，代码排版也很美观，很大的提升了开发速度，根本停不下来了。### 电子招投标系统基础设施平台#### 简介：本系统是一款基础设施类项目，以网络技术为基础, 招标、投标、评标、合同等业务全过程实现数字化、网络化、高度集成化的系统,该系统实现了基本的业务功能要求,同时也考虑了系统的性能及安全性问题,并提出了相应的安全控制措施。安全性和可靠性是本系统的根本问题，本系统具有操作简单、用户界面友好的特点,为招投标业务实现电子化管理的应用奠定了基础,对提高招投标业务管理水平具有重要的现实意义。项目主要针对节点之间通信做安全保障，将节点之间通信的数据不定时的更新密钥，节点接受数据之后调用系统提供的接口通过本系统进行加密，进行安全传输。#### 描述：- 使用C++编写Linux密钥管理客户端模块，实现应用节点和应用节点之间的身份认证- 通过调用报文处理函数API，对服务端收到的相应节点请求进行处理，实现密钥的协商，校验，查看和注销，对密钥进行生命周期管理- 服务器从数据库读取应用节点的密钥信息，保存在共享内存以便实现高速访问，调用共享内存相关操作组件对共享内存进行读写操作- 通过对共享内存的操作来管理密钥信息，在开发过程中解决了因为指针类型转换导致读取内存因为指针偏移步长导致的程序段错误的问题- 使用ASN.l（抽象语法标记语言）处理报文，对传输信息进行编码，解码处理,该标准提供的TLV格式描述了对象的结构，并不关心具体数据的实现，简单易用，清晰明了，参与报文格式的设计，对报文数据进行表示、编码、传输和解码- 分别在Windows和Linux下平台将函数功能实现的部分接口进行封装，实现跨平台使用，导出成供Windows/Linux程序调用的动态库，提供系统外联接口，供前置机上层应用调用 --><hr><h1 id="技能清单"><a href="#技能清单" class="headerlink" title="技能清单"></a>技能清单</h1><ul><li>Linux：<strong>Linux命令/Shell脚本/Nginx</strong></li><li>数据库：<strong>MySQL/PostgreSQL/Oracle/SQLite/SQL Server/Redis</strong></li><li>Web框架：<strong>Django/Flask/Tonado</strong></li><li>任务队列：<strong>Celery</strong></li><li>API调试：<strong>Postman/Charles/Fiddler</strong></li><li>持续构建：<strong>GitLAB CI</strong></li><li>版本管理：<strong>Git/SourceTree</strong></li><li>文档：<strong>Markdown</strong> / <strong>YAML</strong> / <strong>ReStructuredText</strong></li><li>单元测试：<strong>Unittest</strong></li><li>科学上网：自带翻墙技能</li><li>其他：Websocket/MQTT/TensorFlow</li></ul><h1 id="自我评价"><a href="#自我评价" class="headerlink" title="自我评价"></a>自我评价</h1><ul><li>热爱工作，热爱生活，善于充实自我</li><li>具有良好的文档编写能力，能按要求完成项目所需文档的编写</li><li>具有良好的团队合作精神，工作责任心强，能承受一定的工作压力</li><li>工作认真，有较强的责任心，具备良好的团队精神</li><li>有很强的学习能力，态度端正，强烈的求知欲</li></ul><h1 id="资格证书"><a href="#资格证书" class="headerlink" title="资格证书"></a>资格证书</h1><ul><li>PMP项目管理认证</li></ul><hr><h1 id="致谢"><a href="#致谢" class="headerlink" title="致谢"></a>致谢</h1><p>感谢您花时间阅读我的简历，期待能有机会和您共事。</p>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;Python程序员-李志威&quot;&gt;&lt;a href=&quot;#Python程序员-李志威&quot; class=&quot;headerlink&quot; title=&quot;Python程序员-李志威&quot;&gt;&lt;/a&gt;Python程序员-李志威&lt;/h1&gt;&lt;hr&gt;
&lt;h1 id=&quot;联系方式&quot;&gt;&lt;a href=&quot;#联系方式&quot; class=&quot;headerlink&quot; title=&quot;联系方式&quot;&gt;&lt;/a&gt;联系方式&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;手机 ：136-9334-7696&lt;/li&gt;
&lt;li&gt;Email：&lt;a href=&quot;mailto:lzw9560@163.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;lzw9560@163.com&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;微信号：329396703&lt;/li&gt;
&lt;li&gt;Github:  &lt;a href=&quot;https://github.com/lzw9560&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/lzw9560&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Blog: &lt;a href=&quot;https://lzw9560.github.io&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://lzw9560.github.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
    
      <category term="My Resume" scheme="http://yoursite.com/tags/My-Resume/"/>
    
  </entry>
  
  <entry>
    <title>Supervisor 安装配置</title>
    <link href="http://yoursite.com/2019/02/18/tool/supervisor/"/>
    <id>http://yoursite.com/2019/02/18/tool/supervisor/</id>
    <published>2019-02-18T08:21:03.926Z</published>
    <updated>2019-02-18T08:21:03.926Z</updated>
    
    <content type="html"><![CDATA[<h4 id="Supervisor"><a href="#Supervisor" class="headerlink" title="Supervisor"></a>Supervisor</h4><a id="more"></a><h5 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h5><p>-<br>在 web 应用部署到线上后，需要保证应用一直处于运行状态，在遇到程序异常、报错等情况，导致 web 应用终止时，需要保证程序可以立刻重启，继续提供服务。</p><p>所以，就需要一个工具，时刻监控 web 应用的运行情况，管理该进程。</p><p>Supervisor 就是解决这种需求的工具，可以保证程序崩溃后，重新把程序启动起来等功能。</p><p>Supervisor 是一个用 Python 写的进程管理工具，可以很方便的用来在 UNIX-like 系统（不支持 Windows）下启动、重启（自动重启程序）、关闭进程（不仅仅是 Python 进程）。</p><h5 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h5><p>-</p><ol><li>Ubuntu系统下：apt-get install supervisor，通过这种方式安装后，自动设置为开机启动</li><li>也可以通过 pip install supervisor 进行安装，但是需要手动启动，然后设置为开机启动（不推荐这种安装方式）</li></ol><p>参考：</p><ul><li><p><a href="http://liyangliang.me/posts/2015/06/using-supervisor/" target="_blank" rel="noopener">http://liyangliang.me/posts/2015/06/using-supervisor/</a></p></li><li><p><a href="http://www.cnblogs.com/xueweihan/p/6195824.html" target="_blank" rel="noopener">http://www.cnblogs.com/xueweihan/p/6195824.html</a></p></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;Supervisor&quot;&gt;&lt;a href=&quot;#Supervisor&quot; class=&quot;headerlink&quot; title=&quot;Supervisor&quot;&gt;&lt;/a&gt;Supervisor&lt;/h4&gt;
    
    </summary>
    
      <category term="tool" scheme="http://yoursite.com/categories/tool/"/>
    
    
      <category term="Supervisor" scheme="http://yoursite.com/tags/Supervisor/"/>
    
  </entry>
  
  <entry>
    <title>Visual Studio Code开发技巧</title>
    <link href="http://yoursite.com/2019/02/18/tool/vscode/"/>
    <id>http://yoursite.com/2019/02/18/tool/vscode/</id>
    <published>2019-02-18T08:21:03.926Z</published>
    <updated>2019-02-18T08:21:03.926Z</updated>
    
    <content type="html"><![CDATA[<h4 id="下载地址"><a href="#下载地址" class="headerlink" title="下载地址"></a>下载地址</h4><a id="more"></a><p><a href="https://code.visualstudio.com/docs/" target="_blank" rel="noopener">https://code.visualstudio.com/docs/</a></p><h4 id="使用技巧"><a href="#使用技巧" class="headerlink" title="使用技巧"></a>使用技巧</h4><p><a href="http://www.sohu.com/a/109891407_468731" target="_blank" rel="noopener">http://www.sohu.com/a/109891407_468731</a></p><h4 id="vscode插件库"><a href="#vscode插件库" class="headerlink" title="vscode插件库"></a>vscode插件库</h4><p><a href="https://marketplace.visualstudio.com/VSCode" target="_blank" rel="noopener">https://marketplace.visualstudio.com/VSCode</a></p><h4 id="插件推荐"><a href="#插件推荐" class="headerlink" title="插件推荐"></a>插件推荐</h4><ol><li><p>Bracket Pair Colorizer ：对括号对进行着色，再也不会搞不清状况了。</p></li><li><p>Git History: 可以查看Git log, file, 和line 历史记录。</p></li><li><p>Markdown PDF: 将markdown文档转换成pdf的利器</p></li><li><p>VSCode Great Icons: 我非常喜欢的一套Icons主题，对展开的文件有变色处理，很容易分辨</p></li><li><p>vscode-fileheader: 添加头header comment，厉害的</p></li><li><p>monokia dimmed颜色主题，码员大爱</p></li><li><p>Path Intellisense: 路径提示器，好用得不得了</p></li><li><p>Setting Sync: 同步你得设置和插件</p></li><li><p>output colorizer: 输出着色</p></li></ol><p>其他：</p><ol><li><p>Code Spellchecker : 代码拼写检查，有时候也很烦，但是为了养成好的命名习惯也是好的</p></li><li><p>Document This: 为JavaScript和TypeScript提供JSDoc comments</p></li><li><p>filesize : 会在左下角显示文件大小，很不错</p></li><li><p>markdownlint: markdown 语法提示器</p></li><li><p>Visual Studio Code Settings Sync 可以同步配置插件等到 gist</p></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;下载地址&quot;&gt;&lt;a href=&quot;#下载地址&quot; class=&quot;headerlink&quot; title=&quot;下载地址&quot;&gt;&lt;/a&gt;下载地址&lt;/h4&gt;
    
    </summary>
    
      <category term="tool" scheme="http://yoursite.com/categories/tool/"/>
    
    
      <category term="VS Code" scheme="http://yoursite.com/tags/VS-Code/"/>
    
  </entry>
  
  <entry>
    <title></title>
    <link href="http://yoursite.com/2019/02/18/websit/NotesOfOther/"/>
    <id>http://yoursite.com/2019/02/18/websit/NotesOfOther/</id>
    <published>2019-02-18T08:21:03.926Z</published>
    <updated>2020-03-14T15:16:26.537Z</updated>
    
    <content type="html"><![CDATA[<hr><p>title:  Anaconda的升级与卸载<br>date:<br>tags: Python/Users/lizhiwei/Downloads/default<br>categories: Linux/MacOs<br>toc: true<br>—/Users/lizhiwei/Downloads/default</p><h4 id="升级-Users-lizhiwei-Downloads-default"><a href="#升级-Users-lizhiwei-Downloads-default" class="headerlink" title="升级/Users/lizhiwei/Downloads/default"></a>升级/Users/lizhiwei/Downloads/default</h4><a id="more"></a><p>升级Anaconda需要先升级conda</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">conda update conda</span><br><span class="line">conda update anaconda</span><br></pre></td></tr></table></figure><h4 id="卸载"><a href="#卸载" class="headerlink" title="卸载"></a>卸载</h4><p>由于Anaconda的安装文件都包含在一个目录中，所以直接将该目录删除即可。删除整个Anaconda目录：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm -rf anaconda</span><br></pre></td></tr></table></figure></p><p>最后，建议清理下.bashrc中的Anaconda路径。</p>]]></content>
    
    <summary type="html">
    
      &lt;hr&gt;
&lt;p&gt;title:  Anaconda的升级与卸载&lt;br&gt;date:&lt;br&gt;tags: Python/Users/lizhiwei/Downloads/default&lt;br&gt;categories: Linux/MacOs&lt;br&gt;toc: true&lt;br&gt;—/Users/lizhiwei/Downloads/default&lt;/p&gt;
&lt;h4 id=&quot;升级-Users-lizhiwei-Downloads-default&quot;&gt;&lt;a href=&quot;#升级-Users-lizhiwei-Downloads-default&quot; class=&quot;headerlink&quot; title=&quot;升级/Users/lizhiwei/Downloads/default&quot;&gt;&lt;/a&gt;升级/Users/lizhiwei/Downloads/default&lt;/h4&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>iTerm2使用sz/rz</title>
    <link href="http://yoursite.com/2019/02/18/linux/Tool/szrc/"/>
    <id>http://yoursite.com/2019/02/18/linux/Tool/szrc/</id>
    <published>2019-02-18T08:21:03.925Z</published>
    <updated>2019-02-18T08:21:03.925Z</updated>
    
    <content type="html"><![CDATA[<h3 id="sz-rz"><a href="#sz-rz" class="headerlink" title="sz/rz"></a>sz/rz</h3><a id="more"></a><blockquote><p>在Windows下SecureCRT 或者Xshell可以很方便的使用上传下载工具sz、rz，mac下我们一般使用scp来完成。<br>但是在某些场景下（登录服务器使用跳板机等）不能使用scp。</p></blockquote><h3 id="scp"><a href="#scp" class="headerlink" title="scp"></a>scp</h3><ul><li><p>上传<br>  <code>scp -r local_folder remote_username@remote_ip:remote_folder</code></p><p>  <code>scp -r local_folder remote_ip:remote_folder</code></p></li><li><p>下载<br>  <code>scp -r remote_username@remote_ip:remote_folder local_folder</code></p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">几个可能用到的参数：</span><br><span class="line">-v 和大多数linux命令中的-v意思一样,用来显示进度。可以用来查看连接、认证、或是配置错误。</span><br><span class="line">-r 递归处理，将指定目录下的文档和子目录一并处理</span><br><span class="line">-C 使能压缩选项</span><br><span class="line">-P 选择端口。注意-p已经被rcp使用</span><br><span class="line">-4 强行使用IPV4地址</span><br><span class="line">-6 强行使用IPV6地址</span><br></pre></td></tr></table></figure><h3 id="mac下品日志使用rz、sz"><a href="#mac下品日志使用rz、sz" class="headerlink" title="mac下品日志使用rz、sz"></a>mac下品日志使用rz、sz</h3><ul><li>首先需要安装 iterm2</li><li>安装 lrzsz: <code>brew install lrzsz</code></li><li><p>下载iterm2-zmodem</p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">cd /usr/local/bin</span><br><span class="line"></span><br><span class="line">sudo wget https://raw.github.com/mmastrac/iterm2-zmodem/master/iterm2-send-zmodem.sh</span><br><span class="line"></span><br><span class="line">sudo wget https://raw.github.com/mmastrac/iterm2-zmodem/master/iterm2-recv-zmodem.sh</span><br><span class="line"></span><br><span class="line">sudo chmod 777 /usr/local/bin/iterm2-*</span><br></pre></td></tr></table></figure></li></ul><ul><li>添加trigger</li></ul><pre><code>打开Item2，点击profiles，选择某个profile之后然后继续选择advanced → triggers，添加triggers。</code></pre><table><thead><tr><th>Regular</th><th>expression</th><th>Action</th></tr></thead><tbody><tr><td>**B0100</td><td>Run Silent Coprocess</td><td>/usr/local/bin/iterm2-send-zmodem.sh</td></tr><tr><td>**B00000000000000</td><td>Run Silent Coprocess</td><td>/usr/local/bin/iterm2-recv-zmodem.sh</td></tr></tbody></table>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;sz-rz&quot;&gt;&lt;a href=&quot;#sz-rz&quot; class=&quot;headerlink&quot; title=&quot;sz/rz&quot;&gt;&lt;/a&gt;sz/rz&lt;/h3&gt;
    
    </summary>
    
      <category term="tool" scheme="http://yoursite.com/categories/tool/"/>
    
    
      <category term="Linux/sz、rz" scheme="http://yoursite.com/tags/Linux-sz%E3%80%81rz/"/>
    
  </entry>
  
  <entry>
    <title>GitLab-Runner</title>
    <link href="http://yoursite.com/2019/02/18/gitlabci/gitlab_runner/"/>
    <id>http://yoursite.com/2019/02/18/gitlabci/gitlab_runner/</id>
    <published>2019-02-18T08:21:03.923Z</published>
    <updated>2019-02-18T08:21:03.923Z</updated>
    
    <content type="html"><![CDATA[<h4 id="GitLab-Runner"><a href="#GitLab-Runner" class="headerlink" title="GitLab-Runner"></a>GitLab-Runner</h4><a id="more"></a><blockquote><p>GitLab-Runner是配合GitLab-CI进行使用的。一般的，GitLab里面的每一个工程都会定义一个属于这个工程的软件集成脚本，用来自动化地完成一些软件集成工作。当这个工程的仓库代码发生变动时，比如有人push了代码，GitLab就会将这个变动通知GitLab-CI。这时GitLab-CI会找出与这个工程相关联的Runner，并通知这些Runner把代码更新到本地并执行预定义好的执行脚本。</p><p>Runner可以分布在不同的主机上，同一个主机上也可以有多个Runner</p></blockquote><h5 id="Runner类型"><a href="#Runner类型" class="headerlink" title="Runner类型"></a>Runner类型</h5><p><strong>Shared Runner（共享型）</strong></p><blockquote><p>这种Runner是所有工程都能够用的。只有系统管理员能够创建Shared Runner。<br><strong>Specific Runner（指定型）</strong><br>这种Runner只能为指定的工程服务。拥有该工程访问权限的人都能为该工程创建Shared Runner。</p></blockquote><h5 id="创建-Runner"><a href="#创建-Runner" class="headerlink" title="创建 Runner"></a>创建 Runner</h5><blockquote><p>Linux 服务器安装 gitlab-CI-multi-runner <a href="https://gitlab.com/gitlab-org/gitlab-ci-multi-runner" target="_blank" rel="noopener">官方文档</a></p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># For Debian/Ubuntu</span><br><span class="line">$ curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash</span><br><span class="line">$ sudo apt-get install gitlab-ci-multi-runner</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># For CentOS</span><br><span class="line">$ curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash</span><br><span class="line">$ sudo yum install gitlab-ci-multi-runner</span><br></pre></td></tr></table></figure><h5 id="注册"><a href="#注册" class="headerlink" title="注册"></a>注册</h5><blockquote><p>安装好 GitLab Runner 之后，我们只要启动 Runner 然后和 CI 绑定就可以了：</p></blockquote><ul><li>打开你 GitLab 中的项目页面，在项目设置中找到 runners</li><li>运行 sudo gitlab-ci-multi-runner register</li><li>输入 CI URL</li><li>输入 Token</li><li>输入 Runner 的名字</li><li>选择 Runner 的类型，简单起见还是选 Shell 吧</li><li>完成</li></ul><p>参考：</p><ul><li><a href="http://zhaozhiming.github.io/blog/2015/11/30/gitlab-ci-runner-create-and-config/" target="_blank" rel="noopener">http://zhaozhiming.github.io/blog/2015/11/30/gitlab-ci-runner-create-and-config/</a></li><li><a href="http://www.tuicool.com/articles/jEBf6jb" target="_blank" rel="noopener">http://www.tuicool.com/articles/jEBf6jb</a></li><li><a href="https://scarletsky.github.io/2016/07/29/use-gitlab-ci-for-continuous-integration/" target="_blank" rel="noopener">https://scarletsky.github.io/2016/07/29/use-gitlab-ci-for-continuous-integration/</a></li><li><a href="https://www.oschina.net/question/12_219138" target="_blank" rel="noopener">https://www.oschina.net/question/12_219138</a></li><li><a href="http://5404542.blog.51cto.com/5394542/1851887" target="_blank" rel="noopener">http://5404542.blog.51cto.com/5394542/1851887</a></li><li><a href="https://segmentfault.com/a/1190000007180257" target="_blank" rel="noopener">https://segmentfault.com/a/1190000007180257</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;GitLab-Runner&quot;&gt;&lt;a href=&quot;#GitLab-Runner&quot; class=&quot;headerlink&quot; title=&quot;GitLab-Runner&quot;&gt;&lt;/a&gt;GitLab-Runner&lt;/h4&gt;
    
    </summary>
    
      <category term="tool" scheme="http://yoursite.com/categories/tool/"/>
    
    
      <category term="GitLab-CI" scheme="http://yoursite.com/tags/GitLab-CI/"/>
    
  </entry>
  
  <entry>
    <title>GitLab-CI 一些概念</title>
    <link href="http://yoursite.com/2019/02/18/gitlabci/gitlabci/"/>
    <id>http://yoursite.com/2019/02/18/gitlabci/gitlabci/</id>
    <published>2019-02-18T08:21:03.923Z</published>
    <updated>2019-02-18T08:21:03.923Z</updated>
    
    <content type="html"><![CDATA[<h5 id="GitLab-CI"><a href="#GitLab-CI" class="headerlink" title="GitLab-CI"></a>GitLab-CI</h5><a id="more"></a><h6 id="Continuous-Integration-持续集成"><a href="#Continuous-Integration-持续集成" class="headerlink" title="Continuous Integration(持续集成)"></a>Continuous Integration(持续集成)</h6><blockquote><p>持续集成是一种软件开发实践，即团队开发成员经常集成他们的工作，通常每个成员至少集成一次，也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建（包括编译，发布，自动化测试）来验证，从而尽快的发现集成错误。许多团队发现这个过程可以大大减少集成的问题，让团队能都更快的开发内聚的软件。</p><p>软件集成： 代码合并–&gt; 安装依赖–&gt; 编译–&gt; 测试 –&gt;发布。</p></blockquote><h6 id="GitLab-CI-1"><a href="#GitLab-CI-1" class="headerlink" title="GitLab-CI"></a>GitLab-CI</h6><blockquote><p>GitLab-CI 就是一套配合GitLab使用的持续集成系统（Jenkins也可以配合GitLab使用）。</p></blockquote><h6 id="Pipeline"><a href="#Pipeline" class="headerlink" title="Pipeline"></a>Pipeline</h6><blockquote><p>一次 Pipeline 其实相当于一次构建任务，里面可以包含多个流程，如安装依赖、运行测试、编译、部署测试服务器、部署生产服务器等流程。<br>任何提交或者 Merge Request 的合并都可以触发 Pipeline，如下图所示：</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">+------------------+           +----------------+</span><br><span class="line">|                  |  trigger  |                |</span><br><span class="line">|   Commit / MR    +----------&gt;+    Pipeline    |</span><br><span class="line">|                  |           |                |</span><br><span class="line">+------------------+           +----------------+</span><br></pre></td></tr></table></figure><h6 id="Stages"><a href="#Stages" class="headerlink" title="Stages"></a>Stages</h6><p>Stages 表示构建阶段，说白了就是上面提到的流程。<br>我们可以在一次 Pipeline 中定义多个 Stages，这些 Stages 会有以下特点：</p><p>所有 Stages 会按照顺序运行，即当一个 Stage 完成后，下一个 Stage 才会开始<br>只有当所有 Stages 完成后，该构建任务 (Pipeline) 才会成功<br>如果任何一个 Stage 失败，那么后面的 Stages 不会执行，该构建任务 (Pipeline) 失败<br>因此，Stages 和 Pipeline 的关系就是：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">+--------------------------------------------------------+</span><br><span class="line">|                                                        |</span><br><span class="line">|  Pipeline                                              |</span><br><span class="line">|                                                        |</span><br><span class="line">|  +-----------+     +------------+      +------------+  |</span><br><span class="line">|  |  Stage 1  |----&gt;|   Stage 2  |-----&gt;|   Stage 3  |  |</span><br><span class="line">|  +-----------+     +------------+      +------------+  |</span><br><span class="line">|                                                        |</span><br><span class="line">+--------------------------------------------------------+</span><br></pre></td></tr></table></figure><h6 id="Jobs"><a href="#Jobs" class="headerlink" title="Jobs"></a>Jobs</h6><p>Jobs 表示构建工作，表示某个 Stage 里面执行的工作。<br>我们可以在 Stages 里面定义多个 Jobs，这些 Jobs 会有以下特点：</p><p>相同 Stage 中的 Jobs 会并行执行<br>相同 Stage 中的 Jobs 都执行成功时，该 Stage 才会成功<br>如果任何一个 Job 失败，那么该 Stage 失败，即该构建任务 (Pipeline) 失败<br>所以，Jobs 和 Stage 的关系图就是：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">+------------------------------------------+</span><br><span class="line">|                                          |</span><br><span class="line">|  Stage 1                                 |</span><br><span class="line">|                                          |</span><br><span class="line">|  +---------+  +---------+  +---------+   |</span><br><span class="line">|  |  Job 1  |  |  Job 2  |  |  Job 3  |   |</span><br><span class="line">|  +---------+  +---------+  +---------+   |</span><br><span class="line">|                                          |</span><br><span class="line">+------------------------------------------+</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h5 id=&quot;GitLab-CI&quot;&gt;&lt;a href=&quot;#GitLab-CI&quot; class=&quot;headerlink&quot; title=&quot;GitLab-CI&quot;&gt;&lt;/a&gt;GitLab-CI&lt;/h5&gt;
    
    </summary>
    
      <category term="tool" scheme="http://yoursite.com/categories/tool/"/>
    
    
      <category term="GitLab-CI" scheme="http://yoursite.com/tags/GitLab-CI/"/>
    
  </entry>
  
  <entry>
    <title>Golang 安装</title>
    <link href="http://yoursite.com/2019/02/18/code/golang/install/"/>
    <id>http://yoursite.com/2019/02/18/code/golang/install/</id>
    <published>2019-02-18T08:21:03.923Z</published>
    <updated>2019-02-18T08:21:03.923Z</updated>
    
    <content type="html"><![CDATA[<h5 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h5><a id="more"></a><blockquote><p><code>Golang</code> 源码安装 <a href="https://golang.org/project/" target="_blank" rel="noopener">https://golang.org/project/</a></p></blockquote><blockquote><p>Homebrew 安装 管理和升级建议方便</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install go</span><br></pre></td></tr></table></figure><blockquote><p>设置 <em>GOPATH</em>  <em>GOROOT</em> <em>PATH</em></p></blockquote><p><a href="http://www.linuxidc.com/Linux/2015-02/113109.htm" target="_blank" rel="noopener">http://www.linuxidc.com/Linux/2015-02/113109.htm</a></p><h5 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h5><p><a href="http://dmdgeeker.com/goBook/docs/ch01/path.html" target="_blank" rel="noopener">http://dmdgeeker.com/goBook/docs/ch01/path.html</a></p>]]></content>
    
    <summary type="html">
    
      &lt;h5 id=&quot;安装&quot;&gt;&lt;a href=&quot;#安装&quot; class=&quot;headerlink&quot; title=&quot;安装&quot;&gt;&lt;/a&gt;安装&lt;/h5&gt;
    
    </summary>
    
      <category term="Golang" scheme="http://yoursite.com/categories/Golang/"/>
    
    
      <category term="Golang" scheme="http://yoursite.com/tags/Golang/"/>
    
  </entry>
  
  <entry>
    <title>Python Functional Programming</title>
    <link href="http://yoursite.com/2017/11/23/code/Python/Python-FP/"/>
    <id>http://yoursite.com/2017/11/23/code/Python/Python-FP/</id>
    <published>2017-11-22T16:00:00.000Z</published>
    <updated>2019-02-18T08:21:03.922Z</updated>
    
    <content type="html"><![CDATA[<h4 id="Python-函数式编程"><a href="#Python-函数式编程" class="headerlink" title="Python 函数式编程"></a>Python 函数式编程</h4><a id="more"></a><p>函数是Python内建支持的一种封装，我们通过把大段代码拆成函数，通过一层层的函数调用，就可以把复杂的任务分解成简单的任务，这种分解可以称之为面向过程的程序设计。函数时面向过程的程序设计的基本单元。</p><p>函数式编程–<strong>Functional Programming</strong>， 虽然也可以归结到面向过程的程序设计，但启思想更接近书数学计算。</p><p>函数式编程就是一种抽象程度很高的编程范式，纯粹的函数式编程语言编写的函数没有变量，因此任意一个函数只要输入是固定的，输出就是固定的，这种春函数我们称之为没有副作用。</p><p>函数式编程的一个特点是，允许函数本身作为参数传入另一个函数，还允许返回另一个函数！</p>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;Python-函数式编程&quot;&gt;&lt;a href=&quot;#Python-函数式编程&quot; class=&quot;headerlink&quot; title=&quot;Python 函数式编程&quot;&gt;&lt;/a&gt;Python 函数式编程&lt;/h4&gt;
    
    </summary>
    
      <category term="Python" scheme="http://yoursite.com/categories/Python/"/>
    
    
      <category term="Python" scheme="http://yoursite.com/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>iTerm2常用命令</title>
    <link href="http://yoursite.com/2017/11/08/linux/Mac/iTerm2%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/"/>
    <id>http://yoursite.com/2017/11/08/linux/Mac/iTerm2常用命令/</id>
    <published>2017-11-07T16:00:00.000Z</published>
    <updated>2019-02-18T08:21:03.924Z</updated>
    
    <content type="html"><![CDATA[<h4 id="iTerm2常用命令"><a href="#iTerm2常用命令" class="headerlink" title="iTerm2常用命令"></a>iTerm2常用命令</h4><a id="more"></a><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">----------------分屏--------------------</span><br><span class="line">1. 垂直分屏：command + d</span><br><span class="line">2. 水平分屏：command + shift + d</span><br><span class="line">3. 切换屏幕：command + option + 方向键 command + [ 或 command + ]</span><br><span class="line">4. 查看历史命令：command + ;</span><br><span class="line">5. 查看剪贴板历史：command + shift + h</span><br><span class="line">----------------标签--------------------</span><br><span class="line">7. 新建标签：command + t</span><br><span class="line">8. 关闭标签：command + w</span><br><span class="line">9. 切换标签：command + 数字 command + 左右方向键</span><br><span class="line">10. 切换全屏：command + enter</span><br><span class="line">11. 查找：command + f</span><br><span class="line">12. ----------------命令--------------------</span><br><span class="line">13. 清除当前行：ctrl + u</span><br><span class="line">14. 到行首：ctrl + a</span><br><span class="line">15. 到行尾：ctrl + e</span><br><span class="line">16. 前进后退：ctrl + f/b (相当于左右方向键)</span><br><span class="line">17. 上一条命令：ctrl + p</span><br><span class="line">18. 搜索命令历史：ctrl + r</span><br><span class="line">19. 删除当前光标的字符：ctrl + d</span><br><span class="line">20. 删除光标之前的字符：ctrl + h</span><br><span class="line">21. 删除光标之前的单词：ctrl + w</span><br><span class="line">22. 删除到文本末尾：ctrl + k</span><br><span class="line">23. 交换光标处文本：ctrl + t</span><br><span class="line">24. 清屏1：command + r</span><br><span class="line">25. 清屏2：ctrl + l</span><br><span class="line">26. ⌘ + f 所查找的内容会被自动复制</span><br><span class="line">27. ⌘ + r = clear，而且只是换到新一屏，不会想 clear 一样创建一个空屏</span><br><span class="line">28. ctrl + u 清空当前行，无论光标在什么位置</span><br><span class="line">29. 输入开头命令后 按 ⌘ + ; 会自动列出输入过的命令</span><br><span class="line">30. ⌘ + shift + h 会列出剪切板历史</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;iTerm2常用命令&quot;&gt;&lt;a href=&quot;#iTerm2常用命令&quot; class=&quot;headerlink&quot; title=&quot;iTerm2常用命令&quot;&gt;&lt;/a&gt;iTerm2常用命令&lt;/h4&gt;
    
    </summary>
    
      <category term="iTerm2" scheme="http://yoursite.com/categories/iTerm2/"/>
    
    
      <category term="iTerm2" scheme="http://yoursite.com/tags/iTerm2/"/>
    
  </entry>
  
  <entry>
    <title>Mac下Python多版本环境管理</title>
    <link href="http://yoursite.com/2017/10/22/code/Python/pyenv/"/>
    <id>http://yoursite.com/2017/10/22/code/Python/pyenv/</id>
    <published>2017-10-21T16:00:00.000Z</published>
    <updated>2019-02-18T08:21:03.922Z</updated>
    
    <content type="html"><![CDATA[<h4 id="Mac-Python多版本环境管理"><a href="#Mac-Python多版本环境管理" class="headerlink" title="Mac Python多版本环境管理"></a>Mac Python多版本环境管理</h4><a id="more"></a><p>首先通过homebrew安装pyenv，之后的所有Python安装和管理通过pyenv进行。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ brew install pyenv</span><br></pre></td></tr></table></figure></p><p>pyenv安装完以后，就可以选择性的进行Python环境安装了。下面已安装Python2.7为例：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ pyenv install 2.7.5</span><br></pre></td></tr></table></figure></p><p>此外，你还可以通过pyenv查看目前系统中已经安装过的Python版本<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ pyenv versions</span><br></pre></td></tr></table></figure></p><p>如果需要在不同版本的Python间进行切换的话，使用以下命令：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ pyenv global 3.3.1</span><br></pre></td></tr></table></figure></p><p>当然，你也可以让版本切换只对当前目录生效<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ pyenv local 2.7.5</span><br></pre></td></tr></table></figure></p><p>参考文档地址：<br><a href="https://stackoverflow.com/questions/18671253/how-can-i-use-homebrew-to-install-both-python-2-and-3-on-mac" target="_blank" rel="noopener">转自Stackoverflow的回答</a>  </p><p><a href="https://github.com/pyenv/pyenv" target="_blank" rel="noopener">Github地址：pyenv）</a><br><a href="https://github.com/pyenv/pyenv-virtualenv" target="_blank" rel="noopener">Github地址：pyenv-virtuelanv）</a></p><p><a href="https://conda.io/docs/index.html" target="_blank" rel="noopener">conda使用说明</a></p>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;Mac-Python多版本环境管理&quot;&gt;&lt;a href=&quot;#Mac-Python多版本环境管理&quot; class=&quot;headerlink&quot; title=&quot;Mac Python多版本环境管理&quot;&gt;&lt;/a&gt;Mac Python多版本环境管理&lt;/h4&gt;
    
    </summary>
    
      <category term="pyenv" scheme="http://yoursite.com/categories/pyenv/"/>
    
    
      <category term="Python环境管理" scheme="http://yoursite.com/tags/Python%E7%8E%AF%E5%A2%83%E7%AE%A1%E7%90%86/"/>
    
  </entry>
  
  <entry>
    <title>MacVim</title>
    <link href="http://yoursite.com/2017/10/22/linux/Mac/macVim/"/>
    <id>http://yoursite.com/2017/10/22/linux/Mac/macVim/</id>
    <published>2017-10-21T16:00:00.000Z</published>
    <updated>2019-02-18T08:21:03.925Z</updated>
    
    <content type="html"><![CDATA[<h4 id="MacVim"><a href="#MacVim" class="headerlink" title="MacVim"></a>MacVim</h4><a id="more"></a>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;MacVim&quot;&gt;&lt;a href=&quot;#MacVim&quot; class=&quot;headerlink&quot; title=&quot;MacVim&quot;&gt;&lt;/a&gt;MacVim&lt;/h4&gt;
    
    </summary>
    
      <category term="MacVim" scheme="http://yoursite.com/categories/MacVim/"/>
    
    
      <category term="MacVim" scheme="http://yoursite.com/tags/MacVim/"/>
    
  </entry>
  
  <entry>
    <title>item2 + oh-my-zsh + solarized配色</title>
    <link href="http://yoursite.com/2017/10/22/linux/Mac/zsh-theme/"/>
    <id>http://yoursite.com/2017/10/22/linux/Mac/zsh-theme/</id>
    <published>2017-10-21T16:00:00.000Z</published>
    <updated>2019-02-18T08:21:03.925Z</updated>
    
    <content type="html"><![CDATA[<h4 id="item2-oh-my-zsh-solarized配色"><a href="#item2-oh-my-zsh-solarized配色" class="headerlink" title="item2 + oh-my-zsh + solarized配色"></a>item2 + oh-my-zsh + solarized配色</h4><a id="more"></a><h5 id="iTem2设置为默认终端"><a href="#iTem2设置为默认终端" class="headerlink" title="iTem2设置为默认终端"></a>iTem2设置为默认终端</h5><blockquote><p>菜单栏）iTerm2 -&gt; Make iTerm2 Default Term</p></blockquote><h5 id="iTem2设置为默认终端-1"><a href="#iTem2设置为默认终端-1" class="headerlink" title="iTem2设置为默认终端"></a>iTem2设置为默认终端</h5><blockquote><p>打开偏好设置preference，选中Keys，勾选Hotkey下的Show/hide iTerm2 with a system-wide hotkey，将热键设置为command+. ，这样你就可以通过command+. 全局热键来打开或关闭iTerm2窗口，非常方便。</p></blockquote><h5 id="配色方案"><a href="#配色方案" class="headerlink" title="配色方案"></a>配色方案</h5><blockquote><p>这里选用 solarized，效果还不错。点开官网，下载，解压，然后打开 iTerm2 下的偏好设置 preference ，点开 profiles 下的colors 选项，点击右下角的 Color Presets 选项，选择import ，导入解压到的 solarized 文件下的Solarized Dark.itermcolors。</p></blockquote><h5 id="安装oh-my-zsh"><a href="#安装oh-my-zsh" class="headerlink" title="安装oh-my-zsh"></a>安装oh-my-zsh</h5><p>使用 crul 安装：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh -c &quot;$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)&quot;</span><br></pre></td></tr></table></figure><p>或使用wget：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh -c &quot;$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)&quot;</span><br></pre></td></tr></table></figure><h5 id="主题配置"><a href="#主题配置" class="headerlink" title="主题配置"></a>主题配置</h5><p>安装成功后，用vim打开隐藏文件 .zshrc ，修改主题为 agnoster：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># ZSH_THEME=&quot;robbyrussell&quot;</span><br><span class="line">ZSH_THEME=&quot;agnoster&quot;</span><br></pre></td></tr></table></figure><p>应用这个主题需要特殊的字体支持，否则会出现乱码情况，这时我们来配置字体：</p><p>1.使用 Meslo 字体，点开连接<a href="https://github.com/powerline/fonts/blob/master/Meslo%20Slashed/Meslo%20LG%20M%20Regular%20for%20Powerline.tt" target="_blank" rel="noopener">字体</a>f点击 view raw 下载字体。</p><p>2.安装字体到系统字体册。</p><p>3.应用字体到iTerm2下，我自己喜欢将字号设置为14px，看着舒服（iTerm -&gt; Preferences -&gt; Profiles -&gt; Text -&gt; Change Font）。</p><p>4.重新打开iTerm2窗口，这时便可以看到效果了。</p><h5 id="自动提示命令"><a href="#自动提示命令" class="headerlink" title="自动提示命令"></a>自动提示命令</h5><p>当我们输入命令时，终端会自动提示你接下来可能要输入的命令，这时按 → 便可输出这些命令，非常方便。</p><p>设置如下：</p><p>1.克隆仓库到本地 ~/.oh-my-zsh/custom/plugins 路径下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone git://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions</span><br></pre></td></tr></table></figure><p>2.用 vim 打开 .zshrc 文件，找到插件设置命令，默认是 plugins=(git) ，我们把它修改为</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">plugins=(zsh-autosuggestions git)</span><br></pre></td></tr></table></figure><p>3.重新打开终端窗口。</p><p>PS：修改提示字体亮度：</p><p>移动到 ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions 路径下</p><p>cd ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions<br>用 vim 打开 zsh-autosuggestions.zsh 文件，修改<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE=&apos;fg=10&apos;</span><br></pre></td></tr></table></figure></p><h5 id="语法高亮"><a href="#语法高亮" class="headerlink" title="语法高亮"></a>语法高亮</h5><p>1.使用homebrew安装 zsh-syntax-highlighting 插件。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install zsh-syntax-highlighting</span><br></pre></td></tr></table></figure></p><p>2.配置.zshrc文件，插入一行。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source /usr/local/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh</span><br></pre></td></tr></table></figure></p><p>还有的人是这么干的<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">plugins=(zsh-autosuggestions git zsh-syntax-highlighting)</span><br></pre></td></tr></table></figure></p>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;item2-oh-my-zsh-solarized配色&quot;&gt;&lt;a href=&quot;#item2-oh-my-zsh-solarized配色&quot; class=&quot;headerlink&quot; title=&quot;item2 + oh-my-zsh + solarized配色&quot;&gt;&lt;/a&gt;item2 + oh-my-zsh + solarized配色&lt;/h4&gt;
    
    </summary>
    
      <category term="item2" scheme="http://yoursite.com/categories/item2/"/>
    
    
      <category term="主题配置" scheme="http://yoursite.com/tags/%E4%B8%BB%E9%A2%98%E9%85%8D%E7%BD%AE/"/>
    
  </entry>
  
  <entry>
    <title>tmux</title>
    <link href="http://yoursite.com/2017/10/22/linux/Mac/tmux/"/>
    <id>http://yoursite.com/2017/10/22/linux/Mac/tmux/</id>
    <published>2017-10-21T16:00:00.000Z</published>
    <updated>2019-02-18T08:21:03.925Z</updated>
    
    <content type="html"><![CDATA[<h4 id="tmux"><a href="#tmux" class="headerlink" title="tmux"></a><a href="https://github.com/tmux/tmux/wiki" target="_blank" rel="noopener"><strong>tmux</strong></a></h4><a id="more"></a><p><code>tmux</code>是什么？一个工具，是linux中的一种管理窗口的程序。<br>tmux提供了多标签和分割窗体的功能，提供了一个窗体组随时存储和恢复的功能。</p><h5 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h5><ul><li>Session： 会话，一组窗口的组合，通常用来概括统一任务。有自己的名字。</li><li>Window：窗口，单个可见窗口，有自己的编号。</li><li>Pane: 窗格，被划分成小块的窗口。  </li></ul><p>借个图:<br><img src="http://ww2.sinaimg.cn/mw690/6941baebjw1et4uosbtuhj21kw0qvqf1.jpg" alt=""></p><h5 id="Mac下安装"><a href="#Mac下安装" class="headerlink" title="Mac下安装"></a>Mac下安装</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install tmux</span><br></pre></td></tr></table></figure><h5 id="tmux基本操作"><a href="#tmux基本操作" class="headerlink" title="tmux基本操作"></a>tmux基本操作</h5><blockquote><p>Prefix-Command前置操作：所有下面介绍的快捷键，都必须以前置操作开始。tmux默认的前置操作是CTRL+b。例如，我们想要新建一个窗体，就需要先在键盘上摁下CTRL+b，松开后再摁下n键。</p></blockquote><p>下面所有的prefix均代表CTRL+b</p><h2 id="pane"><a href="#pane" class="headerlink" title="pane"></a><code>pane</code></h2><table><thead><tr><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center"></th></tr></thead><tbody><tr><td style="text-align:center">prefix</td><td style="text-align:center">%</td><td style="text-align:center">水平分割</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">:</td><td style="text-align:center">竖直分割</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">z</td><td style="text-align:center">放大当前pane</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">方向键</td><td style="text-align:center">切换</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">ctrl+ 方向键</td><td style="text-align:center"></td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">:</td><td style="text-align:center">竖直分割</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">o</td><td style="text-align:center">依次切换当前窗口下的各个pane。</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">Space (空格键)</td><td style="text-align:center">对当前窗口下的所有pane重新排列布局，每按一次，换一种样式。</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">x</td><td style="text-align:center">关闭当前使用中的pane。</td></tr></tbody></table><h2 id="Windows"><a href="#Windows" class="headerlink" title="Windows"></a><code>Windows</code></h2><table><thead><tr><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center"></th></tr></thead><tbody><tr><td style="text-align:center">prefix</td><td style="text-align:center">c</td><td style="text-align:center">创建</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">数字</td><td style="text-align:center">移动</td></tr><tr><td style="text-align:center">Prefix</td><td style="text-align:center">p</td><td style="text-align:center">(p for previous)：切换到上一个window。</td></tr><tr><td style="text-align:center">Prefix</td><td style="text-align:center">n</td><td style="text-align:center">(n for next): 切换到下一个window。</td></tr><tr><td style="text-align:center">Prefix</td><td style="text-align:center">0</td><td style="text-align:center">: 切换到0号window，依次类推，1、2、3…</td></tr><tr><td style="text-align:center">Prefix</td><td style="text-align:center">w</td><td style="text-align:center">(w for windows):出当前session所有window，通过上、下键可以选择切换到指定window。</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">&amp;</td><td style="text-align:center">关闭</td></tr><tr><td style="text-align:center">prefix</td><td style="text-align:center">，</td><td style="text-align:center">重命名</td></tr></tbody></table><!-- 更名后，我随便使用ls或cd命令后，window名称会随着目录的不同而变化。google后发现这个是zsh下oh-my-zsh的特性。于是打开~/.zshrc, 讲DISABLE_AUTO_TITLE="true"这一行反注释掉。source ~/.zshrc后，测试更改的名称，发现一切正常。 --><h2 id="Session"><a href="#Session" class="headerlink" title="Session"></a><code>Session</code></h2><table><thead><tr><th style="text-align:center"></th><th style="text-align:center"></th><th style="text-align:center"></th></tr></thead><tbody><tr><td style="text-align:center">tmux ls</td><td style="text-align:center"></td></tr><tr><td style="text-align:center">tmux attach</td><td style="text-align:center">如果你已经创建了一个或多个会话，但是还没有运行 Tmux，那么可以输入如下命令以接入已开启的会话</td></tr><tr><td style="text-align:center">tmux attach -t [name-of-session]</td><td style="text-align:center">回到session</td></tr><tr><td style="text-align:center">tmux new -s [name-of-session]</td><td style="text-align:center">创建时命名</td></tr><tr><td style="text-align:center">tmux new-session -s [name-of-session]</td><td style="text-align:center">创建时命名</td></tr><tr><td style="text-align:center">tmux kill-session -t [name-of-session]</td><td style="text-align:center">关闭session</td></tr><tr><td style="text-align:center">tmux a -t [name-of-session]</td><td style="text-align:center">a/attach 重新连接叫做name的session</td></tr><tr><td style="text-align:center">tmux a</td><td style="text-align:center">只有一个session会快速连接</td></tr><tr><td style="text-align:center">tmux kill-session -a -t [name-of-my-session]</td><td style="text-align:center">删除除了name意外的所有session</td></tr><tr><td style="text-align:center"></td><td style="text-align:center"></td></tr><tr><td style="text-align:center">new -s [name-of-session]</td><td style="text-align:center">创建一个新的会话</td></tr><tr><td style="text-align:center">prefix + $</td><td style="text-align:center">重命名</td></tr><tr><td style="text-align:center">prefix + d / exit</td><td style="text-align:center">在只有一个window下输入</td></tr><tr><td style="text-align:center">prefix + s</td><td style="text-align:center">获取现有session的列表</td></tr></tbody></table><h5 id="主题美化"><a href="#主题美化" class="headerlink" title="主题美化"></a>主题美化</h5><blockquote><p>需要先安装相应主题。</p></blockquote><p><a href="https://github.com/VimrcMac/.tmux" target="_blank" rel="noopener">https://github.com/VimrcMac/.tmux</a></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># you may want to backup your existing ~/.tmux.conf first</span><br><span class="line"></span><br><span class="line">mv ~/.tmux.conf ~/.tmux.conf.bak</span><br><span class="line"></span><br><span class="line">cd</span><br><span class="line">git clone https://github.com/gpakosz/.tmux.git</span><br><span class="line">ln -s -f .tmux/.tmux.conf</span><br><span class="line">cp .tmux/.tmux.conf.local .</span><br></pre></td></tr></table></figure><h5 id="Configuration"><a href="#Configuration" class="headerlink" title="Configuration"></a>Configuration</h5><blockquote><p>配置文件不存在的话需要创建： touch ~/.tmux.conf</p></blockquote><!-- 首先，在更改了.tmux.conf后，在tmux里的快捷键没有变化。查找后发现是tmux只有在新建session的时候，才会去找tmux.conf文件。所以说，我之前创建的那些session都没有参考tmux.conf. 所以我就用tmux lstmux kill-session -a只保留当前session。再删除当前session tmux kill-session -t py27。这下删除了所有创建好的session。然后再次用tmux new -s py27创建一个新的名为py27的session。有提示了，但是错误提示显示没有mode-mouse命令。google之发现在2.1之后的tmux版本里，已经废除了这个命令。想要开启mouse mode的话，只需要一个句命令即可set -g mouse on。作者：赤乐君链接：http://www.jianshu.com/p/fd3bbdba9dc9來源：简书著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。 --><h6 id="Send-prefix"><a href="#Send-prefix" class="headerlink" title="Send prefix"></a>Send prefix</h6><blockquote><p>把prefix的ctrl+b变为了ctrl+a，因为这样按起来方便些。基本上用tmux的都改了这个。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># Send prefix</span><br><span class="line">set-option -g prefix C-a</span><br><span class="line">unbind-key C-a</span><br><span class="line">bind-key C-a send-prefix</span><br></pre></td></tr></table></figure><h6 id="Use-Alt-arrow-keys-to-switch-panes"><a href="#Use-Alt-arrow-keys-to-switch-panes" class="headerlink" title="Use Alt-arrow keys to switch panes"></a>Use Alt-arrow keys to switch panes</h6><blockquote><p>不用按prefix，直接用alt+箭头在pane之间switch。实际用过之后才发现真是太方便了！</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># Use Alt-arrow keys to switch panes</span><br><span class="line">bind -n M-Left select-pane -L</span><br><span class="line">bind -n M-Right select-pane -R</span><br><span class="line">bind -n M-Up select-pane -U</span><br><span class="line">bind -n M-Down select-pane -D</span><br></pre></td></tr></table></figure><h6 id="Shift-arrow-to-switch-windows"><a href="#Shift-arrow-to-switch-windows" class="headerlink" title="Shift arrow to switch windows"></a>Shift arrow to switch windows</h6><blockquote><p>不用按prefix，直接用shift+箭头在window之间switch。太方便了！</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># Shift arrow to switch windows</span><br><span class="line">bind -n S-Left previous-window</span><br><span class="line">bind -n S-Right next-window</span><br></pre></td></tr></table></figure><h6 id="Mouse-mode"><a href="#Mouse-mode" class="headerlink" title="Mouse mode"></a>Mouse mode</h6><blockquote><p>开启鼠标模式。用鼠标就能切换window，pane，还能调整pane的大小，方便！</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># Mouse mode</span><br><span class="line">set -g mouse on</span><br></pre></td></tr></table></figure><h6 id="Set-easier-window-split-keys"><a href="#Set-easier-window-split-keys" class="headerlink" title="Set easier window split keys"></a>Set easier window split keys</h6><blockquote><p>这一部分是用来更方便切分pane的。prefix + v 代表竖着切，prefix + h 代表横着切。比起默认的切割方法不仅直观而且方便。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># Set easier window split keys</span><br><span class="line">bind-key v split-window -h</span><br><span class="line">bind-key h split-window -v</span><br></pre></td></tr></table></figure><h6 id="Easy-config-reload"><a href="#Easy-config-reload" class="headerlink" title="Easy config reload"></a>Easy config reload</h6><blockquote><p>下一次如果修改了.tmux.conf的设置的话，不用关掉tmux。直接用prefix+r,就能重新加载设置。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># Easy config reload</span><br><span class="line">bind-key r source-file ~/.tmux.conf \; display-message &quot;.tmux.conf reloaded. Your configuration has been updated.&quot;</span><br></pre></td></tr></table></figure><h6 id="在文本间移动光标"><a href="#在文本间移动光标" class="headerlink" title="在文本间移动光标"></a>在文本间移动光标</h6><blockquote><p>在 Tmux 中可以使用与 Vim 极为相似的方式在文本间移动光标。正如你熟知的那样，用 k 键可以将光标移动到上一行，用 w 键可以向后移动一个单词等等。而且还可以通过把 Tmux 设为 vi 模式，使其与 Vim 的操作更加接近。为此，需要将以下配置加入到文件 ~/.tmux.conf 中。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># Use vim keybindings in copy mode</span><br><span class="line">setw -g mode-keys vi</span><br></pre></td></tr></table></figure><h6 id="将复制下来的文本发送到系统的剪贴板中"><a href="#将复制下来的文本发送到系统的剪贴板中" class="headerlink" title="将复制下来的文本发送到系统的剪贴板中"></a>将复制下来的文本发送到系统的剪贴板中</h6><blockquote><p>在默认情况下，当从 Tmux 中复制文本时，复制下来的文本只能粘贴到同一个 Tmux 会话中。若要使复制下来的文本可以粘贴到任何位置，就需要让 Tmux 将文本复制到系统的剪贴板。为此，我们需要这样做：</p></blockquote><p>安装 retach-to-user-namespace。用 brew 安装的话将会非常简单，只需要运行下面这条命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install reattach-to-user-namespace</span><br></pre></td></tr></table></figure><h6 id="选择并复制文本"><a href="#选择并复制文本" class="headerlink" title="选择并复制文本"></a>选择并复制文本</h6><blockquote><p>首先按下 <code>Ctrl-b</code> [ 进入复制模式，然后可以看到一小段高亮的文本出现在了屏幕的右上角 (“[0/0]”)<br>使用空格键（space）开始内容选取，回车键（Enter）进行拷贝，<br>然后使用 “ctrl-b ]” 进行粘贴。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># invoke reattach-to-user-namespace every time a new window/pane opens</span><br><span class="line">set-option -g default-command &quot;reattach-to-user-namespace -l bash&quot;</span><br></pre></td></tr></table></figure><h6 id="使用vim快捷键"><a href="#使用vim快捷键" class="headerlink" title="使用vim快捷键"></a>使用vim快捷键</h6><blockquote><p>使用 v 开始选择， y 复制</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># start selecting text typing &apos;v&apos; key (once you are in copy mode)</span><br><span class="line">bind-key -t vi-copy v begin-selection</span><br><span class="line"># copy selected text to the system&apos;s clipboard</span><br><span class="line">bind-key -t vi-copy y copy-pipe &quot;reattach-to-user-namespace pbcopy&quot;</span><br></pre></td></tr></table></figure><h5 id="高效的结对编程"><a href="#高效的结对编程" class="headerlink" title="高效的结对编程"></a>高效的结对编程</h5><p>Tmate 是一个 Tmux 的管理工具，使用它不但能够轻松地创建 Tmux 会话而且还能够通过互联网把该会话共享给其他人。若要使用 Tmate 共享 Tmux 会话，请按照以下步骤操作：</p><ul><li><p>安装tmate </p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew update &amp;&amp; brew tap nviennot/tmate &amp;&amp; brew install mate</span><br></pre></td></tr></table></figure></li><li><p>开启一个新的会话</p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tmate</span><br></pre></td></tr></table></figure></li></ul><ul><li>从 Tmux 的会话中复制由 Tmate 产生的 SSH URL。请注意屏幕下方的信息“[tmate] Remote session: ssh …”</li></ul><h5 id="调整-Tmux-以增强其同-Vim-的集成度"><a href="#调整-Tmux-以增强其同-Vim-的集成度" class="headerlink" title="调整 Tmux 以增强其同 Vim 的集成度"></a>调整 Tmux 以增强其同 Vim 的集成度</h5><h6 id="调整背景的配色方案"><a href="#调整背景的配色方案" class="headerlink" title="调整背景的配色方案"></a>调整背景的配色方案</h6><p>将下面配置添加到 .vimrc 文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if exists(&apos;$TMUX&apos;)</span><br><span class="line">  set term=screen-256color</span><br><span class="line">endif</span><br></pre></td></tr></table></figure><h6 id="调整光标的形状"><a href="#调整光标的形状" class="headerlink" title="调整光标的形状"></a>调整光标的形状</h6><p>在默认情况下，当通过 Tmux 运行 Vim 时，无论当前 Vim 是处于插入模式、可视模式还是其他模式，光标的形状都是一样的。这样就很难判断当前的 Vim 模式是什么。若要避免这个问题，就需要让 Tmux 通知 iTerm 更新光标的形状。为此，需要将以下配置加入到文件 ~/.vimrc 中。</p><blockquote><p>这里有问题，需要注意，如果您在Tmux会话中使用Vim，则需要双重转义t SI / t EI中的代码。 TODO</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">if exists(&apos;$ITERM_PROFILE&apos;)</span><br><span class="line">  if exists(&apos;$TMUX&apos;) </span><br><span class="line">    let &amp;amp;t_SI = &quot;\&lt;Esc&gt;[3 q&quot;</span><br><span class="line">    let &amp;amp;t_EI = &quot;\&lt;Esc&gt;[0 q&quot;</span><br><span class="line">  else</span><br><span class="line">    let &amp;amp;t_SI = &quot;\&lt;Esc&gt;]50;CursorShape=1x7&quot;</span><br><span class="line">    let &amp;amp;t_EI = &quot;\&lt;Esc&gt;]50;CursorShape=0x7&quot;</span><br><span class="line">  endif</span><br><span class="line">end</span><br></pre></td></tr></table></figure><h6 id="调整粘贴时的文本缩进"><a href="#调整粘贴时的文本缩进" class="headerlink" title="调整粘贴时的文本缩进"></a>调整粘贴时的文本缩进</h6><p>在 Vim 中粘贴文本时可能会遇到这样的问题，有时文本的缩进会发生变化，特别是在粘贴大量的文本时，这个问题会更加明显。虽然可以通过在粘贴前执行 :set nopaste 来解决这个问题，但是这里还有一种更好的解决方法。就是把下面这段配置加入到配置文件 ~/.vimrc 中，这样 Vim 就会自动地阻止粘贴文本时的自动缩进。</p><p><a href="https://coderwall.com/p/if9mda/automatically-set-paste-mode-in-vim-when-pasting-in-insert-mode" target="_blank" rel="noopener">https://coderwall.com/p/if9mda/automatically-set-paste-mode-in-vim-when-pasting-in-insert-mode</a></p><h4 id="Tmuxinator"><a href="#Tmuxinator" class="headerlink" title="Tmuxinator"></a>Tmuxinator</h4><p>为项目自动创建会话。<a href="https://github.com/tmuxinator/tmuxinator" target="_blank" rel="noopener">Tmuxinator</a> 是一个ruby的gem包，客用户创建Tmux会话。Tmuxinator现在配置文件中定义会话中的细节，然后用命令创建这些会话。</p><ul><li><p>安装</p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gem install tmuxinator</span><br></pre></td></tr></table></figure></li><li><p>创建</p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># mux</span><br><span class="line">tmuxinator new project_a</span><br><span class="line"># 回车之后，会自动打开文件 `~/.tmuxinator/project_a.yml`</span><br></pre></td></tr></table></figure></li></ul><ul><li><p>更新配置文件    </p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">name: project_a</span><br><span class="line">root: &lt;the-folder-of-project-A&gt;</span><br><span class="line">windows:</span><br><span class="line">- server: &lt;command-to-start-application-server&gt;</span><br><span class="line">- editor:</span><br><span class="line">layout: even-horizontal</span><br><span class="line">panes:</span><br><span class="line">- vim</span><br><span class="line">- &lt;command-to-launch-tests-guard&gt;</span><br><span class="line">- shell: &apos;&apos;</span><br></pre></td></tr></table></figure></li></ul><ul><li><p>启动会话</p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">tmuxinator start project_a</span><br><span class="line"></span><br><span class="line"># or</span><br><span class="line"></span><br><span class="line">tmuxinator start project_a</span><br></pre></td></tr></table></figure></li></ul><hr><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"># .tmux.conf</span><br><span class="line"></span><br><span class="line"># Send prefix</span><br><span class="line">set-option -g prefix C-a</span><br><span class="line">unbind-key C-a</span><br><span class="line">bind-key C-a send-prefix</span><br><span class="line"></span><br><span class="line"># Use Alt-arrow keys to switch panes</span><br><span class="line">bind -n M-Left select-pane -L</span><br><span class="line">bind -n M-Right select-pane -R</span><br><span class="line">bind -n M-Up select-pane -U</span><br><span class="line">bind -n M-Dowœœn select-pane -D</span><br><span class="line"></span><br><span class="line"># Shift arrow to switch windows</span><br><span class="line">bind -n S-Left previous-window</span><br><span class="line">bind -n S-Right next-window</span><br><span class="line"></span><br><span class="line"># Mouse mode</span><br><span class="line">set -g mouse on</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># Set easier window split keys</span><br><span class="line">bind-key v split-window -h</span><br><span class="line">bind-key h split-window -v</span><br><span class="line"></span><br><span class="line"># Easy config reload</span><br><span class="line">bind-key r source-file ~/.tmux.conf \; display-message &quot;.tmux.conf reloaded&quot;</span><br><span class="line"></span><br><span class="line"># Invoke reattach-to-user-namespace every time a new window/pane opens</span><br><span class="line">set-option -g default-command &quot;reattach-to-user-namespace -l bash&quot;</span><br><span class="line"></span><br><span class="line"># Use vim keybindings in copy mode</span><br><span class="line">setw -g mode-keys vi</span><br><span class="line"></span><br><span class="line"># start selecting text typing &apos;v&apos; key (once you are in copy mode)</span><br><span class="line">bind-key -t vi-copy v begin-selection</span><br><span class="line"># copy selected text to the system&apos;s clipboard</span><br><span class="line">bind-key -t vi-copy y copy-pipe &quot;reattach-to-user-namespace pbcopy&quot;</span><br></pre></td></tr></table></figure><!--    http://blog.jobbole.com/87584/--><p>Iterm2 常用快捷键</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">⌘ + 数字 ： 各 tab 标签切换</span><br><span class="line">⌘ + f ： 查找 ，所查找的内容会被自动复制 ,输入查找的部分字符，找到匹配的值按tab，即可复制</span><br><span class="line">⌘ + d ： 横着分屏 </span><br><span class="line">⌘ + shift + d ： 竖着分屏</span><br><span class="line">⌘ + r = clear ： 换到新一屏，而不是 类似clear ，会创建一个空屏</span><br><span class="line">ctrl + u ：清空当前行，无论光标在什么位置</span><br><span class="line">() + ⌘ + ; ： [() 输入的命令开头字符],会自动列出输入过的命令</span><br><span class="line">⌘ + shift + h ： 会列出剪切板历史</span><br><span class="line">⌘← / ⌘→ : 到一行命令最左边/最右边 </span><br><span class="line">⌘ + enter : 全屏</span><br></pre></td></tr></table></figure><p>tmux 常用快捷键</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">Ctrl+b // 激活控制台；此时以下按键生效</span><br><span class="line">系统操作</span><br><span class="line">? // 列出所有快捷键；按q返回</span><br><span class="line">d // 脱离当前会话；这样可以暂时返回Shell界面，输入tmux attach能够重新进入之前的会话</span><br><span class="line">D // 选择要脱离的会话；在同时开启了多个会话时使用</span><br><span class="line">Ctrl+z // 挂起当前会话</span><br><span class="line">r // 强制重绘未脱离的会话</span><br><span class="line">s // 选择并切换会话；在同时开启了多个会话时使用</span><br><span class="line">: // 进入命令行模式；此时可以输入支持的命令，例如kill-server可以关闭服务器</span><br><span class="line">[ // 进入复制模式；此时的操作与vi/emacs相同，按q/Esc退出</span><br><span class="line">~ // 列出提示信息缓存；其中包含了之前tmux返回的各种提示信息</span><br><span class="line">窗口操作</span><br><span class="line">c // 创建新窗口</span><br><span class="line">&amp; // 关闭当前窗口</span><br><span class="line">数字键 // 切换至指定窗口</span><br><span class="line">p // 切换至上一窗口</span><br><span class="line">n // 切换至下一窗口</span><br><span class="line">l // 在前后两个窗口间互相切换</span><br><span class="line">w // 通过窗口列表切换窗口</span><br><span class="line">, // 重命名当前窗口；这样便于识别</span><br><span class="line">. // 修改当前窗口编号；相当于窗口重新排序</span><br><span class="line">f // 在所有窗口中查找指定文本</span><br><span class="line">面板操作</span><br><span class="line">” // 将当前面板平分为上下两块</span><br><span class="line">% // 将当前面板平分为左右两块</span><br><span class="line">x // 关闭当前面板</span><br><span class="line">! // 将当前面板置于新窗口；即新建一个窗口，其中仅包含当前面板</span><br><span class="line">Ctrl+方向键 // 以1个单元格为单位移动边缘以调整当前面板大小</span><br><span class="line">Alt+方向键 // 以5个单元格为单位移动边缘以调整当前面板大小</span><br><span class="line">Space // 在预置的面板布局中循环切换；依次包括even-horizontal、even-vertical、main-horizontal、main-vertical、tiled</span><br><span class="line">q // 显示面板编号</span><br><span class="line">o // 在当前窗口中选择下一面板</span><br><span class="line">方向键 // 移动光标以选择面板</span><br><span class="line">&#123; // 向前置换当前面板</span><br><span class="line">&#125; // 向后置换当前面板</span><br><span class="line">Alt+o // 逆时针旋转当前窗口的面板</span><br><span class="line">Ctrl+o // 顺时针旋转当前窗口的面板</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;tmux&quot;&gt;&lt;a href=&quot;#tmux&quot; class=&quot;headerlink&quot; title=&quot;tmux&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/tmux/tmux/wiki&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;strong&gt;tmux&lt;/strong&gt;&lt;/a&gt;&lt;/h4&gt;
    
    </summary>
    
      <category term="tmux" scheme="http://yoursite.com/categories/tmux/"/>
    
    
      <category term="Linux" scheme="http://yoursite.com/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>powerline</title>
    <link href="http://yoursite.com/2017/10/22/linux/Mac/powerline/"/>
    <id>http://yoursite.com/2017/10/22/linux/Mac/powerline/</id>
    <published>2017-10-21T16:00:00.000Z</published>
    <updated>2019-02-18T08:21:03.925Z</updated>
    
    <content type="html"><![CDATA[<h4 id="powerline"><a href="#powerline" class="headerlink" title="powerline"></a>powerline</h4><a id="more"></a><p>powerline是一个stateless status line，即一个全局状态/提示栏.<br><a href="https://github.com/powerline/powerline" target="_blank" rel="noopener">powerline</a></p>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;powerline&quot;&gt;&lt;a href=&quot;#powerline&quot; class=&quot;headerlink&quot; title=&quot;powerline&quot;&gt;&lt;/a&gt;powerline&lt;/h4&gt;
    
    </summary>
    
      <category term="item2" scheme="http://yoursite.com/categories/item2/"/>
    
    
      <category term="主题配置" scheme="http://yoursite.com/tags/%E4%B8%BB%E9%A2%98%E9%85%8D%E7%BD%AE/"/>
    
  </entry>
  
  <entry>
    <title>NERDTree 快捷键</title>
    <link href="http://yoursite.com/2017/10/21/linux/vim/nerdtree/"/>
    <id>http://yoursite.com/2017/10/21/linux/vim/nerdtree/</id>
    <published>2017-10-20T16:00:00.000Z</published>
    <updated>2019-02-18T08:21:03.926Z</updated>
    
    <content type="html"><![CDATA[<h3 id="NerdTree-在-vimrc-中的常用配置"><a href="#NerdTree-在-vimrc-中的常用配置" class="headerlink" title="NerdTree 在 .vimrc 中的常用配置"></a>NerdTree 在 .vimrc 中的常用配置</h3><a id="more"></a><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&quot; 在 vim 启动的时候默认开启 NERDTree（autocmd 可以缩写为 au）</span><br><span class="line">autocmd VimEnter * NERDTree</span><br><span class="line"></span><br><span class="line">&quot; 按下 F2 调出/隐藏 NERDTree</span><br><span class="line">map  :silent! NERDTreeToggle</span><br><span class="line"></span><br><span class="line">&quot; 将 NERDTree 的窗口设置在 vim 窗口的右侧（默认为左侧）</span><br><span class="line">let NERDTreeWinPos=&quot;right&quot;</span><br><span class="line"></span><br><span class="line">&quot; 当打开 NERDTree 窗口时，自动显示 Bookmarks</span><br><span class="line">let NERDTreeShowBookmarks=1</span><br><span class="line"></span><br><span class="line">&quot; nnoremap &lt;silent&gt; &lt;F5&gt; :NERDTree&lt;CR&gt;</span><br><span class="line">  </span><br><span class="line"></span><br><span class="line"></span><br><span class="line">map &lt;F3&gt; :NERDTreeMirror&lt;CR&gt;</span><br><span class="line">map &lt;F3&gt; :NERDTreeToggle&lt;CR&gt;</span><br></pre></td></tr></table></figure><h3 id="切换工作台和目录"><a href="#切换工作台和目录" class="headerlink" title="切换工作台和目录"></a>切换工作台和目录</h3><!--more--><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ctrl + w + h    光标 focus 左侧树形目录</span><br><span class="line">ctrl + w + l    光标 focus 右侧文件显示窗口</span><br><span class="line">ctrl +https://itunes.apple.com/app/read-it-later-pro/id309601447?mt=8 w + w    光标自动在左右侧窗口切换</span><br><span class="line">ctrl + w + r    移动当前窗口的布局位置</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">o       在已有窗口中打开文件、目录或书签，并跳到该窗口</span><br><span class="line">go      在已有窗口 中打开文件、目录或书签，但不跳到该窗口</span><br><span class="line">t       在新 Tab 中打开选中文件/书签，并跳到新 Tab</span><br><span class="line">T       在新 Tab 中打开选中文件/书签，但不跳到新 Tab</span><br><span class="line">i       split 一个新窗口打开选中文件，并跳到该窗口</span><br><span class="line">gi      split 一个新窗口打开选中文件，但不跳到该窗口</span><br><span class="line">s       vsplit 一个新窗口打开选中文件，并跳到该窗口</span><br><span class="line">gs      vsplit 一个新 窗口打开选中文件，但不跳到该窗口</span><br><span class="line">!       执行当前文件</span><br><span class="line">O       递归打开选中 结点下的所有目录</span><br><span class="line">x       合拢选中结点的父目录</span><br><span class="line">X       递归 合拢选中结点下的所有目录</span><br><span class="line">e       Edit the current dif</span><br><span class="line"></span><br><span class="line">双击    相当于 NERDTree-o</span><br><span class="line">中键    对文件相当于 NERDTree-i，对目录相当于 NERDTree-e</span><br><span class="line"></span><br><span class="line">D       删除当前书签</span><br><span class="line"></span><br><span class="line">P       跳到根结点</span><br><span class="line">p       跳到父结点</span><br><span class="line">K       跳到当前目录下同级的第一个结点</span><br><span class="line">J       跳到当前目录下同级的最后一个结点</span><br><span class="line">k       跳到当前目录下同级的前一个结点</span><br><span class="line">j       跳到当前目录下同级的后一个结点</span><br><span class="line"></span><br><span class="line">C       将选中目录或选中文件的父目录设为根结点</span><br><span class="line">u       将当前根结点的父目录设为根目录，并变成合拢原根结点</span><br><span class="line">U       将当前根结点的父目录设为根目录，但保持展开原根结点</span><br><span class="line">r       递归刷新选中目录</span><br><span class="line">R       递归刷新根结点</span><br><span class="line">m       显示文件系统菜单</span><br><span class="line">cd      将 CWD 设为选中目录</span><br><span class="line"></span><br><span class="line">I       切换是否显示隐藏文件</span><br><span class="line">f       切换是否使用文件过滤器</span><br><span class="line">F       切换是否显示文件</span><br><span class="line">B       切换是否显示书签</span><br><span class="line"></span><br><span class="line">q       关闭 NerdTree 窗口</span><br><span class="line">?       切换是否显示 Quick Help</span><br></pre></td></tr></table></figure><h3 id="切换标签页"><a href="#切换标签页" class="headerlink" title="切换标签页"></a>切换标签页</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">:tabnew [++opt选项] ［＋cmd］ 文件      建立对指定文件新的tab</span><br><span class="line">:tabc   关闭当前的 tab</span><br><span class="line">:tabo   关闭所有其他的 tab</span><br><span class="line">:tabs   查看所有打开的 tab</span><br><span class="line">:tabp   前一个 tab</span><br><span class="line">:tabn   后一个 tab</span><br><span class="line"></span><br><span class="line">标准模式下：</span><br><span class="line">gT      前一个 tab</span><br><span class="line">gt      后一个 tab</span><br><span class="line"></span><br><span class="line">MacVim 还可以借助快捷键来完成 tab 的关闭、切换</span><br><span class="line">cmd+w   关闭当前的 tab</span><br><span class="line">cmd+&#123;   前一个 tab</span><br><span class="line">cmd+&#125;   后一个 tab</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;NerdTree-在-vimrc-中的常用配置&quot;&gt;&lt;a href=&quot;#NerdTree-在-vimrc-中的常用配置&quot; class=&quot;headerlink&quot; title=&quot;NerdTree 在 .vimrc 中的常用配置&quot;&gt;&lt;/a&gt;NerdTree 在 .vimrc 中的常用配置&lt;/h3&gt;
    
    </summary>
    
      <category term="vim" scheme="http://yoursite.com/categories/vim/"/>
    
    
      <category term="Linux/vim" scheme="http://yoursite.com/tags/Linux-vim/"/>
    
  </entry>
  
  <entry>
    <title>travis-ci自动部署Hexo</title>
    <link href="http://yoursite.com/2017/09/26/hexo/travis/"/>
    <id>http://yoursite.com/2017/09/26/hexo/travis/</id>
    <published>2017-09-26T07:05:42.000Z</published>
    <updated>2019-02-18T08:21:03.924Z</updated>
    
    <content type="html"><![CDATA[<h2 id="travis-ci-自动部署-Hexo"><a href="#travis-ci-自动部署-Hexo" class="headerlink" title="travis-ci 自动部署 Hexo"></a>travis-ci 自动部署 Hexo</h2><a id="more"></a><blockquote><p>travis-ci是一个持续集成工具，目前已经支持大部分主流语言了，如：node.js、objective-c、android、php、c、java、python、ruby、go等等。travis ci与github集成非常紧密，官方的集成测试托管只支持github项目，而且它对于公有的github仓库免费。在这篇文章中，我将介绍如何通过travis-ci自动化部署hexo博客。</p></blockquote><h4 id="开启-travis-ci"><a href="#开启-travis-ci" class="headerlink" title="开启 travis-ci"></a>开启 travis-ci</h4><ul><li>首先去<a href="https://travis-ci.org/" target="_blank" rel="noopener">travis-ciu</a>]官网，</li><li>点击右上角Sign in with GitHub通过github授权登录。</li><li>然后去到个人信息页面，开启需要使用travis的项目关</li></ul><h4 id="加密私钥"><a href="#加密私钥" class="headerlink" title="加密私钥"></a>加密私钥</h4><ul><li><p>首先我们要安装travis-ci的命令行工具</p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gem install travis</span><br></pre></td></tr></table></figure></li><li><p>然后通过命令行登录travis-ci</p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 通过用户名密码登录</span><br><span class="line"># https://github.com/travis-ci/travis.rb#login</span><br><span class="line">travis login --auto</span><br><span class="line"></span><br><span class="line"># 通过token登录</span><br><span class="line">travis login --github-token &apos;token&apos;</span><br></pre></td></tr></table></figure><blockquote><p>github-token可以去<a href="https://github.com/settings/tokens查看，如果Personal" target="_blank" rel="noopener">https://github.com/settings/tokens查看，如果Personal</a> access tokens列表里面有的话可以选中一个点击Edit，然后点击Regenerate token重新生成就可以看到token了。没有的话点击Generate new token生成一个token</p></blockquote><p>  查看是否登录成功</p>  <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">travis whoami</span><br></pre></td></tr></table></figure><p>  <a href="http://w3cboy.com/post/2016/03/travisci-hexo-deploy/" target="_blank" rel="noopener">http://w3cboy.com/post/2016/03/travisci-hexo-deploy/</a></p></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;travis-ci-自动部署-Hexo&quot;&gt;&lt;a href=&quot;#travis-ci-自动部署-Hexo&quot; class=&quot;headerlink&quot; title=&quot;travis-ci 自动部署 Hexo&quot;&gt;&lt;/a&gt;travis-ci 自动部署 Hexo&lt;/h2&gt;
    
    </summary>
    
      <category term="hexo" scheme="http://yoursite.com/categories/hexo/"/>
    
    
      <category term="travis-ci" scheme="http://yoursite.com/tags/travis-ci/"/>
    
  </entry>
  
</feed>
