<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://junze-xu.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://junze-xu.github.io/" rel="alternate" type="text/html" /><updated>2026-10-15T15:42:17+00:00</updated><id>https://junze-xu.github.io/feed.xml</id><title type="html">JunzeXu’s Blog</title><subtitle>Junze Xu 的个人博客，记录 Linux、C/C++、OpenSSL、Makefile 等技术笔记与开发心得</subtitle><author><name>Junze Xu</name></author><entry><title type="html">读书：穷查理宝典</title><link href="https://junze-xu.github.io/2026/10/08/poor-charlies-almanack-note/" rel="alternate" type="text/html" title="读书：穷查理宝典" /><published>2026-10-08T00:00:00+00:00</published><updated>2026-10-08T00:00:00+00:00</updated><id>https://junze-xu.github.io/2026/10/08/poor-charlies-almanack-note</id><content type="html" xml:base="https://junze-xu.github.io/2026/10/08/poor-charlies-almanack-note/"><![CDATA[<p>这本书的副标题是「查理·芒格的智慧箴言录」，查理·芒格作为沃伦·巴菲特的好基友、投资大师，除了向大家展示了他的决策方法外，还提供了足够多的实用建议与人生智慧。</p>

<p>全书大致分为三部分：</p>

<ol>
  <li>
    <p>芒格传略；</p>
  </li>
  <li>
    <p>芒格的生活、学习和决策方法；</p>
  </li>
  <li>
    <p>芒格的即席谈话、演讲和文章、报道与评论。</p>
  </li>
</ol>

<p>整本书通读下来，有几点是被反复提到的：</p>

<ol>
  <li>
    <p>多元思维模型的重要性；</p>

    <blockquote>
      <p>你必须知道重要学科的重要理论，并经常使用它们——要全部都用上，而不是只用几种。大多数人都只养成一个学科——比如说经济学——的思维模型，试图用一种方法来解决所有问题。你知道谚语是怎么说的：「在手里拿着铁锤的人看来，世界就像一颗钉子。」这是一种处理问题的笨方法。</p>
    </blockquote>
  </li>
</ol>

<p>书摘：</p>

<p>有些话来自芒格，有些则来自他引用的言论与典故。</p>

<p>序言：巴菲特论芒格</p>

<p>首先，要找到比你更聪明、更有智慧的人。找到他之后 ，请他别炫耀他比你高明，这样你就能够因为许多源自他的想法和建议的成就而得到赞扬。你要找到这样的合伙人，在你犯下损失惨重的错误时，他既不会事后诸葛亮，也不会生你的气。他还应该是个慷慨大方的人，会投入自己的钱并努力为你工作而不计报酬。最后，这位伙伴还会在漫漫长路结伴同游时能不断地给你带来快乐。</p>

<p>第二章 芒格的生活、学习和决策方法</p>

<p>当面临要么改变，要么证明无需这么做的选择时，绝大多数人都会忙于寻找证据。——约翰﹒肯尼斯﹒加尔布雷思</p>

<p>「我只想知道我将会死在什么地方，这样我就可以永远不去那里啦。」这是查理很喜欢的一句妙语。</p>

<p>你吸取教训的来源越广泛，而不仅仅从你自己的糟糕经验中吸取教训，你就能变得越好。</p>

<p>如果你说真话，你就不用记住你的谎言啦。</p>

<p>第三章 芒格主义：查理的即席谈话</p>

<p>我们偏向于把大量的钱投在我们不用再另作决策的地方。</p>

<p>如果你确有能力，你就会非常清楚你能力圈的边界在哪里。没有边界的能力根本不能称之为能力。（如果你问题自己是否过了能力的范围，）那这个问题本身就是答案。</p>

<p>第二讲 论基本的、普世的智慧，及其与投资管理和商业的关系</p>

<p>从个人的角度来讲，我已经养成了使用一种双轨分析的习惯。首先，理性地看，哪些因素真正控制了涉及的利益？其次，当大脑处于潜意识状态时，会自动形成哪些潜意识因素——这些潜意识因素总的来讲有用但（在具体情况下）却又常常失灵？</p>

<p>你必须弄清楚自己的优势在哪里，必须在自己的能力圈之内竞争。</p>

<p>上天并没有赐予人类在所有时刻掌握所有事情的本领。但如果人们努力在世界上寻找定错价格的赌注，上天有时会让他们找得到。聪明人在发现这样的机会之后会狠狠地下注。他们碰到好机会就下重注，其它时间则按兵不动。就是这么简单。</p>

<p>“我用一张考勤卡就能改善你最终的财务状况：这张卡片上有 20 格，所以你只能有 20 次打卡的机会——这代表你一生中所能拥有的投资次数。当你把卡打完之后，你就再也不能进行投资了。”他说，“在这样的规则之下，你才会真正慎重地考虑你做的事情，你将不得不花大笔奖金在你真正想投资的项目上。这样你的表现将会好得多。”在我看来，这个道理是极其明显的。沃伦也认为这个道理极其明显。</p>

<p>我遇到一个卖鱼钩的家伙。我问他：“天哪，你这些鱼钩居然是绿色和紫色的。鱼真的会上钩吗？”他说：“先生，我又不是卖给鱼的。”</p>

<p>如果你们必须作选择的话，要把赌注押在企业的发展前景上，而不是押在管理者的智慧上。</p>

<p>另外有一种非常简单的效应，无论是投资经理还是其他人都很少提及，那就是税收的效应。</p>

<p>年轻人在工作中应该追求什么？我有三个基本原则。同时满足这三个原则几乎是不可能的，但你应该努力去尝试：别兜售你自己不会购买的东西；别为你不尊敬和钦佩的人工作；只跟你喜欢的人同事。</p>

<p>不断地将注意力集中在同一个学科，不管这个学科是多么有趣，都会把人的思想禁锢在一个狭窄的领域之内。</p>

<p>在任何行业取得成功的第一步是对该行业产生兴趣。</p>

<p>《小红母鸡》是经典寓言，它用许多事例来说明独立自主的重要性。查理的自学建议遥遥呼应了马克.吐温的经典名言：“我从来不让上学影响我的学习。”</p>

<p>当人们听到坏消息，他们会讨厌带来消息的人。</p>

<p>当你不了解，也没有相关的才能时，不要害怕说出来。</p>

<p>有些人总是很自信地回答他们其实并不了解的问题，我不喜欢跟他们在一起。在我看来，他们就像那只乱跳舞的蜜蜂，只会把整个蜂窝搞得乱哄哄的。</p>

<p>在大多数情况下，要说服一个人，从这个人的利益出发是最有效的。</p>

<p>跨学科知识的合理组织模式应该是这样的：（1）必须完全弄清楚所有知识的原始出处；（2）必须把更基本的解释放在第一位。</p>

<p>全归因治学方法：按照这种治学方法，你必须领悟所有比你自己的学科更加基础的学科的所有重要思想。只有掌握了那些最基础的知识和原理，你们才能够清清楚楚地解释问题。而且你们要永远承认你们所用的基础知识来自哪个学科。</p>

<p>在只有铁锤的人看来，所有问题都非常像一颗钉子。</p>

<p>即使一个管理人员能够亲自更好地完成各种工作，把这些工作分散到各人手里仍然是对大家都有利的做法。</p>

<p>人们从有限的知识库存中得到错误的观念并坚持到底是非常可怕的事情。</p>

<p>要想提高销量，正常的做法是提高价格：</p>

<ol>
  <li>奢侈品：提高价格能够改善奢侈品的“炫耀”功能。例如，奢侈品提高价格之后，在某些存在炫耀心理的消费者看来，它的性能也随之改善了。此外，人们往往认为价格高等于质量好，这有时也能促进销量的增加。</li>
  <li>非奢侈品：和上面提到的第二个因素相同，消费者看到价格更高的商品，往往不是认为它卖贵了，而是认为更高的价格意味着更好的质量。这种办法对那些耐用性的工业品而言尤为适用。</li>
  <li>提高价格：把额外的利润以合法的方式用于改善产品的性能或者改善销售系统。</li>
  <li>提高价格：把额外的利润以非常或者不道理的方式来促进销售，比如说通过贿赂交易经纪人，或者其它对终端消费有害的做法——例如开放式基金的销售回扣。</li>
</ol>

<p>人类社会只有发明了发明的方法之后才能发展，同样道理，你们只有学习了学习的方法之后才能进步。</p>

<p>你们必须掌握许多知识，让它们在你的头脑中形成一个思维框架，在随后的日子里能够自动地运用它们。</p>

<p>对于复杂适应系统及人类大脑而言，如果采用逆向思考，问题往往会变得更容易解决。如果你们把问题反过来思考，你们能量就能够想得更清楚。让我现在就来使用一点逆向思考。什么会让我们在生活中失败呢？我们应该避免什么呢？有些答案很简单。例如，懒惰和言而无信会让我们在生活中失败。如果你们言而无信，那么就算有再多优点，也将无法避免悲惨的下场。所以你们应该养成言出必行的习惯。懒惰和言而无信是显然要避免的。另外一个要避免的是极端强烈的意识形态，因为它会让人们丧失理智。</p>

<p>妒忌、怨憎、仇恨和自怜都是灾难性的思想状态。过度自怜可以让人近乎偏执。偏执是最难逆转的东西之一。自怜总是会产生负面的影响，它是一种错误的思维方式。</p>

<p>如果你想要说服别人，要诉诸利益，而非诉诸理性。</p>

<p>别人的想法，是飘忽不定的。他们想着和恋人幽会，想走大运或出大名。我总是想着麻烦，我的想法是稳重的，所以当麻烦来临时，我早已做好准备。——豪斯曼</p>

<p>人类的大脑即使在有所知觉的时候，也会错误地估量它感知到的东西，因为大脑只能感知到鲜明的对比，而无法像精密的科学仪器那样以科学的单位来估算感知的变化。</p>

<p>社会心理学的重要原理：认知往往取决于情景，所以不同的情景通常会引起不同的结论，哪怕是同一个人在思考同一个问题的时候也是如此。</p>

<p>（1）如果顾问提出的专业建议对他本身特别有利，你就应该特别害怕这些建议；（2）在和顾客打交道时，学习和使用你的顾问所在行业的基础知识；（3）复核、质疑或者更换你得到的建议，除非经过客观考虑之后这些建议看起来还是合适的。</p>

<p>具体来说，祖母的规矩就是要求孩子在吃甜点之前先把他们的胡萝卜吃掉。把它应用到商界，就是要求管理人员每天强迫他们自己先完成他们不喜欢然而必要的任务，再奖励他们自己去处理那些他们喜欢的任务。</p>

<p>喜欢/热爱倾向造成的一个非常具有现实意义的后果就是，它是一种心理调节工具，促使人们：（1）忽略其热爱对象的缺点，对其百依百顺；（2）偏爱那些能够让自己联想起热爱对象的人、物品和行动；（3）为了爱而扭曲其他事实。</p>

<p>政治是正确地处理仇恨的艺术。</p>

<p>在生活中维持许多好习惯，避免或者戒除许多坏习惯，这样的生活才是明智的。</p>

<p>避免不一致性倾向——文明社会发明了许多庄严肃穆的入会仪式，这些仪式通常是公开举行的，能够让新成员更加忠心。</p>

<p>我的猜想是，这是因为人们普遍认为，说某些立场是由艳羡/妒忌促成的，是对采取那种立场的人的极大侮辱，如果那个人所持的看法是正确的，而不是错误的，那就更是如此。</p>

<p>化解过激的敌意的标准方法是，人们可以延迟自己的反应。比如，如果你觉得骂人是很好的主意，你可以留到明天再骂。</p>

<p>避免因为过去的成功而做蠢事的正确对策是：</p>

<p>（1）谨慎地审视以往的每次成功，找出这些成功里面的偶然因素，以免受这些因素误导，从而夸大了计划中的新行为取得成功的概率；
（2）看看新的行动将会遇到哪些在以往的成功经验中没有出现的危险因素。</p>

<p>要避免像哥伦比亚广播公司那样因波斯信使综合征而自食其果，正确的对策是有意识地，养成欢迎坏消息的习惯。伯克希尔有一条普遍的规矩：“有坏消息要立刻向我们汇报。只有好消息是我们可以等待的。”还有就是要保持明智和消息灵通，那就是让人们知道你有可能从别处听说坏消息，这样他们就不敢不把坏消息告诉你了。</p>

<p>未必能够依据群体的平均属性来准确地推断个体的特性。否则彼得将会犯下许多错误，就像某个在一条平均水深 18 英寸的河流中被淹死的人那样。</p>

<p>“未必要有希望才能够坚持。”能够做到这一点的人是非常可敬的。</p>

<p>这种过度高估自己的私人物品的现象在心理学里面有个名称：“禀赋效应”。人们作出决定之后 ，就会觉得自己的决定很好，甚至比没作出这种决定之前所认为的还要好。</p>

<p>被剥夺超级反应倾向</p>

<p>学会如何在其他人犯错的时候别以他们为榜样，因为很少有比这个更值得掌握的技能。</p>

<p>别只是因为一样事实或者一种观念容易得到，就觉得它更为重要。</p>

<p>人们只要勤奋就能降低不用就忘倾向的影响。如果人们能够熟练地掌握一种技能，而不是草草学来应付考试，那么这种技能将会较难以丢失，而且一旦生疏之后，只要重新学习，很快就能够被重新掌握。这些优势可不算小，聪明人在学习重要技能的过程中，如果没有做到真正精通这种技能，他是不会停下来的。</p>

<p>当消费者的活力需要供应商的活力来支持时，适当地提高价格当然是对消费者有利的。</p>

<p>和别人共事的要求是你必须把自己的想法清楚地说出来，光是这个规矩就能让你受益匪浅。</p>

<p>那些从蠢事中获益的人往往会对蠢事大加称赞，而消除蠢事会让某些人感到痛苦。</p>

<p>总体上很有用但经常误导人的心理倾向，详细讨论了每种倾向引发的错误，同时描述如何防止犯这样的错误，并进行一些总体的讨论：</p>

<p>一、奖励和惩罚
    超级反应倾向
二、喜欢/热爱倾向
三、讨厌/憎恨倾向
四、避免怀疑倾向
五、避免不一致性倾向
六、好奇心倾向
七、康德式公平倾向
八、艳羡/妒忌倾向
九、回馈倾向
十、受简单联想影响的倾向
十一、简单的、避免痛苦的心理否认
十二、自视过高的倾向
十三、过度乐观倾向
十四、被剥夺超级反应倾向
十五、社会认同倾向
十六、对比错误反应倾向
十七、压力影响倾向
十八、错误衡量易得性倾向
十九、不用就忘倾向
二十、化学物质错误影响倾向
二十一、衰老——错误影响倾向
二十二、权威——错误影响倾向
二十三、废话倾向
二十四、重视理由倾向
二十五、lollapalooza 倾向——数种心理倾向共同作用造成极端后果的倾向
书目：</p>

<p>《只有偏执狂才能生存》</p>

<p>《影响力》</p>]]></content><author><name>Junze Xu</name></author><category term="读书" /><summary type="html"><![CDATA[穷查理宝典读书笔记。]]></summary></entry><entry><title type="html">面试准备</title><link href="https://junze-xu.github.io/2020/07/12/%E9%9D%A2%E8%AF%95%E5%87%86%E5%A4%87/" rel="alternate" type="text/html" title="面试准备" /><published>2020-07-12T00:00:00+00:00</published><updated>2020-07-12T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/07/12/%E9%9D%A2%E8%AF%95%E5%87%86%E5%A4%87</id><content type="html" xml:base="https://junze-xu.github.io/2020/07/12/%E9%9D%A2%E8%AF%95%E5%87%86%E5%A4%87/"><![CDATA[<h1 id="一操作系统方面">一、操作系统方面</h1>

<p>多线程相关与线程之间同步技术,熟练使用（但不局限于）以下linux API</p>
<ul>
  <li>linux下的线程创建、等待、获取线程id
int pthread_create(pthread_t <em>thread, const pthread_attr_t *attr, void *(</em>start_routine) (void *), void *arg);
int pthread_join(pthread_t thread, void **retval);
pthread_t pthread_self(void);</li>
</ul>

<hr />

<p>常见线程之间的同步技术（何时该用那种技术）</p>
<ul>
  <li><strong>互斥体</strong>
int pthread_mutex_init(pthread_mutex_t *mutex, constpthread_mutexattr_t *mutexattr);<br />
int pthread_mutex_destroy(pthread_mutex_t *mutex);<br />
int pthread_mutex_lock(pthread_mutex_t *mutex);<br />
int pthread_mutex_trylock(pthread_mutex_t *mutex);<br />
int pthread_mutex_unlock(pthread_mutex_t *mutex);</li>
  <li><strong>信号量</strong>
int sem_init(sem_t *sem, int pshared, unsigned int  value);
int sem_destroy(sem_t *sem);
int sem_wait(sem_t *sem); 
int sem_post(sem_t *sem);
int sem_getvalue(sem_t *sem, int *valp);</li>
  <li>
    <p><strong>条件变量</strong>
int pthread_cond_init(pthread_cond_t *restrict cond, constpthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
<strong>读写/自旋锁</strong>
 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, constpthread_rwlockattr_t *restrict attr);
 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
 int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
 int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_spin_init(__pthread_spinlock_t *__lock, int  __pshared);
int pthread_spin_destroy(__pthread_spinlock_t *__lock);
int pthread_spin_trylock(__pthread_spinlock_t *__lock);
int pthread_spin_unlock(__pthread_spinlock_t *__lock);
int pthread_spin_lock(__pthread_spinlock_t *__lock);</p>
  </li>
  <li>熟悉守护进程的创建、原理</li>
  <li>了解计划作业crontab</li>
  <li>熟悉进程、线程状态查看命令（top、strace、pstack）</li>
  <li>熟悉内存状态查看命令memstat、free</li>
  <li>熟悉IO状态查看命令iostat、df、du</li>
  <li>了解linux文件的权限、用户、时间（ctime、mtime、atime）、inode等文件基本属性，熟练使用chmod、chown、chgrp等基本命令。</li>
  <li>熟悉文件传输命令scp、rz、sz命令</li>
  <li>熟悉文件定位命令find、whereis命令</li>
  <li>熟悉软链接，熟悉ln命令。</li>
  <li>熟悉lsof命令。</li>
</ul>

<h1 id="二网络">二、网络</h1>

<ul>
  <li>
    <p>熟悉tcp状态机（三次握手、四次挥手）。</p>
  </li>
  <li>
    <p>熟悉tcpdump命令。</p>
  </li>
  <li>
    <p>熟悉网络状态和防火墙状态查看命令：netstat、ifconfig、iptables</p>
  </li>
  <li>
    <p>熟悉socket API，包括但不限于（connect、accept、bind、listen、send/sendto、recv/recvfrom、select、gethostbyname）
 int connect(int  sockfd, const struct sockaddr *addr, socklen_t addrlen);
 int accept(int  sockfd, struct sockaddr *addr, socklen_t *addrlen);
 int bind(int  socket, const struct sockaddr *address, socklen_t address_len);
 int listen(int  sockfd, int  backlog);
 ssize_t send(int  sockfd, constvoid *buf, size_t len, int  flags);
 ssize_t sendto(int  sockfd, constvoid *buf, size_t len, int  flags, const struct sockaddr *dest_addr, socklen_t addrlen);
 ssize_t recv(int  sockfd, void *buf, size_t len, int  flags);
 ssize_t recvfrom(int  sockfd, void *buf, size_t len, int  flags, struct sockaddr *src_addr, socklen_t *addrlen);
 int select(int  nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
voidFD_CLR(int  fd, fd_set *set);
int   FD_ISSET(int  fd, fd_set *set);
voidFD_SET(int  fd, fd_set *set);
voidFD_ZERO(fd_set *set);
struct hostent *gethostbyname(constchar *name);</p>
  </li>
  <li>
    <p>熟悉epoll，熟悉水平触发与边缘触发。
int epoll_create(int  size);
int epoll_ctl(int  epfd, int  op, int  fd, struct epoll_event *event);
int epoll_wait(int  epfd, struct epoll_event *events, int  maxevents, int  timeout);</p>
  </li>
  <li>
    <p>熟悉阻塞socket和非阻塞socket在connect、send、recv等行为上的区别，如何将socket设置为非阻塞的。</p>
  </li>
</ul>

<h1 id="三脚本工具">三、脚本工具</h1>

<ul>
  <li>了解shell基本语法、变量操作、函数、循环/条件判断等程序结构。</li>
  <li>熟练使用文本编辑工具vi/vim。</li>
  <li>了解使用文本处理命令grep、sed、cut。</li>
  <li>了解awk命令。</li>
</ul>

<h1 id="四数据库">四、数据库</h1>

<ul>
  <li>熟悉数据表结构设计（三范式、字段属性）。</li>
  <li>了解查询优化（索引的概念与创建、sql优化）。</li>
  <li>熟悉常见的mysql API函数：
mysql_real_connect
mysql_select_db
mysql_query
mysql_store_result
mysql_free_result
mysql_num_rows
mysql_close
mysql_errno</li>
</ul>

<h1 id="五编程语言cc方面">五、编程语言:C/C++方面</h1>

<ul>
  <li>熟悉内存分布（堆、栈、静态/全局/局部变量、虚指针…）</li>
  <li>熟悉Makefile。</li>
  <li>熟悉gdb调试（断点、查看内存、执行跟踪、了解CPU主要寄存器作用…）。</li>
  <li>熟悉性能分析工具(gprof)。</li>
  <li>熟悉C-Runtime常用函数（如字符串格式化函数printf、scanf，字符串比较连接函数、内存分配函数、文件与目录操作函数等）。</li>
  <li>熟悉stl库。</li>
  <li>熟悉OO思想、常见设计模式（如单例模式、工厂设计模式、装饰者模式、Builder模式、生产者消费者模式、策略模式等）。</li>
  <li>熟悉RAII、pimpl惯用法。</li>
  <li>有一定的代码质量和重构能力。</li>
</ul>]]></content><author><name>Junze Xu</name></author><category term="Resume" /><summary type="html"><![CDATA[面试的几个方面]]></summary></entry><entry><title type="html">openssl命令行生成密钥、证书</title><link href="https://junze-xu.github.io/2020/03/29/openssl-create-certificate/" rel="alternate" type="text/html" title="openssl命令行生成密钥、证书" /><published>2020-03-29T00:00:00+00:00</published><updated>2020-03-29T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/03/29/openssl-create-certificate</id><content type="html" xml:base="https://junze-xu.github.io/2020/03/29/openssl-create-certificate/"><![CDATA[<h1 id="openssl命令行生成密钥证书">openssl命令行生成密钥、证书</h1>

<h2 id="第一步为服务器端和客户端准备公钥私钥">第一步，为服务器端和客户端准备公钥、私钥</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># 生成服务器端私钥
openssl genrsa -out server.key 1024
# 生成服务器端公钥
openssl rsa -in server.key -pubout -out server.pem
# 生成客户端私钥
openssl genrsa -out client.key 1024
# 生成客户端公钥
openssl rsa -in client.key -pubout -out client.pem
</code></pre></div></div>
<h2 id="第二步生成-ca-证书及注意事项">第二步，生成 CA 证书及注意事项</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># 生成 CA 私钥
openssl genrsa -out ca.key 1024
# X.509 Certificate Signing Request (CSR) Management.
openssl req -new -key ca.key -out ca.csr
# X.509 Certificate Data Management.
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt

</code></pre></div></div>
<p>在执行第二步时会出现：
➜  keys  openssl req -new -key ca.key -out ca.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Zhejiang
Locality Name (eg, city) []:Hangzhou
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My CA
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:
注意，这里的 Organization Name (eg, company) [Internet Widgits Pty Ltd]: 后面生成客户端和服务器端证书的时候也需要填写，不要写成一样的！！！可以随意写如：My CA, My Server, My Client。</p>

<p>然后 Common Name (e.g. server FQDN or YOUR name) []: 这一项，是最后可以访问的域名，我这里为了方便测试，写成 localhost</p>

<h2 id="第三步生成服务器端证书和客户端证书">第三步，生成服务器端证书和客户端证书</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># 服务器端需要向 CA 机构申请签名证书，在申请签名证书之前依然是创建自己的 CSR 文件
openssl req -new -key server.key -out server.csr
# 向自己的 CA 机构申请证书，签名过程需要 CA 的证书和私钥参与，最终颁发一个带有 CA 签名的证书
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
# client 端
openssl req -new -key client.key -out client.csr
# client 端到 CA 签名
openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crt
</code></pre></div></div>]]></content><author><name>Junze Xu</name></author><category term="openssl" /><summary type="html"><![CDATA[openssl命令行生成密钥、证书]]></summary></entry><entry><title type="html">openssl学习</title><link href="https://junze-xu.github.io/2020/03/29/openssl/" rel="alternate" type="text/html" title="openssl学习" /><published>2020-03-29T00:00:00+00:00</published><updated>2020-03-29T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/03/29/openssl</id><content type="html" xml:base="https://junze-xu.github.io/2020/03/29/openssl/"><![CDATA[<h1 id="openssl学习">openssl学习</h1>

<hr />

<h1 id="安全机制">安全机制：</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>加密、数字签名、访问控制、数据完整性、认证交换、流量填充、路由控制、公证
</code></pre></div></div>

<h1 id="安全服务">安全服务：</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>认证
访问控制
数据保密性
	连接保密性
	无连接保密性
	流量保密性
数据完整性
不可否认性
</code></pre></div></div>

<h1 id="设计基本原则">设计基本原则</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>使用成熟的安全系统
以小人之心度输入数据
外部系统是不安全的
最小授权
减少外部接口
缺省使用安全模式
安全不是似是而非
从STRIDE思考
在入口处检查
从管理上保护好你的系统
</code></pre></div></div>

<h1 id="安全算法">安全算法</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>常用安全技术
认证授权
安全通信
密码算法和协议：
	对称加密
	公钥加密
	单向加密
	认证协议
Linux系统：OpenSSL，gpg（pgp协议的实现）
</code></pre></div></div>

<h1 id="对称加密算法">对称加密算法</h1>

<h2 id="对称加密加密和解密使用同一个密钥">对称加密：加密和解密使用同一个密钥</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1算法公开
2秘钥不公开
A--data-加密kev-data'-解密key2-data-B
DES keyl = key2

DES:Data Encryption Standard，56bits
3DES：
AES:Advanced（128，192，256bits）
Blowfish，Twofish 
IDEA，RC6，CAST5
</code></pre></div></div>
<h2 id="特性">特性：</h2>
<p>1、加密、解密使用同一个密钥，效率高
2、将原始数据分割成固定大的块，逐个进行加密</p>

<h2 id="缺陷">缺陷：</h2>
<p>1、密钥过多
2、密钥分发
3、数据来源无法确认</p>

<h1 id="非对称加密算法">非对称加密算法</h1>

<h2 id="公钥加密密钥是成对出现">公钥加密：密钥是成对出现</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt;公钥：公开给所有人；public key
&gt;私钥：自己留存，必须保证其私密性；secret key
</code></pre></div></div>

<h2 id="特点">特点：</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>用公钥加密数据，只能使用与之配对的私钥解密；反之亦然 ## 功能： ``` &gt;数字签名：主要在于让接收方确认发送方身份 &gt;对称密钥交换：发送方用对方的公钥加密一个对称密钥后发送给对方 &gt;数据加密：适合加密较小数音 ```
</code></pre></div></div>

<h2 id="缺点">缺点：</h2>
<p>密钥长，加密解密效率低</p>

<h2 id="算法">算法：</h2>
<p>RSA（加密，数字签名），DSA（数字签名），ELGamal</p>

<p>Pb{Sa(data)}
Pb{data+Sa {hash(data)}}
hash(data)
Pa(Sa {hash(data)})
key{data+Sa (hash(data))}+Pb(key)</p>

<h1 id="密钥交换">密钥交换</h1>

<h2 id="密钥交换ikeinternet-key-exchange">密钥交换：IKE（Internet Key Exchange）</h2>
<p>公钥加密：
DH（Deffie-Hellman）：生成会话密钥，参看：
https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange</p>

<h2 id="dh">DH：</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1、A:a.p协商生成公开的整数a，大素数p B:a，p
2、A：生成隐私数据x区p），计算得出a~×%p，发送给B 
   B：生成隐私数据y，计算得出-a~y%p，发送给A
3、A：计算得出[（a~y%p）~x]%p=a~xy%p，生成为密钥
   B：计算得出[（a~×%p）~y]%p=a~xy%p，生成为密钥
   
   a=2,p=11
   A：x=3
   B: y=4
   2^3=8%11=8
   2^4=16%11=5
   [5^3]%11=4
   [8^4]%11=4
</code></pre></div></div>

<h1 id="使用gpg实现对称加密">使用gpg实现对称加密</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>对称加密file文件
	gpg-c file
	Is file.gpg
在另一台主机上解密file
	gpg-o file-d file.gpg
</code></pre></div></div>

<h1 id="使用gpg工具实现公钥加密">使用gpg工具实现公钥加密</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>在hostB主机上用公钥加密，在hostA主机上解密
在hostA主机上生成公钥/私钥对
	gpg --gen-key
在hostA主机上查看公钥
	gpg --list-keys
在hostA主机上导出公钥到wang.pubkey
	gpg -a --export -o wang.pubkey  (-a以一定格式)
从hostA主机上复制公钥文件到需加密的B主机上
	scp wang.pubkey hostB
	
在需加密数据的hostB主机上生成公钥/私钥对
	gpg --list-keys 
	gpg --gen-key
在hostB主机上导入公钥
	gpg --import wang.pubkey 
	gpg --list-keys
用从hostA主机导入的公钥，加密hostB主机的文件file，生成file.9pg 工再数音
	gpg -e -r wangxiaochun file
	file file.gpg
	
复制加密文件到hostA主机
	scp fstab.gpg hostA：
在hostA主机解密文件
	gpg -d file.gpg
	gpg -o file -d file.gpg
删除公钥和私钥
	gpg- -delete-keys wangxiaochun
 gpg--delete-secret-keys wangxiaochun
</code></pre></div></div>
<h1 id="ab非对称加密关键问题拿到的是否是对方的公钥">A、B非对称加密关键问题，拿到的是否是对方的公钥</h1>
<p>是否有第三方C搞了一把错误的公钥给A，这时候A不但解不开B的数据，
C如果获取还可以解开</p>

<h1 id="ca和证书">CA和证书</h1>

<h2 id="pkipublic-key-infrastructure">PKI:Public Key Infrastructure</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>签证机构：CA（Certificate Authority）
注册机构：RA
证书吊销列表：CRL
证书存取库：
</code></pre></div></div>
<h2 id="x509定义了证书的结构以及认证协议标准">X.509：定义了证书的结构以及认证协议标准</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>版本号
主体公钥
序列号
CRL分发点
签名算法
扩展信息
颁发者
发行者签名
有效期限
主体名称
</code></pre></div></div>

<h1 id="证书获取">证书获取</h1>
<h2 id="证书类型">证书类型:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>证书授权机构的证书
服务器
用户证书
</code></pre></div></div>

<h2 id="获取证书两种方法">获取证书两种方法：·</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>使用证书授权机构
	生成签名请求（csr）
	将csr发送给CA
	从CA处接收签名
自签名的证书
	自已签发自己的公钥
</code></pre></div></div>

<h1 id="安全协议">安全协议</h1>

<h2 id="sslsecure-socket-layer">SSL:Secure Socket Layer</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	TLS:Transport Layer Security
		1995：SSL 2.0 Netscape
		1996：SSL3.01999：TLS 1.0
		2006：TLS 1.1IETF（Internet工程任务组）RFC 4346
		2008：TLS 1.2当前使用
		2015：TLS 1.3
	功能：机密性，认证，完整性，重放保护
</code></pre></div></div>
<h2 id="两阶段协议分为握手阶段和应用阶段">两阶段协议，分为握手阶段和应用阶段</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	握手阶段（协商阶段）：客户端和服务器端认证对方身份（依赖于PKI体系，利用数字证书进行身份认证），并协商通信中使用的安全参数、密码套件以及主密钥。后续通信使用的所有密钥都是通过MasterSecret生成。
	应用阶段：在握手阶段完成后进入，在应用阶段通信双方使用握手阶段协商好的密钥进行安全通信
</code></pre></div></div>

<h2 id="handshake协议">Handshake协议：</h2>
<p>包括协商安全参数和密码套件、服务器身份认证（客户端身份认证可选）、密钥交换</p>
<h2 id="changecipherspec-协议">ChangeCipherSpec 协议：</h2>
<p>一条消息表明握手协议已经完成</p>
<h2 id="alert协议">Alert协议：</h2>
<p>对握手协议中一些异常的错误提醒，分为fatal和warning两个级别，fatal类型错误会直接中断SSL链接，而warning级别的错误SSL链接仍可继续，只是会给出错误警告</p>
<h2 id="record-协议">Record 协议：</h2>
<p>包括对消息的分段、压缩、消息认证和完整性保护、加密等</p>
<h2 id="https协议">HTTPS协议：</h2>
<p>就是“HTTP协议”和“SSL/TLS协议”的组合。HTTP over-SSL”或“HTTP over TLS”，对http协议的文本数据进行加密处理后，成为<strong>二进制</strong>形式传输</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ethernet(ip(tcp(tls(app(data)))))
ethernet(ip(tcp(tls(app(data)))))

https://www.taobao.com
（CA私钥签名的公钥）Sca（Ptaobao）+有效期+CA+算法
CA公钥一般都是在电脑里面了 Ptaobao （得到公钥）

客户端生成sessionkey 用公钥加密， 服务端私钥解密
sessionkey（data）会话秘钥定期会更换
</code></pre></div></div>

<h1 id="openssl开源项目">OpenSSL：开源项目</h1>
<h2 id="三个组件">三个组件：</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>		openssl：多用途的命令行工具，包openssl libcrypto：
		加密算法库，包openssl-libs libssl：
		加密模块应用库，实现了ssl及tls，包nss sopenssl命令：
</code></pre></div></div>
<h2 id="两种运行模式">两种运行模式：</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>		交互模式和批处理模式
		openssl version：程序版本号
		标准命令、消息摘要命令、加密命令
		标准命令：
			enc，ca，req，…
</code></pre></div></div>

<h1 id="openssl命令">Openssl命令</h1>
<h2 id="对称加密">对称加密：</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	工具：openssl enc，9pg
	算法：3des，aes，blowfish，twofish
</code></pre></div></div>
<h2 id="enc命令">enc命令：</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>帮助：man enc
加密：
openssl enc -e -des3 -a -salt -in testfile -out tesfile.cipher
解密：
openssl enc -d -des3 -a -salt -in testfile.cipher -out testfile 
</code></pre></div></div>

<h2 id="单向加密">单向加密：</h2>
<p>工具：md5sum，sha1sum，sha224sum，sha256sum..
openssl dgst</p>
<h2 id="dgst命令">dgst命令</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>帮助：man dgst 
openssl dgst-md5[-hex默认]/PATH/SOMEFILE 
openssl dgst-md5 testfile md5sum/PATH/TO/SOMEFILE ## MAC:Message.Authentication Code 单向加密的一种延伸应用，用于实现网络通信中保证所传输数据的完整性机制
CBC-MAC 
HMAC：使用md5或sha1算法
</code></pre></div></div>

<h2 id="生成用户密码">生成用户密码：</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>passwd命令：
帮助：man sslpasswd 
openssl passwd-1-salt SALT（最多8位）
openssl passwd-1-salt centos ## 生成随机数：
帮助：man sslrand 
openssl rand -base64| -hex NUM 
NUM：表示字节数；-hex时，每个字符为十六进制，相当于4位二进制，出现的字符数为NUM*2
</code></pre></div></div>

<h2 id="公钥加密">公钥加密：</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>算法：RSA，ELGamal
工具：gpg.openssl rsautl（man rsautl） ## 数字签名：
算法：RSA，DSA，ELGamal ## 密钥交换：
算法：dh 
DSA:Digital Signature，Algorithm 
DSS:Digital Signature Standard 
RSA
</code></pre></div></div>

<p>#生成公钥私钥</p>

<h2 id="生成密钥对儿">生成密钥对儿：</h2>
<p>man genrsa</p>
<h2 id="生成私钥">生成私钥</h2>
<p>openssl genrsa -out /PATH/TO/PRIVATEKEY.FILE NUM_BITS
（umask 077；openssl genrsa -out test.key -des 2048）(私钥太危险，使用对称密钥加密一下)</p>

<h2 id="从私钥中提取出公钥">从私钥中提取出公钥</h2>
<p>openssl rsa -in PRIVATEKEYFILE -pubout -out PUBLICKEYFILE 
openssl rsa -in test.key -pubout -out test.key.pub</p>
<h2 id="随机数生成器伪随机数字">随机数生成器：伪随机数字</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>键盘和鼠标
块设备中断
/dev/random：仅从熵池返回随机数；随机数用尽，阻塞
/dev/urandom：从熵池返回随机数；随机数用尽，会利用软件生成伪随机数，非阻塞
</code></pre></div></div>

<h2 id="pkipublic-key-infrastructure-1">PKI:Public Key Infrastructure</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>CA
RA 
CRL
证书存取库 ## 建立私有CA：
OpenCA
openssl ## 证书申请及签署步骤：
1、生成申请请求
2、RA核验
3、CA签署
4、获取证书
</code></pre></div></div>

<h1 id="创建私有ca">创建私有CA：</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	openssl的配置文件：/etc/pki/tls/openssl.cnf
	三种策略：匹配、支持和可选
	匹配指要求申请填写的信息跟CA设置信息必须一致，支持指必须填写这项申请信息，可选指可有可无
</code></pre></div></div>
<h2 id="1创建所需要的文件">1、创建所需要的文件</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	touch /etc/pki/CA/index.txt 生成证书索引数据库文件
	echo 01&gt;/etc/pki/CA/serial 指定第一个颁发证书的序列号
</code></pre></div></div>
<h2 id="2ca自签证书">2、CA自签证书</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	生成私钥cd/etc/pki/CA/
	（umask 066；openssl genrsa -out /etc/pki/CA/private/cakey.pem 2048）
	
	生成自签名证书
	openssl req -new -×509 -key 
	/etc/pki/CA/private/cakey.pem -days 7300 -out
	/etc/pki/CA/cacert.pem
		-new：生成新证书签署请求
		-×509：专用于CA生成自签证书
		-key：生成请求时用到的私钥文件
		-days n：证书的有效期限
		-out /PATH/TO/SOMECERTFILE：证书的保存路径
</code></pre></div></div>
<h2 id="3颁发证书">3、颁发证书</h2>
<h3 id="在需要使用证书的主机生成证书请求">在需要使用证书的主机生成证书请求</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>给web服务器生成私钥
（umask 066；openssl genrsa-out /etc/pki/tls/private/test.key 2048）
生成证书申请文件
openssl req-new-key/etc/pki/tls/private/test.key -days 365 -out etc/pki/tls/test.csr ### 将证书请求文件传输给CA ### CA签署证书，并将证书颁发给请求者
openssl ca -in /tmp/test.csr -out /etc/pki/CA/certs/test.crt -days 365
注意：默认国家，省，公司名称三项必须和CA一致
</code></pre></div></div>

<h3 id="查看证书中的信息">查看证书中的信息：</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl ×509 -in /PATH/FROMWCERT_FILE-noout
-text|issuer|subject|serial|dates 
openssl ca -status SERIAL 查看指定编号的证书状态 ## 4、吊销证书 ### 在客户端获取要吊销的证书的serial 
openssl ×509 -in /PATH/FROM/CERT_FILE -noout -serial -subject ### 对比检验客户提交的serial与subject信息是否与index.txt文件中的信息一致
在CA上，根据客户提交的serial与subject信息，对比检验是否与index.txt文件中的信息一致，吊销证书：
openssl ca -revoke /etc/pki/CA/newcerts/SERIAL.pem
</code></pre></div></div>

<h3 id="指定第一个吊销证书的编号">指定第一个吊销证书的编号</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>注意：第一次更新证书吊销列表前，才需要执行
echo 01 &gt; /etc/pki/CA/crlnumber ### 更新证书吊销列表
openssl ca -gencrl -out /etc/pki/CA/crl/crl.pem
查看cr文件：
openssl crl -in /etc/pki/CA/crl/crl.pem -noout -text
</code></pre></div></div>]]></content><author><name>Junze Xu</name></author><category term="openssl" /><summary type="html"><![CDATA[openssl学习]]></summary></entry><entry><title type="html">如何选择一个开源项目</title><link href="https://junze-xu.github.io/2020/02/23/how-to-choose-opensource-project/" rel="alternate" type="text/html" title="如何选择一个开源项目" /><published>2020-02-23T00:00:00+00:00</published><updated>2020-02-23T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/02/23/how-to-choose-opensource-project</id><content type="html" xml:base="https://junze-xu.github.io/2020/02/23/how-to-choose-opensource-project/"><![CDATA[<h1 id="选如何选择一个开源项目">选：如何选择一个开源项目？</h1>

<h2 id="聚焦是否满足业务">聚焦是否满足业务？</h2>

<p>简单来说：如果你的业务要求1000 TPS，那么一个20000 TPS 和50000 TPS的方案是没有区别的。有的人可能会担心我TPS不断上涨怎么办？其实不用担心，我们的架构会不断演进的，等到真的需要这么高的时候我们再来架构重构，记住：不要过早优化，过早优化是万恶之源 —— 《UNIX编程哲学》</p>

<h2 id="聚焦是否成熟">聚焦是否成熟？</h2>

<p>可以从以下几个方面考察是否成熟：</p>

<ul>
  <li>1）版本号：一般建议除非特殊情况，否则不要选0.X版本的，至少选1.X版本的，版本号越高越好。</li>
  <li>2）使用的公司数量：一般开源项目都会把采用了自己项目的公司列在主页上，公司越大越好，数量越多越好</li>
  <li>3）社区活跃度：看看社区是否活跃，发帖数、回复数、问题处理速度等</li>
</ul>

<h2 id="聚焦运维能力">聚焦运维能力？</h2>

<p>可以从以下几个方案去考察运维能力：</p>

<ul>
  <li>1）开源方案<strong>日志</strong>是否齐全：有的开源方案日志只有寥寥启动停止几行，出了问题根本无法排查</li>
  <li>2）开源方案是否有<strong>命令行</strong>、管理控制台等维护工具，能够看到系统运行时的情况</li>
  <li>3）开源方案是否有<strong>故障检测和恢复的能力</strong>，例如告警、倒换等</li>
</ul>

<p>案例2：很多团队最初使用MySQL的时候，也没有怎么研究过，经常有业务部门抱怨MySQL太慢了，其实经过定位，发现最关键的几个参数（例如innodb_buffer_pool_size, sync_binlog，innodb_log_file_size等）都没有配置或者配置错误，性能当然会慢。</p>

<h1 id="用如何使用开源方案">用：如何使用开源方案？</h1>

<h2 id="深入研究仔细测试">深入研究，仔细测试</h2>

<p>可以从如下几方面进行研究和测试：</p>

<ul>
  <li>1）通读开源项目的设计文档或者白皮书，了解其设计原理</li>
  <li>2）核对每个配置项的作用和影响，识别出关键配置项</li>
  <li>3）进行多种场景的性能测试</li>
  <li>4）进行压力测试，连续跑几天，观察cpu、内存、磁盘io等指标波动</li>
  <li>5）进行故障测试：kill，断电、拔网线、重启100次以上、倒换等</li>
</ul>

<p>如果我们在商业项目中采用了一些开源项目，前提是自己一定是理解其原理，完全掌握了才建议在商业项目使用，一些UI类的开源控件还好，尤其是对于一些框架类的开源项目，如网络请求库、ORM框架、各种图片加载库、依赖注入框架等等，不求你掌握他具体实现的每个细节，但是一定要理解其原理，并且熟练掌握他的各种API，再考虑运用到公司的项目中。</p>

<h2 id="小心应用灰度发布">小心应用，灰度发布</h2>

<p>假如我们做了上面的“深入研究、仔细测试”，发现没什么问题，是否就可以放心大胆的应用到线上了呢？别高兴太早，即使你的研究再深入，测试再仔细，也还是要小心为妙，因为再怎么深入的研究，再怎么仔细的测试，都只能降低风险，但不可能完全覆盖所有线上场景。</p>

<p>但是，不管研究多深入、测试多仔细、自信心多爆棚，时刻对线上要有敬畏之心，小心驶的万年船。我们的经验就是先在非核心的业务上用，然后有经验后慢慢扩展。</p>

<h2 id="做好应急以防万一">做好应急，以防万一</h2>
<p>虽然因为一次故障就完全反对尝试是有点反应过度了，但确实故障也给我们提了一个醒：对于重要的业务或者数据，使用开源项目时，最好有另外一个比较成熟的方案做备份，尤其是数据存储。例如：如果要用MongoDB或者Redis，可以用MySQL做备份存储。这样做虽然复杂度和成本高一些，但关键时刻能够救命！
一旦他出问题了，或者说他突然宣布某一天不开源了，那你要崩溃了，替换的代价几乎可以重写了。所以建议大家使用那种专注的开源框架，如只做网络库的，只做图片处理的，而这种大多都有替代品，一旦他出事，你还有其他别的选择。</p>

<h1 id="改如何基于开源项目做二次开发">改：如何基于开源项目做二次开发？</h1>

<h2 id="保持纯洁加以包装">保持纯洁，加以包装</h2>
<p>我们的建议是不要改动原系统，而是要开发辅助系统: 监控，报警，负载均衡，管理等。以Redis为例，如果我们想增加集群功能，不要去改动Redis本身的实现，而是增加一个proxy层来实现，Twitter的Twemproxy就是这样做的，而Redis到了3.0后本身提供了集群功能，原有的方案简单切换到Redis 3.0即可。</p>

<p>如果实在想改到原有系统，怎么办呢？我们的建议是直接给开源项目提需求或者bug，但弊端就是响应比较缓慢，这个就要看业务紧急程度了，如果实在太急那就只能自己改了，不过不是太急，建议做好备份或者应急手段即可。</p>

<p>在使用一些开源项目的时候，不可能永远满足我们自己的需求，我们一般都会在其基础上定制些我们自己的业务需求，这个时候建议大家不要改源码，而是在自己的项目里对引用的开源框架进行扩展，如果他不可扩展或者说扩展起来很麻烦，只能说他的设计还不够好。
为什么不建议大家改源码？因为好的开源项目一般会持续维护与更新，而一旦我们更改源码，这意味着以后我们想要更新版本变得很麻烦。所以，不是特别必要，都强烈建议大家不要改源码。</p>

<p>计算机史上有个万能的解决方案就是，如果原有层面解决不了问题，那么就请再加一层！对于开源项目，我们知道有些库设计的确实很棒，使用者调用起来非常方便，一行代码直接搞定，拿图片加载库 Picasso 举个例子：Picasso.with(context).load(imageUrl).into(imageView);
使用起来是不是特简单？你也许问我，都封装的这么好了还用得着再封装一层么？那你错了，哪怕他已经很完美了，都要这样做：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>public class ImageLoader 
{
    public static void with(Context context, String imageUrl, ImageView imageView) 
    {
        Picasso.with(context).load(imageUrl).into(imageView); 
    }
}
</code></pre></div></div>
<p>这样我所有项目调用的方式直接就是 ImageLoader.with() ，这样做的好处是：</p>
<ul>
  <li>入口统一，所有图片加载都在这一个地方管理，一目了然，即使有什么改动我也只需要改这一个类就可以了。</li>
  <li>随着你们业务的需求，发现 Picasso 这个图片加载库已经满足不了你们了，你们需要换成 Fresco ，如果你没有封装一层的话，想要替换这个库那你要崩溃了，要把所有调用 Picasso 的地方都改一遍，而如果你中间封装了一层，那真的非常轻松，三天两头的换一次也没问题。
这就是所谓的外部表现一致，内部灵活处理原则。</li>
</ul>

<table>
  <thead>
    <tr>
      <th>选开源项目</th>
      <th>是否</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>是否满足业务</td>
      <td> </td>
    </tr>
    <tr>
      <td>版本号</td>
      <td> </td>
    </tr>
    <tr>
      <td>使用的公司数量</td>
      <td> </td>
    </tr>
    <tr>
      <td>社区活跃度</td>
      <td> </td>
    </tr>
    <tr>
      <td>日志</td>
      <td> </td>
    </tr>
    <tr>
      <td>故障检测和恢复的能力</td>
      <td> </td>
    </tr>
  </tbody>
</table>

<table>
  <thead>
    <tr>
      <th>用开源项目</th>
      <th>是否</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>读开源项目的设计文档或者白皮书，了解其设计原理</td>
      <td> </td>
    </tr>
    <tr>
      <td>配置项的作用和影响，识别出关键配置项</td>
      <td> </td>
    </tr>
    <tr>
      <td>读开源项目的设计文档或者白皮书，了解其设计原理</td>
      <td> </td>
    </tr>
    <tr>
      <td>性能测试</td>
      <td> </td>
    </tr>
    <tr>
      <td>压力测试，连续跑几天，观察cpu、内存、磁盘io等指标波动</td>
      <td> </td>
    </tr>
    <tr>
      <td>故障测试</td>
      <td> </td>
    </tr>
  </tbody>
</table>

<table>
  <thead>
    <tr>
      <th>改开源项目</th>
      <th>是否</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>是否易封装</td>
      <td> </td>
    </tr>
  </tbody>
</table>

<h1 id="举例">举例</h1>
<p>我们目前的项目中要嵌入一个日志系统，首要选择的就是在Linux平台下，C/C++开发，方便集成到项目中的，学习成本比较低的开源库</p>

<p>首先从一些优秀的开源项目中查看有哪些优秀的日志系统</p>
<ul>
  <li><a href="http://fffaraz.github.io/awesome-cpp/">Awesome C++</a>
    <h2 id="logging">Logging</h2>
  </li>
  <li><a href="https://github.com/3Hren/blackhole">Blackhole</a> - Attribute-based logging framework, which is designed to be fast, modular and highly customizable. [MIT]</li>
  <li><a href="http://www.boost.org/doc/libs/1_56_0/libs/log/doc/html/index.html">Boost.Log</a> - Designed to be very modular and extensible. [Boost]</li>
  <li><a href="https://github.com/easylogging/easyloggingpp">Easylogging++</a> - Extremely light-weight high performance logging library for C++11 (or higher) applications. [MIT] <a href="https://muflihun.github.io/easyloggingpp">website</a></li>
  <li><a href="https://github.com/KjellKod/g3log">G3log</a> - Asynchronous logger with Dynamic Sinks. [PublicDomain]</li>
  <li><a href="https://github.com/google/glog">glog</a> - C++ implementation of the Google logging module.</li>
  <li><a href="http://log4cpp.sourceforge.net/">Log4cpp</a> - A library of C++ classes for flexible logging to files, syslog, IDSA and other destinations. [LGPL]</li>
  <li><a href="https://github.com/log4cplus/log4cplus">log4cplus</a> - A simple to use C++ logging API providing thread-safe, flexible, and arbitrarily granular control over log management and configuration. [BSD &amp; Apache2]</li>
  <li><a href="https://github.com/emilk/loguru">loguru</a> - A lightweight C++ logging library. [PublicDomain]</li>
  <li><a href="https://github.com/SergiusTheBest/plog">plog</a> - Portable and simple log for C++ in less than 1000 lines of code. [MPL2]</li>
  <li><a href="https://github.com/mattiasflodin/reckless">reckless</a> - Low-latency, high-throughput, asynchronous logging library for C++. [MIT]</li>
  <li><a href="https://github.com/gabime/spdlog">spdlog</a> - Super fast, header only, C++ logging library.</li>
  <li><a href="http://www.templog.org/">templog</a> - A very small and lightweight C++ library which you can use to add logging to your C++ applications. [Boost]</li>
  <li><a href="http://baical.net/p7.html">P7Baical</a> - An open source and cross-platform library for high-speed sending telemetry &amp; trace data  with minimal usage of CPU and memory. [LGPL]</li>
</ul>

<h2 id="如何选择开源许可证">如何选择开源许可证</h2>

<p><img src="https://personal-website-1251812117.cos.ap-beijing.myqcloud.com/如何选择开源许可证？.png" alt="如何选择开源许可证" /></p>

<p><a href="http://choosealicense.com/licenses/apache/">Apache</a>一个较宽松且简明地指出了专利授权的协议。</p>

<ul>
  <li><strong>商业软件可以使用，也可以修改使用Apache协议的代码。</strong></li>
</ul>

<p><a href="http://choosealicense.com/licenses/gpl-v2/">GPL</a>此协议是应用最为广泛的开源协议，拥有较强的版权自由( copyleft )要求。衍生代码的分发需开源并且也要遵守此协议。此协议有许多变种，不同变种的要求略有不同。</p>

<ul>
  <li><strong>商业软件不能使用GPL协议的代码。</strong></li>
</ul>

<p><a href="http://choosealicense.com/licenses/mit/">MIT</a>宽松简单且精要的一个协议。在适当标明来源及免责的情况下，它允许你对代码进行任何形式的使用。</p>

<ul>
  <li><strong>商业软件可以使用，也可以修改MIT协议的代码，甚至可以出售MIT协议的代码。</strong></li>
</ul>

<p><a href="http://choosealicense.com/licenses/artistic/">Artistic</a> Perl 区尤为钟爱此协议。要求更改后的软件不能影响原软件的使用。</p>

<p><a href="http://choosealicense.com/licenses/bsd/">BSD</a>较为宽松的协议，包含两个变种<a href="http://choosealicense.com/licenses/bsd">BSD 2-Clause</a> 和<a href="http://choosealicense.com/licenses/bsd-3-clause">BSD 3-Clause</a>，两者都与MIT协议只存在细微差异。</p>

<ul>
  <li><strong>商业软件可以使用，也可以修改使用BSD协议的代码。</strong></li>
</ul>

<p><a href="http://choosealicense.com/licenses/eclipse/">Eclipse</a>对商用非常友好的一种协议，可以用于软件的商业授权。包含对专利的优雅授权，并且也可以对相关代码应用商业协议。</p>

<p><a href="http://choosealicense.com/licenses/lgpl-v2.1/">LGPL</a>主要用于一些代码库。衍生代码可以以此协议发布（言下之意你可以用其他协议），但与此协议相关的代码必需遵循此协议。</p>

<ul>
  <li><strong>商业软件可以使用，但不能修改LGPL协议的代码。</strong></li>
</ul>

<p><a href="http://choosealicense.com/licenses/mozilla/">Mozilla</a>  Mozilla Public License(MPL 2.0)是由Mozilla基金创建维护的。此协议旨在较为宽松的BSD协议和更加互惠的GPL协议中寻找一个折衷点。</p>

<ul>
  <li><strong>商业软件可以使用，也可以修改MPL协议的代码，但修改后的代码版权归软件的发起者。</strong></li>
</ul>

<p><a href="http://choosealicense.com/licenses/no-license/">No license</a>你保留所有权利，不允许他人分发，复制或者创造衍生物。当你将代码发表在一些网站上时需要遵守该网站的协议，此协议可能包含了一些对你劳动成果的授权许可。比如你将代码发布到GitHub，那么你就必需同意别人可以查看和 Fork你的代码。</p>

<p><a href="http://choosealicense.com/licenses/unlicense/">Public domain dedication</a>在许多国家，默认版权归作者自动拥有，所以<a href="http://unlicense.org/">Unlicense</a>协议提供了一种通用的模板，此协议表明你放弃版权，将劳动成果无私贡献出来。你将丧失对作品的全部权利，包括在MIT/X11中定义的无担保权利。</p>

<ul>
  <li><strong>商业软件可以使用，但不能修改LGPL协议的代码。</strong></li>
</ul>

<h2 id="初步筛选出来的日志系统">初步筛选出来的日志系统</h2>
<p><a href="http://baical.net/p7.html">http://baical.net/p7.html</a>
<a href="http://log4cpp.sourceforge.net/">http://log4cpp.sourceforge.net/</a>
<a href="https://github.com/amrayn/easyloggingpp">https://github.com/amrayn/easyloggingpp</a>
<a href="https://github.com/google/glog">https://github.com/google/glog</a>
<a href="https://github.com/gabime/spdlog">https://github.com/gabime/spdlog</a>
首先这些项目的社区较好，对于后期出现问题排查可能会好一些。另外就是用的人还比较多。有自己单独的网站，文档方面也较全，学习起来会好一些。</p>

<h2 id="进一步筛选">进一步筛选</h2>

<h1 id="参考">参考</h1>
<ul>
  <li>
    <p><a href="https://mp.weixin.qq.com/s/IWE5LBYzsUZL5YL8xP_mKA">使用开源项目的正确姿势，都是血和泪的总结！</a></p>
  </li>
  <li>
    <p><a href="https://www.cnblogs.com/tc310/p/11053072.html">如何正确使用开源项目?</a></p>
  </li>
  <li>
    <p><a href="https://wenku.baidu.com/view/70df4f7402768e9951e738dc.html">各种开源协议说明</a></p>
  </li>
  <li>
    <p><a href="https://blog.csdn.net/xiaoxiao133/article/details/83049959">GPL协议，LGPL协议，MPL协议</a></p>
  </li>
  <li>
    <p><a href="http://www.ruanyifeng.com/blog/2011/05/how_to_choose_free_software_licenses.html">如何选择开源许可证？</a></p>
  </li>
</ul>]]></content><author><name>Junze Xu</name></author><category term="Blog" /><summary type="html"><![CDATA[如何选择一个开源项目]]></summary></entry><entry><title type="html">1.2 Linux文件及目录管理</title><link href="https://junze-xu.github.io/2020/02/18/02_file_manage/" rel="alternate" type="text/html" title="1.2 Linux文件及目录管理" /><published>2020-02-18T00:00:00+00:00</published><updated>2020-02-18T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/02/18/02_file_manage</id><content type="html" xml:base="https://junze-xu.github.io/2020/02/18/02_file_manage/"><![CDATA[<h1 id="文件及目录管理">文件及目录管理</h1>

<h2 id="概述">概述</h2>
<p>文件管理不外乎文件或目录的创建、删除、查询、移动，有mkdir/rm/mv</p>

<p>文件查询是重点，用find来进行查询；find的参数丰富，也非常强大；</p>

<p>查看文件内容是个大的话题，文本的处理有太多的工具供我们使用，在本章中只是点到即止，后面会有专门的一章来介绍文本的处理工具；</p>

<h2 id="创建和删除">创建和删除</h2>
<ul>
  <li>创建：mkdir</li>
  <li>删除：rm</li>
  <li>删除非空目录：rm -rf file目录</li>
  <li>删除日志  rm *log    (等价: $find ./ -name “*log” -exec rm {} \;)</li>
  <li>移动：mv</li>
  <li>复制：cp   (复制目录：cp -r )
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//查看当前目录下文件个数
$find ./ | wc -l
//复制目录
$cp -r source_dir  dest_dir
</code></pre></div>    </div>
  </li>
</ul>

<h2 id="目录切换">目录切换:</h2>
<ul>
  <li>找到文件/目录位置：cd</li>
  <li>切换到上一个工作目录：cd -</li>
  <li>切换到home目录：cd ~</li>
  <li>显示当前路径:  pwd</li>
  <li>更改当前工作路径为path: $cd path</li>
</ul>

<h2 id="列出目录项">列出目录项</h2>

<ul>
  <li>显示当前目录下的文件 ls</li>
  <li>按时间排序，以列表的方式显示目录项 ls -lrt</li>
</ul>

<p>以上这个命令用到的频率如此之高，以至于我们需要为它建立一个快捷命令方式:</p>

<p>在.bashrc 中设置命令别名::</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>alias lsl='ls -lrt'
alias lm='ls -al|more'
</code></pre></div></div>

<p>这样，使用lsl，就可以显示目录中的文件按照修改时间排序；以列表方式显示；</p>

<ul>
  <li>
    <p>给每项文件前面增加一个id编号(看上去更加整洁)::</p>

    <blockquote>
      <p>ls | cat -n
   1  a
   2  a.out
   3  app
   4  b
   5  bin
   6  config</p>
    </blockquote>
  </li>
</ul>

<p>注：.bashrc 在/home/你的用户名/ 文件夹下，以隐藏文件的方式存储；可使用 ls -a 查看；</p>

<h2 id="查找目录及文件-findlocate">查找目录及文件 find/locate</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//搜寻文件或目录:
$find ./ -name "core*" | xargs file

//查找目标文件夹中是否有obj文件:
$find ./ -name '*.o'

//递归当前目录及子目录删除所有.o文件:
$find ./ -name "*.o" -exec rm {} \;

//find是实时查找，如果需要更快的查询，可试试locate；locate会为文件系统建立索引数据库，如果有文件更新，需要定期执行更新命令来更新索引库:
$updatedb

//寻找包含有string的路径:
$locate string

//与find不同，locate并不是实时查找。你需要更新数据库，以获得最新的文件索引信息。
</code></pre></div></div>

<h2 id="查看文件内容">查看文件内容</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//查看文件：cat vi head tail more

//显示时同时显示行号:
$cat -n       
          
//按页显示列表内容:
$ls -al | more
 
//只看前10行:
$head - 10 **           

//显示文件第一行:
$head -1 filename       

//显示文件倒数第五行:
$tail -5 filename       

//查看两个文件间的差别:
$diff file1 file2       

//动态显示文本最新信息:
$tail -f crawler.log
</code></pre></div></div>
<h2 id="查找文件内容">查找文件内容</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//使用grep、egrep查询文件内容:

egrep '03.1\/CO\/AE' TSF_STAT_111130.log.012
egrep 'A_LMCA777:C' TSF_STAT_111130.log.035 &gt; co.out2
</code></pre></div></div>
<h2 id="文件与目录权限修改">文件与目录权限修改</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- 改变文件的拥有者   chown
- 改变文件读、写、执行等属性   chmod
- 递归子目录修改： chown -R tuxapp source/
- 增加脚本可执行权限： chmod a+x  myscript
</code></pre></div></div>
<h2 id="给文件增加别名">给文件增加别名</h2>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//创建符号链接/硬链接:

ln cc ccAgain :硬连接；删除一个，将仍能找到；

ln -s cc ccTo :符号链接(软链接)；删除源，另一个无法使用；（后面一个ccTo 为新建的文件）
</code></pre></div></div>
<h2 id="管道和重定向">管道和重定向</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- 批处理命令连接执行，使用 |
- 串联: 使用分号 ;
- 前面成功，则执行后面一条，否则，不执行:&amp;&amp;
- 前面失败，则后一条执行: ||

ls /proc &amp;&amp; echo suss! || echo failed.(这个有点像编程语言中的短路，前面失败后面就不执行，与)

//能够提示命名是否执行成功or失败；

//与上述相同效果的是:

if ls /proc; 
then echo suss; 
else echo fail; 
fi

//重定向:
ls  proc/*.c &gt; list 2&gt; &amp;l 将标准输出和标准错误重定向到同一文件；

//等价的是:
ls  proc/*.c &amp;&gt; list

//清空文件:
 :&gt; a.txt

//重定向(追加): 
echo aa &gt;&gt; a.txt
</code></pre></div></div>

<h2 id="设置环境变量">设置环境变量</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>启动帐号后自动执行的文件为 .profile，然后通过这个文件可设置自己的环境变量；

安装的软件路径一般需要加入到path中::
    PATH=$APPDIR:/opt/app/soft/bin:$PATH:/usr/local/bin:$TUXDIR/bin:$ORACLE_HOME/bin;export PATH

</code></pre></div></div>
<h2 id="bash快捷输入或删除">Bash快捷输入或删除</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>快捷键:
Ctl-U   删除光标到行首的所有字符,在某些设置下,删除全行
Ctl-W   删除当前光标到前边的最近一个空格之间的字符
Ctl-H   backspace,删除光标前边的字符
Ctl-R   匹配最相近的一个文件，然后输出
</code></pre></div></div>
<h2 id="综合应用">综合应用</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>查找record.log中包含AAA，但不包含BBB的记录的总数:
cat -v record.log | grep AAA | grep -v BBB | wc -l
</code></pre></div></div>
<h2 id="总结">总结</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>文件管理，目录的创建、删除、查询、管理: mkdir rm mv

文件的查询和检索: find locate

查看文件内容：cat vi tail more

管道和重定向: ; | &amp;&amp;  &gt;
</code></pre></div></div>]]></content><author><name>Junze Xu</name></author><category term="Linux" /><summary type="html"><![CDATA[文件及目录管理]]></summary></entry><entry><title type="html">1.3 Linux 文本处理</title><link href="https://junze-xu.github.io/2020/02/18/03_text_processing/" rel="alternate" type="text/html" title="1.3 Linux 文本处理" /><published>2020-02-18T00:00:00+00:00</published><updated>2020-02-18T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/02/18/03_text_processing</id><content type="html" xml:base="https://junze-xu.github.io/2020/02/18/03_text_processing/"><![CDATA[<h2 id="概述">概述</h2>
<p>本节将介绍Linux下使用Shell处理文本时最常用的工具：
find、grep、xargs、sort、uniq、tr、cut、paste、wc、sed、awk；
提供的例子和参数都是常用的；</p>

<h2 id="find-文件查找">find 文件查找</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>//查找txt和pdf文件:
find . \( -name "*.txt" -o -name "*.pdf" \) -print

//正则方式查找.txt和pdf:
find . -regex  ".*\(\.txt\|\.pdf\)$"
-iregex： 忽略大小写的正则

//否定参数 ,查找所有非txt文本:
find . ! -name "*.txt" -print

//指定搜索深度,打印出当前目录的文件（深度为1）:
find . -maxdepth 1 -type f
</code></pre></div></div>
<h2 id="定制搜索">定制搜索</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $whatis command
</code></pre></div></div>
<h2 id="更加详细的说明文档">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-1">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-2">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-3">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-4">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-5">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-6">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-7">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-8">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-9">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-10">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h2 id="更加详细的说明文档-11">更加详细的说明文档:</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>

<h2 id="查看路径">查看路径</h2>

<p>查看程序的binary文件所在路径:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $which command  
</code></pre></div></div>
<p>eg:查找make程序安装路径::</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $which make
    /opt/app/openav/soft/bin/make install
</code></pre></div></div>
<p>查看程序的搜索路径:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $whereis command
</code></pre></div></div>
<p>当系统中安装了同一软件的多个版本时，不确定使用的是哪个版本时，这个命令就能派上用场；</p>

<h2 id="总结">总结</h2>
<p>whatis info man which whereis</p>]]></content><author><name>Junze Xu</name></author><category term="Linux" /><summary type="html"><![CDATA[概述 本节将介绍Linux下使用Shell处理文本时最常用的工具： find、grep、xargs、sort、uniq、tr、cut、paste、wc、sed、awk； 提供的例子和参数都是常用的；]]></summary></entry><entry><title type="html">Linux 命令帮助</title><link href="https://junze-xu.github.io/2020/02/18/04_disk/" rel="alternate" type="text/html" title="Linux 命令帮助" /><published>2020-02-18T00:00:00+00:00</published><updated>2020-02-18T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/02/18/04_disk</id><content type="html" xml:base="https://junze-xu.github.io/2020/02/18/04_disk/"><![CDATA[<h1 id="学会使用命令帮助">学会使用命令帮助</h1>

<h2 id="概述">概述</h2>
<p>在linux终端，面对命令不知道怎么用，或不记得命令的拼写及参数时，我们需要求助于系统的帮助文档；
linux系统内置的帮助文档很详细，通常能解决我们的问题，我们需要掌握如何正确的去使用它们；</p>

<ul>
  <li>在只记得部分命令关键字的场合，我们可通过man -k来搜索；</li>
  <li>需要知道某个命令的简要说明，可以使用whatis；而更详细的介绍，则可用info命令；</li>
  <li>查看命令在哪个位置，我们需要使用which；</li>
  <li>而对于命令的具体参数及使用方法，我们需要用到强大的man；</li>
</ul>

<p>下面介绍这些命令；</p>

<h2 id="命令使用">命令使用</h2>

<h3 id="简要说明命令的作用显示命令所处的man分类页面">简要说明命令的作用（显示命令所处的man分类页面）:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $whatis command
</code></pre></div></div>
<h3 id="更加详细的说明文档">更加详细的说明文档:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h3 id="使用man">使用man</h3>
<p>查询命令command的说明文档:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $man command
    eg：man date
</code></pre></div></div>
<p>使用page up和page down来上下翻页</p>

<p>在man的帮助手册中，将帮助文档分为了9个类别，对于有的关键字可能存在多个类别中，
我们就需要指定特定的类别来查看；（一般我们查询bash命令，归类在1类中）；</p>

<p>man页面所属的分类标识(常用的是分类1和分类3)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    (1)、用户可以操作的命令或者是可执行文件 
    (2)、系统核心可调用的函数与工具等
    (3)、一些常用的函数与数据库 
    (4)、设备文件的说明 
    (5)、设置文件或者某些文件的格式 
    (6)、游戏  
    (7)、惯例与协议等。例如Linux标准文件系统、网络协议、ASCⅡ，码等说明内容  
    (8)、系统管理员可用的管理条令  
    (9)、与内核有关的文件 
</code></pre></div></div>

<p>前面说到使用whatis会显示命令所在的具体的文档类别，我们学习如何使用它 :</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $whatis printf  
    printf               (1)  - format and print data  
    printf               (1p)  - write formatted output  
    printf               (3)  - formatted output conversion  
    printf               (3p)  - print formatted output  
    printf [builtins]    (1)  - bash built-in commands, see bash(1)  
</code></pre></div></div>

<p>我们看到printf在分类1和分类3中都有；分类1中的页面是命令操作及可执行文件的帮助；而3是常用函数库说明；如果我们想看的是C语言中printf的用法，可以指定查看分类3的帮助：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $man 3 printf
    $man -k keyword
</code></pre></div></div>
<p>查询关键字
根据命令中部分关键字来查询命令，适用于只记住部分命令的场合；</p>

<p>eg：查找GNOME的config配置工具命令::</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$man -k GNOME config| grep 1  
</code></pre></div></div>

<p>对于某个单词搜索，可直接使用/word来使用:   /-a;
多关注下SEE ALSO 可看到更多精彩内容</p>

<h2 id="查看路径">查看路径</h2>

<p>查看程序的binary文件所在路径:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $which command  
</code></pre></div></div>
<p>eg:查找make程序安装路径::</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $which make
    /opt/app/openav/soft/bin/make install
</code></pre></div></div>
<p>查看程序的搜索路径:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $whereis command
</code></pre></div></div>
<p>当系统中安装了同一软件的多个版本时，不确定使用的是哪个版本时，这个命令就能派上用场；</p>

<h2 id="总结">总结</h2>
<p>whatis info man which whereis</p>]]></content><author><name>Junze Xu</name></author><category term="Linux" /><summary type="html"><![CDATA[学会使用命令帮助]]></summary></entry><entry><title type="html">1.1 Linux 命令帮助</title><link href="https://junze-xu.github.io/2020/02/10/01_use_man/" rel="alternate" type="text/html" title="1.1 Linux 命令帮助" /><published>2020-02-10T00:00:00+00:00</published><updated>2020-02-10T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/02/10/01_use_man</id><content type="html" xml:base="https://junze-xu.github.io/2020/02/10/01_use_man/"><![CDATA[<h1 id="学会使用命令帮助">学会使用命令帮助</h1>

<h2 id="概述">概述</h2>
<p>在linux终端，面对命令不知道怎么用，或不记得命令的拼写及参数时，我们需要求助于系统的帮助文档；
linux系统内置的帮助文档很详细，通常能解决我们的问题，我们需要掌握如何正确的去使用它们；</p>

<ul>
  <li>在只记得部分命令关键字的场合，我们可通过man -k来搜索；</li>
  <li>需要知道某个命令的简要说明，可以使用whatis；而更详细的介绍，则可用info命令；</li>
  <li>查看命令在哪个位置，我们需要使用which；</li>
  <li>而对于命令的具体参数及使用方法，我们需要用到强大的man；</li>
</ul>

<p>下面介绍这些命令；</p>

<h2 id="命令使用">命令使用</h2>

<h3 id="简要说明命令的作用显示命令所处的man分类页面">简要说明命令的作用（显示命令所处的man分类页面）:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $whatis command
</code></pre></div></div>
<h3 id="更加详细的说明文档">更加详细的说明文档:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $info command  
</code></pre></div></div>
<h3 id="使用man">使用man</h3>
<p>查询命令command的说明文档:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $man command
    eg：man date
</code></pre></div></div>
<p>使用page up和page down来上下翻页</p>

<p>在man的帮助手册中，将帮助文档分为了9个类别，对于有的关键字可能存在多个类别中，
我们就需要指定特定的类别来查看；（一般我们查询bash命令，归类在1类中）；</p>

<p>man页面所属的分类标识(常用的是分类1和分类3)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    (1)、用户可以操作的命令或者是可执行文件 
    (2)、系统核心可调用的函数与工具等
    (3)、一些常用的函数与数据库 
    (4)、设备文件的说明 
    (5)、设置文件或者某些文件的格式 
    (6)、游戏  
    (7)、惯例与协议等。例如Linux标准文件系统、网络协议、ASCⅡ，码等说明内容  
    (8)、系统管理员可用的管理条令  
    (9)、与内核有关的文件 
</code></pre></div></div>

<p>前面说到使用whatis会显示命令所在的具体的文档类别，我们学习如何使用它 :</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $whatis printf  
    printf               (1)  - format and print data  
    printf               (1p)  - write formatted output  
    printf               (3)  - formatted output conversion  
    printf               (3p)  - print formatted output  
    printf [builtins]    (1)  - bash built-in commands, see bash(1)  
</code></pre></div></div>

<p>我们看到printf在分类1和分类3中都有；分类1中的页面是命令操作及可执行文件的帮助；而3是常用函数库说明；如果我们想看的是C语言中printf的用法，可以指定查看分类3的帮助：</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $man 3 printf
    $man -k keyword
</code></pre></div></div>
<p>查询关键字
根据命令中部分关键字来查询命令，适用于只记住部分命令的场合；</p>

<p>eg：查找GNOME的config配置工具命令::</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$man -k GNOME config| grep 1  
</code></pre></div></div>

<p>对于某个单词搜索，可直接使用/word来使用:   /-a;
多关注下SEE ALSO 可看到更多精彩内容</p>

<h2 id="查看路径">查看路径</h2>

<p>查看程序的binary文件所在路径:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $which command  
</code></pre></div></div>
<p>eg:查找make程序安装路径::</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $which make
    /opt/app/openav/soft/bin/make install
</code></pre></div></div>
<p>查看程序的搜索路径:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    $whereis command
</code></pre></div></div>
<p>当系统中安装了同一软件的多个版本时，不确定使用的是哪个版本时，这个命令就能派上用场；</p>

<h2 id="总结">总结</h2>
<p>whatis info man which whereis</p>]]></content><author><name>Junze Xu</name></author><category term="Linux" /><summary type="html"><![CDATA[学会使用命令帮助]]></summary></entry><entry><title type="html">跟我一起学Makefile 学习记录2</title><link href="https://junze-xu.github.io/2020/02/08/Makefile-2/" rel="alternate" type="text/html" title="跟我一起学Makefile 学习记录2" /><published>2020-02-08T00:00:00+00:00</published><updated>2020-02-08T00:00:00+00:00</updated><id>https://junze-xu.github.io/2020/02/08/Makefile-2</id><content type="html" xml:base="https://junze-xu.github.io/2020/02/08/Makefile-2/"><![CDATA[<h3 id="命令执行">命令执行</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#上一条命令的结果应用在下一条命令时，你应该使用分 号分隔这两条命令
exec:
    cd /home/hchen 
    pwd
#cd没有作用，pwd会打印出当前的Makefile

exec:
    cd /home/hchen; pwd
#忽略命令的出错，我们可以在Makefile的命令行前加一个减号“-”
clean:
    -rm -f *.o

#还有一个全局的办法是，给make加上“-i”或是“--ignore-errors”参数，Makefile中所有命令都会忽略错误。

#make的参数的是“-k”或是“--keep-going”，这个参数的意思是，如果某规则中的命令出错了，那么就终目该规则的执行，但继续执行其它规则
--------------------------------------------------------------
</code></pre></div></div>
<h3 id="嵌套执行make">嵌套执行make</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#子目录叫subdir，这个目录下有个Makefile 文件，来指明了这个目录下文件的编译规则。
#这两个例子的意思都是先进入“subdir”目录，然后执行 make 命令。
#定义$(MAKE)宏变量的意思是，也许我们的 make 需要一些参数，所以定义成一个变量比较 利于维护。
subsystem:
    cd subdir &amp;&amp; $(MAKE)
#等价于：
subsystem:
    $(MAKE) -C subdir
    
#这个Makefile叫做“总控 Makefile”，总控 Makefile的变量可以传递到下级的 Makefile 中（如果你显示的声明），但是不会覆盖下层的 Makefile中所定义的变量，除非指定了“-e”参数。

#如果你要传递变量到下级 Makefile中，那么你可以使用这样的声明：
export &lt;variable ...&gt;

#如果你不想让某些变量传递到下级 Makefile 中，那么你可以这样声明：
unexport &lt;variable ...&gt;

export variable = value
等价于：
variable = value 
export variable

export variable += value
其等价于：
variable += value 
export variable

如果你要传递所有的变量，那么，只要一个export就行了。后面什么也不用跟，表示传递 所有的变量。

需要注意的是，有两个变量，一个是 SHELL，一个是MAKEFLAGS这两个变量不管你是否 export，其总是要传递到下层 Makefile 中，特别是MAKEFILES变量，其中包含了 make 的参数信息，如果我们执行“总控 Makefile”时有 make参数或是在上层 Makefile 中定义了这个变量，那么MAKEFILES变量将会是这些参数，并会传递到下层Makefile中，这是一个系统级的环境变量。

#如果你不想往下层传递参数，可以这样来：
subsystem:
    cd subdir &amp;&amp; $(MAKE) MAKEFLAGS=
--------------------------------------------------------------
</code></pre></div></div>
<h3 id="定义命令包">定义命令包</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#如果 Makefile 中出现一些相同命令序列，那么我们可以为这些相同的命令序列定义一个变 量。以“define”开始，以“endef”结束
define run-yacc 
yacc $(firstword $^) 
mv y.tab.c $@ 
endef


这里，“run-yacc”是这个命令包的名字，其不要和 Makefile 中的变量重名。在“define” 和“endef”中的两行就是命令序列。

#这个命令包中的第一个命令是运行 Yacc 程序，因为 Yacc 程序总是生成“y.tab.c”的文件，所以第二行的命令就是把这个文件改改名字。

foo.c : foo.y 
    $(run-yacc)
--------------------------------------------------------------
</code></pre></div></div>
<h3 id="makefile-使用变量">Makefile 使用变量</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>在 Makefile 中的定义的变量，就像是 C/C++语言中的宏一样，他代表了一个文本字串。其与 C/C++所不同的是，你可以在 Makefile 中改变其值。

变量可以使用在“目标”，“依赖目标”，“命令”或是 Makefile 的其它部分中。

变量的命名字可以包含字符、数字，下划线（可以是数字开头），但不应该含有“:”、“#”、 “=”或是空字符（空格、回车等）。变量是大小写敏感的，推荐使用大小写搭配的变量名，如：MakeFlags。这样可以避免和系统的变量冲突，而发生意外的事情。


变量在声明时需要给予初值，而在使用时，需要给在变量名前加上“$”符号，但最好用小括号“（）”或是大括号“{}”把变量给包括起来。如果你要使用真实的“$”字符，那么你需要用“$$”来表示。

objects = program.o foo.o utils.o program : $(objects) 
    cc -o program $(objects)
$(objects) : defs.h
--------------------------------------------------------------

</code></pre></div></div>
<h3 id="变量中的变量">变量中的变量</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>在“=”左侧是变量，右侧是变量的值，右侧变量的值可以定义在文件的任何一处，也就是说，右侧中的变量不一定非要是已定义好的值， 其也可以使用后面定义的值。如：

foo = $(bar) 
bar = $(ugh) 
ugh = Huh?
all:
    echo $(foo)
    
我们可以使用 make 中的另一种用变量来定义变量的方法。这种方法使用的是“:=”操作符.第一个例子中y的值是“bar”，而不是“foo bar”。

x := foo 
y := $(x) bar 
x := later
其等价于：
y := foo bar 
x := later

ifeq (0,${MAKELEVEL}) 
cur-dir := $(shell pwd) 
whoami := $(shell whoami) 
host-type := $(shell arch) 
MAKE := ${MAKE} host-type=${host-type} whoami=${whoami} 
endif

#后面采用“#”注释符来表示变量定义的终止
nullstring :=
space := $(nullstring) # end of the line


dir := /foo/bar    # directory to put the frobs in


FOO没有被定义过，那么变量 FOO 的值就是“bar”，如果 FOO 先前被定义过，那么这条语将什么也不做
FOO ?= bar
    等价于：
ifeq ($(origin FOO), undefined) 
    FOO = bar 
endif
--------------------------------------------------------------
</code></pre></div></div>
<h3 id="变量高级用法">变量高级用法</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#变量值的替换
先定义了一个“$(foo)”变量，而第二行的意思是把“$(foo)”中所有 以“.o”字串“结尾”全部替换成“.c”，所以我们的“$(bar)”的值就是“a.c b.c c.c”。
foo := a.o b.o c.o 
bar := $(foo:.o=.c)

#把变量的值再当成变量

$(x)的值是“y”，所以$($(x))就是$(y)，于是$(a)的值就是“z”。（注 意，是“x=y”，而不是“x=$(y)”）
x = y 
y = z 
a := $($(x))

x = $(y) 
y = z 
z = Hello 
a := $($(x))

这里的$($(x))被替换成了$($(y))，因为$(y)值是“z”，所以，最终结果是：a:=$(z)， 也就是“Hello”。

--------------------------------------------------------------
</code></pre></div></div>
<h3 id="追加变量值">追加变量值</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#$(objects)值变成：“main.o foo.o bar.o utils.o another.o” （another.o 被追加进去了）

objects = main.o foo.o bar.o utils.o objects += another.o

#override 指示符

</code></pre></div></div>]]></content><author><name>Junze Xu</name></author><category term="Makefile" /><summary type="html"><![CDATA[工作中用到Makefile学习]]></summary></entry></feed>