<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Femn</title>
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://www.femn.me/"/>
  <updated>2017-08-25T08:26:01.285Z</updated>
  <id>https://www.femn.me/</id>
  
  <author>
    <name>leipengkai</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>shell_sed_awk</title>
    <link href="https://www.femn.me/2017/08/23/shell-grep-sed-awk/"/>
    <id>https://www.femn.me/2017/08/23/shell-grep-sed-awk/</id>
    <published>2017-08-23T01:05:44.000Z</published>
    <updated>2017-08-25T08:26:01.285Z</updated>
    
    <content type="html"><![CDATA[<h3 id="Sed全名为Stream-EDitor-即流式编辑器-行编辑器"><a href="#Sed全名为Stream-EDitor-即流式编辑器-行编辑器" class="headerlink" title="Sed全名为Stream EDitor,即流式编辑器,行编辑器"></a>Sed全名为Stream EDitor,即流式编辑器,行编辑器</h3><p>sed常用用法<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sed [options] <span class="string">'script(模式命令)'</span> input_file...</div><div class="line">sed [options] -f script_file(sed脚本) input_file...</div></pre></td></tr></table></figure></p>
<p>options </p>
<p>-n 静默模式,不打印模式空间中的内容</p>
<p>-e 执行模式命令,适用于多脚本处理</p>
<p>-i 直接操作原文件<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">sed -n -e <span class="string">'1p'</span> -e <span class="string">'37,40p'</span> /etc/passwd &gt; passwd.txt &amp;&amp; cat passwd.txt </div><div class="line"><span class="comment"># 输出如下</span></div><div class="line">root:x:0:0:root:/root:/bin/bash</div><div class="line">rtkit:x:118:126:RealtimeKit,,,:/proc:/bin/<span class="literal">false</span></div><div class="line">saned:x:119:127::/var/lib/saned:/bin/<span class="literal">false</span></div><div class="line">usbmux:x:120:46:usbmux daemon,,,:/var/lib/usbmux:/bin/<span class="literal">false</span></div><div class="line">femn:x:1000:1000:femn,,,:/home/femn:/bin/bash</div></pre></td></tr></table></figure></p>
<p>模式命令  s:替换 p:打印 d:删除 a:增加 g:表示一行上的替换所有的匹配<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">sed -e <span class="string">'1,37d'</span> /etc/passwd</div><div class="line"><span class="comment"># 输出如下</span></div><div class="line">saned:x:119:127::/var/lib/saned:/bin/<span class="literal">false</span></div><div class="line">usbmux:x:120:46:usbmux daemon,,,:/var/lib/usbmux:/bin/<span class="literal">false</span></div><div class="line">femn:x:1000:1000:femn,,,:/home/femn:/bin/bash</div><div class="line">mysql:x:121:130:MySQL Server,,,:/nonexistent:/bin/<span class="literal">false</span></div></pre></td></tr></table></figure></p>
<p>a \:在模式匹配到的行后面添加新内容<br>i                   前面<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">sed -e <span class="string">'/root/i \this is head'</span> \</div><div class="line">    -e <span class="string">'/femn/a \this is tail\n'</span> passwd.txt </div><div class="line"><span class="comment"># 输出如下</span></div><div class="line">this is head</div><div class="line">root:x:0:0:root:/root:/bin/bash</div><div class="line">rtkit:x:118:126:RealtimeKit,,,:/proc:/bin/<span class="literal">false</span></div><div class="line">saned:x:119:127::/var/lib/saned:/bin/<span class="literal">false</span></div><div class="line">usbmux:x:120:46:usbmux daemon,,,:/var/lib/usbmux:/bin/<span class="literal">false</span></div><div class="line">femn:x:1000:1000:femn,,,:/home/femn:/bin/bash</div><div class="line">this is tail</div></pre></td></tr></table></figure></p>
<p>匹配内容的行’/{content}/‘ 可以使用正则匹配<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">sed -n -e <span class="string">'/\&lt;root\&gt;/s/bin/nologin/p'</span> -e <span class="string">'s/femn/hehe/p'</span> passwd.txt</div><div class="line"><span class="comment"># 输出如下</span></div><div class="line">root:x:0:0:root:/root:/nologin/bash</div><div class="line">hehe:x:1000:1000:femn,,,:/home/femn:/bin/bash</div></pre></td></tr></table></figure></p>
<p>-f 指定文件<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">vim ss</div><div class="line">    /\&lt;root\&gt;/s/bin/nologin/p</div><div class="line">    s/femn/hehe/p</div><div class="line">sed -n -f ss passwd.txt</div></pre></td></tr></table></figure></p>
<p>sed脚本</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">vim ss.sh</div><div class="line">    <span class="comment">#!/bin/sed -f</span></div><div class="line">    /\&lt;root\&gt;/s/bin/nologin/p</div><div class="line">    s/femn/hehe/p</div><div class="line">chmod a+u ss.sh</div><div class="line">./ss.sh passwd.txt</div></pre></td></tr></table></figure>
<p>删除注释和空行 显示删除之后的行数<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sed -e <span class="string">'/^#/d'</span> -e <span class="string">'/^$/d'</span> passwd.txt | wc -l</div><div class="line">wc -l !$   <span class="comment"># 上个文件多少行</span></div></pre></td></tr></table></figure></p>
<p>个人的一个实用脚本,将中文符号换成英文<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#!/bin/bash </span></div><div class="line"></div><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> `ls /home/femn/blog/<span class="built_in">source</span>/_posts/*.md`</div><div class="line"><span class="keyword">do</span> </div><div class="line">    sed -i -e <span class="string">'s/:/:/g'</span> \</div><div class="line">        -e <span class="string">'s/;/;/g'</span> \</div><div class="line">        -e <span class="string">'s/,/,/g'</span> \</div><div class="line">        -e <span class="string">'s/././g'</span> \</div><div class="line">        -e <span class="string">'s/(/(/g'</span> \</div><div class="line">        -e <span class="string">'s/)/)/g'</span> \</div><div class="line">        -e <span class="string">'s/"/"/g'</span> \</div><div class="line">        -e <span class="string">'s/"/"/g'</span> \</div><div class="line">        -e <span class="string">"s/'/'/g"</span> \</div><div class="line">        -e <span class="string">"s/'/'/g"</span> \</div><div class="line">        <span class="string">"<span class="variable">$i</span>"</span></div><div class="line"><span class="keyword">done</span></div></pre></td></tr></table></figure></p>
<h3 id="awk擅于处理列"><a href="#awk擅于处理列" class="headerlink" title="awk擅于处理列"></a>awk擅于处理列</h3><p>awk的一些内建变量</p>
<p>FS 输入字段分隔符 默认是空格或Tab    </p>
<p>$0 当前记录(这个变量中存放着整个行  的内容)</p>
<p>$1~$n 当前记录的第n个字段,字段间由FS分隔    </p>
<p>OFS 输出字段分隔符, 默认也是空格</p>
<p>NR 已经读出的记录数,就是行号    </p>
<p>FNR 文件自己的行号</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">awk  <span class="string">'BEGIN&#123;FS=":"&#125; &#123;print $1,$3,$6&#125;'</span> &lt; passwd.txt</div><div class="line"><span class="comment"># 如下输出</span></div><div class="line">root 0 /root</div><div class="line">rtkit 118 /proc</div><div class="line">saned 119 /var/lib/saned</div><div class="line">usbmux 120 /var/lib/usbmux</div><div class="line">femn 1000 /home/femn</div></pre></td></tr></table></figure>
<p>匹配内容<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">awk  -F: <span class="string">'$1=="root" || $1 ~ /femn|mysql/ &#123;print NR, FNR, $1,$3,$6&#125;'</span> OFS=<span class="string">"\t"</span> passwd.txt</div><div class="line"><span class="comment"># 如下输出</span></div><div class="line">1   1   root    0   /root                </div><div class="line">5   5   femn    1000    /home/femn</div><div class="line"><span class="comment"># -F: 指定分隔符为':'去分隔文件 默认为空格或Tab</span></div><div class="line"><span class="comment"># ~ 表示匹配模式开始./ /中是模式.这就是一个正则表达式的匹配.!~ 表示取反</span></div></pre></td></tr></table></figure></p>
<p>把指定的列输出到文件<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">awk <span class="string">'NR!=1&#123;if($1 ~ /root|femn/) print &gt; "1.txt"; \</span></div><div class="line"><span class="string">    else if($1 ~ /mysql/) print &gt; "2.txt"; \</span></div><div class="line"><span class="string">    else print &gt; "3.txt" &#125;'</span> passwd.txt</div><div class="line">vim 1.txt </div><div class="line">    emn:x:1000:1000:femn,,,:/home/femn:/bin/bash</div><div class="line">    <span class="comment"># NR!=1表示不处理表头,所以没有root的那一行</span></div><div class="line">vim 2.txt <span class="comment"># 是个空的</span></div><div class="line">vim 3.txt</div><div class="line">    rtkit:x:118:126:RealtimeKit,,,:/proc:/bin/<span class="literal">false</span></div><div class="line">    saned:x:119:127::/var/lib/saned:/bin/<span class="literal">false</span></div><div class="line">    usbmux:x:120:46:usbmux daemon,,,:/var/lib/usbmux:/bin/<span class="literal">false</span></div></pre></td></tr></table></figure></p>
<p>注意其中的if-else-if语句,可见awk其实是个脚本解释器</p>
<p>统计<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">ll *.txt | awk <span class="string">'&#123;print $5,$9&#125;'</span></div><div class="line"><span class="comment"># 输出如下</span></div><div class="line">46 1.txt</div><div class="line">0 2.txt</div><div class="line">151 3.txt</div><div class="line">229 passwd.txt</div><div class="line"></div><div class="line">ll *.txt |awk <span class="string">'&#123;sum+=$5&#125; END &#123;print sum&#125;'</span></div><div class="line"><span class="comment"># 输出如下</span></div><div class="line">426</div></pre></td></tr></table></figure></p>
<p>统计每个用户的进程的占了多少内存,sum的RSS那一列<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">ps aux | awk <span class="string">'NR!=1&#123;a[$1]+=$6;&#125; END &#123; for(i in a) print i ", " a[i]"KB";&#125;'</span></div></pre></td></tr></table></figure></p>
<p>按连接数查看客户端IP<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">netstat -ntu | awk <span class="string">'&#123;print $5&#125;'</span> | cut -d: -f1 | sort | uniq -c | sort -nr</div></pre></td></tr></table></figure></p>
<p>awk脚本<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">awk -F: <span class="string">'BEGIN &#123;i=1&#125; &#123; if ($7=="/bin/bash")  i+=1 &#125; END &#123;print "number "i&#125;'</span> &lt; /etc/passwd</div><div class="line"><span class="comment"># 输出如下</span></div><div class="line">number 3</div><div class="line"></div><div class="line">vim aa</div><div class="line">    BEGIN &#123;i=1&#125;</div><div class="line">    &#123; <span class="keyword">if</span> (<span class="variable">$7</span>==<span class="string">"/bin/bash"</span>)  i+=1 &#125;</div><div class="line">    END &#123;<span class="built_in">print</span> <span class="string">"number "</span>i&#125;</div><div class="line">cat /etc/passwd | awk -F: -f aa</div></pre></td></tr></table></figure></p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;Sed全名为Stream-EDitor-即流式编辑器-行编辑器&quot;&gt;&lt;a href=&quot;#Sed全名为Stream-EDitor-即流式编辑器-行编辑器&quot; class=&quot;headerlink&quot; title=&quot;Sed全名为Stream EDitor,即流式编辑器,行编辑
    
    </summary>
    
      <category term="shell" scheme="https://www.femn.me/categories/shell/"/>
    
    
  </entry>
  
  <entry>
    <title>pymongo基本操作</title>
    <link href="https://www.femn.me/2017/08/18/pymongo/"/>
    <id>https://www.femn.me/2017/08/18/pymongo/</id>
    <published>2017-08-18T06:48:02.000Z</published>
    <updated>2017-08-24T04:10:08.361Z</updated>
    
    <content type="html"><![CDATA[<p>知道了大概的mongodb命令后,再下载Mongodb的python驱动,sudo pip3 install pymongo ,然后在python文件中导入相应的库,进行如下的配置:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">from pymongo import MongoClient</div><div class="line">_client = MongoClient(<span class="string">'127.0.0.1'</span>, 27017) <span class="comment">#主机IP,Port</span></div><div class="line"><span class="comment">#先创建一个名为Mongodb的数据库,再连接到此数据库</span></div><div class="line">_db = _client[<span class="string">'Mongodb'</span>]</div><div class="line">_db.authenticate(<span class="string">'username'</span>, <span class="string">'password'</span>)<span class="comment">#如果是设置了密码登陆时</span></div><div class="line"><span class="built_in">test</span> = _db[<span class="string">'test'</span>] <span class="comment"># 表名</span></div><div class="line">femn = _db[<span class="string">'femn'</span>]</div></pre></td></tr></table></figure>
<h3 id="返回结果"><a href="#返回结果" class="headerlink" title="返回结果"></a>返回结果</h3><p><code>insert , insert_one , insert_many</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">insert(&#123;<span class="string">'name'</span>:<span class="number">1</span>&#125;)         <span class="comment"># &lt;class 'bson.objectid.ObjectId'&gt; </span></div><div class="line">insert([&#123;<span class="string">'name'</span>:<span class="number">1</span>&#125;,&#123;<span class="string">'name'</span>:<span class="number">2</span>&#125;])   <span class="comment"># [ObjectId('xx'),ObjectId('xx')]</span></div><div class="line">insert_one  <span class="comment"># r.inserted_id &lt;class 'bson.objectid.ObjectId'&gt;</span></div><div class="line">insert_many          <span class="comment"># &lt;class 'pymongo.results.InsertManyResult'&gt;</span></div><div class="line">print(r.inserted_ids) <span class="comment"># list [ObjectId('xx'), ObjectId('xx')]</span></div></pre></td></tr></table></figure></p>
<p> <code>update</code><br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">&#123;<span class="string">'ok'</span>: 1, <span class="string">'updatedExisting'</span>: True, <span class="string">'nModified'</span>: 1, <span class="string">'n'</span>: 1&#125;</div></pre></td></tr></table></figure></p>
<p> <code>upsert=True</code><br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">&#123;<span class="string">'ok'</span>:1,<span class="string">'nModified'</span>:0,<span class="string">'upserted'</span>:ObjectId(<span class="string">''</span>),<span class="string">'n'</span>:1,<span class="string">'updatedExisting'</span>:True&#125;</div></pre></td></tr></table></figure></p>
<p> <code>update_one</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">r = db.test.update_one(&#123;<span class="string">'_id'</span>:<span class="string">'xx'</span>&#125;,&#123;<span class="string">'$set'</span>:&#123;<span class="string">'name'</span>:<span class="string">'femn'</span>&#125;&#125;) </div><div class="line"><span class="comment"># &lt;pymongo.results.UpdateResult object at 0x7f9cb2ebaaf8&gt;</span></div><div class="line">r.raw_result =&#123;<span class="string">'nModified'</span>: <span class="number">0</span>, <span class="string">'n'</span>: <span class="number">1</span>, <span class="string">'updatedExisting'</span>: <span class="keyword">True</span>, <span class="string">'ok'</span>: <span class="number">1</span>&#125;</div></pre></td></tr></table></figure></p>
<p><code>delete_many delete_one</code></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">result = db.test.delete_many(&#123;<span class="string">'x'</span>: <span class="number">1</span>&#125;)      <span class="comment">#pymongo.results.DeleteResult</span></div><div class="line">result.deleted_count  <span class="comment"># 2</span></div><div class="line">result.raw_result <span class="comment"># &#123;'n': 2, 'ok': 1&#125;   </span></div><div class="line"> <span class="comment">#n表示匹配成功删除的个数 和delete_one是一样的</span></div></pre></td></tr></table></figure>
<p><code>find find_one</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">find() find(&#123;&#125;)         <span class="comment"># return 一个pymongo.cursor.CursorType</span></div><div class="line">find_one(&#123;<span class="string">'_id'</span>:<span class="string">'xx'</span>&#125;)  <span class="comment"># return dict 如果没有则返回None</span></div><div class="line">find_one_and_update()   <span class="comment"># return dict</span></div></pre></td></tr></table></figure></p>
<h3 id="find-find-one-命令"><a href="#find-find-one-命令" class="headerlink" title="find find_one 命令"></a>find find_one 命令</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">femn.find(filter=&#123;<span class="string">'field'</span>:<span class="string">'xx'</span>&#125;,</div><div class="line">    projection=&#123;<span class="string">'mobile'</span>:<span class="number">1</span>,<span class="string">'name'</span>:<span class="number">0</span>&#125;,limit=<span class="number">10</span>,skip=<span class="number">0</span>,</div><div class="line">    sort=[(<span class="string">'update_time'</span>:pymongo.DESCENDING)])</div><div class="line"></div><div class="line">femn.find(&#123;<span class="string">'name'</span>:xx&#125;,&#123;<span class="string">'name'</span>:<span class="number">1</span>&#125;).limit().skip().</div><div class="line">    sort=([(<span class="string">'update_time'</span>:pymongo.DESCENDING)])</div></pre></td></tr></table></figure>
<p>filter中的多个查询操作符</p>
<p><code>$all $in $nin 此字段可包含(或排除)多个值的文档</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">(&#123;filed:&#123;<span class="string">'$all'</span>:[]&#125;&#125;) </div><div class="line"><span class="comment"># 这个字段是数组并满足这个数组的值和指定的相同的文档</span></div><div class="line"></div><div class="line">(&#123;filed:&#123;<span class="string">'$in'</span>,<span class="string">'$nin'</span> :[<span class="string">'x'</span>]&#125;&#125;) </div><div class="line"><span class="comment"># 而这个只表示'x'在字段不管是数组类型的值,还是字符串类型的值,只要有这个'x'的文档就行</span></div></pre></td></tr></table></figure></p>
<p><code>$regex 正规匹配字段的值</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">(&#123;filed:&#123;<span class="string">'$regex'</span>: <span class="string">'%s'</span> % student_name&#125;&#125;) 就是    <span class="string">' *%s* '</span></div><div class="line">(&#123;filed:&#123;<span class="string">'$not'</span>:&#123;<span class="string">'$regex'</span>:<span class="string">'femn'</span>&#125;&#125;&#125;)</div></pre></td></tr></table></figure></p>
<p><code>$exists 判断文档是否有此字段</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">(&#123;filed: &#123;<span class="string">'$exists'</span>: <span class="keyword">False</span>&#125;&#125;)</div><div class="line"><span class="comment">#得到所有不存在flag字段的文档 可取True</span></div></pre></td></tr></table></figure></p>
<p><code>$or 满足一个字段的值就行</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">(&#123;<span class="string">'gender'</span>: <span class="string">'女'</span>, <span class="string">'$or'</span>: [&#123;<span class="string">'expand.expand_time'</span>: <span class="string">'2015-01-01'</span>&#125;,</div><div class="line">     &#123;<span class="string">'coin'</span>: &#123;<span class="string">'$lt'</span>: <span class="number">2</span>&#125;&#125;]&#125;)</div></pre></td></tr></table></figure></p>
<p><code>$slice</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">(&#123;<span class="string">'expand.expand_time'</span>:&#123;<span class="string">'$slice'</span>:[<span class="number">5</span>,<span class="number">3</span>]&#125;&#125;)</div><div class="line"><span class="comment"># 不是分片,去掉前5个后,再取3个 ,-5时去掉后5个取,取最后3个</span></div></pre></td></tr></table></figure></p>
<p><code>混合包含和排除不能同时用</code></p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">(&#123;<span class="string">'album_id'</span>:&#123;<span class="string">'$in'</span>:[i]&#125;&#125;,projection=&#123;<span class="string">'play_count'</span>:<span class="number">1</span>,<span class="string">'cover_image'</span>:<span class="number">1</span>&#125;)</div></pre></td></tr></table></figure>
<p>混合包含和排除不能同时用,既in:[],cover_image:1,comment:0不能同时使用,但可以 in:[],cover_image:1,comment:1</p>
<p>其它的查询操作符 $eachMatch,$gt:2, $lte, $gte, $lt, ‘$slice’  $ne不等于</p>
<h3 id="find-one-and-update命令"><a href="#find-one-and-update命令" class="headerlink" title="find_one_and_update命令"></a>find_one_and_update命令</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line">find_one_and_update(q,u,p,upsert=<span class="keyword">False</span>,</div><div class="line">    return_document=ReturnDocument.AFTER)</div><div class="line"></div><div class="line">test.update(&#123;<span class="string">'name'</span>:<span class="string">'femn'</span>&#125;,</div><div class="line">    &#123;</div><div class="line">    <span class="comment"># update中的多个更新操作符</span></div><div class="line">    <span class="string">'$set'</span>:&#123;<span class="string">'name'</span>:<span class="string">'xx'</span>&#125;,</div><div class="line">    <span class="comment"># 改变某个字段的值</span></div><div class="line"></div><div class="line">    <span class="string">'$inc'</span>:&#123;<span class="string">'age'</span>:<span class="number">-1</span>&#125;,</div><div class="line">    <span class="comment"># 增加或减少 一个字段内容是数值的值</span></div><div class="line"></div><div class="line">    <span class="string">'$addToSet'</span>:&#123;<span class="string">'name_list'</span>:&#123;<span class="string">'$each'</span>:[<span class="string">''</span>,<span class="string">''</span>]&#125;&#125;,</div><div class="line">    <span class="comment"># 往一个数组的字段,添加不一样的内容,可避免反复添加</span></div><div class="line">    <span class="comment"># $each 一次性增加多个值</span></div><div class="line">    <span class="comment"># $push 往一个数组的字段中,可重复的添加一样的内容</span></div><div class="line"></div><div class="line">    <span class="string">'$pull'</span>:&#123;<span class="string">'list'</span>:&#123;<span class="string">'key'</span>:<span class="string">'value'</span>&#125;&#125;,</div><div class="line">    <span class="comment"># 删除数组中 所有key为value的数组都会删除掉 将所有匹配到的数据都删除</span></div><div class="line"></div><div class="line">    <span class="string">'$pullAll'</span>:&#123;<span class="string">'l'</span>:[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]&#125;</div><div class="line">    <span class="comment"># 一次性删除多个数组</span></div><div class="line">    &#125;)</div><div class="line"></div><div class="line">test.update(&#123;<span class="string">'_id'</span>:id&#125;,&#123;<span class="string">'$set'</span>:</div><div class="line">    &#123;<span class="string">'recording'</span>:&#123;<span class="string">'openid'</span>:openid,<span class="string">'book_id'</span>:book_id&#125;&#125;&#125;)</div><div class="line"> <span class="comment"># recording 是一个Object类型</span></div><div class="line">test.find_one(&#123;<span class="string">'_id'</span>:bookcase_id,recording.book_id<span class="string">':book_id&#125;)</span></div></pre></td></tr></table></figure>
<p>改变数值中的值 通过位置或者操作符$</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 通过$</span></div><div class="line">test.update(&#123;<span class="string">"relationships.fname"</span>:<span class="string">"xiong"</span>,<span class="string">'_id'</span>:id&#125;,</div><div class="line">        &#123;$set:&#123;<span class="string">"relationships.$.age"</span>:<span class="number">22</span>&#125;&#125;) </div><div class="line"><span class="comment"># 通过位置用来定位查询文档已匹配的元素,并进行更新</span></div><div class="line">test.update(&#123;<span class="string">'_id'</span>:id&#125;,</div><div class="line">    &#123;<span class="string">'$inc'</span>:&#123;<span class="string">'book_class.'</span>+str(i)+<span class="string">'.class_count'</span>:count&#125;&#125;)</div><div class="line"><span class="comment"># 指定一个数组中的一个字段改变 </span></div><div class="line"></div><div class="line">test.update(&#123;<span class="string">'_id'</span>:id&#125;,</div><div class="line">    &#123;<span class="string">'activity_history'</span>:&#123;<span class="string">'click_total'</span>:<span class="number">1</span>,per:<span class="number">1</span>,<span class="string">'login'</span>:<span class="number">1</span>&#125;&#125;&#125;)</div><div class="line"><span class="comment"># 此方法不行 换成如下方法</span></div><div class="line">test.update(&#123;<span class="string">'_id'</span>:id&#125;,</div><div class="line">    &#123;<span class="string">'$inc'</span>:&#123;<span class="string">'activity_history.0.click_total'</span>:<span class="number">1</span>,</div><div class="line">    <span class="string">'activity_history.0.2017-02'</span>:<span class="number">1</span>,</div><div class="line">    <span class="string">'activity_history.0.login'</span>:<span class="number">1</span>&#125;&#125;,)</div></pre></td></tr></table></figure>
<h4 id="注意pull一个个的数组是个整体"><a href="#注意pull一个个的数组是个整体" class="headerlink" title="注意pull一个个的数组是个整体"></a>注意<a href="https://docs.mongodb.com/manual/reference/operator/update/pull/#up._S_pull" target="_blank" rel="external">pull</a>一个个的数组是个整体</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="string">'reservation_list'</span>:[&#123;<span class="string">'time'</span>:<span class="string">""</span>,<span class="string">'device_id'</span>:<span class="string">''</span>,</div><div class="line">        <span class="string">'order_book'</span>:[&#123;<span class="number">1</span>&#125;,&#123;<span class="number">2</span>&#125;]&#125;,&#123;...&#125;,&#123;...&#125;]</div><div class="line">    <span class="comment"># 错误的设计 不可能单独的删除order_book中的1,2还保留着...</span></div><div class="line">    <span class="comment"># 它会删除整个的那个数组reservation_list</span></div><div class="line"><span class="string">'reservation_list'</span>:[&#123;<span class="string">'device_id'</span>:<span class="string">''</span>,<span class="string">'book_id'</span>:<span class="string">''</span>,</div><div class="line">        <span class="string">'book_plu'</span>:<span class="string">''</span>,<span class="string">'shelf_number'</span>:<span class="number">101</span>&#125;]</div><div class="line">    <span class="comment"># 所以要将order_book中保存的信息,放出来</span></div></pre></td></tr></table></figure>
<p><code>数组字段的内容album_id = [&#39;1&#39;,&#39;xx&#39;],不是JSON类型</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">test.update(&#123;<span class="string">'_id'</span>:id&#125;,&#123;<span class="string">'$pull'</span>:&#123;<span class="string">'album_id'</span>:<span class="string">'xx'</span>&#125;&#125;) </div><div class="line"><span class="comment"># album_id必须是数组</span></div><div class="line">&#123;<span class="string">'$pull'</span>: &#123;<span class="string">'album_id'</span>: &#123;<span class="string">'$in'</span>: [<span class="string">'xx'</span>]&#125;&#125;</div><div class="line"> <span class="comment">#也可以使用其它的查询操作符 $gt</span></div></pre></td></tr></table></figure></p>
<p><code>删除以字典形式保存的数组</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"> &#123;<span class="string">'$pull'</span>: &#123;<span class="string">'praise'</span>: &#123;<span class="string">'user_id'</span>: user_id,<span class="string">'_id'</span>:<span class="string">'xx'</span>&#125;&#125; </div><div class="line">&#123;<span class="string">'$pull'</span>: &#123;<span class="string">'save_receiver_address'</span>: &#123;<span class="string">'flag'</span>: del_flag&#125;&#125;&#125;)</div></pre></td></tr></table></figure></p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;知道了大概的mongodb命令后,再下载Mongodb的python驱动,sudo pip3 install pymongo ,然后在python文件中导入相应的库,进行如下的配置:&lt;/p&gt;
&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr
    
    </summary>
    
      <category term="python3" scheme="https://www.femn.me/categories/python3/"/>
    
    
  </entry>
  
  <entry>
    <title>mongodb基本命令</title>
    <link href="https://www.femn.me/2017/08/18/mongodb/"/>
    <id>https://www.femn.me/2017/08/18/mongodb/</id>
    <published>2017-08-18T03:56:18.000Z</published>
    <updated>2017-08-24T04:10:08.361Z</updated>
    
    <content type="html"><![CDATA[<p>先去<a href="https://www.mongodb.com/" target="_blank" rel="external">mongodb官网</a>下载mongod,配置好环境变量.最好也再下个<a href="https://robomongo.org/" target="_blank" rel="external">robomongo</a>,进行更好的图形界面管理</p>
<p><a href="https://docs.mongodb.com/manual/" target="_blank" rel="external">mongodb官方文档</a>    </p>
<p><a href="http://docs.mongoing.com/manual-zh/" target="_blank" rel="external">mongodb中文文档</a></p>
<h4 id="启动Mongod"><a href="#启动Mongod" class="headerlink" title="启动Mongod:"></a>启动Mongod:</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mongod --dbpath /home/python/data/mongodb  --logpath /home/python/data/<span class="built_in">log</span> --auth</div></pre></td></tr></table></figure>
<p>或者用配置文件的方式启动:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">mongod -f ./mongod.conf</div><div class="line">vim ./mongod.conf</div><div class="line">    dbpath = /home/python/data/mongodb/</div><div class="line">    logpath = /home/python/data/<span class="built_in">log</span></div><div class="line">    port = 27017</div><div class="line">    auth = <span class="literal">true</span></div></pre></td></tr></table></figure></p>
<h4 id="进入Mongo的CLI"><a href="#进入Mongo的CLI" class="headerlink" title="进入Mongo的CLI:"></a>进入Mongo的CLI:</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">monogo -uusername -ppasswd 192.168.0.197:27017/db </div><div class="line"><span class="comment"># 如果有语言上的错误</span></div><div class="line"><span class="built_in">export</span> LC_ALL=C</div></pre></td></tr></table></figure>
<h4 id="选择admin数据库-并认证"><a href="#选择admin数据库-并认证" class="headerlink" title="选择admin数据库,并认证:"></a>选择admin数据库,并认证:</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">use admin</div><div class="line">db.auth(<span class="string">'username'</span>,<span class="string">'password'</span>)</div></pre></td></tr></table></figure>
<p>指定好当前数据库后,用db命令查看,之后用密码登陆.</p>
<p><em>查看所有的数据库</em></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">show dbs</div></pre></td></tr></table></figure>
<h3 id="创建或选定数据库"><a href="#创建或选定数据库" class="headerlink" title="创建或选定数据库"></a>创建或选定数据库</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">use 1 <span class="comment"># 该命令将创建一个新的数据库,如果它不存在,否则将返回现有的数据库.</span></div><div class="line">db.dropDatabase(<span class="string">'1'</span>)  <span class="comment"># 删除数据库</span></div></pre></td></tr></table></figure>
<p><em>创建集合(表),删除表,显示所有表</em></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">db.createCollection(<span class="string">'test'</span>)</div><div class="line">db.test.drop()</div><div class="line">show collections</div></pre></td></tr></table></figure>
<p><em>创建文档(记录)</em></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">db.test_table.insert(&#123;<span class="string">'1'</span>:1&#125;)</div></pre></td></tr></table></figure>
<p><em>指定数据库,一定要先选定再创建,创建用户角色</em></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">use <span class="built_in">test</span></div><div class="line">db.createUser( &#123;</div><div class="line">user: <span class="string">"femn2014"</span>,</div><div class="line"><span class="built_in">pwd</span>: <span class="string">"femn2014"</span>,</div><div class="line">roles: [ &#123; role : <span class="string">"readWrite"</span>, db: <span class="string">"test"</span> &#125; ]</div><div class="line">&#125;);</div></pre></td></tr></table></figure>
<p>role:”sysadmin”,”read”,”readWrite”,”sysadmin”和”root”角色只能在第一次创建一次,之后创建的必须是其它的角色,同时也要注意db:’xxx’要改变,如果指定的是admin数据库,则此用户可以看到所有的数据库,并只是针对db:’test’这个数据库有读写操作.</p>
<p><em>指定数据库之后,查看用户</em><br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">use <span class="built_in">test</span></div><div class="line">db.getUsers()</div></pre></td></tr></table></figure></p>
<h3 id="一旦创建好用户之后-就必须要切换到admin数据库中-才能进行对用户角色的管理"><a href="#一旦创建好用户之后-就必须要切换到admin数据库中-才能进行对用户角色的管理" class="headerlink" title="一旦创建好用户之后,就必须要切换到admin数据库中,才能进行对用户角色的管理"></a>一旦创建好用户之后,就必须要切换到admin数据库中,才能进行对用户角色的管理</h3><p><em>用admin数据库,查看,管理所有数据库中的所有用户</em><br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">use admin</div><div class="line">db.system.users.find()</div><div class="line">db.system.users.remove(&#123;user:<span class="string">'femn2014'</span>&#125;) 删除用户</div></pre></td></tr></table></figure></p>
<h4 id="得到test表的索引"><a href="#得到test表的索引" class="headerlink" title="得到test表的索引"></a>得到test表的索引</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">db.test.getIndexes()</div></pre></td></tr></table></figure>
<p><em>创建新的索引,此命令不会覆盖掉之前的索引</em></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">db.test.ensureIndex(&#123;<span class="string">'mobile'</span>:1&#125;)</div></pre></td></tr></table></figure>
<p><em>创建二维索引,通过查询location这个数组,来得到文档</em></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">db.test.ensureIndex(&#123;<span class="string">"location"</span> : <span class="string">"2d"</span>&#125;,&#123;<span class="string">"background"</span> : <span class="literal">true</span>&#125;,</div><div class="line">    &#123;min:-180,max:180&#125;)</div></pre></td></tr></table></figure>
<p>MongoDB的Geospatial Indexing 2d默认取值范围[-179,-179]到[180,180] 包含这两个点,超出范围将报错</p>
<h4 id="备份Mongo"><a href="#备份Mongo" class="headerlink" title="备份Mongo:"></a>备份Mongo:</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">mongodump --host=192.168.1.217 --port=27017 --username=username \</div><div class="line">    --password=passwd --authenticationDatabase admin -dMongodb \</div><div class="line">    -cfemn -o /home/python/nosql_dump</div></pre></td></tr></table></figure>
<h4 id="恢复Mongo"><a href="#恢复Mongo" class="headerlink" title="恢复Mongo:"></a>恢复Mongo:</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">mongorestore -udba -pdba --host=60.205.140.13 --port=27017 \ </div><div class="line">    --authenticationDatabase admin -dbozhongboyue -cvideo \ </div><div class="line">    --drop /home/python/nosql_dump/1-5/bozhongboyue/video.bson</div><div class="line"><span class="comment"># 不经常使用如下命令</span></div><div class="line">mongoexport --host=192.168.1.217 --port=27017 --username=username \ </div><div class="line">    --password=passwd --authenticationDatabase admin -dMongodb -cfemn -o femn.json</div></pre></td></tr></table></figure>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;先去&lt;a href=&quot;https://www.mongodb.com/&quot; target=&quot;_blank&quot; rel=&quot;external&quot;&gt;mongodb官网&lt;/a&gt;下载mongod,配置好环境变量.最好也再下个&lt;a href=&quot;https://robomongo.org/&quot; 
    
    </summary>
    
      <category term="数据库" scheme="https://www.femn.me/categories/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
    
  </entry>
  
  <entry>
    <title>ghost下载与使用</title>
    <link href="https://www.femn.me/2017/08/18/ghost/"/>
    <id>https://www.femn.me/2017/08/18/ghost/</id>
    <published>2017-08-18T03:11:58.000Z</published>
    <updated>2017-08-24T04:10:08.341Z</updated>
    
    <content type="html"><![CDATA[<h3 id="在VPS中-推荐下载最新的ghost"><a href="#在VPS中-推荐下载最新的ghost" class="headerlink" title="在VPS中,推荐下载最新的ghost"></a>在VPS中,推荐下载最新的<a href="https://docs.ghost.org/docs/installing-ghost-via-the-cli" target="_blank" rel="external">ghost</a></h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">yum install gcc nodejs</div><div class="line">npm install -g ghost-cli</div><div class="line">mkdir /var/www/blog</div><div class="line"><span class="built_in">cd</span> /var/www/blog</div><div class="line">ghost install <span class="built_in">local</span></div><div class="line">http://localhost:2368/</div><div class="line"><span class="comment"># 将url换成你博客的地址</span></div><div class="line">vim config.development.json </div><div class="line">    url: http://www.femnyy.com</div><div class="line">ghost restart</div><div class="line">http://www.femnyy.com</div></pre></td></tr></table></figure>
<p>配置一下nginx</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">vim /etc/nginx/conf.d/ghost.conf</div><div class="line">    server &#123; <span class="comment"># 定义一个虚拟主机</span></div><div class="line">        listen 80;</div><div class="line">        <span class="comment">#server_name myip;</span></div><div class="line">        <span class="comment">#server_name 0.0.0.0; 上面的公网IP也不行了,</span></div><div class="line">        <span class="comment">#server_name mydomians; error</span></div><div class="line">        server_name myip www.femnyy.com;</div><div class="line">        location / &#123;</div><div class="line">            proxy_set_header   X-Real-IP <span class="variable">$remote_addr</span>;</div><div class="line">            proxy_set_header   Host      <span class="variable">$http_host</span>;</div><div class="line">            proxy_pass         http://127.0.0.1:2368;</div><div class="line">            &#125;</div><div class="line">        &#125; </div><div class="line">    nginx -t</div><div class="line">    systemctl start nginx</div><div class="line">    systemctl <span class="built_in">enable</span> nginx</div><div class="line">    setsebool -P httpd_can_network_connect <span class="literal">true</span></div></pre></td></tr></table></figure>
<p>访问 <a href="http://www.femnyy.com" target="_blank" rel="external">http://www.femnyy.com</a>  or <a href="http://myip/ghost" target="_blank" rel="external">http://myip/ghost</a></p>
<h3 id="ghost-命令"><a href="#ghost-命令" class="headerlink" title="ghost 命令"></a>ghost 命令</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">ghost -h</div><div class="line"><span class="comment"># 其它命令</span></div><div class="line">ghost ls/update/start/stop/restart</div></pre></td></tr></table></figure>
<h3 id="ghost管理界面的一些基本操作"><a href="#ghost管理界面的一些基本操作" class="headerlink" title="ghost管理界面的一些基本操作"></a>ghost管理界面的一些基本操作</h3><p>同时在管理界面能操作的,就不要去动服务器中的ghost代码,本人能力有限,改了几次,配置都不能用了,只能重新安装(在旧版本中)</p>
<ol>
<li><p><a href="http://www.moiblog.net/2016/ghost-tag/" target="_blank" rel="external">设置标签</a>   再将Tab 设置成Navigation,同样新版本也可以操作Design了.</p>
</li>
<li><p>备份你的博客 导入博客<br> Labs –&gt; Export /Import</p>
</li>
<li><p>提高被搜索的概率<br> setting –&gt; Meta Date –&gt; 输入搜索时的关键字</p>
</li>
</ol>
<h3 id="开始写博客"><a href="#开始写博客" class="headerlink" title="开始写博客"></a>开始写博客</h3><ol>
<li><p><a href="http://blog.leanote.com/post/freewalk/Markdown-%E8%AF%AD%E6%B3%95%E6%89%8B%E5%86%8C" target="_blank" rel="external">有关Markdown的语法手册</a></p>
</li>
<li><p>图片的处理<br><a href="https://portal.qiniu.com/" target="_blank" rel="external">使用七牛的对象存储</a> 或者用<a href="https://sm.ms/" target="_blank" rel="external">sm.ms</a>支持https</p>
</li>
</ol>
<h3 id="不推荐安装旧版本-旧版本安装不好友-想更新ghost版本也费劲-主要是有可以还安不成功"><a href="#不推荐安装旧版本-旧版本安装不好友-想更新ghost版本也费劲-主要是有可以还安不成功" class="headerlink" title="不推荐安装旧版本,旧版本安装不好友,想更新ghost版本也费劲,主要是有可以还安不成功"></a>不推荐安装旧版本,旧版本安装不好友,想更新ghost版本也费劲,主要是有可以还安不成功</h3><p><a href="https://hostpresto.com/community/tutorials/how-to-install-ghost-blogging-platform-on-centos-7/" target="_blank" rel="external">参考</a>于此<br> install nodejs and setting npm source<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">yum -y update</div><div class="line">yum install -y gcc-c++ make unzip netstat</div><div class="line">curl --silent --location https://rpm.nodesource.com/setup_4.x | bash -</div><div class="line">yum -y install nodejs</div><div class="line">node -v</div><div class="line">mkdir -p /var/www/</div><div class="line"><span class="built_in">cd</span> /var/www/</div><div class="line">wget https://ghost.org/zip/ghost-latest.zip</div><div class="line">unzip -uo ghost-latest.zip -d /var/www/ghost</div><div class="line"><span class="built_in">cd</span> ghost</div><div class="line">npm config <span class="built_in">set</span> registry http://registry.npmjs.org/</div><div class="line">npm config <span class="built_in">set</span> strict-ssl <span class="literal">false</span></div></pre></td></tr></table></figure></p>
<p>其中当npm install –production,下载依赖包时,可能会遇到内存不足的问题,可以通过增加交换空间来<a href="https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-ubuntu-12-04?comment=551" target="_blank" rel="external">解决</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">sudo dd <span class="keyword">if</span>=/dev/zero of=/swapfile bs=1024 count=1024k</div><div class="line">sudo mkswap /swapfile</div><div class="line">sudo swapon /swapfile</div><div class="line">vim /etc/fstab</div><div class="line"><span class="built_in">echo</span> 10 | sudo tee /proc/sys/vm/swappiness</div><div class="line"><span class="built_in">echo</span> vm.swappiness = 10 | sudo tee -a /etc/sysctl.conf</div><div class="line">sudo chown root:root /swapfile </div><div class="line">sudo chmod 0600 /swapfile</div></pre></td></tr></table></figure>
<p> install ghost</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">cd</span> /var/www/ghost</div><div class="line">npm install --production</div><div class="line"><span class="comment"># start ghost</span></div><div class="line">cp config.example.js config.js</div><div class="line">vim config.js</div><div class="line">    config = &#123;</div><div class="line">        production: &#123;</div><div class="line">        url: <span class="string">'http://myip'</span></div><div class="line">sudo firewall-cmd --permanent --add-port=80/tcp</div><div class="line">sudo firewall-cmd --permanent --add-port=2368/tcp</div><div class="line">firewall-cmd --reload</div><div class="line">npm start --production</div><div class="line">ss -lnp     |grep 2368</div><div class="line">http://localhost:2368/ghost</div><div class="line"><span class="built_in">kill</span> -9 **</div></pre></td></tr></table></figure>
<p> use pm2 manage ghost  之后就可以不用 nohup npm start –production 启动了</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">npm install -g pm2</div><div class="line"><span class="built_in">echo</span> <span class="string">"export NODE_ENV=production"</span> &amp;gt;&amp;gt; ~/.profile</div><div class="line">. ~/.profile</div><div class="line">pm2 start index.js --name ghost</div><div class="line"><span class="comment"># pm2其它命令</span></div><div class="line">pm2 show/start/stop ghost</div><div class="line">pm2 status/logs/save</div><div class="line"><span class="comment"># 自从我修改了default.hbs之后,pm2就用不了了,害得我还得去重新install ghost</span></div></pre></td></tr></table></figure>
<p> install nginx<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">yum -y install epel-release</div><div class="line">yum -y update</div><div class="line">yum -y install nginx</div><div class="line"><span class="comment"># 配置方法和最新的ghost配置一样</span></div></pre></td></tr></table></figure></p>
<p> 访问 <a href="http://www.femnyy.com" target="_blank" rel="external">http://www.femnyy.com</a> or <a href="http://myip/ghost" target="_blank" rel="external">http://myip/ghost</a></p>
<p>如果是在国内安装的话,可能会比较慢,<a href="https://npm.taobao.org/" target="_blank" rel="external">推荐用淘宝镜像安装</a>,你可以使用我们定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">npm install -g cnpm --registry=https://registry.npm.taobao.org</div></pre></td></tr></table></figure>
<h4 id="update-nodejs-npm"><a href="#update-nodejs-npm" class="headerlink" title="update nodejs npm"></a>update nodejs npm</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">sudo npm cache clean -f</div><div class="line">sudo npm install -g n</div><div class="line">sudo n stable</div></pre></td></tr></table></figure>
<p><a href="https://docs.ghost.org/" target="_blank" rel="external">ghost文档帮助</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;在VPS中-推荐下载最新的ghost&quot;&gt;&lt;a href=&quot;#在VPS中-推荐下载最新的ghost&quot; class=&quot;headerlink&quot; title=&quot;在VPS中,推荐下载最新的ghost&quot;&gt;&lt;/a&gt;在VPS中,推荐下载最新的&lt;a href=&quot;https://do
    
    </summary>
    
      <category term="server" scheme="https://www.femn.me/categories/server/"/>
    
    
  </entry>
  
  <entry>
    <title>linux 服务与进程</title>
    <link href="https://www.femn.me/2017/08/17/linux-server-process/"/>
    <id>https://www.femn.me/2017/08/17/linux-server-process/</id>
    <published>2017-08-17T07:44:24.000Z</published>
    <updated>2017-08-24T05:55:08.595Z</updated>
    
    <content type="html"><![CDATA[<h3 id="linux启动流程"><a href="#linux启动流程" class="headerlink" title="linux启动流程"></a><a href="http://www.ruanyifeng.com/blog/2013/08/linux_boot_process.html" target="_blank" rel="external">linux启动流程</a></h3><p>通电 –&gt;BIOS(哪个磁盘有MBR) –&gt;MBR(哪个分区为要开启的OS) –&gt;OS –&gt;/boot(kernel) –&gt;init(PID:1) –&gt;/etc/rc*.d/ –&gt;/etc/init.d/ –&gt;用户登陆(/etc/profilc–&gt;~/.profile .bash_login .bash_profile–&gt;~/.bashrc)</p>
<h3 id="添加启动项"><a href="#添加启动项" class="headerlink" title="添加启动项"></a>添加启动项</h3><p>/etc/rc[0~6].d 这7个目录中,每个目录分别存放着对应运行级别加载时需要关闭或启动的服务,每个脚本文件都对应着/etc/init.d/目录下具体的服务</p>
<p>K开头的脚本文件代表运行级别加载时需要关闭的,S开头的代表需要执行,数字代表执行顺序<br>因此,当我们需要开机启动自己的脚本时,只需要将可执行脚本丢在/etc/init.d目录下,然后在/etc/rc*.d中建立软链接即可</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">sudo shmod 755 /etc/init.d/ssh</div><div class="line"><span class="built_in">cd</span> /etc/init.d</div><div class="line">sudo update-rc.d ssh defaults 95 5 . <span class="comment"># 执行顺序95,加入运行级别5级中</span></div><div class="line"><span class="comment">#即在rc*.d中各建立了一个软连接,因此也可以自己手动建立软连接,如下</span></div><div class="line">ln -s /etc/init.d/ssh /etc/rc5.d/S95sshd</div><div class="line">sudo /etc/init.d/ssh start</div><div class="line">sudo service S95sshd start</div><div class="line"></div><div class="line"><span class="comment"># 开机启动</span></div><div class="line">sudo apt-get install openssh-server</div><div class="line"><span class="comment"># 二选一</span></div><div class="line">sudo /etc/init.d/ssh start</div><div class="line">sudo service sshd start</div></pre></td></tr></table></figure>
<h3 id="简单的启动命令"><a href="#简单的启动命令" class="headerlink" title="简单的启动命令"></a>简单的启动命令</h3><p>Linux 在启动的时候会执行 /etc/rc.local 里面的脚本,所以只要在这里添加执行命令就可以</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">vim /etc/rc.loca</div><div class="line">/usr/bin/supervisord -c /etc/supervisor/supervisord.conf</div><div class="line"><span class="comment"># 如果是 Ubuntu 16.04 以上,rc.local 被当成了服务,而且默认是不会启动,需要手动启用一下服务</span></div><div class="line"><span class="comment"># 启动rc.local服务:</span></div><div class="line">sudo systemctl <span class="built_in">enable</span> rc-local.service</div></pre></td></tr></table></figure>
<h3 id="定时任务"><a href="#定时任务" class="headerlink" title="定时任务"></a>定时任务</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">vim /etc/crontab </div><div class="line"><span class="comment"># 权限要一致,且要可执行</span></div><div class="line"><span class="comment"># 分　时　日　月　周　命令</span></div><div class="line"><span class="comment"># 每天11点执行</span></div><div class="line">0 11 * * *  root  sh /home/python/xx.sh </div><div class="line"></div><div class="line"><span class="comment"># 每两个小时 </span></div><div class="line">0 */2 * * * <span class="built_in">echo</span> <span class="string">"Have a break now."</span> &gt;&gt; /tmp/test.txt</div><div class="line"></div><div class="line"><span class="comment"># 晚上11点到早上8点之间每两个小时和早上八点 </span></div><div class="line">0 23-7/2,8 * * * <span class="built_in">echo</span> <span class="string">"Have a good dream"</span> &gt;&gt; /tmp/test.txt</div><div class="line"></div><div class="line"><span class="comment"># 保存退出即生效(刚添加的任务会到2-3分钟后才开始生效)</span></div></pre></td></tr></table></figure>
<h3 id="查看服务状态"><a href="#查看服务状态" class="headerlink" title="查看服务状态"></a>查看服务状态</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># ubuntu centos</span></div><div class="line">service sshd status/stop/restart <span class="comment"># service 在rc*.d/的名字</span></div><div class="line"></div><div class="line">systemctl start docker <span class="comment">#centos启动服务</span></div><div class="line">systemctl <span class="built_in">enable</span> docker <span class="comment"># 开机启动</span></div><div class="line">systemctl status nginx</div><div class="line">systemctl start firewalld.service</div><div class="line">systemctl <span class="built_in">enable</span> firewalld.service</div><div class="line">systemctl daemon-reload <span class="comment"># 修改启动参数时的 </span></div><div class="line">systemctl restart docker</div><div class="line"><span class="comment"># 只有systmectl 状态 服务名</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="comment"># redhat 操作系统下</span></div><div class="line">chkconfig 命令</div><div class="line">chkconfig --list sshd</div></pre></td></tr></table></figure>
<h3 id="进程有关的"><a href="#进程有关的" class="headerlink" title="进程有关的"></a>进程有关的</h3><p>“衍生出来的进程”正是 Linux 的父子进程的概念.<br>当我们登录系统后,会取得一个 bash shell,然后我们利用这个 bash 提供的接口去执行另一个命令,</p>
<p>例如 bash 或者 ps 等.那些另外执行的命令也会被触发成为 PID,那个后来执行的命令产生的 PID 就是”子进程”,而原本的 bash 环境下,就称为”父进程”了<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">bash</div><div class="line">ps -o pid,ppid,tty,time,cmd</div><div class="line">    PID  PPID TT           TIME CMD</div><div class="line">    11373  4396 pts/12   00:00:00 bash</div><div class="line">    13043 11373 pts/12   00:00:00 bash</div><div class="line">    13110 13043 pts/12   00:00:00 ps -o pid,ppid,tty,time,cmd</div><div class="line">PID: 运行着的命令(CMD)的进程编号</div><div class="line">PPID:父进程号</div><div class="line">TTY: 命令所运行的位置(终端)</div><div class="line">TIME: 运行着的该命令所占用的CPU处理时间</div><div class="line">CMD: 该进程所运行的命令</div><div class="line"><span class="comment"># ps 仅仅显示本终端的进程</span></div></pre></td></tr></table></figure></p>
<p>我所做的操作是在原来的 bash shell 中执行了 bash 命令,然后又执行了 ps -o pid,ppid,comm命令.我们可以看到<br>,第二个进程 bash 是第一个进程 bash 的子进程,而第三个进程ps是第二个进程的子进程</p>
<p>新的进程要通过老的进程复制自身得到,这就是 fork.fork 是一个系统调用.<br>进程存活于内存中.每个进程都在内存中分配有属于自己的一片空间 (内存空间,包含栈、堆、全局静态区、文本常量区、程序代码区).</p>
<p>当一个程序调用 fork 的时候,实际上就是将上面的内存空间,又复制出来一个,构成一个新的进程,<br>并在内核中为该进程创建新的附加信息 (比如新的 PID,而 PPID 为原进程的 PID).此后,两个进程分别地继续运行下去.<br>新的进程和原有进程有相同的运行状态(相同的变量值,相同的指令…).我们只能通过进程的附加信息来区分两者.</p>
<h4 id="工作管理-job-control"><a href="#工作管理-job-control" class="headerlink" title="工作管理(job control)"></a>工作管理(job control)</h4><p>是用在 bash 环境下的,也就是说,当我们登录系统取得 bash shell 之后,在单一终端机下可以同时进行多个工作的行为管理.</p>
<p>假如我们只有一个终端,因此在可以出现提示符让你操作的环境就成为前台(foreground),至于其他工作就可以放在后台(background)去暂停或运行<br>程序调用 exec 的时候,进程清空自身的内存空间,并根据新的程序文件重建程序代码、文本常量、全局静态、堆和栈(此时堆和栈大小都为 0),并开始运行.</p>
<h4 id="直接将命令放到后台执行-amp"><a href="#直接将命令放到后台执行-amp" class="headerlink" title="直接将命令放到后台执行 ( &amp;)"></a>直接将命令放到后台执行 ( &amp;)</h4><h4 id="将目前工作放到后台并暂停-ctrl-z"><a href="#将目前工作放到后台并暂停-ctrl-z" class="headerlink" title="将目前工作放到后台并暂停(ctrl+z)"></a>将目前工作放到后台并暂停(ctrl+z)</h4><h4 id="将后台工作拿到前台来处理-fg-工作序号"><a href="#将后台工作拿到前台来处理-fg-工作序号" class="headerlink" title="将后台工作拿到前台来处理(fg %工作序号)"></a>将后台工作拿到前台来处理(fg %工作序号)</h4><h3 id="进程管理命令"><a href="#进程管理命令" class="headerlink" title="进程管理命令"></a>进程管理命令</h3><h4 id="ps-PID-CMD-PORT"><a href="#ps-PID-CMD-PORT" class="headerlink" title="ps: PID,CMD,PORT"></a>ps: PID,CMD,PORT</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line">ps <span class="comment"># 仅仅显示本终端的进程</span></div><div class="line"></div><div class="line">-a <span class="comment"># 显示终端中进行的所有进程</span></div><div class="line">-x <span class="comment"># 会显示没有控制终端的进程</span></div><div class="line">-e <span class="comment"># 所有的进程</span></div><div class="line">-u <span class="comment"># 查看某个用户的所有进程</span></div><div class="line">-f <span class="comment"># 来查看格式化的信息列表</span></div><div class="line">ps -u femn <span class="comment"># 查看所有femn用户的进程 </span></div><div class="line">ps aux <span class="comment"># 可以对系统进程更加全面的了解</span></div><div class="line">ps -aux | less </div><div class="line"><span class="comment"># less是一个分页显示文件的工具工具,它允许你一页一页(或一个屏幕一个屏幕)地查看信息</span></div><div class="line"></div><div class="line">ps -ef <span class="comment"># 所有进程 PID PPID </span></div><div class="line">ps -efH <span class="comment"># 把输出的进程组成一个层级的格式 树状 </span></div><div class="line">ps axjf  <span class="comment"># 树状视图 等于 pstree</span></div><div class="line">ps -ef | grep python3 | cut -c 10-15 | xargs <span class="built_in">kill</span> -9 </div><div class="line"><span class="comment"># Kill 某个用户或命令的所有进程</span></div><div class="line">ps axjf |grep nginx</div><div class="line">pgrep nginx <span class="comment"># 单单的得到PID,和其子进程号</span></div><div class="line"></div><div class="line">ps -aux --sort -pcpu | head -n 10</div><div class="line"><span class="comment"># 根据 CPU 使用来升序排序 +pcpu倒序</span></div><div class="line">ps -aux --sort -pmem | head -n 10</div><div class="line"><span class="comment"># 根据 内存 使用来升序排序</span></div><div class="line">ps -aux --sort -pcpu,-pmem | head -n 10</div><div class="line"></div><div class="line"><span class="comment"># 仅仅得到本机的程序名相关的进程</span></div><div class="line">ps aux/-ef |grep ssserver <span class="comment"># 程序名(命令名)或者PID</span></div></pre></td></tr></table></figure>
<h4 id="netstat-PID-CMD-PORT"><a href="#netstat-PID-CMD-PORT" class="headerlink" title="netstat:PID,CMD,PORT"></a>netstat:PID,CMD,PORT</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 会牵扯到此程序 相关联的socket服务,或其它的网络相接进程(网络是双向的)</span></div><div class="line">netstat -anp |grep ssh <span class="comment">#程序名  得到PID 端口号</span></div><div class="line">netstat -lnp |grep 8388  <span class="comment">#端口号 得到PID,进程名</span></div><div class="line">sudo lsof -i :8001   <span class="comment">#查看此端口 PID,User,进程名</span></div><div class="line"></div><div class="line">ll /proc/进程号  </div><div class="line">sudo lsof -p 1609</div><div class="line">killall http* 它支持通过进程名而不是进程号来结束进程,也支持通配符.</div></pre></td></tr></table></figure>
<h4 id="top"><a href="#top" class="headerlink" title="top"></a>top</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">top <span class="comment"># 动态显示进程 q 退出, M 内存占用降序排序,P 按CPU占用降序排序 </span></div><div class="line">[top使用说明](http://www.linuxidc.com/Linux/2011-03/33582.htm)</div><div class="line">ssserver内存占用随时间升高</div><div class="line">free -m <span class="comment"># 内在的使用情况</span></div><div class="line"><span class="comment"># 查看目前进程正在实际被使用的内存,是used-(buffers+cache)</span></div><div class="line">htop <span class="comment"># 更加友好的显示top</span></div></pre></td></tr></table></figure>
<h3 id="进程的状态"><a href="#进程的状态" class="headerlink" title="进程的状态"></a>进程的状态</h3><h4 id="sleeping"><a href="#sleeping" class="headerlink" title="sleeping"></a>sleeping</h4><p>D(sleeping),往往是由于 I/O(磁盘IO,网络IO,其他外设IO) 资源得不到满足,而引发等待</p>
<p>举个例子,当 NFS 服务端关闭之时,若未事先 umount 相关目录,在 NFS 客户端执行 df 就会挂住整个登录会话,按 Ctrl+C 、Ctrl+Z 都无济于事.<br>断开连接再登录,执行 ps axf 则看到刚才的 df 进程状态位已变成了 D ,kill -9 无法杀灭.</p>
<p>正确的处理方式,是马上恢复 NFS 服务端,再度提供服务,刚才挂起的 df 进程发现了其苦苦等待的资源,便完成任务,自动消亡.若 NFS 服务端无法恢复服务,在 reboot 之前也应将 /etc/mtab 里的相关 NFS mount 项删除,以免 reboot 过程例行调用 netfs stop 时再次发生等待资源,导致系统重启过程挂起.</p>
<h3 id="zombile"><a href="#zombile" class="headerlink" title="zombile"></a>zombile</h3><p>Z(zombie) 之所以杀不死,是因为它已经死了,否则怎么叫 Zombie(僵尸).在UNIX/Linux中,每个进程都有一个父进程,进程号叫PID(Process ID), 相应地,父进程号就叫PPID(Parent PID).</p>
<p>当进程死亡时,它会自动关闭已打开的文件,舍弃已占用的内存、交换空间等等系统资源,然后向其父进程返回一个退出状态值,报告死讯.如果程序有 bug,就会在这最后一步出问题.子进程说我死了,父进程却没听见,所以子进程便成了僵尸.在UNIX/Linux中消灭僵尸的手段比较残忍,执行 ps axjf 找出僵尸进程的父进程号(PPID,第一列),先杀其父,然后再由进程天子 init(其PID为1,PPID为0)来一起收拾父子僵尸.注意,子进程变成僵尸只是碍眼而已,并不碍事,如果僵尸的父进程当前有要务在身,则千万不可贸然杀之.</p>
<p>这些进程已经死亡,但没有释放系统资源,包括内存和一些一些系统表等,如果这样的进程很多,会引发系统问题.用ps -el看出的进程状态如果是Z,就是僵尸进程.<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">ps -ef|grep defunc <span class="comment"># 可以找出僵尸进程</span></div><div class="line"><span class="comment"># 清除ZOMBIE(僵尸)进程可以使用如下方法:</span></div><div class="line"></div><div class="line"><span class="built_in">kill</span> –18 PPID (PPID是其父进程)</div><div class="line"><span class="comment"># 这个信号是告诉父进程,该子进程已经死亡了,请收回分配给他的资源.</span></div></pre></td></tr></table></figure></p>
<p>如果不行则看能否终止其父进程(如果其父进程不需要的话).先看其父进程又无其他子进程,如果有,可能需要先kill其他子进程,也就是兄弟进程.方法是:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">kill</span> –15 PID1 PID2 <span class="comment"># (PID1,PID2是僵尸进程的父进程的其它子进程).</span></div><div class="line"><span class="built_in">kill</span> –15 PPID  <span class="comment"># 然后再kill父进程,这样僵尸进程就可能被完全杀掉了</span></div></pre></td></tr></table></figure></p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;linux启动流程&quot;&gt;&lt;a href=&quot;#linux启动流程&quot; class=&quot;headerlink&quot; title=&quot;linux启动流程&quot;&gt;&lt;/a&gt;&lt;a href=&quot;http://www.ruanyifeng.com/blog/2013/08/linux_boot_
    
    </summary>
    
      <category term="linux" scheme="https://www.femn.me/categories/linux/"/>
    
    
      <category term="server" scheme="https://www.femn.me/tags/server/"/>
    
  </entry>
  
  <entry>
    <title>shadowsocks</title>
    <link href="https://www.femn.me/2017/08/16/shadowsocks-server/"/>
    <id>https://www.femn.me/2017/08/16/shadowsocks-server/</id>
    <published>2017-08-16T07:24:48.000Z</published>
    <updated>2017-08-24T06:05:22.010Z</updated>
    
    <content type="html"><![CDATA[<h3 id="用shadowsocks作为翻墙的工具"><a href="#用shadowsocks作为翻墙的工具" class="headerlink" title="用shadowsocks作为翻墙的工具"></a>用shadowsocks作为翻墙的工具</h3><p>一般的翻墙工具还有VPN,pptp是VPN的一种,我们在这里介绍的是shadowsocks翻墙工具 </p>
<p> <a href="https://shadowsocks.org/en/download/clients.html" target="_blank" rel="external">shadowsocks 官网</a></p>
<p> <a href="https://www.loyalsoldier.me/fuck-the-gfw-with-my-own-shadowsocks-server/" target="_blank" rel="external">centos7 install shadowsocks</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">yum install python-setuptools &amp;&amp; easy_install pip  </div><div class="line">pip install shadowsocks</div><div class="line">vim /root/ss/ssserver.json</div><div class="line">    &#123;</div><div class="line">      <span class="string">"server"</span>: <span class="string">"0.0.0.0"</span>,</div><div class="line">      <span class="string">"server_port"</span>: 8388,</div><div class="line">      <span class="string">"local_address"</span>: <span class="string">"127.0.0.1"</span>,</div><div class="line">      <span class="string">"local_port"</span>: 1080,</div><div class="line">      <span class="string">"password"</span>: <span class="string">"yourpassword"</span>,</div><div class="line">      <span class="string">"timeout"</span>: 300,</div><div class="line">      <span class="string">"method"</span>: <span class="string">"aes-256-cfb"</span>,</div><div class="line">      <span class="string">"fast_open"</span>: <span class="literal">false</span></div><div class="line">    &#125;</div><div class="line"></div><div class="line">systemctl start firewalld.service</div><div class="line">systemctl <span class="built_in">enable</span> firewalld.service</div><div class="line">firewall-cmd --permanent --add-port=8388/tcp</div><div class="line">firewall-cmd --reload</div></pre></td></tr></table></figure>
<p>启动 ssserver服务<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">nohup ssserver -c /root/ss/ssserver.json -d start &amp;</div></pre></td></tr></table></figure></p>
<p>查看ssserver 有没有启动成功</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">ps aux |grep ssserver</div></pre></td></tr></table></figure>
<p>如果没有成功,可能是因为/root/ss/ssserver.json 的server_ip的原因,我买了个<a href="https://intl.aliyun.com/zh" target="_blank" rel="external">国际阿里云</a>的ECS服务器,我写的是公网的IP,结果一直运行不起来<br>因为公网是通过nat IP实现的(所以在安全组中只能是选择内网进行配置),所以改成Privaty IP就可以正常启动了,最好是设置为0.0.0.0就好.</p>
<p>阿里云的ECS服务器上配置使用任意端口的服务后,端口会自动开启监听,但它还有一个安全组的概念,最好设置一个(内网   入  允许 全部 -1/-1   0.0.0.0/0  优先级110)<br>这样就完全可以由ECS的系统完全的操作防火墙,就像没有安全组概念一样了.</p>
<p> <a href="https://www.vultr.com/docs/how-to-deploy-google-bbr-on-centos-7" target="_blank" rel="external">centos7 install BBR</a> 要注意下sudo grub2-set-default 0,应该是为0的,使用最新的,文档却写成了1<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># update kernet</span></div><div class="line"><span class="comment"># look current kernet</span></div><div class="line">uname -r</div><div class="line"><span class="comment"># Install the ELRepo repo:</span></div><div class="line">sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org</div><div class="line">sudo rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm</div><div class="line"><span class="comment"># install newer kernet</span></div><div class="line">sudo yum --enablerepo=elrepo-kernel install kernel-ml -y</div><div class="line"><span class="comment"># look install newer kernet</span></div><div class="line">rpm -qa | grep kernel</div><div class="line">sudo egrep ^menuentry /etc/grub2.cfg | cut -f 2 -d \<span class="string">'</span></div><div class="line"><span class="string"># setting newer kernet</span></div><div class="line"><span class="string">sudo grub2-set-default 0</span></div><div class="line"><span class="string">sudo shutdown -r now</span></div><div class="line"><span class="string">uname -r</span></div><div class="line"><span class="string"></span></div><div class="line"><span class="string"></span></div><div class="line"><span class="string"># enable BBr</span></div><div class="line"><span class="string">echo '</span>net.core.default_qdisc=fq<span class="string">' | sudo tee -a /etc/sysctl.conf</span></div><div class="line"><span class="string">echo '</span>net.ipv4.tcp_congestion_control=bbr<span class="string">' | sudo tee -a /etc/sysctl.conf</span></div><div class="line"><span class="string">sudo sysctl -p</span></div><div class="line"><span class="string">sudo sysctl net.ipv4.tcp_available_congestion_control</span></div><div class="line"><span class="string">net.ipv4.tcp_available_congestion_control = bbr cubic reno</span></div><div class="line"><span class="string">sudo sysctl -n net.ipv4.tcp_congestion_control</span></div><div class="line"><span class="string">bbr</span></div><div class="line"><span class="string">lsmod |grep bbr   # output   tcp_bbr                16384  0</span></div></pre></td></tr></table></figure></p>
<p><a href="https://github.com/shadowsocks/shadowsocks-qt5/wiki/%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97" target="_blank" rel="external">client install shadowsocks</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">#ubuntu</span></div><div class="line">sudo add-apt-repository ppa:hzwhuang/ss-qt5</div><div class="line">sudo apt-get update</div><div class="line">sudo apt-get install shadowsocks-qt5</div><div class="line">ss-qt5</div><div class="line"><span class="comment"># 将ssserver.json的配置,设置到ss中</span></div></pre></td></tr></table></figure>
<h3 id="注意-一定要再去配置下代理Pxory-0-0-0-0-1080-或者用本地的-pac文件-Local-Port就必须和service-pac文件-此文件是过滤网址用的-如果访问文件中的网址则走代理-启动的端口一致"><a href="#注意-一定要再去配置下代理Pxory-0-0-0-0-1080-或者用本地的-pac文件-Local-Port就必须和service-pac文件-此文件是过滤网址用的-如果访问文件中的网址则走代理-启动的端口一致" class="headerlink" title="注意:一定要再去配置下代理Pxory 0.0.0.0:1080 或者用本地的.pac文件,Local Port就必须和service.pac文件(此文件是过滤网址用的,如果访问文件中的网址则走代理)启动的端口一致."></a>注意:一定要再去配置下代理Pxory 0.0.0.0:1080 或者用本地的.pac文件,Local Port就必须和service.pac文件(此文件是过滤网址用的,如果访问文件中的网址则走代理)启动的端口一致.</h3><p><a href="http://pac.ddcc.me/1.pac" target="_blank" rel="external">http://pac.ddcc.me/1.pac</a> == local.pac</p>
<h4 id="在国际里云购买的ESC-配置好shadowsocks之后-在手机上能正常使用-也不需要去设置代理-但在Ubuntu桌面下却一直用不了"><a href="#在国际里云购买的ESC-配置好shadowsocks之后-在手机上能正常使用-也不需要去设置代理-但在Ubuntu桌面下却一直用不了" class="headerlink" title="在国际里云购买的ESC,配置好shadowsocks之后,在手机上能正常使用,也不需要去设置代理,但在Ubuntu桌面下却一直用不了"></a>在国际里云购买的ESC,配置好shadowsocks之后,在手机上能正常使用,也不需要去设置代理,但在Ubuntu桌面下却一直用不了</h4><p> 如果自己不想搭建服务器的话,可以按下面的操作进行翻墙:</p>
<p> <a href="https://doub.io/sszhfx/" target="_blank" rel="external">Shadowsocks免费账号分享</a>,但这个网址要先翻墙才行,哈哈<br> 具体的使用:在免费账号分享的这个网址上 </p>
<p>1.使用二维码:点击二维码会出现一个二维码的图 这里打开shadowsocks软件–&gt;点鼠标右键–&gt;add–&gt;scan QR code on screen</p>
<p>2.使用生成二维码的url:在add–&gt;选择url中ss以及后面的部分<br>如果失败的话,可以换其它的二维码试试.</p>
<p><a href="https://github.com/TestSmirk/ss-ip" target="_blank" rel="external">这个是我大哥自己搭建的一些ss帐号</a></p>
<h3 id="ubuntu-etc-resolv-conf"><a href="#ubuntu-etc-resolv-conf" class="headerlink" title="ubuntu /etc/resolv.conf"></a>ubuntu /etc/resolv.conf</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">nameserver 127.0.1.1</div><div class="line"><span class="comment"># nameserver 8.8.8.8</span></div><div class="line">search DHCP HOST</div></pre></td></tr></table></figure>
<h3 id="加速SS的链接速度"><a href="#加速SS的链接速度" class="headerlink" title="加速SS的链接速度"></a><a href="http://vegetablefinn.github.io/2016/05/02/SS%E7%A5%9E%E5%99%A8-FinalSpeed-XSocks-%E7%AC%94%E8%AE%B0/" target="_blank" rel="external">加速SS的链接速度</a></h3>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;用shadowsocks作为翻墙的工具&quot;&gt;&lt;a href=&quot;#用shadowsocks作为翻墙的工具&quot; class=&quot;headerlink&quot; title=&quot;用shadowsocks作为翻墙的工具&quot;&gt;&lt;/a&gt;用shadowsocks作为翻墙的工具&lt;/h3&gt;&lt;p&gt;一般
    
    </summary>
    
      <category term="server" scheme="https://www.femn.me/categories/server/"/>
    
    
  </entry>
  
  <entry>
    <title>sshd</title>
    <link href="https://www.femn.me/2017/08/16/sshd-server/"/>
    <id>https://www.femn.me/2017/08/16/sshd-server/</id>
    <published>2017-08-16T07:24:48.000Z</published>
    <updated>2017-08-24T05:56:42.876Z</updated>
    
    <content type="html"><![CDATA[<h4 id="server"><a href="#server" class="headerlink" title="server"></a>server</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">sudo apt-get install openssh-server</div><div class="line">ps ef|grep ssh</div><div class="line">sudo /etc/init.d/ssh start 或者 service sshd start</div><div class="line"></div><div class="line"><span class="comment"># 创建一个普通用户</span></div><div class="line">useradd username</div><div class="line">passwd username</div><div class="line">vim /etc/ssh/sshd_config</div><div class="line">    Port 22333</div><div class="line">    PermitRootLogin no</div><div class="line">    TCPKeepAlive yes</div><div class="line">    ClientAliveInterval 360</div><div class="line">    ClientAliveCountMax 20</div><div class="line"></div><div class="line"><span class="comment"># 给普通用户附sudo权限</span></div><div class="line">chmod u+w /etc/sudoers</div><div class="line">vim /etc/sudoers</div><div class="line">    root            ALL=(ALL)                ALL</div><div class="line">    username            ALL=(ALL)                ALL</div><div class="line">chmod u-w /etc/sudoers</div><div class="line"></div><div class="line">/etc/init.d/ssh start</div><div class="line">service sshd restart</div><div class="line">firewall-cmd --permanent --add-port=22333/tcp</div><div class="line">firewall-cmd --reload</div></pre></td></tr></table></figure>
<h4 id="client"><a href="#client" class="headerlink" title="client"></a>client</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">ssh -p 22333 username@ip</div></pre></td></tr></table></figure>
<h3 id="SSH无密码登录"><a href="#SSH无密码登录" class="headerlink" title="SSH无密码登录"></a>SSH无密码登录</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># client:生成SSH公钥</span></div><div class="line">ssh-keygen -t rsa -C <span class="string">"邮箱"</span> </div><div class="line"></div><div class="line"><span class="comment"># 将SSH公钥上传到Linux服务器</span></div><div class="line">ssh-copy-id -p 22 username@remote-server</div><div class="line"><span class="comment"># 将client端的gedit ~/.ssh/id_rsa.pub的内容放到server端~/.ssh/authorized_keys</span></div><div class="line"><span class="comment"># 等同于如下</span></div><div class="line">cat ~/.ssh/id_rsa.pub | ssh username@your_host \ </div><div class="line">    <span class="string">"cat - &gt;&gt; /home/username/.ssh/authorized_keys"</span></div></pre></td></tr></table></figure>
]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;server&quot;&gt;&lt;a href=&quot;#server&quot; class=&quot;headerlink&quot; title=&quot;server&quot;&gt;&lt;/a&gt;server&lt;/h4&gt;&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutt
    
    </summary>
    
      <category term="server" scheme="https://www.femn.me/categories/server/"/>
    
    
  </entry>
  
  <entry>
    <title>内容分发网络</title>
    <link href="https://www.femn.me/2017/08/16/CDN-server/"/>
    <id>https://www.femn.me/2017/08/16/CDN-server/</id>
    <published>2017-08-16T07:24:48.000Z</published>
    <updated>2017-08-24T06:08:05.636Z</updated>
    
    <content type="html"><![CDATA[<h3 id="CDN"><a href="#CDN" class="headerlink" title="CDN:"></a>CDN:</h3><p>内容分发网络(Content delivery network或Content distribution network,缩写:CDN)是指一种通过互联网互相连接的电脑网络系统,<br>利用最靠近每位用户的服务器,更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户,来提供高性能、可扩展性及低成本的网络内容传递给用户</p>
<h3 id="CDN的作用"><a href="#CDN的作用" class="headerlink" title="CDN的作用"></a>CDN的作用</h3><h4 id="1-加速您网站的访问"><a href="#1-加速您网站的访问" class="headerlink" title="1.加速您网站的访问:"></a>1.加速您网站的访问:</h4><p>访问者的每个访问请求,都会被自动发送到物理距离最近、速度最快的节点上.<br>将blog内容的所有的东西(图片,文字,视频)都是保存在自己的服务器中,要从自己的服务器中取得,当如果某个页面需要加载很多内容时,速度就会变慢.<br>而cdn就会把所以网址上的东西,全部分送到它们在全世界各地所架设的云端的伺服务器上,也就是说我的网址会被散播(拆解)到全世界的伺服务器上,取最近的.</p>
<h4 id="2-防骇客-抵御DoS攻击-访问我们的网址-相当于访问到云端的伺服务器上"><a href="#2-防骇客-抵御DoS攻击-访问我们的网址-相当于访问到云端的伺服务器上" class="headerlink" title="2.防骇客,抵御DoS攻击,访问我们的网址,相当于访问到云端的伺服务器上."></a>2.防骇客,抵御DoS攻击,访问我们的网址,相当于访问到云端的伺服务器上.</h4><h4 id="3-可以承受网站的流量-节省您的流量"><a href="#3-可以承受网站的流量-节省您的流量" class="headerlink" title="3.可以承受网站的流量,节省您的流量:"></a>3.可以承受网站的流量,节省您的流量:</h4><p>您的网站内容将被缓存在 CloudFlare 的节点中,访问者并不直接从您的主机获取内容,从而最大限度地节省主机的流量<br>同时网站的下载速度也会比以往的快些.</p>
<h3 id="使用cloudflare加速"><a href="#使用cloudflare加速" class="headerlink" title="使用cloudflare加速"></a>使用<a href="https://www.cloudflare.com/" target="_blank" rel="external">cloudflare</a>加速</h3><p>cloudflare是一个国外著名的免费CDN网站加速服务公司<br>甚至可以在网站主服务器宕机的情况下,访问者依然可以通过 CloudFlare 的分发服务器访问到您的网站</p>
<p><a href="http://www.xujiahua.com/4680.html" target="_blank" rel="external">使用cloudflare的教程</a></p>
<h3 id="但使用了cloudflare之后-就不再支持泛域名的解析了-所以还得多配置nginx"><a href="#但使用了cloudflare之后-就不再支持泛域名的解析了-所以还得多配置nginx" class="headerlink" title="但使用了cloudflare之后,就不再支持泛域名的解析了,所以还得多配置nginx."></a>但使用了cloudflare之后,就不再支持泛域名的解析了,所以还得多配置nginx.</h3>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;CDN&quot;&gt;&lt;a href=&quot;#CDN&quot; class=&quot;headerlink&quot; title=&quot;CDN:&quot;&gt;&lt;/a&gt;CDN:&lt;/h3&gt;&lt;p&gt;内容分发网络(Content delivery network或Content distribution network,缩写:
    
    </summary>
    
      <category term="server" scheme="https://www.femn.me/categories/server/"/>
    
    
  </entry>
  
  <entry>
    <title>VPS搭建网站</title>
    <link href="https://www.femn.me/2017/08/15/vps-server/"/>
    <id>https://www.femn.me/2017/08/15/vps-server/</id>
    <published>2017-08-15T03:16:14.000Z</published>
    <updated>2017-08-24T07:41:51.896Z</updated>
    
    <content type="html"><![CDATA[<h3 id="空间-虚拟主机-虚拟空间"><a href="#空间-虚拟主机-虚拟空间" class="headerlink" title="空间(虚拟主机,虚拟空间)"></a>空间(虚拟主机,虚拟空间)</h3><p>它是利用软件在服务器上硬盘上划分出来的一部分容量.共享的是服务器资源.<br>没有独立的IP和操作系统.开通以后只有一个FTP权限.它所支持的程序也是在服务器上默认配置好的.空间一般都装有面板,是傻瓜化的操作<br>由于多台虚拟主机共享一台真实主机的资源,每个用户所要承担的各类费用大幅度降低.</p>
<p>自从进入IT圈,以前使用国内的空间,感觉还行,速度快,但是后面的备案系统让大多数的站长跑到墙外来选择空间:<br>Godaddy、Dreamhost、Froghost、Photonvps等空间相信大多数的站长多多少少都会用过<br>但是随之而来的各种问题都让大家受到精神上的折磨,不过相信大家都是比较的喜欢捣鼓吧,从2012年开始很多的站长都选择到VPS行列中了,<br>以前高高在上的VPS现在已经沦为普通人都买得起用得起的产品了,但是想要好一点的,响应快一点的VPS主机价格还是很贵,</p>
<p>VPS还是比较适合对网站空间要求比较高的朋友来使用的,独立IP,完全自主的控制权限这些都是一般的虚拟主机所没有的.</p>
<p>自从2013年digitalocean把SSD的主机价格拉到5元每月之后,相信很多人都从Linode转过来了,不为什么,价格决定啊,而且性能上和高大上的Linode差别不是很多,<br>还是能得到大多数人的肯定,今年Vultr 的杀入,更是让大多数人目瞪口呆,因为价格更加便宜,而且内存上加到到768Ma,<br>而价格最优惠可以到2.5美金一个月,这样的产品绝对是对国人来说是一个杀伤力</p>
<h3 id="VPS-Virtual-Private-Server-虚拟服务器"><a href="#VPS-Virtual-Private-Server-虚拟服务器" class="headerlink" title="VPS(Virtual Private Server)虚拟服务器"></a>VPS(Virtual Private Server)虚拟服务器</h3><p>VPS就是将一台真正的服务器主机(可以理解为独立服务器),分为多台虚拟服务器主机.<br>但是虚拟出来的每一台服务器都有主机独立的内存、CPU、硬盘,因此在性能上相当一台真实存在的主机,但是成本却是很低,降低了初学者进入VPS主机门槛<br>VPS提供商:<br><a href="https://www.vultr.com/" target="_blank" rel="external"> Vultar</a>,<a href="https://www.digitalocean.com/" target="_blank" rel="external">DigitalOcean</a>,<a href="https://www.linode.com/" target="_blank" rel="external">Linode</a>,<a href="https://virmach.com/" target="_blank" rel="external">virmach</a>, <a href="https://bandwagonhost.com/" target="_blank" rel="external">Bandwagon</a>,<a href="https://intl.aliyun.com/" target="_blank" rel="external">国际阿里云</a></p>
<p>VPS除了可以用来做网站的服务器,还可以建立自己的ssh,vpn,shadowsocks等进行代理翻墙,可以一键快速配置Docker,GitLab,wonCloud.WordPress等其它应用.</p>
<p>Vultr VPS采用的是KVM虚拟化技术(openvz 还是 kvm 还是 xen 或者是 vmare ).</p>
<h3 id="1-购买VPS"><a href="#1-购买VPS" class="headerlink" title="1.购买VPS:"></a>1.购买VPS:</h3><p><a href="https://vultr.com/" target="_blank" rel="external">vultr官网</a></p>
<p><a href="http://www.hostloc.com" target="_blank" rel="external">全球主机交流</a></p>
<p><a href="http://tool.chinaz.com/" target="_blank" rel="external">站长工具</a></p>
<h3 id="2-购买域名"><a href="#2-购买域名" class="headerlink" title="2.购买域名"></a>2.购买域名</h3><p><a href="https://www.name.com" target="_blank" rel="external">name.com</a> 购买域名的优惠码: privacyplease 注意:目前只支持paypal或信用卡支持,不支持支付宝</p>
<h3 id="3-设置DNS-将域名记录到此DNS服务器上-并将域名指定到VPS上-域名解析成IP"><a href="#3-设置DNS-将域名记录到此DNS服务器上-并将域名指定到VPS上-域名解析成IP" class="headerlink" title="3.设置DNS(将域名记录到此DNS服务器上),并将域名指定到VPS上(域名解析成IP)"></a>3.设置DNS(将域名记录到此DNS服务器上),并将域名指定到VPS上(域名解析成IP)</h3><p><a href="http://www.chinaz.com/web/2013/0103/287946.shtml" target="_blank" rel="external">DNS解析</a> 可以通过My Account –&gt; My Domains –&gt;选择Quick Links这个下拉框的Manage Domain</p>
<h4 id="推荐域名管理页面-添加解析域名记录"><a href="#推荐域名管理页面-添加解析域名记录" class="headerlink" title="推荐域名管理页面(添加解析域名记录)"></a>推荐域名管理页面(添加解析域名记录)</h4><p>将购买的域名放在<a href="https://www.dnspod.cn/" target="_blank" rel="external">dnspod</a>下进行管理:便于管理多个域名,只要再修改下name.com的DNS,换成dnspod的域名解析服务器,<br>以后就可以在这里添加解析自己的域名记录了</p>
<p><a href="https://support.dnspod.cn/Kb/showarticle/tsid/177/#ChangeDomainNS" target="_blank" rel="external">修改DNS解析服务器</a></p>
<h3 id="4-申请证书-支持泛域名"><a href="#4-申请证书-支持泛域名" class="headerlink" title="4.申请证书,支持泛域名"></a>4.申请证书,支持泛域名</h3><p><a href="http://51.ruyo.net/p/3804.html" target="_blank" rel="external">申请AlphaSSL免费证书教程</a></p>
<p><a href="https://csr.chinassl.net/generator-csr.html" target="_blank" rel="external">1.生成CSR,KEY文件</a><br>注意: 邮箱:自己常用的邮箱 域名:*.femnyy.com</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 也可以用命令行生成</span></div><div class="line">openssl req -new -newkey rsa:2048 -nodes -keyout howsvps.key -out howsvps.csr</div><div class="line"><span class="comment">#注意在填写域名时,不需要添加二级域名:femnyy.com这样认证之后的这个证书,就可以是通配使用了</span></div><div class="line">并没有将admin@femnyy.com的链接发到我的邮箱上,如果并没有给你发邮箱的话,</div></pre></td></tr></table></figure>
<p>2.注册域名邮箱,本人使用的是qq注册域名邮箱</p>
<p>注意: 使用其他邮箱给 admin 邮箱发送一份邮件,能接收,说明没问题！ 不能使用关联的QQ邮箱<br>如果不能接收,检查你的域名 MX / TXT 是否解析到其他地方了<br>别名就是主机记录,别名主机就是记录值<br>然后再加一个成员管理admin</p>
<p><a href="https://assl.loovit.com/" target="_blank" rel="external">3.免费SSL certificates</a><br>注意: 认证的邮箱 与上面的1步骤要一致</p>
<p>4.选择你刚刚注册的域名邮箱</p>
<p>5.邮件确认SSL证书申请,点击 I APPROVE,之后会再来一封.crt的文件 <a href="https://doub.io/wlzy-28/" target="_blank" rel="external">安装AlphaSLL教程</a></p>
<p>6.再将<a href="https://www.alphassl.com/support/install-root-certificate.html" target="_blank" rel="external">中级证书</a>中,SHA-256 – Orders March 31, 2014 and After的代码,复制到.crt的文件,合成最终的.crt文件</p>
<p>7.再将.crt key文件 复制到服务器上,nginx的配置如下,同腾讯的一样配置</p>
<p>8.有了泛域名之后,就可以在 server_name 增加 *.femnyy.com;</p>
<h3 id="4-上面的证书没有成功的话-那就用腾讯云SSL证书-免费一年"><a href="#4-上面的证书没有成功的话-那就用腾讯云SSL证书-免费一年" class="headerlink" title="4.上面的证书没有成功的话,那就用腾讯云SSL证书 免费一年"></a>4.上面的证书没有成功的话,那就用<a href="https://console.qcloud.com/ssl" target="_blank" rel="external">腾讯云SSL证书</a> 免费一年</h3><p>csr证书请求文件–交给CA签名后形成服务端自己的证书,认证通过之后,签证机构给你crt文件 crt+key = pem </p>
<p>cat crt key = pem<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line">vim /etc/nginx/conf.d/ghost</div><div class="line">    server &#123;</div><div class="line">        listen 80;</div><div class="line">        <span class="comment">#server_name puplic IP;</span></div><div class="line">        <span class="comment">#server_name 0.0.0.0; 上面的公网IP也不行了,</span></div><div class="line">        server_name www.femnyy.com puplic_IP yy.femnyy.com;</div><div class="line">        <span class="comment">#server_name femnyy.com;</span></div><div class="line">        rewrite ^(.*) https://<span class="variable">$host</span><span class="variable">$1</span> permanent;</div><div class="line">        <span class="built_in">return</span> 301 https://<span class="variable">$server_name</span><span class="variable">$request_uri</span>;</div><div class="line">    &#125;</div><div class="line">    server&#123;</div><div class="line">        listen  443;</div><div class="line">        server_name  www.femnyy.com;</div><div class="line">        ssl on; </div><div class="line">        <span class="comment">#index index.htm index.html;</span></div><div class="line">        ssl_certificate   /etc/nginx/conf.d/Nginx_ssl/server.crt;</div><div class="line">        ssl_certificate_key  /etc/nginx/conf.d/Nginx_ssl/server.key;</div><div class="line">        ssl_session_timeout 5m; </div><div class="line">        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;</div><div class="line">        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;</div><div class="line">        ssl_prefer_server_ciphers on; </div><div class="line">        location / &#123;</div><div class="line">            proxy_set_header   X-Real-IP <span class="variable">$remote_addr</span>;</div><div class="line">            proxy_set_header   Host      <span class="variable">$http_host</span>;</div><div class="line">            proxy_pass         http://127.0.0.1:2368;</div><div class="line">        &#125;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">firewall-cmd --permanent --add-port=443/tcp</div><div class="line">firewall-cmd --reload</div></pre></td></tr></table></figure></p>
<h3 id="推荐管理主机的状态-nodequery"><a href="#推荐管理主机的状态-nodequery" class="headerlink" title="推荐管理主机的状态 nodequery"></a>推荐管理主机的状态 <a href="https://nodequery.com/" target="_blank" rel="external">nodequery</a></h3><h3 id="统计访问量"><a href="#统计访问量" class="headerlink" title="统计访问量"></a>统计访问量</h3><p>其实在dnspod下管理域名时,就会有流量统计这个功能,但本人使用<a href="https://www.cloudflare.com/" target="_blank" rel="external">cloudflare</a>加速网页之后,就没有此功能了<br>(<a href="https://www.femnyy.com/cdn/" target="_blank" rel="external">可以看下本人的CND设置</a>)</p>
<p>所以使用<a href="https://www.google.com/intl/zh-CN/analytics/" target="_blank" rel="external">谷歌统计访问量</a><br>注册好了之后–&gt;管理–&gt; .js跟踪信息–&gt;代码跟踪–&gt;将网站跟踪的代码复制到ghost的code injection 的Blog Footer</p>
<p>如果有github学生礼包的话,就可以<a href="https://education.github.com/" target="_blank" rel="external">登陆</a><br><a href="https://www.caoqq.net/github-pack.html" target="_blank" rel="external">此链接</a>,是教如何使用礼包教程<br>这样就可以免费使用digitalocean VPS和namecheap域名了(免费使用.me的域名一年).</p>
<p>使用digitalocean<br>1.gmail注册的,用paypal必须要充$5,其它支付方式,好像不需要<br>注册时比较坑的时,要等两个小时,害得我不断的去注册个人信息 我去(英语不好哈哈)！同时还比较麻烦的就是在关联paypal的时候,还会发信息给注册paypal的邮箱,并要求回复信息,认证是本人.<br>2.创建实例,居然是用Droplets这个单词</p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;空间-虚拟主机-虚拟空间&quot;&gt;&lt;a href=&quot;#空间-虚拟主机-虚拟空间&quot; class=&quot;headerlink&quot; title=&quot;空间(虚拟主机,虚拟空间)&quot;&gt;&lt;/a&gt;空间(虚拟主机,虚拟空间)&lt;/h3&gt;&lt;p&gt;它是利用软件在服务器上硬盘上划分出来的一部分容量.共享的
    
    </summary>
    
      <category term="server" scheme="https://www.femn.me/categories/server/"/>
    
    
  </entry>
  
  <entry>
    <title>python 函数式编程</title>
    <link href="https://www.femn.me/2017/08/14/python-fun-program/"/>
    <id>https://www.femn.me/2017/08/14/python-fun-program/</id>
    <published>2017-08-14T03:02:55.000Z</published>
    <updated>2017-08-24T07:51:13.177Z</updated>
    
    <content type="html"><![CDATA[<p>函数式编程最常见的技术就是对一个集合做Map,Reduce,Filter操作.这比起过程式的语言来说,在代码上要更容易阅读.(传统过程式的语言需要使用for/while循环,然后在各种变量中把数据倒过来倒过去的)</p>
<p>函数式编程的准则:不依赖于外部的数据,而且也不改变外部数据的值,而是返回一个新的值给你</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">return_add_model_id</span><span class="params">(self, modelList)</span>:</span></div><div class="line">    func = <span class="keyword">lambda</span> x: modify_idKeys(x) <span class="comment"># 闭包</span></div><div class="line">    model_id = self._id</div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">modify_idKeys</span><span class="params">(goods)</span>:</span>  </div><div class="line">        g = goods.copy()</div><div class="line">        <span class="keyword">for</span> keys, value <span class="keyword">in</span> goods.items():</div><div class="line">            <span class="keyword">if</span> keys == <span class="string">'_id'</span>:</div><div class="line">                g[model_id] = value</div><div class="line">                <span class="comment"># g.pop('_id'),还保留着</span></div><div class="line">                <span class="keyword">return</span> g</div><div class="line">    <span class="keyword">return</span> list(map(func, modelList))</div><div class="line"><span class="comment"># 依次执行函数得到结果,并将结果组成一个新的list对象后进行返回</span></div><div class="line"></div><div class="line">province_list = [&#123;<span class="string">'name'</span>: <span class="string">'北京市'</span>, <span class="string">'code'</span>: <span class="string">'11'</span>&#125;, \</div><div class="line">    &#123;<span class="string">'name'</span>:<span class="string">'天津市'</span>,<span class="string">'code'</span>:<span class="string">'12'</span>&#125;,&#123;<span class="string">'name'</span>:<span class="string">'河北省'</span>,<span class="string">'code'</span>:<span class="string">'13'</span>&#125;]</div><div class="line">remove_province_list = [<span class="string">'河北省'</span>]</div><div class="line"><span class="comment"># 函数式编程的filter 不仅可以做判断的依据,而且还可以修改其值</span></div><div class="line">list(filter(<span class="keyword">lambda</span> x: x.get(<span class="string">'name'</span>) <span class="keyword">not</span> <span class="keyword">in</span> remove_province_list \</div><div class="line">    <span class="keyword">and</span> x.pop(<span class="string">'code'</span>), province_list))</div><div class="line"><span class="comment"># [&#123;'name': '北京市'&#125;, &#123;'name': '天津市'&#125;]</span></div><div class="line"></div><div class="line">a = list(map(<span class="keyword">lambda</span> x, y : x*y, [<span class="number">1.2</span>, <span class="number">3</span>, <span class="number">5</span>], [<span class="number">2</span>, <span class="number">4</span>, <span class="number">6</span>]))</div><div class="line">print(a)<span class="comment">#[2.4,12,30]</span></div><div class="line">a = reduce(<span class="keyword">lambda</span> x,y:x+y,a)</div><div class="line">print(a)<span class="comment">#44.4</span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">toUpper</span><span class="params">(item)</span>:</span></div><div class="line">  <span class="keyword">return</span> item.upper()</div><div class="line"> </div><div class="line">list(map(toUpper, [<span class="string">"hao"</span>, <span class="string">"chen"</span>, <span class="string">"coolshell"</span>]))</div><div class="line"><span class="comment"># ['HAO', 'CHEN', 'COOLSHELL']</span></div></pre></td></tr></table></figure>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;函数式编程最常见的技术就是对一个集合做Map,Reduce,Filter操作.这比起过程式的语言来说,在代码上要更容易阅读.(传统过程式的语言需要使用for/while循环,然后在各种变量中把数据倒过来倒过去的)&lt;/p&gt;
&lt;p&gt;函数式编程的准则:不依赖于外部的数据,而且也不
    
    </summary>
    
      <category term="python3" scheme="https://www.femn.me/categories/python3/"/>
    
    
  </entry>
  
  <entry>
    <title>python 闭包</title>
    <link href="https://www.femn.me/2017/08/11/python-closure/"/>
    <id>https://www.femn.me/2017/08/11/python-closure/</id>
    <published>2017-08-11T03:27:40.000Z</published>
    <updated>2017-08-24T07:56:08.084Z</updated>
    
    <content type="html"><![CDATA[<h3 id="闭包-Closure-又称函数闭包-function-closures"><a href="#闭包-Closure-又称函数闭包-function-closures" class="headerlink" title="闭包(Closure)又称函数闭包(function closures)"></a>闭包(Closure)又称函数闭包(function closures)</h3><p>引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外.所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体.闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例</p>
<p>在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包.运行时,一旦外部的 函数被执行,一个闭包就形成了,闭包中包含了内部函数的代码,以及所需外部函数中的变量的引用.</p>
<p>闭包被广泛使用于函数式编程语言</p>
<p>闭包可以形象的把它理解为一个封闭的包裹(封闭作用域),这个包裹就是一个函数,当然还有函数内部对应的逻辑,包裹里面的东西就是自由变量,自由变量可以在随着包裹到处游荡.当然还得有个前提,这个包裹是被创建出来的.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">(name)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">inner_func</span><span class="params">(age)</span>:</span> <span class="comment"># 闭包</span></div><div class="line">        <span class="comment"># name为自由变量</span></div><div class="line">        print( <span class="string">'name:'</span>, name, <span class="string">'age:'</span>, age)</div><div class="line">    <span class="keyword">return</span> inner_func</div><div class="line">bb = func(<span class="string">'the5fire'</span>)</div><div class="line">bb(<span class="number">26</span>)</div><div class="line"><span class="comment"># name: the5fire age: 26</span></div></pre></td></tr></table></figure>
<p>这里面调用func的时候就产生了一个闭包——inner_func,并且该闭包持有自由变量——name,因此这也意味着,当函数func的生命周期结束之后,name这个变量依然存在,因为它被闭包引用了,所以不会被回收</p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;闭包-Closure-又称函数闭包-function-closures&quot;&gt;&lt;a href=&quot;#闭包-Closure-又称函数闭包-function-closures&quot; class=&quot;headerlink&quot; title=&quot;闭包(Closure)又称函数闭包(func
    
    </summary>
    
      <category term="python3" scheme="https://www.femn.me/categories/python3/"/>
    
    
  </entry>
  
  <entry>
    <title>python 装饰器</title>
    <link href="https://www.femn.me/2017/08/10/python-decorator/"/>
    <id>https://www.femn.me/2017/08/10/python-decorator/</id>
    <published>2017-08-10T07:31:24.000Z</published>
    <updated>2017-08-24T08:20:32.547Z</updated>
    
    <content type="html"><![CDATA[<p>装饰器(decorator):它能对任何可调用的对象进行包装,既能够用于方法也能够用于函数,想要对一个已有的模块做一些”修饰工作”,但又不让这个小装饰(小功能)侵入到原有的模块中的代码里去,</p>
<p>在python中圆括号意味着调用函数.在没有圆括号的情况下,python会把函数当作普通对象</p>
<p>函数名是某个函数的引用(reference),所以,我们可以对同一个函数设置不同的函数名.(可以理解为,函数也是对象,可以通过赋值来设置不同的对象名)</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">&gt;&gt;&gt; def succ(x):</div><div class="line">        <span class="built_in">return</span> x+1</div><div class="line"></div><div class="line">&gt;&gt;&gt; successor = succ</div><div class="line">&gt;&gt;&gt; successor(10) <span class="comment"># 11</span></div><div class="line">&gt;&gt;&gt; succ(10) <span class="comment"># 11</span></div><div class="line"><span class="comment"># successor和succ都指向同一个函数(应该是对象),都指向同一个内存区域.</span></div><div class="line">&gt;&gt;&gt; id(successor) <span class="comment"># 139701625513368</span></div><div class="line">&gt;&gt;&gt; id(succ) <span class="comment"># 139701625513368</span></div><div class="line">&gt;&gt;&gt; del succ</div><div class="line">&gt;&gt;&gt; successor(10) <span class="comment"># 11</span></div><div class="line">&gt;&gt;&gt; <span class="built_in">type</span>(successor) <span class="comment"># function</span></div></pre></td></tr></table></figure>
<p>装饰器的两种类型:函数装饰器和类装饰器</p>
<h3 id="函数装饰器"><a href="#函数装饰器" class="headerlink" title="函数装饰器"></a>函数装饰器</h3><p><em>无参数装饰器-包装无参数函数</em><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">decorator</span><span class="params">(func)</span>:</span></div><div class="line">    <span class="comment"># 装饰函数</span></div><div class="line">    print(<span class="string">'hello'</span>)</div><div class="line">    <span class="keyword">return</span> func</div><div class="line"><span class="meta">@decorator</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">()</span>:</span></div><div class="line">    <span class="comment"># 被装饰函数 回调函数 闭包函数(当有自由变量)</span></div><div class="line">    print(<span class="string">'foo end'</span>)</div><div class="line">    <span class="comment"># 其解释器将此方法解释为</span></div><div class="line">    <span class="comment"># foo = decorator(foo)</span></div><div class="line">    <span class="comment"># 把一个函数当参数传到另一个函数中,然后再回调</span></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    foo </div><div class="line">    <span class="comment"># hello</span></div><div class="line">    foo()</div><div class="line">    <span class="comment"># hello</span></div><div class="line">    <span class="comment"># foo end</span></div><div class="line">    </div><div class="line">    foo_text = decorator(foo)</div><div class="line">    print(type(foo_text))</div><div class="line">    <span class="comment"># hello</span></div><div class="line">    <span class="comment"># hello</span></div><div class="line">    <span class="comment"># &lt;class 'function'&gt;</span></div><div class="line">    foo_text()</div><div class="line">    <span class="comment"># foo end</span></div></pre></td></tr></table></figure></p>
<p>装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的(被装饰)的函数</p>
<p>下面这个例子向我们展示了decorator的本质:hello(foo)返回了wrapper()函数,所以,foo其实变成了wrapper的一个变量,而后面的foo()执行其实变成了wrapper()<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">hello</span><span class="params">(fn)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">wrapper</span><span class="params">()</span>:</span></div><div class="line">        print(<span class="string">"hello, %s"</span> % fn.__name__)</div><div class="line">        fn()</div><div class="line">        print(<span class="string">"goodby, %s"</span> % fn.__name__)</div><div class="line"></div><div class="line">    <span class="keyword">return</span> wrapper</div><div class="line"></div><div class="line"><span class="meta">@hello</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo</span><span class="params">()</span>:</span> </div><div class="line">    print(<span class="string">"i am foo"</span>)</div><div class="line">    <span class="comment"># foo = hello(foo)</span></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    foo()</div><div class="line">    <span class="comment"># hello, foo</span></div><div class="line">    <span class="comment"># i am foo</span></div><div class="line">    <span class="comment"># goodby, foo</span></div></pre></td></tr></table></figure></p>
<p>类似地<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 多个decorator</span></div><div class="line"><span class="meta">@decorator_one</span></div><div class="line"><span class="meta">@decorator_two</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">()</span>:</span></div><div class="line">    <span class="keyword">pass</span></div><div class="line">    <span class="comment"># func = decorator_one(decorator_two(func))</span></div><div class="line"></div><div class="line"><span class="comment"># 带参数的decorator</span></div><div class="line"><span class="meta">@decorator(arg1, arg2)</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">()</span>:</span></div><div class="line">    <span class="keyword">pass</span></div><div class="line">    <span class="comment"># func = decorator(arg1,arg2)(func)</span></div><div class="line">    <span class="comment"># 这意味着decorator(arg1, arg2)这个函数需要返回一个"真正的decorator"</span></div></pre></td></tr></table></figure></p>
<p><em>无参数装饰器-包装带参数函数</em><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">decorator_func_args</span><span class="params">(func)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">handle_args</span><span class="params">(*args, **kwargs)</span>:</span></div><div class="line">        print(<span class="string">"handle args start"</span>)</div><div class="line">        func(*args, **kwargs)</div><div class="line">        print(<span class="string">"handle args end"</span>)</div><div class="line">    <span class="keyword">return</span> handle_args</div><div class="line"></div><div class="line"><span class="meta">@decorator_func_args</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo2</span><span class="params">(a, b=<span class="number">2</span>)</span>:</span></div><div class="line">    print(a,b)</div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    foo2(<span class="number">1</span>)</div><div class="line">    <span class="comment"># handle args start</span></div><div class="line">    <span class="comment"># 1 2</span></div><div class="line">    <span class="comment"># handle args end</span></div><div class="line"></div><div class="line">    <span class="comment"># 先传递函数名,再传递参数</span></div><div class="line">    foo2_text = decorator_func_args(foo2)</div><div class="line">    print(<span class="string">'--'</span>)</div><div class="line">    foo2_text(<span class="number">1</span>)</div><div class="line">    <span class="comment"># --</span></div><div class="line">    <span class="comment"># handle args start</span></div><div class="line">    <span class="comment"># handle args start</span></div><div class="line">    <span class="comment"># 1 2</span></div><div class="line">    <span class="comment"># handle args end</span></div><div class="line">    <span class="comment"># handle args end</span></div></pre></td></tr></table></figure></p>
<p><em>带参数装饰器 – 包装无参数函数</em><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">decorator_with_params</span><span class="params">(arg_of_decorator)</span>:</span></div><div class="line">    print(arg_of_decorator)</div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">newDecorator</span><span class="params">(func)</span>:</span></div><div class="line">        print(func)</div><div class="line">        <span class="keyword">return</span> func</div><div class="line">    <span class="keyword">return</span> newDecorator</div><div class="line"></div><div class="line"><span class="meta">@decorator_with_params("deco_args")</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo3</span><span class="params">()</span>:</span></div><div class="line">    <span class="keyword">pass</span></div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    foo3()</div><div class="line">    <span class="comment"># deco_args</span></div><div class="line">    <span class="comment"># &lt;function foo3 at 0x7fba7bfcf7b8&gt;</span></div><div class="line">    </div><div class="line">    <span class="comment"># 先传递参数,再传递函数名</span></div><div class="line">    foo3_text = decorator_with_params(<span class="string">"deco_args"</span>)</div><div class="line">    print(<span class="string">'--'</span>)</div><div class="line">    foo3 = foo3_text(foo3)</div><div class="line">    <span class="comment"># deco_args</span></div><div class="line">    <span class="comment"># &lt;function foo3 at 0x7fba7bfcf7b8&gt;</span></div><div class="line">    <span class="comment"># deco_args</span></div><div class="line">    <span class="comment"># --</span></div><div class="line">    <span class="comment"># &lt;function foo3 at 0x7fba7bfcf7b8&gt;</span></div><div class="line">    </div><div class="line">    func = decorator_with_params(<span class="string">'1'</span>)(foo3)</div><div class="line">    <span class="comment"># deco_args</span></div><div class="line">    <span class="comment"># &lt;function foo3 at 0x7ff913a6f730&gt;</span></div><div class="line">    <span class="comment"># 1</span></div><div class="line">    <span class="comment"># &lt;function foo3 at 0x7ff913a6f730&gt;</span></div></pre></td></tr></table></figure></p>
<p><em>带参数装饰器– 包装带参数函数</em><br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">decorator_with_params_and_func_args</span><span class="params">(arg_of_decorator)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">handle_func</span><span class="params">(func)</span>:</span></div><div class="line">        <span class="function"><span class="keyword">def</span> <span class="title">handle_args</span><span class="params">(*args, **kwargs)</span>:</span></div><div class="line">            print(<span class="string">"begin"</span>)</div><div class="line">            func(*args, **kwargs)</div><div class="line">            print(<span class="string">"end"</span>)</div><div class="line">            print(arg_of_decorator, func, args, kwargs)</div><div class="line">        <span class="keyword">return</span> handle_args</div><div class="line">    <span class="keyword">return</span> handle_func</div><div class="line"></div><div class="line"><span class="meta">@decorator_with_params_and_func_args("123")</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">foo4</span><span class="params">(a, b=<span class="number">2</span>)</span>:</span></div><div class="line">    print(<span class="string">"content"</span>)</div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    foo4(<span class="number">1</span>, b=<span class="number">3</span>)</div><div class="line">    <span class="comment"># begin</span></div><div class="line">    <span class="comment"># content</span></div><div class="line">    <span class="comment"># end</span></div><div class="line">    <span class="comment"># 123 &lt;function foo4 at 0x7f4f0f056730&gt; (1,) &#123;'b': 3&#125;</span></div><div class="line"></div><div class="line">    foo4_dec = decorator_with_params_and_func_args(<span class="string">"123"</span>)</div><div class="line">    print(<span class="string">'**'</span>)</div><div class="line">    foo4_func = foo4_dec(foo4)</div><div class="line">    print(<span class="string">'@@'</span>)</div><div class="line">    foo4_text = foo4_func(<span class="number">1</span>, b=<span class="number">3</span>)</div><div class="line">    <span class="comment"># **</span></div><div class="line">    <span class="comment"># @@</span></div><div class="line">    <span class="comment"># begin</span></div><div class="line">    <span class="comment"># begin</span></div><div class="line">    <span class="comment"># content</span></div><div class="line">    <span class="comment"># end</span></div><div class="line">    <span class="comment"># 123 &lt;function foo4 at 0x7f663fd82730&gt; (1,) &#123;'b': 3&#125;</span></div><div class="line">    <span class="comment"># end</span></div><div class="line">    <span class="comment"># 123 &lt;function decorator_with_params_and_func_args.&lt;locals&gt;.handle_func.</span></div><div class="line">        <span class="comment"># &lt;locals&gt;.handle_args at 0x7f663fd827b8&gt; (1,) &#123;'b': 3&#125;</span></div></pre></td></tr></table></figure></p>
<p>给decorator参数赋值,返回handle_func对象<br>handle_func()函数接收foo4对象,返回handle_args对象<br>handle_args()函数接收传递给foo4的参数.<br>一个有点意义的例子</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">makeHtmlTag</span><span class="params">(tag, *args, **kwds)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">real_decorator</span><span class="params">(fn)</span>:</span></div><div class="line">        css_class = <span class="string">" class='&#123;0&#125;'"</span>.format(kwds[<span class="string">"css_class"</span>]) \</div><div class="line">            <span class="keyword">if</span> <span class="string">"css_class"</span> <span class="keyword">in</span> kwds <span class="keyword">else</span> <span class="string">""</span></div><div class="line"></div><div class="line">        <span class="function"><span class="keyword">def</span> <span class="title">wrapped</span><span class="params">(*args, **kwds)</span>:</span></div><div class="line">            <span class="keyword">return</span> <span class="string">"&lt;"</span> + tag + css_class + <span class="string">"&gt;"</span> + fn(*args,**kwds) + <span class="string">"&lt;/"</span> + tag + <span class="string">"&gt;"</span></div><div class="line"></div><div class="line">        <span class="keyword">return</span> wrapped</div><div class="line"></div><div class="line">    <span class="keyword">return</span> real_decorator</div><div class="line"></div><div class="line"></div><div class="line"><span class="meta">@makeHtmlTag(tag="b", css_class="bold_css")</span></div><div class="line"><span class="meta">@makeHtmlTag(tag="i", css_class="italic_css")</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">hello</span><span class="params">(name)</span>:</span></div><div class="line">    <span class="keyword">return</span> <span class="string">"hello world &#123;0&#125;"</span>.format(name)</div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    print(hello(<span class="string">'femn'</span>))</div><div class="line">    <span class="comment"># &lt;b class='bold_css'&gt;&lt;i class='italic_css'&gt;hello world femn&lt;/i&gt;&lt;/b&gt;</span></div></pre></td></tr></table></figure>
<p>makeHtmlTag有两个参数.所以,为了让 hello = makeHtmlTag(arg1, arg2)(hello) 成功,<br>makeHtmlTag 必需返回一个decorator(这就是为什么我们在makeHtmlTag中加入了real_decorator()的原因),<br>这样一来,我们就可以进入到 decorator 的逻辑中去了——<br>decorator得返回一个wrapper,wrapper里回调hello. “</p>
<h3 id="函数的元数据"><a href="#函数的元数据" class="headerlink" title="函数的元数据"></a>函数的元数据</h3><p>函数的一些属性:</p>
<ol>
<li><strong>name</strong>(函数名),</li>
<li><strong>doc</strong>(描述)和</li>
<li><strong>module</strong>(模块位置)<br>在使用装饰器的时候,函数会丢失这些元数据.<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">greeting</span><span class="params">(func)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">function_wrapper</span><span class="params">(x)</span>:</span></div><div class="line">        <span class="string">"""function_wrapper of greeting"""</span></div><div class="line">        print(<span class="string">"Hi, "</span> + func.__name__ + <span class="string">" returns:"</span>)</div><div class="line">        <span class="keyword">return</span> func(x)</div><div class="line">    <span class="keyword">return</span> function_wrapper</div><div class="line"></div><div class="line"><span class="meta">@greeting</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">f</span><span class="params">(x)</span>:</span></div><div class="line">    <span class="string">"""just some silly function"""</span></div><div class="line">    <span class="keyword">return</span> x + <span class="number">4</span></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    f(<span class="number">10</span>)</div><div class="line">    print(<span class="string">"function name: "</span> + f.__name__)</div><div class="line">    print(<span class="string">"docstring: "</span> + f.__doc__)</div><div class="line">    print(<span class="string">"module name:"</span> + f.__module__) <span class="string">")</span></div></pre></td></tr></table></figure>
</li>
</ol>
<p>运行结果如下<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">Hi, f returns:</div><div class="line">function name: function_wrapper</div><div class="line">docstring: function_wrapper of greeting</div><div class="line">module name:__main__</div></pre></td></tr></table></figure></p>
<p>在正常情况下,f.<strong>name</strong>应该为f,而通过装饰器之后,由于没有保存函数的元数据,所以变成了function_wrapper.<br>每当定义一个装饰器时,应该总是记得为底层的包装函数添加functools库中的@wraps装饰器</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">from</span> functools <span class="keyword">import</span> wraps</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">greeting</span><span class="params">(func)</span>:</span></div><div class="line"><span class="meta">    @wraps(func)</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">function_wrapper</span><span class="params">(x)</span>:</span></div><div class="line">        <span class="string">"""function_wrapper of greeting"""</span></div><div class="line">        print(<span class="string">"Hi, "</span> + func.__name__ + <span class="string">" returns:"</span>)</div><div class="line">        <span class="keyword">return</span> func(x)</div><div class="line">    <span class="keyword">return</span> function_wrapper</div><div class="line"></div><div class="line"><span class="meta">@greeting</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">f</span><span class="params">(x)</span>:</span></div><div class="line">    <span class="string">"""just some silly function"""</span></div><div class="line">    <span class="keyword">return</span> x + <span class="number">4</span></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    f(<span class="number">10</span>)</div><div class="line">    print(<span class="string">"function name: "</span> + f.__name__)</div><div class="line">    print(<span class="string">"docstring: "</span> + f.__doc__)</div><div class="line">    print(<span class="string">"module name:"</span> + f.__module__) <span class="string">")</span></div></pre></td></tr></table></figure>
<p>运行结果如下<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">Hi, f returns:</div><div class="line">function name: f</div><div class="line">docstring: just some silly function</div><div class="line">module name:__main__</div></pre></td></tr></table></figure></p>
<h3 id="类装饰器"><a href="#类装饰器" class="headerlink" title="类装饰器"></a>类装饰器</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">myDecorator</span><span class="params">(object)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, fn)</span>:</span></div><div class="line">        print( <span class="string">"inside myDecorator.__init__()"</span>)</div><div class="line">        <span class="comment"># 在我们给某个函数decorator时被调用,所以</span></div><div class="line">        <span class="comment"># 需要有一个fn的参数,也就是被decorator的函数</span></div><div class="line">        self.fn = fn</div><div class="line"></div><div class="line">    <span class="comment"># 调用被decorator函数时被调用的</span></div><div class="line">    <span class="comment"># 也可以在这个传入fn __call__(self.fn)</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__call__</span><span class="params">(self)</span>:</span></div><div class="line">        self.fn()</div><div class="line">        print( <span class="string">"inside myDecorator.__call__()"</span>)</div><div class="line"></div><div class="line"></div><div class="line"><span class="meta">@myDecorator</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">aFunction</span><span class="params">()</span>:</span></div><div class="line">    print( <span class="string">"inside aFunction()"</span>)</div><div class="line">print( <span class="string">"Finished decorating aFunction()"</span>)</div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    aFunction()</div><div class="line">    <span class="comment"># inside myDecorator.__init__()</span></div><div class="line">    <span class="comment"># Finished decorating aFunction()</span></div><div class="line">    <span class="comment"># inside aFunction()</span></div><div class="line">    <span class="comment"># inside myDecorator.__call__()</span></div></pre></td></tr></table></figure>
<p>下面这个示例展示了通过URL的路由来调用相关注册的函数示例<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyApp</span><span class="params">()</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        self.func_map = &#123;&#125;</div><div class="line"></div><div class="line">    <span class="comment"># decorator类中没有__call__(),但是wrapper返回了原函数</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">register</span><span class="params">(self, name)</span>:</span></div><div class="line">        <span class="function"><span class="keyword">def</span> <span class="title">func_wrapper</span><span class="params">(func)</span>:</span></div><div class="line">            self.func_map[name] = func</div><div class="line">            <span class="keyword">return</span> func</div><div class="line"></div><div class="line">        <span class="keyword">return</span> func_wrapper</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">call_method</span><span class="params">(self, name=None)</span>:</span></div><div class="line">        func = self.func_map.get(name, <span class="keyword">None</span>)</div><div class="line">        <span class="keyword">if</span> func <span class="keyword">is</span> <span class="keyword">None</span>:</div><div class="line">            <span class="keyword">raise</span> Exception(<span class="string">"No function registered against - "</span> + str(name))</div><div class="line">        <span class="keyword">return</span> func()</div><div class="line"></div><div class="line">app = MyApp()</div><div class="line"></div><div class="line"><span class="meta">@app.register('/')</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">main_page_func</span><span class="params">()</span>:</span></div><div class="line">    <span class="keyword">return</span> <span class="string">"This is the main page."</span></div><div class="line"></div><div class="line"><span class="meta">@app.register('/next_page')</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">next_page_func</span><span class="params">()</span>:</span></div><div class="line">    <span class="keyword">return</span> <span class="string">"This is the next page."</span></div><div class="line"></div><div class="line">print(app.call_method(<span class="string">'/'</span>))</div><div class="line">print(app.call_method(<span class="string">'/next_page'</span>))</div><div class="line"><span class="comment"># This is the main page.</span></div><div class="line"><span class="comment"># This is the next page.</span></div></pre></td></tr></table></figure></p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;装饰器(decorator):它能对任何可调用的对象进行包装,既能够用于方法也能够用于函数,想要对一个已有的模块做一些”修饰工作”,但又不让这个小装饰(小功能)侵入到原有的模块中的代码里去,&lt;/p&gt;
&lt;p&gt;在python中圆括号意味着调用函数.在没有圆括号的情况下,pyth
    
    </summary>
    
      <category term="python3" scheme="https://www.femn.me/categories/python3/"/>
    
    
  </entry>
  
  <entry>
    <title>linux 常用命令</title>
    <link href="https://www.femn.me/2017/08/08/linux-common-commands/"/>
    <id>https://www.femn.me/2017/08/08/linux-common-commands/</id>
    <published>2017-08-08T08:05:43.000Z</published>
    <updated>2017-08-25T00:41:10.058Z</updated>
    
    <content type="html"><![CDATA[<h3 id="权限"><a href="#权限" class="headerlink" title="权限"></a>权限</h3><p>Linux权限基于UGO模型进行控制,权限rwx对目录的影响:<br>r:可列出目录内容,w:可在目录中创建删除文件,<br>x:可访问目录内容(进入目录),目录必须拥有X权限,否则无法进入目录<br>rwx(4+2+1)</p>
<p>默认权限:umask的值会从对象的全权限值中减掉<br>普通用户的umask:0002,root用户的为0022<br>目录的全权限 777-002<br>文件的全权限 666-002<br>umask: 显示 12位长的权限 UGO占用9bite<br>umask 0022 : 去设置默认权限</p>
<p>但一个目录,只能属于一个组,当多个组需要共同使用这个目录时,UGO模型的权限就不行了.<br>ACL(Access Control List)是一种高级权限机制,允许我们对一个文件或目录进行灵活的复杂的权限设置.<br>允许针对不同用户,不同组对一个目标文件或目录进行权限设置,不受UGO模型限制.<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div></pre></td><td class="code"><pre><div class="line">who <span class="comment"># 显示哪些用户已经登陆系统</span></div><div class="line">whoami <span class="comment"># 显示当前用户</span></div><div class="line"></div><div class="line"><span class="comment"># 用户组 /etc/group</span></div><div class="line">groupadd femnGroup</div><div class="line">groupdel femnGroup</div><div class="line"></div><div class="line"><span class="comment"># 用户 /etc/shadow</span></div><div class="line">useradd -G femnGroup femn1 </div><div class="line"><span class="comment"># 此femn1用户主属组是femn1,附属组是femnGroup</span></div><div class="line"></div><div class="line">useradd -d /home/femn1 -u 1000 femn1  <span class="comment"># femn1是用户名 -u用户ID</span></div><div class="line">sudo usermod -d /home/femn1 -s /bin/bash femn1 <span class="comment"># -s默认bash</span></div><div class="line">userdel femn1</div><div class="line">userdel -r femn1 <span class="comment"># 同时删除用户的家目录</span></div><div class="line"></div><div class="line"><span class="comment"># 改文件的UGO权限</span></div><div class="line">chmod -R 777 文件名  </div><div class="line">chmod u+rw,g+o</div><div class="line">chmod go+rw</div><div class="line">chmod a-x <span class="comment"># a代指ugo</span></div><div class="line"></div><div class="line"><span class="comment">#  chown改所属用户 -R  </span></div><div class="line">chown -R name:name 文件</div><div class="line">chown femn(用户名)learn.txt(文件名,如果是目录,则加上 -R参数)</div><div class="line"></div><div class="line"><span class="comment"># chgrp改所属组 -R递归修改目录下的所有文件的所属组</span></div><div class="line">chgrp -R femnGroup learn.txt</div><div class="line"></div><div class="line"><span class="comment"># umask的最前面的那位,是用来保留特殊权限的.</span></div><div class="line">chmod u+s 文件:</div><div class="line"><span class="comment"># 特殊权限一般是给可执行文件去用的.1770</span></div><div class="line"></div><div class="line">chmod g+s 目录:</div><div class="line"><span class="comment"># 在此目录下生成的文件或目录,都会继承此目录的用户组 2770</span></div><div class="line"></div><div class="line">chmod o+t 目录:</div><div class="line"><span class="comment"># 只能是本人可以删除自己的文件,即使是本组中的人员也不能删除别人的文件.4770</span></div><div class="line"></div><div class="line"><span class="comment"># ACL需要在挂载文件的时候打开ACL功能:</span></div><div class="line">mount -o acl /dev/sda5 /mnt</div><div class="line"><span class="comment"># 只要我们的文件系统打开了ACL功能,就可以查看一个文件或目录的ACL设置:</span></div><div class="line">getfacl linux</div><div class="line"></div><div class="line"><span class="comment"># 针对一个用户对文件进行ACL设置:</span></div><div class="line">setfacl -m u:name:rwx linux</div><div class="line">setfacl -m g:name:rw linux</div><div class="line">setfacl -x u:name linux</div></pre></td></tr></table></figure></p>
<h3 id="磁盘和挂载"><a href="#磁盘和挂载" class="headerlink" title="磁盘和挂载"></a>磁盘和挂载</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line">df -h <span class="comment"># 设备文件名称,本系统中的磁盘的使用大小情况</span></div><div class="line">df -at <span class="comment"># 文件系统, 磁盘的状态</span></div><div class="line">du -sh <span class="comment"># 显示此目录总所占空间</span></div><div class="line">du -sh ~/* | sort -nr </div><div class="line"><span class="comment"># 参数让结果按降序输出   管道命令将du命令的输出重定向到sort命令</span></div><div class="line"></div><div class="line"></div><div class="line">fdisk -l  <span class="comment"># 查看本机的所有磁盘,以及磁盘的分区情况</span></div><div class="line">fdisk /dev/sda <span class="comment"># 查看,创建,删除某个磁盘 分区</span></div><div class="line">dumpe2fs -h /dev/sdb3 <span class="comment"># 得到这个磁盘分区的所有信息</span></div><div class="line"></div><div class="line"><span class="comment"># 格式化之前先不要挂载 </span></div><div class="line">mkfs -t ext4 /dev/sda4 </div><div class="line">mkfs.ext4 /dev/sda4</div><div class="line"><span class="comment"># 将这个分区(或硬盘)格式化为ext4文件系统,格式化磁盘</span></div><div class="line">mke2fs -j -L <span class="string">"partition-label-name"</span> -b 4096 -i -c 128 /dev/sda4  </div><div class="line"><span class="comment"># 这样就可以传4.3G的大文件到U盘上了,只是这样格式,在Win不能用</span></div><div class="line"></div><div class="line"><span class="comment"># 挂载</span></div><div class="line">mount /dev/sdc1 /home/name/usb  </div><div class="line">mount -o remount,rw,auto /dev/sdc1 </div><div class="line"><span class="comment"># 将/dev/sdc1重新挂载,并加入参数rw,auto</span></div><div class="line">umount /home/name/usb     or /dev/sdc1 挂载点或设备文件名 </div><div class="line"><span class="comment"># -l参数是强制</span></div><div class="line">lsof |grep /dev/sdc1</div><div class="line"><span class="comment"># 当挂载不掉时,用下面的命令 ,会得到进程号</span></div><div class="line"></div><div class="line"><span class="comment"># 特殊设备loop挂载(镜像文件不刻录就挂载使用)</span></div><div class="line">mount -o loop /home/name/ubuntu-16.04-desktop-amd64.iso \</div><div class="line">    /hame/name/usb  </div><div class="line"><span class="comment">#使用 dd 命令写入下载好的 ISO 镜像到 U 盘中</span></div><div class="line">sudo dd <span class="keyword">if</span>=xxxxx.iso of=/dev/sdc &amp;&amp; sync</div><div class="line"></div><div class="line">nautilus .     <span class="comment"># 默认是打开home目录</span></div></pre></td></tr></table></figure>
<p>传统的磁盘管理问题:<br>当分区大小不够用时无法扩展其大小,只能通过添加硬盘,创建新分区来扩充空间,但是新添加进来的硬盘是作为独立文件系统存在的,原有的文件系统并未得到扩充,上层应用很多时候只能访问一个文件系统,只能让现有磁盘下线,换上新的磁盘之后,再将原始数据导入.</p>
<h3 id="LVM逻辑卷管理-Logical-volume-Manager"><a href="#LVM逻辑卷管理-Logical-volume-Manager" class="headerlink" title="LVM逻辑卷管理(Logical volume Manager)"></a><a href="https://www.qingsword.com/qing/924.html" target="_blank" rel="external">LVM</a>逻辑卷管理(Logical volume Manager)</h3><p>PE(physical extend)物理扩展:逻辑卷空间管理的最基本单位,默认是4M<br>PV(physica volume)物理卷:将底层磁盘格式化成物理卷,可以是物理硬盘上的分区,也可以是整块物理硬盘<br>VG(volume group)卷组:空间池是给来装PE的,我们可以将一个或多个PV,加入到VG当中,当创建好了VG会有/dev/vgname的目录<br>LV(logical volume)逻辑卷(操作系统最终使用的是逻辑卷格式化之后的数据)/dev/vgname/lvname的目录,每个的逻辑卷空间有可以来自不同的物理磁盘<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div></pre></td><td class="code"><pre><div class="line">1. 创建PV</div><div class="line"><span class="comment"># 整块物理硬盘创建PV</span></div><div class="line">sudo pvcreate /dev/sd[b-c]</div><div class="line"></div><div class="line"><span class="comment"># 物理硬盘上的分区创建PV</span></div><div class="line">fdisk /dev/sdb1 使用t将分区类型改成8e(LVM)</div><div class="line">partprobe <span class="comment"># 刷新分区表</span></div><div class="line">sudo pvcreate /dev/sdb1</div><div class="line"></div><div class="line">sudo pvs <span class="comment"># 查看创建好的PV</span></div><div class="line"></div><div class="line">2. PV创建好了就可以创建VG了</div><div class="line">sudo vgcreate vg0 /dev/sdb1</div><div class="line">sudo vgs <span class="comment"># 查看创建好的VG</span></div><div class="line">sudo pvs <span class="comment"># sdb1这个PV就属于vg0这个卷组池了</span></div><div class="line"></div><div class="line">3. 创建好卷组池就能从池中划分容量给逻辑卷(LV)了</div><div class="line">sudo lvcreate -n lv0 -L 10G vg0</div><div class="line"><span class="comment"># 从卷组vg0中拿出10G,分配给lv0,其中-n后面是lv自定义名称,</span></div><div class="line"><span class="comment"># -L后面跟需要从vg0中分配给lv0的大小以及从哪个VG分配</span></div><div class="line"></div><div class="line">4. 创建好lv后就可以格式化它,成为文件系统使用</div><div class="line">sudo mkfs.ext4 /dev/vg0/lv0</div><div class="line"><span class="comment"># 创建好的lv所在目录是"/dev/卷组名称/逻辑卷名称",</span></div><div class="line"><span class="comment"># 所以本例就是/dev/vg0/lv0,将它格式化成ext4文件系统</span></div><div class="line"></div><div class="line">5. 挂载和使用</div><div class="line">sudo mount /dev/vg0/lv0 /mnt</div><div class="line"></div><div class="line">6. 扩充VG</div><div class="line">sudo pvcreate /dev/sdd</div><div class="line"><span class="comment">#新增加一块硬盘sdd(20G),将它创建成PV后划分到vg0下,</span></div><div class="line"><span class="comment"># 此时vg0的容量将增加sdd硬盘的大小</span></div><div class="line">sudo vgextend vg0 /dev/sdd</div><div class="line"></div><div class="line">7. 扩充LV</div><div class="line">sudo vgs <span class="comment"># 先确保VG池中有足够的VFree空间可供使用</span></div><div class="line">sudo lvextend -L +5G /dev/vg0/lv0</div><div class="line">sudo resize2fs /dev/vg0/lv0 <span class="comment"># 更新</span></div></pre></td></tr></table></figure></p>
<h3 id="安装和下载"><a href="#安装和下载" class="headerlink" title="安装和下载"></a>安装和下载</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line">vim /proc/meminfo 文件来观察LINux系统上虚拟内存的当前状态.</div><div class="line">sudo dpkg -i **.deb <span class="comment"># 安装 查看-l</span></div><div class="line">sudo dpkg -purge **</div><div class="line">sudo apt install **</div><div class="line"></div><div class="line">curl https://wordpress.org/latest.tar.gz | tar -zxvf -</div><div class="line"></div><div class="line">wget -O redis.tar.gz \</div><div class="line">    http://download.redis.io/releases/redis-3.2.0.tar.gz</div><div class="line">tar -zxvf redis.tar.gz -C /usr/src/redis</div><div class="line">make -C /usr/src/redis \</div><div class="line">    &amp;&amp; make -C /usr/src/redis install </div><div class="line"></div><div class="line">wget https://ghost.org/zip/ghost-latest.zip</div><div class="line">unzip -uo ghost-latest.zip -d /var/www/ghost </div><div class="line"></div><div class="line">curl -LOk https://ghost.org/zip/ghost-latest.zip</div><div class="line">unzip ghost-latest.zip -d ghost-temp</div><div class="line"></div><div class="line">curl http://localhost:8000/wrap?name=femn&amp;  get()</div><div class="line">http://localhost:8000/wrap -d name=femn    post()方法请求</div><div class="line"><span class="comment"># Siege对我们的应用在10秒内执行大约10个并发请求</span></div><div class="line">siege http://localhost:8000/?q=pants -c10 -t10s</div></pre></td></tr></table></figure>
<h3 id="文件和目录操作"><a href="#文件和目录操作" class="headerlink" title="文件和目录操作"></a>文件和目录操作</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div></pre></td><td class="code"><pre><div class="line">    ll linux.md</div><div class="line">    <span class="comment"># ll 查看的信息 第二列是链接数量</span></div><div class="line">    ll |grep -v linux.md <span class="comment"># 取反</span></div><div class="line">    <span class="built_in">history</span> | grep -c rar <span class="comment"># 计算匹配的数量</span></div><div class="line">    touch file1 <span class="comment"># 创建文件</span></div><div class="line">    file file1 <span class="comment"># 查看文件类型</span></div><div class="line">    cp -Rf <span class="built_in">source</span> destination </div><div class="line">    <span class="comment"># -R 允许你通过命令递归地复制整个目录的内容.</span></div><div class="line">    <span class="comment"># -f 强制覆盖已经存在的目标文件,不提示 </span></div><div class="line">    <span class="comment"># -l 硬链接,它们是同一个文件,索引节点是相同的</span></div><div class="line">    \cp -R dir1 dir2 <span class="comment"># 同上</span></div><div class="line">    \cp -R content/themes/casper ../ghost/content/themes</div><div class="line">    rm -rf file1</div><div class="line">    tail -f -n 20 /etc/passwd</div><div class="line"></div><div class="line">    <span class="comment"># 软连接可以不用事先创建目录,硬连接必须先创建目录</span></div><div class="line">    sudo ln -s /home/femn/file /usr/share/nginx/html/file</div><div class="line">    mkdir ~/file</div><div class="line">    </div><div class="line">    <span class="comment"># mv排除文件</span></div><div class="line">    <span class="comment"># 将本路径下所有的文件移动到本路径下vimrc_config目录下,</span></div><div class="line">    <span class="comment"># 但vimrc_config本身不动</span></div><div class="line">    mv !(vimrc_config) vimrc_config</div><div class="line">    <span class="comment"># 但此命令不包括mv 隐藏文件</span></div><div class="line">    rm命令类似</div><div class="line">    </div><div class="line">    sort -t <span class="string">':'</span> -k 3 -n /etc/passwd</div><div class="line">    <span class="comment"># 按字段分隔数据,按分隔后的第几个进行排序 </span></div><div class="line"></div><div class="line">    scp -r -P 22 root@ip:/server/app/main/handlers \</div><div class="line">        ./main/handlers/</div><div class="line">    scp -P 22 ./1.txt python@ip:/usr/share/nginx/html/file/</div><div class="line">    <span class="comment"># 只需要file目录有写权限,普通用户就可以用了</span></div><div class="line">    rsync -av -e <span class="string">"ssh -p 22"</span> /home/python/app1.6/main/ \</div><div class="line">        root@ip:/server/app1.6/main/</div><div class="line">    rsync -av -e <span class="string">"ssh -p 22"</span> /home/python/oldapp_8000/ \</div><div class="line">        root@ip:/server/app/main/</div><div class="line"></div><div class="line"><span class="comment"># 截图</span></div><div class="line">    <span class="comment">#你将可以使用鼠标选取一个矩形框.在你放下鼠标左键的那一刻,</span></div><div class="line">    <span class="comment"># 一个该矩形框的截屏会以import后面跟的文件名保存在当前目录下</span></div><div class="line">    import screenshot.jpg </div><div class="line">    gnome-screenshot -a</div><div class="line"></div><div class="line"><span class="comment"># 改变视频文件大小(分辨率)http://blog.topspeedsnail.com/archives/1699</span></div><div class="line">    ffmpeg -i source.mpg -s 960x540 -c:a copy  destination.mp4</div><div class="line"><span class="comment"># Linux系统将每个对象当作文件来处理,这包括输入和输入的过程.Linux用文件描述符来标识每个文件对象.</span></div></pre></td></tr></table></figure>
<h3 id="解压缩"><a href="#解压缩" class="headerlink" title="解压缩"></a>解压缩</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># tar</span></div><div class="line">tar -zcvf /home/name/conclusion.tar.gz ./conclusion </div><div class="line">tar -zxvf ./conclusion.tar.gz </div><div class="line">tar -cvf /tmp/etc.tar /etc &lt;==仅打包,不压缩</div><div class="line"></div><div class="line"><span class="comment"># rar </span></div><div class="line">rar x file.rar <span class="comment"># 解压</span></div><div class="line"></div><div class="line"><span class="comment"># zip</span></div><div class="line">zip test.zip <span class="built_in">test</span> </div><div class="line">unzip test.zip</div></pre></td></tr></table></figure>
<h3 id="环境变量"><a href="#环境变量" class="headerlink" title="环境变量"></a>环境变量</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">printenv <span class="comment"># 查看所有全局环境变量</span></div><div class="line"><span class="built_in">set</span> <span class="comment"># 会显示为某个特定进程设置的所有环境变量</span></div><div class="line"><span class="comment"># 设置PATH环境变量</span></div><div class="line">vim ~/.profile</div><div class="line">    <span class="built_in">export</span> JAVA_HOME=/home/name/jdk1.8.0_92</div><div class="line">    <span class="built_in">export</span> ANT_HOME=/home/name/apache-ant-1.9.7</div><div class="line">    PATH=<span class="variable">$&#123;PATH&#125;</span>:/home/name/jdk1.8.0_92/bin:/home/name/apache/bin</div><div class="line"><span class="comment"># 设置局部变量(只能在定义的进程可见)</span></div><div class="line">femn=<span class="string">'hello,my name is femn'</span></div><div class="line"><span class="comment"># 设置全局变量</span></div><div class="line"><span class="built_in">export</span> femn  <span class="comment"># 记住不要再用美元符($) </span></div><div class="line"><span class="comment"># 删除环境变量</span></div><div class="line"><span class="built_in">unset</span> femn</div></pre></td></tr></table></figure>
<h3 id="ubuntu-ip"><a href="#ubuntu-ip" class="headerlink" title="ubuntu ip"></a>ubuntu ip</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 禁用IPV6</span></div><div class="line">vim /etc/modprobe.d/blacklist.conf </div><div class="line"><span class="comment">#在文档最后添加 blacklist ipv6</span></div><div class="line"><span class="comment"># 设置一ip</span></div><div class="line">sudo ifconfig enp0s3 192.168.1.101 netmask 255.255.255.0</div><div class="line">sudo route add default gw 192.168.1.254</div><div class="line"><span class="comment"># 设置二ip</span></div><div class="line">sudo vim /etc/network/interfaces</div><div class="line">    auto enp0s3 </div><div class="line">    iface enp0s3 inet static <span class="comment"># dhcp</span></div><div class="line">    address 192.168.1.101</div><div class="line">    gateway 192.168.1.254</div><div class="line">    netmask 255.255.255.0</div><div class="line">    <span class="comment">#network 192.168.1.0  </span></div><div class="line">    <span class="comment">#broadcast 192.168.1.255 </span></div><div class="line"><span class="comment"># 配置DNS</span></div><div class="line">sudo vim/etc/resolv.conf</div><div class="line">    nameserver 127.0.1.1</div><div class="line">    <span class="comment"># nameserver 8.8.8.8</span></div><div class="line">    search DHCP HOST</div><div class="line">    </div><div class="line"><span class="comment"># 手动重启网络服务</span></div><div class="line">sudo /etc/init.d/networking restart</div><div class="line"><span class="comment">#实在没有生效 reboot</span></div><div class="line"></div><div class="line"><span class="comment"># /etc/hosts:ip与域名的对应关系,DNS记录信息,</span></div><div class="line"><span class="comment"># /etc/hostname:存放的是主机名.域名与主机名没有任何关系</span></div><div class="line">sudo hostname python-Vostro-3901 <span class="comment"># 修改主机名 ubuntu</span></div><div class="line">sudo hostnamectl <span class="built_in">set</span>-hostname intl.aliyun.centos7 </div><div class="line"><span class="comment"># 修改主机名 centos</span></div><div class="line"></div><div class="line"><span class="comment"># 永久修改主机名</span></div><div class="line">vim /etc/hostname <span class="comment"># ubuntu centos</span></div></pre></td></tr></table></figure>
<h3 id="centos7-ip"><a href="#centos7-ip" class="headerlink" title="centos7 ip"></a>centos7 ip</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">vim /etc/sysconfig/network-scripts/ifcfg-网卡名字</div><div class="line">    BOOTPROTO=static <span class="comment">#dhcp改为static   </span></div><div class="line">    ONBOOT=yes <span class="comment">#开机启用本配置  </span></div><div class="line">    IPADDR=192.168.1.107 <span class="comment">#静态IP  </span></div><div class="line">    GATEWAY=192.168.1.254 <span class="comment"># 默认网关  </span></div><div class="line">    NETMASK=255.255.255.0 <span class="comment">#子网掩码  </span></div><div class="line">service network restart</div></pre></td></tr></table></figure>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;权限&quot;&gt;&lt;a href=&quot;#权限&quot; class=&quot;headerlink&quot; title=&quot;权限&quot;&gt;&lt;/a&gt;权限&lt;/h3&gt;&lt;p&gt;Linux权限基于UGO模型进行控制,权限rwx对目录的影响:&lt;br&gt;r:可列出目录内容,w:可在目录中创建删除文件,&lt;br&gt;x:可访问目录
    
    </summary>
    
      <category term="linux" scheme="https://www.femn.me/categories/linux/"/>
    
    
  </entry>
  
  <entry>
    <title>python 对象</title>
    <link href="https://www.femn.me/2017/08/06/python-object/"/>
    <id>https://www.femn.me/2017/08/06/python-object/</id>
    <published>2017-08-06T01:26:18.000Z</published>
    <updated>2017-08-25T08:35:12.877Z</updated>
    
    <content type="html"><![CDATA[<h3 id="面向对象编程-Object-Oriented-Programming-简称OOP"><a href="#面向对象编程-Object-Oriented-Programming-简称OOP" class="headerlink" title="面向对象编程:Object Oriented Programming,简称OOP"></a>面向对象编程:Object Oriented Programming,简称OOP</h3><p>把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),<br>通过类的封装(encapsulation)隐藏内部细节<br>通过继承(inheritance)实现类的特化(specialization)(重写)/泛化(generalization)<br>通过多态(polymorphism)实现基于对象类型的动态分派(dynamic dispatch)</p>
<h4 id="多态-不同对象的相同方法的不同行为"><a href="#多态-不同对象的相同方法的不同行为" class="headerlink" title="多态:不同对象的相同方法的不同行为"></a>多态:不同对象的相同方法的不同行为</h4><p>   在JAVA在继承-重写才能体现多态,在python中,不知道对象到底是什么类型,但是又要对对象做点什么的时候,都会用到多态.很多的函数和运算符都是多态.唯一能毁掉多态的就是显式的检查类型<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="number">1</span>+<span class="number">2</span> <span class="comment"># 3</span></div><div class="line"><span class="string">'fe'</span>+<span class="string">'mn'</span> <span class="comment"># femn</span></div><div class="line"></div><div class="line"><span class="string">'abc'</span>.count(<span class="string">'a'</span>) <span class="comment"># 1</span></div><div class="line">[<span class="number">1</span>,<span class="number">2</span>,<span class="string">'a'</span>].count(<span class="string">'a'</span>) <span class="comment"># 1</span></div></pre></td></tr></table></figure></p>
<h4 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span><span class="params">(object)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        print( <span class="string">"A.__init__"</span> )</div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span><span class="params">(A)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        super().__init__()</div><div class="line">        print(<span class="string">"B.__init__"</span> )</div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span><span class="params">(B)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        super().__init__()</div><div class="line">        print(<span class="string">"C.__init__"</span> )</div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">D</span><span class="params">(A)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        super().__init__()</div><div class="line">        print(<span class="string">"D.__init__"</span> )</div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">E</span><span class="params">(D)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        super().__init__()</div><div class="line">        print(<span class="string">"E.__init__"</span> )</div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">F</span><span class="params">(C,E)</span>:</span><span class="comment"># C,E 相当于是子 父关系</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        super().__init__()</div><div class="line">        print(<span class="string">"F.__init__"</span> )</div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    f = F()</div><div class="line">    <span class="comment"># A.__init__</span></div><div class="line">    <span class="comment"># D.__init__</span></div><div class="line">    <span class="comment"># E.__init__</span></div><div class="line">    <span class="comment"># B.__init__</span></div><div class="line">    <span class="comment"># C.__init__</span></div><div class="line">    <span class="comment"># F.__init__</span></div></pre></td></tr></table></figure>
<p>对于你定义的每一个类,Python会计算出一个所谓的方法解析顺序(MRO)列表. 这个MRO列表就是一个简单的所有基类的线性顺序表.例如</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"><span class="meta">&gt;&gt;&gt; </span>F.__mro__</div><div class="line">(class'__main__.F'&gt;,&lt;class'__main__.C'&gt;,&lt;class'__main__.B'&gt;,</div><div class="line">&lt;class'__main__.E'&gt;,&lt;class'__main__.D'&gt;,&lt;class'__main__.A'&gt;,</div><div class="line">&lt;<span class="class"><span class="keyword">class</span>'<span class="title">object</span>'&gt;)</span></div></pre></td></tr></table></figure>
<p>为了实现继承,Python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止<br>而这个MRO列表的构造是通过一个C3线性化算法来实现的,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:</p>
<ol>
<li>子类会先于父类被检查</li>
<li>多个父类会根据它们在列表中的顺序被检查</li>
<li>如果对下一个类存在两个合法的选择,选择第一个父类</li>
</ol>
<h4 id="C3算法特点"><a href="#C3算法特点" class="headerlink" title="C3算法特点"></a>C3算法特点</h4><ol>
<li><p>本地优先级:指声明时父类的顺序,比如F(C,E),如果访问F类对象属性时,应该根据声明顺序,优先查找C类,然后再查找E类.</p>
</li>
<li><p>单调性:如果在F的解析顺序中,C排在E的前面,那么在F的所有子类里,也必须满足这个顺序</p>
</li>
</ol>
<p><img src="css/images/c3.png" alt=""></p>
<h4 id="类-Class"><a href="#类-Class" class="headerlink" title="类(Class):"></a>类(Class):</h4><p>用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.<br>类创建后,类命名空间中所有的命名都是有效属性名</p>
<h4 id="对象-类的实例化"><a href="#对象-类的实例化" class="headerlink" title="对象:类的实例化"></a>对象:类的实例化</h4><p>通过类定义的数据结构实例.对象包括两个数据成员(类变量和实例变量)和方法.<br>对象基本上可以看作数据(特征)以及由一系列可以存取,操作这些数据的方法所组成的集合.<br>使用对象替代全局变量和函数的原因可以有很多.多态(鸭子类型),封装,继承<br>封装和继承是被用作现实世界中对象的模型</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span><span class="params">(dict)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self,name)</span>:</span></div><div class="line">        super(Person,self).__init__()</div><div class="line">        self.name = name</div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_name</span><span class="params">(self)</span>:</span></div><div class="line">        <span class="keyword">return</span> self.name</div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    p = Person(<span class="string">'femn'</span>)</div><div class="line">    print(p) <span class="comment"># &#123;&#125;  self本身为空 &#123;&#125; ,但其属性不为空</span></div><div class="line">    print(p.get_name()) <span class="comment"># femn</span></div><div class="line"><span class="comment"># 如果知道p是Person类的实例的话,</span></div><div class="line"><span class="comment"># 就可以把p.get_name()看作是Person.get_name(p)的简写.</span></div></pre></td></tr></table></figure>
<h3 id="属性-域-字段-成员变量-全局变量-数据成员-数据-私有成员-成员对象"><a href="#属性-域-字段-成员变量-全局变量-数据成员-数据-私有成员-成员对象" class="headerlink" title="属性:域,字段,成员变量,全局变量,数据成员(数据),私有成员,成员对象"></a>属性:域,字段,成员变量,全局变量,数据成员(数据),私有成员,成员对象</h3><p>属性:这个词来称呼任何点后面跟的名称 — 比如,在表达式z.real中,real就是对象z的属性.<br>更直接的说,对模块中名称的引用就是属性引用:在表达式 modname.funcname 中,<br>modname是模块对象而funcname是它的一个属性.<br>在这种情况下模块的属性和它里面所定义的全局名称之间就刚好有一个直接的映射关系:他们共享同一个命名空间</p>
<h4 id="类变量-在整个实例化的对象中是公用的-定义在类中且在函数体之外-通常不作为实例变量使用"><a href="#类变量-在整个实例化的对象中是公用的-定义在类中且在函数体之外-通常不作为实例变量使用" class="headerlink" title="类变量:在整个实例化的对象中是公用的.定义在类中且在函数体之外,通常不作为实例变量使用."></a>类变量:在整个实例化的对象中是公用的.定义在类中且在函数体之外,通常不作为实例变量使用.</h4><h4 id="实例变量-定义在方法中的变量-只作用于当前实例的类"><a href="#实例变量-定义在方法中的变量-只作用于当前实例的类" class="headerlink" title="实例变量:定义在方法中的变量,只作用于当前实例的类"></a>实例变量:定义在方法中的变量,只作用于当前实例的类</h4><p>property()方法实例<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Rectangle</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        self.width = <span class="number">0</span></div><div class="line">        self.height = <span class="number">0</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">setSize</span><span class="params">(self, size)</span>:</span></div><div class="line">        <span class="string">"""访问器方法,把所有的属性都放到访问器方法中"""</span></div><div class="line">        self.width, self.height = size</div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getSize</span><span class="params">(self)</span>:</span></div><div class="line">        <span class="keyword">return</span> self.width, self.height</div><div class="line">    size = property(getSize, setSize)</div><div class="line">    <span class="comment"># 类属性,其中的访问器方法被用作参数(先取值,然后是赋值)</span></div><div class="line"></div><div class="line">r = Rectangle()</div><div class="line">r.width = <span class="number">10</span></div><div class="line">r.height = <span class="number">5</span></div><div class="line">r.size <span class="comment">#  (10, 5)</span></div><div class="line">r.size = <span class="number">150</span>, <span class="number">100</span></div><div class="line">r.width <span class="comment"># 150</span></div></pre></td></tr></table></figure></p>
<p>@property 装饰器实例<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span><span class="params">(object)</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self,name,age)</span>:</span></div><div class="line">        <span class="string">"""Constructor"""</span></div><div class="line">        self.name = <span class="string">''</span></div><div class="line">        self.age = <span class="number">0</span></div><div class="line">    <span class="comment"># 修改属性的值 一</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">getName</span><span class="params">(self)</span>:</span></div><div class="line">        print(<span class="string">'property()'</span>)</div><div class="line">        <span class="keyword">return</span> self._name</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">setName</span><span class="params">(self,name)</span>:</span></div><div class="line">        <span class="string">""" 要使用_name 将实例属性name标记成protected变量</span></div><div class="line"><span class="string">        不然就将name类属性,改个名字,</span></div><div class="line"><span class="string">        只要满足类属性和实例属性不同名,否则会进入无限的递归"""</span></div><div class="line">        self._name = name <span class="comment"># protected实例变量:_name</span></div><div class="line">    name = property(getName,setName) <span class="comment"># publie类变量:name</span></div><div class="line">    __aim = <span class="string">'become stronger'</span> <span class="comment"># private 类变量:__aim</span></div><div class="line"></div><div class="line">    <span class="comment"># @property装饰器:</span></div><div class="line"><span class="comment"># 将方法变成了属性,我们可以使用正常的点符号访问它,但无法对属性值直接修改</span></div><div class="line"><span class="meta">    @property</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">info</span><span class="params">(self)</span>:</span></div><div class="line">        <span class="string">""" Return my info """</span></div><div class="line">        <span class="keyword">return</span> <span class="string">"my name is %s, age is %s"</span> % (self.name, self.age)</div><div class="line"></div><div class="line">    <span class="comment"># 修改属性的值 二</span></div><div class="line"><span class="comment">#一个property其实是 getter、setter 和 deleter 方法的集合,而不是单个方法</span></div><div class="line"><span class="comment"># 访问它的时候会自动触发 getter 、setter 和 deleter 方法</span></div><div class="line"><span class="meta">    @property</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self)</span>:</span></div><div class="line">        print(<span class="string">'@property装饰器'</span>)</div><div class="line">        <span class="keyword">return</span> self._age</div><div class="line"></div><div class="line"><span class="meta">    @age.setter</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self,age)</span>:</span></div><div class="line">        self._age = age</div><div class="line"></div><div class="line"><span class="meta">    @age.deleter</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">age</span><span class="params">(self)</span>:</span></div><div class="line">        <span class="keyword">raise</span> AttributeError(<span class="string">"Can't delete attribute"</span>)</div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    p = Person(<span class="string">'leipengkai'</span>,<span class="number">25</span>)</div><div class="line">    <span class="comment"># 方法一</span></div><div class="line">    p.set_name = <span class="string">'femn1'</span></div><div class="line">    p.name = <span class="string">'femn1.1'</span></div><div class="line">    print(p.name)</div><div class="line">    <span class="comment"># 方法二</span></div><div class="line">    p.age = <span class="number">18</span></div><div class="line">    print(p.age) </div><div class="line"><span class="comment"># 输出如下</span></div><div class="line"><span class="comment"># property()</span></div><div class="line"><span class="comment"># femn1.1</span></div><div class="line"><span class="comment"># @property生成器</span></div><div class="line"><span class="comment"># 18</span></div></pre></td></tr></table></figure></p>
<h3 id="方法-绑定方法-动作"><a href="#方法-绑定方法-动作" class="headerlink" title="方法(绑定方法,动作)"></a>方法(绑定方法,动作)</h3><ol>
<li><p>绑定方法:将它们的第一参数绑定到所属的实例上,因此您无须显示提供该参数.当然也可以将特征绑定到一个普通的函数上,这样就不会有特殊的self参数了</p>
</li>
<li><p>函数:self参数是对象自身的引用.它正是方法和函数的区别.<br>在java中,方法和函数是一样的.在python中,方法(self)必须在类中,而函数可以在任意位置定义</p>
</li>
<li><p>静态方法:无法访问类属性、实例属性,没有self参数.相当于一个相对独立的方法,<br>跟类其实没什么关系,换个角度来讲,其实就是放在一个类的作用域里的函数而已.<br>被装入staticmethod类型的对象中.</p>
</li>
<li><p>类成员方法:可以访问类属性,无法访问实例属性.<br>需要名为cls的类似于self的参数,可以用类的具体对象调用.cls自动被绑定到类中<br>被装入classmethod类型的对象中</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span><span class="params">()</span>:</span></div><div class="line">    a =<span class="number">1</span> <span class="comment">#类属性</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self,b,c)</span></span></div><div class="line">        self.b=b</div><div class="line">        self.c=c<span class="comment">#实例属性</span></div></pre></td></tr></table></figure>
</li>
</ol>
<h3 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">print_params</span><span class="params">(x, y, z=<span class="number">3</span>, *pospar, **keypar)</span>:</span> <span class="comment">#**代表命名参数</span></div><div class="line">    print(x,y,z)</div><div class="line">    print(pospar)</div><div class="line">    print(keypar)</div><div class="line">print_params(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>,foo=<span class="number">1</span>, bar=<span class="number">2</span>)</div><div class="line"><span class="number">1</span> <span class="number">2</span> <span class="number">3</span></div><div class="line">(<span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>)</div><div class="line">&#123;<span class="string">'foo'</span>: <span class="number">1</span>, <span class="string">'bar'</span>: <span class="number">2</span>&#125;</div><div class="line">print_params(<span class="number">1</span>,<span class="number">2</span>,foo=<span class="number">1</span>, bar=<span class="number">2</span>)</div><div class="line"><span class="number">1</span> <span class="number">2</span> <span class="number">3</span></div><div class="line">()</div><div class="line">&#123;<span class="string">'foo'</span>: <span class="number">1</span>, <span class="string">'bar'</span>: <span class="number">2</span>&#125;</div></pre></td></tr></table></figure>
<h3 id="Python-的作用域和命名空间"><a href="#Python-的作用域和命名空间" class="headerlink" title="Python 的作用域和命名空间"></a>Python 的作用域和命名空间</h3><p>命名空间(namespace)是从名称(标识符)到对象的映射,可以将其理解为字典,各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响</p>
<p>如果狭义点的话,可以将命名空间简单的理解为是变量(包括类和内置类型等)的引用.</p>
<p>四个namespace:一个函数的所有local,一个类对象的所有属性(数据成员,成员函数),一个模块的global(这个模块定义的函数,类,变量)和built-in(包括内置函数,内置常量,内置类型)</p>
<p>命名空间都是有创建时间和生存期的:</p>
<ol>
<li><p>对于Python built-in names组成的命名空间,它在Python解释器启动的时候被创建,<br>在解释器退出的时候才被删除.内置名称实际上也存在于一个模块中; 这个模块叫 builtins.</p>
</li>
<li><p>对于一个Python模块的global namespace,它在这个module被import的时候创建,<br>在解释器退出的时候退出.被最高级别的解释器调用的语句,不论是从脚本还是从交互读取的,<br>都被认为是一个名叫<strong>main</strong>的模块的一部分,所以它们有自己的全局命名空间.</p>
</li>
<li><p>对于一个函数的local namespace,它在函数每次被调用的时候创建,<br>函数返回的时候被删除.当然,递归调用会有它们自己的局部命名空间</p>
</li>
</ol>
<p>总结来说:一个模块的引入,类的定义,函数的调用都会引入命名空间</p>
<p>在执行过程中遇到了某个标识符(名称)时,Python首先尝试在local命名空间中查找它,如果没有找到,<br>再在global命名空间中查找,如果还是没有找到,接着在built-in命名空间中查找.<br>如果都不存在,则被认为是一个错误,会抛出一个”NameError”异常</p>
<h4 id="变量的作用域-scope"><a href="#变量的作用域-scope" class="headerlink" title="变量的作用域(scope):"></a>变量的作用域(scope):</h4><p>是Python程序的文本区域,在该区域某个命名空间中的名字可以被直接引用.你所申明的变量(包括类和内置变量等)可以在哪些地方使用.</p>
<p>一个Python程序的几个作用域:</p>
<ol>
<li>最里面的局部作用域,基本类型的作用域:(从变量定义处开始,以到结束此方法时截止)</li>
<li>外层函数的局部作用域:对象的作用域:(对象出了方法外后,只是引用消失了,但是对象本身还在堆中.资源回收站会定期回收垃圾对象)</li>
<li>模块的全局作用域</li>
<li>包含Python内置对象的最外层作用域</li>
</ol>
<h4 id="赋值-assignment"><a href="#赋值-assignment" class="headerlink" title="赋值(assignment):"></a>赋值(assignment):</h4><p>赋值操作不会拷贝,只是把标识符和对象做一个绑定,也就是说赋值操作就是名字和对象的绑定或重绑定,也可以说赋值是把原来对象的引用传递给另一个引用！</p>
<h4 id="global声明的变量会引用到当前模块的全局命名空间的变量"><a href="#global声明的变量会引用到当前模块的全局命名空间的变量" class="headerlink" title="global声明的变量会引用到当前模块的全局命名空间的变量"></a>global声明的变量会引用到当前模块的全局命名空间的变量</h4><h4 id="nonlocal-用于声明非全局的外层变量-这个声明会从声明处从里到外的namespace去搜寻这个变量-直到模块的全局域-不包括全局域"><a href="#nonlocal-用于声明非全局的外层变量-这个声明会从声明处从里到外的namespace去搜寻这个变量-直到模块的全局域-不包括全局域" class="headerlink" title="nonlocal:用于声明非全局的外层变量.这个声明会从声明处从里到外的namespace去搜寻这个变量,直到模块的全局域(不包括全局域)"></a>nonlocal:用于声明非全局的外层变量.这个声明会从声明处从里到外的namespace去搜寻这个变量,直到模块的全局域(不包括全局域)</h4><p>找到了则引用这个命名空间的这个名字和对象,若作赋值操作,则直接改变外层域中的这个名字的绑定.如果在外层域中没有找到,则会报错</p>
<p>这是一个例子用于说明如何引用不同的作用域和命名空间, global 和 nonlocal 如何影响变量绑定:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">scope_test</span><span class="params">()</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">do_local</span><span class="params">()</span>:</span></div><div class="line">        spam = <span class="string">"local spam"</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">do_nonlocal</span><span class="params">()</span>:</span></div><div class="line">        <span class="keyword">nonlocal</span> spam</div><div class="line">        spam = <span class="string">"nonlocal spam"</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">do_global</span><span class="params">()</span>:</span></div><div class="line">        <span class="keyword">global</span> spam</div><div class="line">        spam = <span class="string">"global spam"</span></div><div class="line"></div><div class="line">    spam = <span class="string">"test spam"</span></div><div class="line">    do_local()</div><div class="line">    print(<span class="string">"After local assignment:"</span>, spam)</div><div class="line">    <span class="comment"># test spam</span></div><div class="line">    do_nonlocal()</div><div class="line">    print(<span class="string">"After nonlocal assignment:"</span>, spam)</div><div class="line">    <span class="comment"># nonlocal spam</span></div><div class="line">    do_global()</div><div class="line">    print(<span class="string">"After global assignment:"</span>, spam)</div><div class="line">    <span class="comment"># nonlocal spam</span></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    scope_test()</div><div class="line">    print(<span class="string">"In global scope:"</span>, spam)</div><div class="line">    <span class="comment"># global spam</span></div></pre></td></tr></table></figure></p>
<p>注意局部的赋值(默认)并没有改变scope_test绑定的spam.<br>而nonlocal则改变了scope_test中的spam,而global则改变了模块级别的绑定.</p>
<p>你可以看到在global赋值之前并没有绑定spam的值</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span><span class="params">()</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">do_nonlocal</span><span class="params">()</span>:</span></div><div class="line">         <span class="keyword">nonlocal</span> spam</div><div class="line">         print(<span class="string">"asssignment:"</span>, spam)  </div><div class="line">         <span class="function"><span class="keyword">def</span> <span class="title">do_nonlocal2</span><span class="params">()</span>:</span></div><div class="line">            <span class="keyword">nonlocal</span> spam</div><div class="line">            spam = <span class="string">"nonlocal2 spam"</span>  <span class="comment">#修改了test()中spam的绑定</span></div><div class="line">            do_nonlocal2()</div><div class="line">    spam = <span class="string">"test spam"</span></div><div class="line">    do_nonlocal()</div><div class="line">    print(<span class="string">"after nonlocal2 asssignment:"</span>, spam)  </div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    test()</div><div class="line">    <span class="comment"># asssignment: test spam</span></div><div class="line">    <span class="comment"># after nonlocal2 asssignment: test spam</span></div><div class="line">    <span class="comment"># do_nonlocal2()中的spam引用的是其外面的二层,也就是test()函数域中的spam</span></div></pre></td></tr></table></figure>
<p>总结:Python会按照从内层到外层的顺序逐个寻找作用域中的变量(局部到全局),在函数内引用全局变量不需要global,函数内修改全局变量要加global,nonlocal也是一样</p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;面向对象编程-Object-Oriented-Programming-简称OOP&quot;&gt;&lt;a href=&quot;#面向对象编程-Object-Oriented-Programming-简称OOP&quot; class=&quot;headerlink&quot; title=&quot;面向对象编程:Objec
    
    </summary>
    
      <category term="python3" scheme="https://www.femn.me/categories/python3/"/>
    
    
      <category term="面向对象" scheme="https://www.femn.me/tags/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/"/>
    
  </entry>
  
  <entry>
    <title>python_threads</title>
    <link href="https://www.femn.me/2017/08/05/python-threads/"/>
    <id>https://www.femn.me/2017/08/05/python-threads/</id>
    <published>2017-08-05T06:46:15.000Z</published>
    <updated>2017-08-25T07:04:52.419Z</updated>
    
    <content type="html"><![CDATA[<p>线程例子1<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line">    <span class="keyword">import</span> threading</div><div class="line">    <span class="keyword">from</span> time <span class="keyword">import</span> ctime,sleep</div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">music</span><span class="params">(func)</span>:</span></div><div class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">2</span>):</div><div class="line">            print( <span class="string">"I was listening to %s. %s"</span> %(func,ctime()))</div><div class="line">            sleep(<span class="number">1</span>)</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">move</span><span class="params">(func)</span>:</span></div><div class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">2</span>):</div><div class="line">            print( <span class="string">"I was at the %s! %s"</span> %(func,ctime()))</div><div class="line">            sleep(<span class="number">5</span>)</div><div class="line">    <span class="comment"># 主线程中 加两个子线程</span></div><div class="line">    threads = [] <span class="comment"># 装载多个线程的数组 看着像是同时进行的</span></div><div class="line">    t1 = threading.Thread(target=music,args=(<span class="string">u'爱情买卖'</span>,))</div><div class="line">    threads.append(t1)</div><div class="line">    t2 = threading.Thread(target=move,args=(<span class="string">u'阿凡达'</span>,))</div><div class="line">    threads.append(t2)</div><div class="line"></div><div class="line"></div><div class="line">    <span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">        <span class="keyword">for</span> t <span class="keyword">in</span> threads:<span class="comment"># 子线程</span></div><div class="line">            t.setDaemon(<span class="keyword">True</span>)</div><div class="line">            <span class="string">""" 线程声明为守护线程,必须在start() 方法调用之前设置</span></div><div class="line"><span class="string">            如果不设置为守护线程程序会被无限挂起.</span></div><div class="line"><span class="string">            子线程启动后,父线程也继续执行下去,当父线程执行完最后一条语句print "all over %s" %ctime()后</span></div><div class="line"><span class="string">没有等待子线程,直接就退出了,同时子线程也一同结束"""</span></div><div class="line">            t.start()<span class="comment">#开始线程活动</span></div><div class="line">        t.join()</div><div class="line"><span class="string">""" 在子线程完成运行之前,这个子线程的父线程将一直被阻塞.join()实际上意味着等到队列为空,再执行别的操作</span></div><div class="line"><span class="string">join()方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程 """</span></div><div class="line">        print( <span class="string">"all over %s"</span> %ctime()) <span class="comment">#主线程</span></div></pre></td></tr></table></figure></p>
<p>线程例子2<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"><span class="keyword">import</span> _thread</div><div class="line"><span class="keyword">import</span> threading</div><div class="line"><span class="keyword">import</span> time</div><div class="line"></div><div class="line">exitFlag = <span class="number">0</span></div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">myThread</span> <span class="params">(threading.Thread)</span>:</span>   </div><div class="line">    <span class="comment">#继承父类threading.Thread</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self,  name, delay)</span>:</span></div><div class="line">        threading.Thread.__init__(self)</div><div class="line">        self.name = name</div><div class="line">        self.delay = delay</div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span>        </div><div class="line">       <span class="comment">#把要执行的代码写到run函数里面 线程在创建后会直接运行run函数</span></div><div class="line">        print( <span class="string">"Starting "</span> + self.name)</div><div class="line">        print_time(threadName=self.name,delay=self.delay,counter=<span class="number">5</span>)</div><div class="line">        print( <span class="string">"Exiting "</span> + self.name)</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">print_time</span><span class="params">(threadName, delay, counter)</span>:</span></div><div class="line">    <span class="keyword">while</span> counter:</div><div class="line">        <span class="keyword">if</span> exitFlag:</div><div class="line">            _thread.exit()</div><div class="line">        time.sleep(delay)</div><div class="line">        print( <span class="string">"%s: %s"</span> % (threadName, time.ctime(time.time())))</div><div class="line">        counter -= <span class="number">1</span></div><div class="line"></div><div class="line">thread1 = myThread(name=<span class="string">"Thread-1"</span>, delay=<span class="number">1</span>)</div><div class="line">thread2 = myThread(name=<span class="string">"Thread-2"</span>, delay=<span class="number">2</span>)</div><div class="line"></div><div class="line"><span class="comment"># 开启线程</span></div><div class="line">thread1.start()</div><div class="line">thread2.start()</div><div class="line">print( <span class="string">"Exiting Main Thread"</span>)</div></pre></td></tr></table></figure></p>
<p>同步线程<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">    <span class="keyword">import</span> threading</div><div class="line">    <span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</div><div class="line">    <span class="keyword">import</span> time</div><div class="line">    <span class="keyword">import</span> _thread</div><div class="line"></div><div class="line">    exitFlag = <span class="number">0</span></div><div class="line"></div><div class="line">    <span class="class"><span class="keyword">class</span> <span class="title">myThread</span> <span class="params">(threading.Thread)</span>:</span></div><div class="line">        <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self,  name, delay)</span>:</span></div><div class="line">            threading.Thread.__init__(self)</div><div class="line">            <span class="comment"># self.threadID = threadID</span></div><div class="line">            self.name = name</div><div class="line">            self.delay = delay</div><div class="line">        <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></div><div class="line">            print( <span class="string">"Starting "</span> + self.name)</div><div class="line"><span class="comment"># 如果多个线程共同对某个数据修改,则可能出现不可预料的结果,</span></div><div class="line"><span class="comment"># 为了保证数据的正确性,需要对多个线程进行同步.</span></div><div class="line"></div><div class="line"><span class="comment"># 线程同步(为了确保数据的完整没有被其它的线程修改,必须要得锁和解锁</span></div><div class="line"><span class="comment"># 所以也导致了要一个线程全部结束之后,才能执行下一个的线程)</span></div><div class="line"><span class="comment"># 这会导致同步阻塞,也就是只有一个线程工作完之后,才能进行下一个线程</span></div><div class="line"></div><div class="line">            <span class="comment"># 获得锁,成功获得锁定后返回True</span></div><div class="line">            <span class="comment"># 可选的timeout参数不填时将一直阻塞直到获得锁定</span></div><div class="line">            <span class="comment"># 否则超时后将返回False</span></div><div class="line">            threadLock.acquire()</div><div class="line">            print_time(threadName=self.name, delay=self.delay, counter=<span class="number">5</span>)</div><div class="line">            <span class="comment"># 释放锁</span></div><div class="line">            threadLock.release()</div><div class="line">            print( <span class="string">"Exiting "</span> + self.name)</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">print_time</span><span class="params">(threadName, delay, counter)</span>:</span></div><div class="line">        <span class="keyword">while</span> counter:</div><div class="line">            <span class="keyword">if</span> exitFlag:</div><div class="line">                _thread.exit()</div><div class="line">            time.sleep(delay)</div><div class="line">            print( <span class="string">"%s: %s"</span> % (threadName, time.ctime(time.time())))</div><div class="line">            counter -= <span class="number">1</span></div><div class="line"></div><div class="line">    <span class="comment"># 线程同步</span></div><div class="line">    threadLock = threading.Lock() </div><div class="line">    threads = []</div><div class="line">    thread1 = myThread(name=<span class="string">"Thread-1"</span>, delay=<span class="number">1</span>)</div><div class="line">    thread2 = myThread(name=<span class="string">"Thread-2"</span>, delay=<span class="number">2</span>)</div><div class="line"></div><div class="line">    <span class="comment"># 开启线程</span></div><div class="line">    n = datetime.now()</div><div class="line">    thread1.start()</div><div class="line">    thread1.join()<span class="comment">#因为没有queue可继续执行下面的线程</span></div><div class="line">    thread2.start() <span class="comment">#</span></div><div class="line"></div><div class="line">    <span class="comment"># 添加线程到线程列表</span></div><div class="line">    threads.append(thread1)</div><div class="line">    threads.append(thread2)</div><div class="line"></div><div class="line">    <span class="comment"># 等待所有线程完成</span></div><div class="line">    <span class="keyword">for</span> t <span class="keyword">in</span> threads:</div><div class="line">        t.join()</div><div class="line">    print(<span class="string">"Exiting Main Thread"</span>)</div><div class="line"></div><div class="line">    print(datetime.now()-n)</div></pre></td></tr></table></figure></p>
<p>quere<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">    <span class="keyword">import</span> queue, time, threading, datetime</div><div class="line"></div><div class="line">    <span class="class"><span class="keyword">class</span> <span class="title">Job</span>:</span></div><div class="line">        <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name)</span>:</span></div><div class="line">            self.name = name</div><div class="line"></div><div class="line">        <span class="function"><span class="keyword">def</span> <span class="title">do</span><span class="params">(self)</span>:</span></div><div class="line">            time.sleep(<span class="number">2</span>)</div><div class="line">            print(<span class="string">"\t[Info] Job(&#123;0&#125;) is done!"</span>.format(self.name))</div><div class="line"></div><div class="line"></div><div class="line">    que = queue.Queue()</div><div class="line"><span class="comment">#FIFO即First in First Out,先进先出 a[len(a):1]=[queue] 加在后面的</span></div><div class="line"><span class="comment"># lifoqueue = queue.LifoQueue()#LIFO即Last in First Out</span></div><div class="line"><span class="comment"># 后进先出 a[0:0]=[queue] 加在最前面的 入栈 出栈</span></div><div class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">20</span>):</div><div class="line">        <span class="comment"># 保存要去工作的信息 在queue中</span></div><div class="line">        que.put(Job(str(i + <span class="number">1</span>)))</div><div class="line"><span class="comment">#调用队列对象的put()方法在队尾插入一个项目</span></div><div class="line"><span class="comment"># put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为1</span></div><div class="line"><span class="comment"># 如果队列当前满且block为1,put()方法就使调用线程暂停,直到空出一个数据单元.</span></div><div class="line"><span class="comment"># 如果block为0,put方法将引发Queue.Full异常</span></div><div class="line">    print(<span class="string">"\t[Info] Queue size=&#123;0&#125;..."</span>.format(que.qsize()))<span class="comment">#返回队列的大小</span></div><div class="line"></div><div class="line">    <span class="comment"># # Start activity to digest queue.</span></div><div class="line">    st = datetime.datetime.now()</div><div class="line"></div><div class="line"></div><div class="line">    <span class="comment">#需要40秒</span></div><div class="line">    <span class="keyword">while</span> que.qsize() &gt; <span class="number">0</span>:</div><div class="line">        job = que.get()</div><div class="line">        job.do()</div><div class="line"></div><div class="line">    td = datetime.datetime.now() - st</div><div class="line">    print(<span class="string">"\t[Info] Spending time=&#123;0&#125;!"</span>.format(td))</div><div class="line"></div><div class="line"><span class="comment">#q.qsize() 返回队列的大小</span></div><div class="line"><span class="comment"># q.empty() 如果队列为空,返回True,反之False</span></div><div class="line"><span class="comment"># q.full() 如果队列满了,返回True,反之False</span></div><div class="line"><span class="comment"># q.full 与 maxsize 大小对应</span></div><div class="line"><span class="comment"># q.get([block[, timeout]]) 获取队列,timeout等待时间</span></div><div class="line"><span class="comment"># q.get_nowait() 相当q.get(False)</span></div><div class="line"><span class="comment"># 非阻塞 q.put(item) 写入队列,timeout等待时间</span></div><div class="line"><span class="comment"># q.put_nowait(item) 相当q.put(item, False)</span></div><div class="line"><span class="comment"># q.task_done() 在完成一项工作之后,q.task_done()函数向任务已经完成的队列发送一个信号</span></div><div class="line"><span class="comment"># q.join() 实际上意味着等到队列为空,再执行别的操作</span></div></pre></td></tr></table></figure></p>
<p>线程quere<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"><span class="keyword">import</span> queue, time, threading, datetime</div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Job</span>:</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, name)</span>:</span></div><div class="line">        self.name = name</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">do</span><span class="params">(self)</span>:</span></div><div class="line">        time.sleep(<span class="number">2</span>)</div><div class="line">        print(<span class="string">"\t[Info] Job(&#123;0&#125;) is done!"</span>.format(self.name))</div><div class="line"></div><div class="line"></div><div class="line">que = queue.Queue()</div><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">20</span>):</div><div class="line">    que.put(Job(str(i + <span class="number">1</span>)))</div><div class="line">print(<span class="string">"\t[Info] Queue size=&#123;0&#125;..."</span>.format(que.qsize()))</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">doJob</span><span class="params">(*args)</span>:</span></div><div class="line">    queue = args[<span class="number">0</span>]</div><div class="line">    <span class="keyword">while</span> queue.qsize() &gt; <span class="number">0</span>:</div><div class="line">        job = queue.get()</div><div class="line"><span class="comment">#调用队列对象的get()方法从队头删除并返回一个项目.可选参数为block,默认为True.</span></div><div class="line"><span class="comment"># 如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用.</span></div><div class="line"><span class="comment"># 如果队列为空且block为False,队列将引发Queue.Empty异常</span></div><div class="line">        job.do()</div><div class="line"></div><div class="line">    <span class="comment"># Open three threads</span></div><div class="line">thd1 = threading.Thread(target=doJob, name=<span class="string">'Thd1'</span>, args=(que,))</div><div class="line">thd2 = threading.Thread(target=doJob, name=<span class="string">'Thd2'</span>, args=(que,))</div><div class="line">thd3 = threading.Thread(target=doJob, name=<span class="string">'Thd3'</span>, args=(que,))</div><div class="line"><span class="comment"># thd4 = threading.Thread(target=doJob, name='Thd3', args=(que,))</span></div><div class="line"><span class="comment"># thd5 = threading.Thread(target=doJob, name='Thd3', args=(que,))</span></div><div class="line"></div><div class="line"><span class="comment"># # Start activity to digest queue.</span></div><div class="line">st = datetime.datetime.now()</div><div class="line">thd1.start()</div><div class="line">thd2.start()</div><div class="line">thd3.start()</div><div class="line"><span class="comment"># thd1.join()</span></div><div class="line"><span class="comment">#在子线程完成运行之前,这个子线程的父线程将一直被阻塞.</span></div><div class="line"><span class="comment"># join() 实际上意味着等到队列为空,再执行别的操作</span></div><div class="line"></div><div class="line"><span class="comment">#這會讓呼叫 join() 方法的線程被 blocked, 一直到被呼叫 join() 的線程結束為止</span></div><div class="line"><span class="comment">#不会再进行下面的线程了</span></div><div class="line"><span class="comment"># thd4.start()</span></div><div class="line"><span class="comment"># thd5.start()</span></div><div class="line"><span class="comment">#首先當 Thread 類別被實例化, 你可以呼叫物件上面的方法 start() 來啟動該線程,</span></div><div class="line"><span class="comment">#  一旦線程啟動, 它的狀態會變成 "alive" ;</span></div><div class="line"></div><div class="line"><span class="comment"># Wait for all threads to terminate.</span></div><div class="line"><span class="keyword">while</span> thd1.is_alive() <span class="keyword">or</span> thd2.is_alive() <span class="keyword">or</span> thd3.is_alive():</div><div class="line">    time.sleep(<span class="number">1</span>)</div><div class="line"></div><div class="line"><span class="comment"># 當執行完畢 run() 後狀態便不在是 "alive".</span></div><div class="line"></div><div class="line">td = datetime.datetime.now() - st</div><div class="line">print(<span class="string">"\t[Info] Spending time=&#123;0&#125;!"</span>.format(td))</div></pre></td></tr></table></figure></p>
<p>推荐使用<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> queue</div><div class="line"><span class="keyword">import</span> threading</div><div class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</div><div class="line"></div><div class="line">SHARE_Q = queue.Queue()  <span class="comment"># 构造一个不限制大小的的队列</span></div><div class="line">_WORKER_THREAD_NUM = <span class="number">4</span>  <span class="comment"># 设置线程的个数</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">worker</span><span class="params">()</span>:</span></div><div class="line">    <span class="keyword">global</span> SHARE_Q</div><div class="line">    <span class="keyword">while</span> <span class="keyword">not</span> SHARE_Q.empty():</div><div class="line">        one_dict = SHARE_Q.get()  <span class="comment"># 获得任务</span></div><div class="line">        <span class="comment"># to worker ...</span></div><div class="line">        SHARE_Q.task_done()</div><div class="line"></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></div><div class="line">    a= datetime.now()</div><div class="line">    threads = []</div><div class="line">    <span class="keyword">global</span> SHARE_Q</div><div class="line"></div><div class="line">    library_list =[<span class="string">'9787550215184'</span>,<span class="string">'9787550206267'</span>]</div><div class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> library_list:</div><div class="line">        SHARE_Q.put(i)</div><div class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> range(_WORKER_THREAD_NUM):</div><div class="line">        thr = threading.Thread(target=worker)</div><div class="line">        <span class="comment"># 必须要有 target去指定函数</span></div><div class="line">        thr.start()</div><div class="line">        threads.append(thr)</div><div class="line">    <span class="keyword">for</span> thread <span class="keyword">in</span> threads:</div><div class="line">        thread.join()</div><div class="line">    SHARE_Q.join()</div><div class="line">    print(datetime.now() -a)<span class="comment">#0:00:00.376745</span></div><div class="line">    print(<span class="string">'success'</span>)</div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    main()</div></pre></td></tr></table></figure></p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;线程例子1&lt;br&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot;&gt;1&lt;/div&gt;&lt;div class=&quot;line&quot;&gt;2&lt;/div&gt;&lt;div class
    
    </summary>
    
      <category term="python3" scheme="https://www.femn.me/categories/python3/"/>
    
    
  </entry>
  
  <entry>
    <title>进程与线程</title>
    <link href="https://www.femn.me/2017/08/05/threads/"/>
    <id>https://www.femn.me/2017/08/05/threads/</id>
    <published>2017-08-05T03:16:14.000Z</published>
    <updated>2017-08-25T07:05:55.884Z</updated>
    
    <content type="html"><![CDATA[<p>性能:在其他同等条件下,高性能的程序应该可以等同于CPU的利用率,CPU的利用率越高(一直在工作,没有闲下来的时候),程序的性能越高.</p>
<p>体验:这里的体验不只是界面多么漂亮,功能多么顺手,这里的体验指程序的响应速度,响应速度越快,用户体验越好.</p>
<p>由于我们要解决的问题是CPU高速执行能力和IO设备的龟速严重不匹配,多线程和多进程只是解决这一问题的一种方法.</p>
<p>另一种解决IO问题的方法是异步IO.当代码需要执行一个耗时的IO操作时,它只发出IO指令,并不等待IO结果,然后就去执行其他代码了.<br>一段时间后,当IO返回结果时,再通知CPU进行处理,在处理 IO 的时候,阻塞和非阻塞都是同步 IO. 只有使用了特殊的 API 才是异步 IO.</p>
<p>首先对一些名词的理解</p>
<h3 id="被调用方-同步与异步关乎做事情的方式-同步-做完一件事再去做另一件-异步-同时做多件事情-某个事情有结果了再去处理-又一个新事情-我的理解-被调用方有没有能力同时处理问题的能力"><a href="#被调用方-同步与异步关乎做事情的方式-同步-做完一件事再去做另一件-异步-同时做多件事情-某个事情有结果了再去处理-又一个新事情-我的理解-被调用方有没有能力同时处理问题的能力" class="headerlink" title="被调用方:同步与异步关乎做事情的方式. 同步:做完一件事再去做另一件. 异步:同时做多件事情,某个事情有结果了再去处理(又一个新事情)我的理解: 被调用方有没有能力同时处理问题的能力."></a>被调用方:同步与异步关乎做事情的方式. 同步:做完一件事再去做另一件. 异步:同时做多件事情,某个事情有结果了再去处理(又一个新事情)我的理解: 被调用方有没有能力同时处理问题的能力.</h3><p>同步和异步关注的是消息通信机制(synchronous communication/ asynchronous communication):<br>所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回,但是一旦调用返回,就得到返回值了<br>换句话说,就是由调用者主动等待这个调用的结果</p>
<p>而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果.换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果.<br>而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用</p>
<h3 id="调用方-阻塞与非阻塞关乎如何对待事情产生的结果-阻塞-不等到想要的结果我就不走了-非阻塞-有结果我就带走-没结果我就空手而回-总之一句话-爷等不起"><a href="#调用方-阻塞与非阻塞关乎如何对待事情产生的结果-阻塞-不等到想要的结果我就不走了-非阻塞-有结果我就带走-没结果我就空手而回-总之一句话-爷等不起" class="headerlink" title="调用方:阻塞与非阻塞关乎如何对待事情产生的结果. 阻塞:不等到想要的结果我就不走了. 非阻塞:有结果我就带走,没结果我就空手而回,总之一句话:爷等不起"></a>调用方:阻塞与非阻塞关乎如何对待事情产生的结果. 阻塞:不等到想要的结果我就不走了. 非阻塞:有结果我就带走,没结果我就空手而回,总之一句话:爷等不起</h3><h3 id="并发与并行"><a href="#并发与并行" class="headerlink" title="并发与并行"></a>并发与并行</h3><p>并发指在同一时刻,只能有一条指令执行,但多个进程指令被快速轮换执行(纳秒级),使得在宏观上具有多个进程同时执行的效果.<br>只能运行一个进程,CPU不断地在这些进程之间轮换执行,</p>
<p>并行指在同一时刻,有多条指令在多个处理器上同时执行;多个CPU处理器</p>
<h3 id="进程-拥有独立的内存单元-chrome使用多进程-与线程-也被称作轻量级进程"><a href="#进程-拥有独立的内存单元-chrome使用多进程-与线程-也被称作轻量级进程" class="headerlink" title="进程(拥有独立的内存单元,chrome使用多进程)与线程(也被称作轻量级进程)"></a>进程(拥有独立的内存单元,chrome使用多进程)与线程(也被称作轻量级进程)</h3><p>进程:程序的一次执行. 线程:CPU的基本调度单位 ,而在Linux系统里面,在最底层,线程和进程确实是不区分的.</p>
<p>进程是系统进行资源分配和调度的一个独立单位,线程是进程的执行单元.线程的调度和管理由进程本身负责完成.线程在进程中是独立的、并发的执行流.</p>
<p>当一个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程.当一个程序进入内存,运行后,即变成一个进程.</p>
<h4 id="进程的三个特性"><a href="#进程的三个特性" class="headerlink" title="进程的三个特性"></a>进程的三个特性</h4><ol>
<li><p>独立性:进程是系统中独立存在的实体,它可以拥有自己独立的资源,每一个进程都拥有自己私有的地址空间.在没有经过进程本身允许的情况下,一个用户进程不可以直接就访问其他进程的地址空间.</p>
</li>
<li><p>动态性:进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合.在进程中加入了时间的概念.进程具有自己的生命周期和各种不同的状态,这些概念在程序中都是不具备的.</p>
</li>
<li><p>并发性:多个进程可以在单个处理器上并发执行,多个进程之间不会互相影响</p>
</li>
</ol>
<p>车间:</p>
<p>   <a href="http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html" target="_blank" rel="external">一个进程与线程的一个简单解释</a><br>   程序(车间,有独立的内存空间)之间进行内存数据交换(通信)比较麻烦:每个程序的内存空间都是被保护的,不能被别的程序直接访问,所以要通过某种介质,管道或第三方工具,去通信.<br>   nosql(第三方):将内存的数据缓存进来,供其它的程序调用,所有的程序都可以往里存数据,所有的程序都可以取数据.相当于实现了一个共享的内存空间</p>
<p>餐桌:</p>
<p>   一群人(多个线程)在一个桌子(进程)上吃饭,他们会涉及到一些问题,比如多个人可能会夹一个菜(竞争)<br>A和B同时看到盘子里面有一块肉,同时伸出筷子去夹,A先夹走,B迟了一点伸到盘子的时候已经没了,只能缩回来(临界资源,互斥)<br>有一个点心需要用馍夹肉一起吃.A夹了肉,B夹了馍,A需要B的馍,B需要A的肉,他们僵持不下谁都不让步(死锁).<br>多线程之间的资源共享是非常方便的,因为他们共用进程的资源空间(在一个桌子上),但是需要注意一系列的问题,竞争,死锁,同步等</p>
<p>   如果在旁边再开一个桌子(进程). 那么桌子之间讲话,递东西又不方便(进程间通信),而开一个桌子的开销比在一个桌子上多加一个人的开销要大.<br>另外一个桌子上的人数不可能无限制增加,桌子的容量有限也坐不下这么多人(进程的线程句柄是有限制的).<br>一个桌子坏了不会影响到另一个桌子上面人的就餐情况(进程间相互独立,一个进程崩溃不会影响另一个),而一个桌子上的某人喝挂了需要送医院,<br>估计这一桌人都要散了(线程挂掉会导致整个进程也挂掉).所以多线程与多进程是各有优缺点,不能一概而论</p>
<ol>
<li>对于 Windows系统来说,【开桌子】的开销很大,因此Windows鼓励大家在一个桌子上吃菜.因此Windows多线程学习重点是要大量面对资源争抢与同步方面的问题.</li>
<li>对于Linux系统来说,【开桌子】的开销很小,因此Linux鼓励大家尽量每个人都开自己的桌子吃菜.这带来新的问题是:坐在两张不同的桌子上,说话不方便.<br>因此,Linux下的学习重点大家要学习进程间通讯的方法.</li>
</ol>
<h3 id="单线程-单任务-按顺序去完成-和多线程"><a href="#单线程-单任务-按顺序去完成-和多线程" class="headerlink" title="单线程(单任务,按顺序去完成)和多线程"></a>单线程(单任务,按顺序去完成)和多线程</h3><p>   多线程则扩展了多进程的概念,使得同一个进程可以同时并发(轮换执行)处理多个任务.线程(Thread)也被称作轻量级进程(LightweightProcess),线程是进程的执行单元.</p>
<p>   就像进程在操作系统中的地位一样,线程在进程中是独立的、并发的执行流.进程操作系统–线程进程,当线程被初始化后,主线程就被创建了对于应用程序而言,</p>
<p>   通常至少有一个主线程,可以在该进程内创建多条顺序执行流,这些顺序执行流就是线程,每条线程也是相互独立的;</p>
<p>   线程是进程的的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程,线程可以拥有自己的堆栈、自己的程序计数器和自己的局部变量,<br>但是不再拥有系统资源,它与父进程的其他线程共享该进程所拥有的全部资源.</p>
<p>   因为多个线程共享父进程里的全部资源,因此编程更加方便;但必须更加小心,必须确保线程不会妨碍同一进程里的其他线程.线程的调度和管理由进程本身负责完成.</p>
<p>进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率</p>
<p>车间:</p>
<p>当要完成一项工作或多项工作时(但还是在一个主线程中),单线程就好比一个工人,而多线程就是招了多个工人一起干活,效率当然快了！<br>但管理就费劲了(死锁,竟争),允许单个任务分成不同的部分运行</p>
<p>餐桌:</p>
<p>单线程就是整个餐厅只有一个单人桌,这个人吃完了,下一个人轮上.<br>但大餐馆用的可能是八仙桌,同时能容纳八个人吃饭,这就是多线程:从一次一个变成了一次多个或者多次多个</p>
<h4 id="多线程的作用"><a href="#多线程的作用" class="headerlink" title="多线程的作用"></a>多线程的作用</h4><p>1.把程序细分成几个功能相对独立的模块,防止其中一个功能模块阻塞导致整个程序假死(GUI程序是典型).一个线程一件事,多线程做多件事</p>
<p>2.提高运行效率,比如多个核同时跑,或者单核里面,某个线程进行IO操作时,另一个线程可以同时执行<br>这样一条主线程,处理整个程序任务的主方向的链,而其链上又有许许多多的分支,就像树枝那样,<br> 这样,既有了主线程去处理那些主要任务,又有了那些细小线程去处理耗时费力任务,从而让界面看起来更加流畅</p>
<h4 id="多线程做同一件事"><a href="#多线程做同一件事" class="headerlink" title="多线程做同一件事"></a>多线程做同一件事</h4><p>多线程使得程序内部可以分出多个线程来做多件事情,而不会造成程序界面卡死.比如迅雷等多线程下载工具就是典型的多线程.<br>一个下载任务进来,迅雷把文件平分成10份,然后开10个线程分别下载.这时主界面是一个单独的线程,并不会因为下载文件而卡死.<br>而且主线程可以控制下属线程,比如某个线程下载缓慢甚至停止,主线程可以把它强行关掉并重启另外一个线程.</p>
<p>多线程因为在同一个进程里,所以可以共享内存和其他资源,比如迅雷里10个线程一齐下载一个文件,这个文件是由进程打开的,<br>然后10个线程都可以往里写入东西.如果是10个进程就不行了,操作系统不允许一个文件由两个进程同时写入</p>
<p>python中使用 GIL(global interpreter lock)保证了线程安全(保证数据被安全读取),即同时只能有一个线程在CPU上运行,<br>这个线程也不能扩散到其它CPU上,GIL是以CPU为单位去控制这个锁,对于python的多线程,多核也没有实际的提速作用,</p>
<h4 id="所以多线程在Python中只能跑在一个CPU上-如果想利用多CPU的话-就使用多进程-需要给独立的内存空间-所以比较占内存资源"><a href="#所以多线程在Python中只能跑在一个CPU上-如果想利用多CPU的话-就使用多进程-需要给独立的内存空间-所以比较占内存资源" class="headerlink" title="所以多线程在Python中只能跑在一个CPU上.如果想利用多CPU的话,就使用多进程(需要给独立的内存空间,所以比较占内存资源)."></a>所以多线程在Python中只能跑在一个CPU上.如果想利用多CPU的话,就使用多进程(需要给独立的内存空间,所以比较占内存资源).</h4><p>当每个CPU核心运行一个进程的时候,由于每个进程的资源都独立,所以CPU核心之间切换的时候无需考虑上下文.</p>
<p>当每个CPU核心运行一个线程的时候,由于每个线程需要共享资源,所以这些资源必须从CPU的一个核心被复制到另外一个核心,才能继续运算,这占用了额外的开销.<br>换句话说,在CPU为多核的情况下,多线程在性能上不如多进程.</p>
<h3 id="1-以多进程形式-允许多个任务同时运行"><a href="#1-以多进程形式-允许多个任务同时运行" class="headerlink" title="(1)以多进程形式,允许多个任务同时运行;"></a>(1)以多进程形式,允许多个任务同时运行;</h3><h3 id="2-以多线程形式-允许单个任务分成不同的部分运行"><a href="#2-以多线程形式-允许单个任务分成不同的部分运行" class="headerlink" title="(2)以多线程形式,允许单个任务分成不同的部分运行;"></a>(2)以多线程形式,允许单个任务分成不同的部分运行;</h3><h3 id="3-提供协调机制-一方面防止进程之间和线程之间产生冲突-另一方面允许进程之间和线程之间共享资源"><a href="#3-提供协调机制-一方面防止进程之间和线程之间产生冲突-另一方面允许进程之间和线程之间共享资源" class="headerlink" title="(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源."></a>(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源.</h3><h3 id="协程-又称微线程-coroutine-相当于单线程的能力-与子程序-函数调用是通过栈实现的-一个线程就是执行一个子程序-子程序就是协程的一种特例"><a href="#协程-又称微线程-coroutine-相当于单线程的能力-与子程序-函数调用是通过栈实现的-一个线程就是执行一个子程序-子程序就是协程的一种特例" class="headerlink" title="协程(又称微线程(coroutine),相当于单线程的能力)与子程序(函数调用是通过栈实现的,一个线程就是执行一个子程序,子程序就是协程的一种特例)"></a>协程(又称微线程(coroutine),相当于单线程的能力)与子程序(函数调用是通过栈实现的,一个线程就是执行一个子程序,子程序就是协程的一种特例)</h3><p>  子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕.<br>  协程(协作完成任务),tornado好像就是用协程来实现异步的协程,协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行.</p>
<h3 id="协程的特点在于是一个线程执行-所有协程有如下优势"><a href="#协程的特点在于是一个线程执行-所有协程有如下优势" class="headerlink" title="协程的特点在于是一个线程执行,所有协程有如下优势"></a>协程的特点在于是一个线程执行,所有协程有如下优势</h3><p>  最大的优势就是协程极高的执行效率.因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显.</p>
<p>第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多.<br><a href="https://github.com/willwinworld/asyncmultispider" target="_blank" rel="external">参考于此</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;性能:在其他同等条件下,高性能的程序应该可以等同于CPU的利用率,CPU的利用率越高(一直在工作,没有闲下来的时候),程序的性能越高.&lt;/p&gt;
&lt;p&gt;体验:这里的体验不只是界面多么漂亮,功能多么顺手,这里的体验指程序的响应速度,响应速度越快,用户体验越好.&lt;/p&gt;
&lt;p&gt;由
    
    </summary>
    
      <category term="linux" scheme="https://www.femn.me/categories/linux/"/>
    
    
  </entry>
  
  <entry>
    <title>迭代器与生成器</title>
    <link href="https://www.femn.me/2017/08/05/iterable-iterator-generator/"/>
    <id>https://www.femn.me/2017/08/05/iterable-iterator-generator/</id>
    <published>2017-08-05T01:46:55.000Z</published>
    <updated>2017-08-24T04:10:08.349Z</updated>
    
    <content type="html"><![CDATA[<h3 id="为什么使用迭代"><a href="#为什么使用迭代" class="headerlink" title="为什么使用迭代"></a>为什么使用迭代</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1000</span>): <span class="keyword">pass</span></div></pre></td></tr></table></figure>
<p>会导致生成一个 1000 个元素的 List</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">for</span> i <span class="keyword">in</span> xrange(<span class="number">1000</span>): <span class="keyword">pass</span></div></pre></td></tr></table></figure>
<p>则不会生成一个 1000 个元素的 List,而是在每次迭代中返回下一个数值,内存空间占用很小.</p>
<p>因为 xrange 不返回 List,而是返回一个 iterable 对象</p>
<h3 id="迭代"><a href="#迭代" class="headerlink" title="迭代"></a>迭代</h3><p>迭代的意思是重复做一些事情很多次,记得在for循环中对序列和字典进行过迭代,for .. in .. 语法的叫做一个迭代器</p>
<p>迭代是一个实现可迭代对象(实现的是 <strong>iter</strong>() 方法)和迭代器(实现的是 <strong>next</strong>() 方法)的过程.</p>
<h3 id="可迭代对象-iterable"><a href="#可迭代对象-iterable" class="headerlink" title="可迭代对象(iterable)"></a>可迭代对象(iterable)</h3><p>一个实现了 <strong>iter</strong>方法的对象是可迭代的对象,该方法返回一个迭代器对象</p>
<p>iterable包括list,set,dict等一般的对象,处于打开状态的files,sockets 也是可迭代对象</p>
<h3 id="迭代器-iterator"><a href="#迭代器-iterator" class="headerlink" title="迭代器(iterator)"></a>迭代器(iterator)</h3><p>一个实现了next方法的对象则是迭代器,迭代器是一个带状态的对象,返回容器中的下一个值,并为下一次调用next()方法修改状态</p>
<p>可迭代对象是你可以从其获取到一个迭代器的任一对象.迭代器是那些允许你迭代可迭代对象的对象<br>我们自定义一个迭代器,以斐波那契数列为例:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Fab</span><span class="params">(object)</span>:</span></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, max)</span>:</span></div><div class="line">    self.max = max</div><div class="line">    self.n, self.a, self.b = <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">__iter__</span><span class="params">(self)</span>:</span></div><div class="line">    <span class="keyword">return</span> self</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">next</span><span class="params">(self)</span>:</span> <span class="comment"># python3使用__next__()</span></div><div class="line">    <span class="keyword">if</span> self.n &lt; self.max:</div><div class="line">        r = self.b</div><div class="line">        self.a, self.b = self.b, self.a + self.b</div><div class="line">        self.n = self.n + <span class="number">1</span></div><div class="line">        <span class="keyword">return</span> r</div><div class="line">    <span class="keyword">raise</span> StopIteration()</div><div class="line"><span class="meta">&gt;&gt;&gt; </span><span class="keyword">for</span> n <span class="keyword">in</span> Fab(<span class="number">5</span>): <span class="keyword">print</span> n</div></pre></td></tr></table></figure></p>
<p>迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用.</p>
<p>有很多关于迭代器的例子<br><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">it=iter([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>])  iterkeys(&#123;<span class="number">1</span>:<span class="string">"1"</span>,<span class="number">2</span>:<span class="string">"2"</span>&#125;) iteritems(&#123;&#125;) <span class="comment"># 可迭代对象</span></div><div class="line">it.next() <span class="comment"># python3.0之前 迭代器</span></div><div class="line">next(it)   <span class="comment">#       之后</span></div><div class="line"></div><div class="line"><span class="comment"># itertools函数返回的都是迭代器对象</span></div><div class="line"><span class="keyword">from</span> itertools <span class="keyword">import</span> cycle , islice</div><div class="line">colors = cycle([<span class="string">'red'</span>, <span class="string">'white'</span>, <span class="string">'blue'</span>])</div><div class="line">next(colors)</div><div class="line">limited = islice(colors, <span class="number">0</span>, <span class="number">4</span>)</div><div class="line"><span class="keyword">for</span> x <span class="keyword">in</span> limited:<span class="keyword">print</span> x</div></pre></td></tr></table></figure></p>
<h3 id="生成器-generator"><a href="#生成器-generator" class="headerlink" title="生成器(generator)"></a>生成器(generator)</h3><p>是一种用普通函数语法定义的迭代器.生成器一定是迭代器(反之不成立)</p>
<p>yield 保持简洁性的同时获得了 iterable 的效果.把一个函数改写为一个 generator 就获得了迭代能力</p>
<p>yield 是一个类似 return 的关键字,只是这个函数返回的是个生成器</p>
<p>yield 进程挂起 保持连接</p>
<ol>
<li>使用生成器,定义斐波那契数列<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">fab</span><span class="params">(max)</span>:</span></div><div class="line">    n, a, b = <span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span></div><div class="line">    <span class="keyword">while</span> n &lt; max:</div><div class="line">        <span class="keyword">yield</span> b <span class="comment">#</span></div><div class="line">        <span class="comment"># yield 的作用就是把一个函数变成一个 generator</span></div><div class="line">        <span class="comment"># 调用 fab(5)不会执行fab函数,而是返回一个iterable对象</span></div><div class="line">        a, b = b, a + b</div><div class="line">        n = n + <span class="number">1</span></div><div class="line">        <span class="comment"># 如果没有return,则默认执行至函数完毕,如果在执行过程中return</span></div><div class="line">        <span class="comment">#则直接抛出StopIteration终止迭代</span></div></pre></td></tr></table></figure>
</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">for</span> n <span class="keyword">in</span> fab(<span class="number">5</span>): <span class="keyword">print</span> n</div></pre></td></tr></table></figure>
<p>在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时<br>fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行<br>而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield<br>看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">f = fab(<span class="number">5</span>)</div><div class="line"><span class="keyword">print</span> f.next()</div></pre></td></tr></table></figure>
<p>手动调用 fab(5) 的 next() 方法(因为 fab(5) 是一个 generator 对象,该对象具有 next() 方法),<br>这样我们就可以更清楚地看到 fab 的执行流程</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">f1 = fab(<span class="number">5</span>)</div><div class="line"><span class="keyword">print</span> f1.next()</div></pre></td></tr></table></figure>
<p>每次调用 fab 函数都会生成一个新的 generator 实例,各实例互不影响</p>
<ol>
<li>使用生成器,定义斐波那契数列</li>
</ol>
<figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">()</span>:</span></div><div class="line">    prev, curr = <span class="number">0</span>, <span class="number">1</span></div><div class="line">    <span class="keyword">while</span> <span class="keyword">True</span>:</div><div class="line">        <span class="keyword">yield</span> curr</div><div class="line">        prev, curr = curr, curr + prev</div><div class="line"><span class="keyword">from</span> itertools <span class="keyword">import</span> islice</div><div class="line"><span class="meta">&gt;&gt;&gt; </span>f = fib()</div><div class="line"><span class="meta">&gt;&gt;&gt; </span>list(islice(f, <span class="number">0</span>, <span class="number">10</span>))</div><div class="line">[<span class="number">1</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">8</span>, <span class="number">13</span>, <span class="number">21</span>, <span class="number">34</span>, <span class="number">55</span>]</div></pre></td></tr></table></figure>
<h3 id="生成器推导式"><a href="#生成器推导式" class="headerlink" title="生成器推导式"></a>生成器推导式</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">d=(x*x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>))</div><div class="line">sum(d)</div><div class="line"><span class="comment"># 285</span></div><div class="line">d.next() <span class="comment"># StopIteration sum(d)已经迭代完了</span></div></pre></td></tr></table></figure>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;为什么使用迭代&quot;&gt;&lt;a href=&quot;#为什么使用迭代&quot; class=&quot;headerlink&quot; title=&quot;为什么使用迭代&quot;&gt;&lt;/a&gt;为什么使用迭代&lt;/h3&gt;&lt;figure class=&quot;highlight python&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class
    
    </summary>
    
      <category term="python3" scheme="https://www.femn.me/categories/python3/"/>
    
    
  </entry>
  
  <entry>
    <title>docker RUN ENTRYPOINT CMD命令</title>
    <link href="https://www.femn.me/2017/08/04/docker-RUN-ENTRYPOINT-CMD/"/>
    <id>https://www.femn.me/2017/08/04/docker-RUN-ENTRYPOINT-CMD/</id>
    <published>2017-08-04T12:19:31.000Z</published>
    <updated>2017-08-24T04:10:08.329Z</updated>
    
    <content type="html"><![CDATA[<h3 id="运行时机"><a href="#运行时机" class="headerlink" title="运行时机"></a>运行时机</h3><p>RUN在Dockerfile构建镜像的过程(Build)中运行,最终被commit的到镜像.</p>
<p>ENTRYPOINT和CMD在容器运行(run、start)时运行</p>
<h3 id="都有shell和exec形式"><a href="#都有shell和exec形式" class="headerlink" title="都有shell和exec形式"></a>都有shell和exec形式</h3><p>shell形式<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">RUN <span class="built_in">command</span> param1 param2</div><div class="line">CMD <span class="built_in">command</span> param1 param2</div><div class="line">ENTRYPOINT <span class="built_in">command</span> param1 param2</div><div class="line"><span class="comment"># ENTRYPOINT的Shell格式会忽略任何CMD或docker run提供的参数</span></div><div class="line"><span class="comment">#eg</span></div><div class="line">RUN apt-get install python3  </div><div class="line">ENTRYPOINT <span class="built_in">echo</span> <span class="string">"Hello world"</span> </div><div class="line">CMD <span class="built_in">echo</span> <span class="string">"Hello world"</span>  </div><div class="line"></div><div class="line">ENV name Cloud Man  </div><div class="line">ENTRYPOINT <span class="built_in">echo</span> <span class="string">"Hello, <span class="variable">$name</span>"</span> </div><div class="line"><span class="comment"># shell 格式底层会调用 /bin/sh -c &lt;command&gt;</span></div><div class="line"><span class="comment"># 所以执行 docker run &lt;image&gt; 将输出</span></div><div class="line"><span class="comment"># Hello, Cloud Man</span></div></pre></td></tr></table></figure></p>
<h4 id="shell形式还有一个严重的问题-由于其默认使用-bin-sh来运行命令-如果镜像中不包含-bin-sh-容器会无法启动"><a href="#shell形式还有一个严重的问题-由于其默认使用-bin-sh来运行命令-如果镜像中不包含-bin-sh-容器会无法启动" class="headerlink" title="shell形式还有一个严重的问题:由于其默认使用/bin/sh来运行命令,如果镜像中不包含/bin/sh,容器会无法启动."></a>shell形式还有一个严重的问题:由于其默认使用/bin/sh来运行命令,如果镜像中不包含/bin/sh,容器会无法启动.</h4><p>exec形式<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">RUN [<span class="string">"executable"</span>, <span class="string">"param1"</span>, <span class="string">"param2"</span>]</div><div class="line">ENTRYPOINT [<span class="string">"executable"</span>, <span class="string">"param1"</span>, <span class="string">"param2"</span>]</div><div class="line">CMD [<span class="string">"executable"</span>, <span class="string">"param1"</span>, <span class="string">"param2"</span>]</div><div class="line"><span class="comment">#eg</span></div><div class="line">RUN [<span class="string">"apt-get"</span>, <span class="string">"install"</span>, <span class="string">"python3"</span>]  </div><div class="line">ENTRYPOINT [<span class="string">"/bin/echo"</span>, <span class="string">"Hello world"</span>]</div><div class="line">CMD [<span class="string">"/bin/echo"</span>, <span class="string">"Hello world"</span>]  </div><div class="line"></div><div class="line">ENV name Cloud Man  </div><div class="line">ENTRYPOINT [<span class="string">"/bin/echo"</span>, <span class="string">"Hello, <span class="variable">$name</span>"</span>]</div><div class="line"><span class="comment"># Hello, $name</span></div><div class="line">ENV name Cloud Man  </div><div class="line">ENTRYPOINT [<span class="string">"/bin/sh"</span>, <span class="string">"-c"</span>, <span class="string">"echo Hello, <span class="variable">$name</span>"</span>]</div><div class="line"><span class="comment"># Hello, Cloud Man</span></div></pre></td></tr></table></figure></p>
<p>CMD还多了一种用于为ENTRYPOINT提供参数的形式:<br>此时 ENTRYPOINT 必须使用 Exec 格式<br>参数格式<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">CMD [<span class="string">"param1"</span>,<span class="string">"param2"</span>]</div></pre></td></tr></table></figure></p>
<p>shell形式和exec的形式的本质区别在于shell形式提供了默认的指令/bin/sh -c,所以其指定的command将在shell的环境下运行.因此指定command的pid将不会是1,因为pid为1的是shell,command进程是shell的子进程.</p>
<h4 id="exec形式则不然-但由于exec指定的命令不由shell启动-因此也就无法使用shell中的环境变量-如-HOME-如果希望能够使用环境变量-可以指定命令为sh-CMD-“sh”-“-c”-“echo”-“-HOME”"><a href="#exec形式则不然-但由于exec指定的命令不由shell启动-因此也就无法使用shell中的环境变量-如-HOME-如果希望能够使用环境变量-可以指定命令为sh-CMD-“sh”-“-c”-“echo”-“-HOME”" class="headerlink" title="exec形式则不然,但由于exec指定的命令不由shell启动,因此也就无法使用shell中的环境变量,如$HOME.如果希望能够使用环境变量,可以指定命令为sh:CMD [ “sh”, “-c”, “echo”, “$HOME” ]"></a>exec形式则不然,但由于exec指定的命令不由shell启动,因此也就无法使用shell中的环境变量,如$HOME.如果希望能够使用环境变量,可以指定命令为sh:CMD [ “sh”, “-c”, “echo”, “$HOME” ]</h4><h3 id="重载问题"><a href="#重载问题" class="headerlink" title="重载问题"></a>重载问题</h3><p>Dockerfile中只有最后一个ENTRYPOINT指令会生效,其他会被重载.</p>
<p>Dockerfile中只有最后一个CMD指令会生效,其他会被重载.</p>
<p>CMD指定的命令可以被docker run传递的命令覆盖.<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">CMD <span class="built_in">echo</span> <span class="string">"Hello world"</span></div><div class="line"><span class="comment"># 运行容器 docker run -it [image] 将输出:</span></div><div class="line"><span class="comment"># Hello world</span></div><div class="line">docker run -it [image] /bin/bash</div><div class="line"><span class="comment"># CMD 会被忽略掉,命令 bash 将被执行</span></div><div class="line"><span class="comment"># root@10a32dc7d3d3:/#</span></div></pre></td></tr></table></figure></p>
<p>ENTRYPOINT指定的命令不会被docker run传递的命令覆盖.容器名后面的所有内容都当成参数传递给其指定的命令.<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">ENTRYPOINT [<span class="string">"/bin/echo"</span>, <span class="string">"Hello"</span>]  </div><div class="line">CMD [<span class="string">"echo"</span>,<span class="string">"world"</span>]</div><div class="line"></div><div class="line"><span class="comment"># 当容器通过 docker run -it [image] 启动时,输出为:</span></div><div class="line"><span class="comment"># Hello echo world</span></div><div class="line"></div><div class="line"><span class="comment"># 而如果通过 docker run -it [image] CloudMan 启动,则输出为:</span></div><div class="line"><span class="comment"># Hello CloudMan</span></div></pre></td></tr></table></figure></p>
<p>当然,ENTRYPOINT指定的命令并不是不能重载的,只需指定–entrypoint来重载即可.</p>
<h3 id="最佳实践"><a href="#最佳实践" class="headerlink" title="最佳实践"></a>最佳实践</h3><ol>
<li><p>使用 RUN 指令安装应用和软件包,构建镜像.</p>
</li>
<li><p>如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令.CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数.</p>
</li>
<li><p>如果想为容器设置默认的启动命令,可使用 CMD 指令.用户可在 docker run 命令行中替换此默认命令.</p>
<h3 id="ENTRYPOINT和CMD进行组合-运行shell脚本"><a href="#ENTRYPOINT和CMD进行组合-运行shell脚本" class="headerlink" title="ENTRYPOINT和CMD进行组合,运行shell脚本"></a>ENTRYPOINT和CMD进行组合,运行shell脚本</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">FROM busybox</div><div class="line">MAINTAINER femn</div><div class="line"></div><div class="line">COPY ./entrypoint.sh /</div><div class="line">RUN chmod +x /entrypoint.sh</div><div class="line">ENTRYPOINT [<span class="string">"/entrypoint.sh"</span>]</div><div class="line">CMD [<span class="string">"echo"</span>,<span class="string">"CMD"</span>]</div></pre></td></tr></table></figure>
</li>
</ol>
<p>entrypoint.sh如下:<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#!/bin/sh</span></div><div class="line"><span class="built_in">set</span> -e</div><div class="line"><span class="built_in">echo</span> <span class="string">"ENTRYPOINT"</span></div><div class="line"><span class="built_in">exec</span> <span class="string">"<span class="variable">$@</span>"</span></div><div class="line"><span class="comment"># 脚本中使用exec "$@"来运行CMD中的命令</span></div></pre></td></tr></table></figure></p>
<p>运行时则输出 ENTRYPOINT CMD,而运行的参数 都是传递给entrypoint.sh的.</p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;运行时机&quot;&gt;&lt;a href=&quot;#运行时机&quot; class=&quot;headerlink&quot; title=&quot;运行时机&quot;&gt;&lt;/a&gt;运行时机&lt;/h3&gt;&lt;p&gt;RUN在Dockerfile构建镜像的过程(Build)中运行,最终被commit的到镜像.&lt;/p&gt;
&lt;p&gt;ENTRYPOI
    
    </summary>
    
      <category term="docker" scheme="https://www.femn.me/categories/docker/"/>
    
    
  </entry>
  
  <entry>
    <title>docker-hub</title>
    <link href="https://www.femn.me/2017/08/04/docker-hub/"/>
    <id>https://www.femn.me/2017/08/04/docker-hub/</id>
    <published>2017-08-04T07:24:48.000Z</published>
    <updated>2017-08-24T04:10:08.313Z</updated>
    
    <content type="html"><![CDATA[<h3 id="新建私有镜像仓库-只有registry-2这个镜像运行时-才能push-pull私有镜像库"><a href="#新建私有镜像仓库-只有registry-2这个镜像运行时-才能push-pull私有镜像库" class="headerlink" title="新建私有镜像仓库,只有registry:2这个镜像运行时,才能push,pull私有镜像库"></a>新建私有镜像仓库,只有registry:2这个镜像运行时,才能push,pull私有镜像库</h3><p>私有镜像仓库的好处:</p>
<p>1.上传下载速度快</p>
<p>2.企业可自行维护镜像仓库</p>
<p>3.需要维护镜像仓库服务器</p>
<p>4.同步docker官方镜像到企业私有镜像仓库</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line">docker pull registry:2</div><div class="line"><span class="comment"># 使用官方的 registry 镜像来启动本地的私有仓库 </span></div><div class="line"><span class="comment"># 仓库会被创建在容器下/var/lib/registry下</span></div><div class="line"><span class="comment"># 将镜像文件存放在本机的指定路径/data/registry</span></div><div class="line">docker run -d -p 5000:5000 --restart=always --name registry \</div><div class="line">    -v /data/registry:/var/lib/registry registry:2</div><div class="line"><span class="comment"># 将镜像运行为容器 -d 将这个进程后台运行 -p 映射端口主机端口:容器端口     </span></div><div class="line"><span class="comment"># --restart=always当容器服务死掉之后自动重启 --name容器的名字 </span></div><div class="line"><span class="comment"># -v 映射容器的目录到宿主机下</span></div><div class="line"><span class="comment"># -m 128m 内存限制在128M</span></div><div class="line"></div><div class="line"><span class="comment"># 查看主机端口在容器的映射情况</span></div><div class="line">docker port nostalgic_morse 5000 </div><div class="line"></div><div class="line">docker pull nginx</div><div class="line"><span class="comment">#镜像的重命名 标记镜像</span></div><div class="line">docker tag nginx 47.52.94.126:5000/nginx:last  </div><div class="line">docker tag nginx 192.168.1.116:5000/nginx:last  </div><div class="line"></div><div class="line"><span class="comment"># modify docker daemon启动参数</span></div><div class="line">vim /usr/lib/systemd/system/docker.service</div><div class="line"><span class="comment"># centos   ubuntu:/lib/systemd/system/docker.service</span></div><div class="line">    ExecStart=之前的不要动加上  --insecure-registry=0.0.0.0/0</div><div class="line">systemctl daemon-reload</div><div class="line">systemctl restart docker</div><div class="line"><span class="comment"># 看参数有没有正确的添加.</span></div><div class="line">ps aux |grep docker  </div><div class="line"></div><div class="line"><span class="comment"># 上传标记镜像到私有仓库</span></div><div class="line">docker push 192.168.1.116:5000/nginx:last <span class="comment"># 本机测试的成功</span></div><div class="line">docker pull 192.168.1.116:5000/nginx:last </div><div class="line"><span class="comment"># 只要能连接上私有仓库,就可以从私有仓库中pull</span></div><div class="line"><span class="comment"># 因为本机做为私有仓库,已经有这image了,所以下载得很快</span></div><div class="line"><span class="comment"># docker push 47.52.94.126:5000/nginx:last 上传public IP失败</span></div></pre></td></tr></table></figure>
<h3 id="镜像上传到Docker-Hub"><a href="#镜像上传到Docker-Hub" class="headerlink" title="镜像上传到Docker Hub"></a>镜像上传到Docker Hub</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">docker login <span class="comment">#输入 hub.docker.com注册时的用户名和密码</span></div><div class="line">docker pull registry</div><div class="line">docker tag   registry femn/registry:last</div><div class="line"><span class="comment"># 镜像名:femn/registry tag:last</span></div><div class="line"></div><div class="line"><span class="comment">#上传到Docker Hub 镜像名必须是 username/imagesname,才能上传</span></div><div class="line"><span class="comment"># 并且不需要提前去Docker Hub创建仓库</span></div><div class="line">docker push femn/registry </div><div class="line"><span class="comment"># 将本地镜像上传到https://hub.docker.com的个人仓库中了.</span></div></pre></td></tr></table></figure>
<h3 id="Docker-Hub"><a href="#Docker-Hub" class="headerlink" title="Docker Hub"></a>Docker Hub</h3><p>Docker通过docer search、pull、login和push等命令提供了连接Docker Hub服务的功能.</p>
<p>Docker Hub是一个由Docker公司负责维护的公共注册中心,它包含了超过15,000个可用来下载和构建容器的镜像,并且还提供认证、工作组结构、工作流工具(比如webhooks)<br>构建触发器以及私有工具(比如私有仓库可用于存储你并不想公开分享的镜像)</p>
<h3 id="自动构建"><a href="#自动构建" class="headerlink" title="自动构建"></a>自动构建</h3><p>自动构建功能会自动从Github或BitBucket直接将镜像构建或更新至Docker Hub,通过为Github或Bitbucket的仓库添加一个提交的hook来实现,<br>当你推送提交的时候就会触发构建和更新,但是,你不能通过docker push推送一个自动化构建,而只能通过在Github或者BitBucket提交你的代码来管理它.<br>你可以在一个Docker的仓库中创建多个自动构建,配置它们只指定的Dockerfile或Git 分支</p>
<h3 id="Automated-Builds的一个实例"><a href="#Automated-Builds的一个实例" class="headerlink" title="Automated Builds的一个实例"></a><a href="https://hub.docker.com/r/leno730/pause/" target="_blank" rel="external">Automated Builds的一个实例</a></h3><p>建Dockerfile的目的,就是为了使用dockerfile里面的from语法的作用,来借用github服务器新建我需要的镜像</p>
<p>由于不能从google container上直接pull镜像,所以这里通过docker hub的Automated Builds功能从项目的dockerfile中Build到docker的官方服务器上,然后再从它们上面拉取</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 步骤2中 创建一个带有Dockerfile的Github项目</span></div><div class="line">mkdir docker_lib</div><div class="line"><span class="built_in">cd</span> docker_lib</div><div class="line">git init</div><div class="line">mkdir google-etcd-amd64</div><div class="line"><span class="built_in">cd</span> google-etcd-amd64</div><div class="line">vim Dockerfile</div><div class="line">    FROM gcr.io/google_containers/etcd:2.0.12</div><div class="line">    MAINTAINER femn2014</div><div class="line">git add .</div><div class="line">git commit -m <span class="string">'增加Dockerfile文件,解决镜像被墙的问题'</span></div><div class="line"><span class="comment"># 在github 创建一个名为docker_lib的项目</span></div><div class="line">git remote add origin https://github.com/femn2014/docker_lib.git</div><div class="line">git push -u origin master</div><div class="line"></div><div class="line"><span class="comment"># 当完成此实例的所有步骤之后,再测试下,推送提交的时候就会触发构建和更新</span></div><div class="line">vim Dockerfile</div><div class="line">    FROM nginx</div><div class="line">    MAINTAINER femn2014</div><div class="line">git add .</div><div class="line">git commit -m <span class="string">'当推送提交时触发构建和更新'</span></div><div class="line">git push -u origin master</div><div class="line"></div><div class="line"><span class="comment"># 这时 docker pull femn/etcd 时下载的将会是nginx的镜像</span></div></pre></td></tr></table></figure>
<h3 id="总结来说-自动构建的步骤"><a href="#总结来说-自动构建的步骤" class="headerlink" title="总结来说 自动构建的步骤"></a>总结来说 自动构建的步骤</h3><p>1.创建一个Docker Hub账户并且登陆<br>2.通过create选择 create automated build创建一个项目,再选择连接一个包含Dockerfile的GitHub或者BitBucket.<br>3.给自动构建创建一个名称:etcd(相当于也就是Docker Hub的项目的镜像名称)<br>4.配置自动化构建 (click here to customize)<br>5.选择你想用于构建的分支(默认是master分支)<br>6.指定Dockerfile的路径,默认是/,也可以在github中建立个目录再创建Dockerfile文件,为了方便我们后面区分镜像包<br>7.指定一个Docker标签来构建</p>
<p>另一个镜像管理工具<a href="https://quay.io/" target="_blank" rel="external">Quay</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;新建私有镜像仓库-只有registry-2这个镜像运行时-才能push-pull私有镜像库&quot;&gt;&lt;a href=&quot;#新建私有镜像仓库-只有registry-2这个镜像运行时-才能push-pull私有镜像库&quot; class=&quot;headerlink&quot; title=&quot;新建
    
    </summary>
    
      <category term="docker" scheme="https://www.femn.me/categories/docker/"/>
    
    
  </entry>
  
  <entry>
    <title>docker容器与镜像</title>
    <link href="https://www.femn.me/2017/08/04/docker/"/>
    <id>https://www.femn.me/2017/08/04/docker/</id>
    <published>2017-08-04T07:24:48.000Z</published>
    <updated>2017-08-24T04:10:08.325Z</updated>
    
    <content type="html"><![CDATA[<h3 id="docker镜像-业务代码和运行环境进行整体的打包"><a href="#docker镜像-业务代码和运行环境进行整体的打包" class="headerlink" title="docker镜像:业务代码和运行环境进行整体的打包."></a>docker镜像:业务代码和运行环境进行整体的打包.</h3><p>1.1快速创建环境(开发,测试,生产)</p>
<p>1.2整体交付(运行环境+代码(之前只是代码))</p>
<p>1.3可保证环境(开发,测试,生产)的一致性</p>
<p>1.4更好的完成devops</p>
<h4 id="镜像-Image-就是一堆只读层-read-only-layer-的统一视角"><a href="#镜像-Image-就是一堆只读层-read-only-layer-的统一视角" class="headerlink" title="镜像(Image)就是一堆只读层(read-only layer)的统一视角"></a>镜像(Image)就是一堆只读层(read-only layer)的统一视角</h4><p>这些层是Docker内部的实现细节,并且能够在主机的文件系统上访问到,统一文件系统(union file system)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统,你可以在你的主机文件系统上找到有关这些层的文件.它们存在于/var/lib/docker/aufs目录下<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo tree -L 1 /var/lib/docker/</div></pre></td></tr></table></figure></p>
<h4 id="容器-镜像-读写层-并且容器的定义并没有提及是否要运行容器"><a href="#容器-镜像-读写层-并且容器的定义并没有提及是否要运行容器" class="headerlink" title="容器=镜像+读写层.并且容器的定义并没有提及是否要运行容器"></a>容器=镜像+读写层.并且容器的定义并没有提及是否要运行容器</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 创建容器</span></div><div class="line">docker create &lt;image_id&gt;</div><div class="line"><span class="comment"># 运行容器</span></div><div class="line">docker start &lt;image_id&gt;</div><div class="line"><span class="comment"># 上两条命令组合下如下命令</span></div><div class="line">docker run &lt;image_id&gt;</div></pre></td></tr></table></figure>
<p>所以容器(container)的定义和镜像(image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的.</p>
<h4 id="镜像分层技术-AUFS-Another-UnionFS-支持将多个目录挂载到同一个虚拟目录下-已构建的镜像会设置成只读模式-read-write操作是在read-only上的一种增量操作"><a href="#镜像分层技术-AUFS-Another-UnionFS-支持将多个目录挂载到同一个虚拟目录下-已构建的镜像会设置成只读模式-read-write操作是在read-only上的一种增量操作" class="headerlink" title="镜像分层技术:AUFS (Another UnionFS)支持将多个目录挂载到同一个虚拟目录下.已构建的镜像会设置成只读模式,read-write操作是在read-only上的一种增量操作."></a>镜像分层技术:AUFS (Another UnionFS)支持将多个目录挂载到同一个虚拟目录下.已构建的镜像会设置成只读模式,read-write操作是在read-only上的一种增量操作.</h4><p>把一个镜像创造成一个容器才能往里写东西.<br>所谓UnionFS就是把不同物理位置的目录合并mount到同一个目录中.UnionFS的一个最主要的应用是,把一张CD/DVD和一个硬盘目录给联合 mount在一起<br>然后,你就可以对这个只读的CD/DVD上的文件进行修改(当然,修改的文件存于硬盘上的目录里)</p>
<h4 id="docker容器管理技术-是内核技术-容器本身是进程-其启动程序就是容器应用进程-容器就是为了主进程而存在的-主进程退出-容器就失去了存在的意义-从而退出-其它辅助进程不是它需要关心的东西"><a href="#docker容器管理技术-是内核技术-容器本身是进程-其启动程序就是容器应用进程-容器就是为了主进程而存在的-主进程退出-容器就失去了存在的意义-从而退出-其它辅助进程不是它需要关心的东西" class="headerlink" title="docker容器管理技术,是内核技术,容器本身是进程 其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西"></a>docker容器管理技术,是内核技术,容器本身是进程 其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西</h4><p>它并不是虚拟技术(VM),docker最关键的点是提出了docker images标准化,image打包了应用:如nginx镜像,通过镜像启动一个nginx容器,其实就是在主机上启动了一个nignx进程.<br>容器不等于微服务,推荐只运行一个服务,如果运行多个服务,需要结合进程管理工具(supervisor,S6),<br>因为容器本身就是进程,所以数据库容器也可以运行,但需要对数据做好保护(volume).</p>
<p>既然是进程,那么在启动容器的时候,需要指定所运行的程序及参数.CMD 指令就是用于指定默认的容器主进程的启动命令的,<br>在运行时可以指定新的命令来替代镜像设置中的这个默认命令,比如,ubuntu 镜像默认的 CMD 是 /bin/bash,如果我们直接 docker run -it ubuntu 的话,会直接进入 bash.</p>
<p>容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念.</p>
<h3 id="ubuntu-install-docker"><a href="#ubuntu-install-docker" class="headerlink" title="ubuntu install docker"></a>ubuntu install docker</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">sudo apt-get update</div><div class="line">curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -</div><div class="line">sudo add-apt-repository <span class="string">"deb [arch=amd64] \</span></div><div class="line"><span class="string">    https://download.docker.com/linux/ubuntu <span class="variable">$(lsb_release -cs)</span> stable"</span></div><div class="line">sudo apt-get update</div><div class="line">sudo apt-cache policy docker-ce</div><div class="line">sudo apt-get install -y docker-ce</div><div class="line">sudo systemctl status docker</div><div class="line">sudo usermod -aG docker $(whoami)</div><div class="line">service docker start</div><div class="line">docker images</div><div class="line"><span class="comment"># 虚拟机是用此方法下载 当前用户就可以使用whoami</span></div></pre></td></tr></table></figure>
<h3 id="debain-install-docker"><a href="#debain-install-docker" class="headerlink" title="debain install docker"></a><a href="http://wiki.jikexueyuan.com/project/docker/installation/debian.html" target="_blank" rel="external">debain install docker</a></h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 坑一</span></div><div class="line">sudo apt-get update</div><div class="line">sudo apt-get install docker.io</div><div class="line">apt-get purge docker.io*  </div><div class="line"></div><div class="line"><span class="comment"># 坑二</span></div><div class="line">apt-get dist-upgrade -y</div><div class="line">apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys \</div><div class="line">    58118E89F3A912897C070ADBF76221572C52609D</div><div class="line"><span class="built_in">echo</span> <span class="string">"deb https://apt.dockerproject.org/repo debian-jessie main"</span> | \</div><div class="line">tee /etc/apt/sources.list.d/docker.list</div><div class="line">apt-get update</div><div class="line">apt-get install docker-engine -y</div><div class="line">apt-get purge docker-engine -y </div><div class="line"></div><div class="line"><span class="comment"># 成功</span></div><div class="line">apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 \</div><div class="line">    --recv-keys 58118E89F3A912897C070ADBF76221572C52609D</div><div class="line"><span class="built_in">echo</span> <span class="string">"deb https://apt.dockerproject.org/repo ubuntu-trusty main "</span> &gt;   \</div><div class="line">    /etc/apt/sources.list.d/docker.list</div><div class="line">apt-get update </div><div class="line">apt-get install docker-engine=1.10.1-0~trusty</div><div class="line">apt install docker.io</div><div class="line">docker -v</div><div class="line"><span class="comment"># 本机是此方法下载docker 必须是root身份才能使用</span></div></pre></td></tr></table></figure>
<h3 id="启动docker服务"><a href="#启动docker服务" class="headerlink" title="启动docker服务"></a>启动docker服务</h3><p><a href="https://hub.docker.com/explore/" target="_blank" rel="external">docker官方镜像</a> 类似AppStore 是由各自官方机构做的镜像认证后,上传到docker官方镜像的,这个仓库的地址是在国外,所以下载的速度会慢点<br>利用镜像的分层技术,如果主机上已有layer(层)存在,那只会下载新增加的layer(类似git代码提交机制)</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">service docker start    </div><div class="line">docker port nostalgic_morse 5000 <span class="comment"># 查看主机端口在容器的映射情况</span></div><div class="line"><span class="comment"># modify docker daemon启动参数 Docker的配置文件 </span></div><div class="line">vim /usr/lib/systemd/system/docker.service </div><div class="line"><span class="comment"># centos   ubuntu:/lib/systemd/system/docker.service</span></div><div class="line">ExecStart=之前的不要动加上     --insecure-registry=0.0.0.0/0</div><div class="line">systemctl daemon-reload</div><div class="line">systemctl restart docker</div><div class="line">ps aux |grep docker  <span class="comment">#看参数有没有正确的添加.</span></div></pre></td></tr></table></figure>
<h3 id="容器操作命令"><a href="#容器操作命令" class="headerlink" title="容器操作命令"></a>容器操作命令</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div></pre></td><td class="code"><pre><div class="line">docker run -dit -p 80:80 --name app nginx</div><div class="line"><span class="comment"># -d后台运行 -it此时的容器就有了标准的输入和输出</span></div><div class="line">docker create  -p 80:80 --name app nginx</div><div class="line"><span class="comment"># 创建容器</span></div><div class="line">docker start app <span class="comment">#运行容器</span></div><div class="line"></div><div class="line">docker commit &lt;container-id&gt;</div><div class="line"><span class="comment"># 将容器的可读写层转换为一个只读层,这样就把一个容器转换成了不可变的镜像</span></div><div class="line"><span class="comment"># 用Dockerfile 生成镜像,命名为app</span></div><div class="line">docker build -t app .</div><div class="line"></div><div class="line">docker <span class="built_in">exec</span> -it app bash    </div><div class="line"><span class="comment"># 在运行中的容器执行一个新进程</span></div><div class="line"><span class="comment"># 以bash的方式登陆到容器里面  exit 从容器中退出</span></div><div class="line">docker <span class="built_in">exec</span> -it app bash ls /tmp</div><div class="line"></div><div class="line">docker rename app new_app <span class="comment">#重命容器名</span></div><div class="line"></div><div class="line">docker stop/<span class="built_in">kill</span>/pause/unpause/restart &lt;container_id&gt;</div><div class="line"><span class="comment"># 对容器中的进程发信号</span></div><div class="line"></div><div class="line">docker inspect/stats/port/ps/top/dip/dpid &lt;container-id&gt;</div><div class="line"><span class="comment"># 查看容器状态</span></div><div class="line">docker top app  <span class="comment">#查看当前容器跑了多少进程</span></div><div class="line">docker ps <span class="comment"># 列出所有运行中的容器,这隐藏了非运行态容器的存在</span></div><div class="line">docker ps -a  <span class="comment"># 查看所有容器</span></div><div class="line">docker inspect nginx/app |grep -i memory <span class="comment"># 查看指定镜像/容器</span></div><div class="line"><span class="comment"># 会提取出容器或者镜像最顶层的元数据</span></div><div class="line">docker stats $(docker ps | awk <span class="string">'NR&gt;1 &#123;print $NF&#125;'</span>)</div><div class="line"></div><div class="line">docker update  -m 256m app <span class="comment">#更新容器信息</span></div><div class="line">docker rm  -f -v app <span class="comment"># 移除构成容器的可读写层</span></div><div class="line"><span class="comment"># -f 强制删除 -v 连同Volumes也一起删除</span></div><div class="line"><span class="comment"># -v如果这个容器有Volume这个文件存在的话,也一起删除掉</span></div><div class="line">docker copy 本地文件 容器路径 </div><div class="line">docker copy app:/usr/share/ngxin/html/index.html .</div><div class="line">docker copy index.html app:/tmp</div><div class="line">docker <span class="built_in">export</span>  app (把容器保存成tar文件)</div><div class="line">docker import app.tar (把tar文件导会到镜像列表)</div></pre></td></tr></table></figure>
<h4 id="镜像命令"><a href="#镜像命令" class="headerlink" title="镜像命令"></a>镜像命令</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">docker commit -a admin@femnyy.com -m <span class="string">'app commit image'</span> app app:2.0</div><div class="line"><span class="comment"># -a作者 -m提交时的标记 app容器名 app:2.0镜像名</span></div><div class="line"><span class="comment"># 用容器创建镜像 推荐用Dockerfile</span></div><div class="line">docker save nginx &gt;nginx.tar</div><div class="line"><span class="comment">#  镜像 --&gt;tar包</span></div><div class="line">docker rmi nginx</div><div class="line"><span class="comment"># 删除镜像</span></div><div class="line"><span class="comment"># 1.此镜像是其他镜像的父镜像 </span></div><div class="line"><span class="comment"># 2.有容器使用镜像 镜像已经被创建为容器 不能删除本地镜像</span></div><div class="line"></div><div class="line">docker load &lt; nginx.tar</div><div class="line"><span class="comment"># tar包--导入到镜像列表中</span></div><div class="line"></div><div class="line">docker images</div><div class="line"><span class="comment"># 列出了所有顶层(top-level)镜像</span></div><div class="line">docker <span class="built_in">history</span> &lt;image_id&gt;</div><div class="line"><span class="comment"># 列出镜像的所有层</span></div><div class="line">docker pull nginx</div><div class="line"><span class="comment"># 下载镜像</span></div><div class="line">docker tag nginx 192.168.1.116:5000/nginx:last  </div><div class="line"><span class="comment"># 镜像的重命名(标记镜像)</span></div><div class="line">docker push 192.168.1.116:5000/nginx:last <span class="comment"># 本机测试的成功</span></div><div class="line"><span class="comment"># 上传镜像</span></div><div class="line">docker search nginx</div><div class="line"><span class="comment"># 查看镜像</span></div></pre></td></tr></table></figure>
<h3 id="容器与镜像"><a href="#容器与镜像" class="headerlink" title="容器与镜像"></a>容器与镜像</h3><p>镜像不能直接访问,只有启动成容器,才可以访问.镜像和容器的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体.容器可以被创建、启动、停止、删除、暂停等.同一个 Images 可生成多个不同配置的 Container.</p>
<h3 id="容器连接-相当于进程间的通信吧"><a href="#容器连接-相当于进程间的通信吧" class="headerlink" title="容器连接(相当于进程间的通信吧)"></a>容器连接(相当于进程间的通信吧)</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">sudo docker run -d --name db training/postgres</div><div class="line"><span class="comment"># 指定了 training/webapp 镜像,并且这个镜像已经包含了简单的 Python Flask web 应用程序</span></div><div class="line"><span class="comment"># 最后,我们指定了我们容器要运行的命令: python app.py.这样我们的 web 应用就启动了</span></div><div class="line">sudo docker run -d -P --name web --link db:db training/webapp python app.py</div><div class="line">docker ps </div><div class="line"><span class="comment"># db和web,我们还在名字列中可以看到web容器也显示db/web.这告诉我们web容器和db容器是父/子关系.</span></div></pre></td></tr></table></figure>
<h3 id="Volume-持久化容器数据-以及容器之间共享数据"><a href="#Volume-持久化容器数据-以及容器之间共享数据" class="headerlink" title="Volume(持久化容器数据,以及容器之间共享数据)"></a>Volume(持久化容器数据,以及容器之间共享数据)</h3><h3 id="保留容器的数据"><a href="#保留容器的数据" class="headerlink" title="保留容器的数据"></a>保留容器的数据</h3><p>当容器删除时,就是杀死进程,只要我们的数据在,当再启动时,数据又回来了,但我们想在容器中产生的数据保留起来 </p>
<h4 id="容器间的数据共享-root用户下-主机巻"><a href="#容器间的数据共享-root用户下-主机巻" class="headerlink" title="容器间的数据共享(root用户下,主机巻)"></a>容器间的数据共享(root用户下,主机巻)</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line">docker run -d -v /web_data:/tmp:ro --name data-container nginx</div><div class="line"><span class="built_in">cd</span> /web_data</div><div class="line">mkdir files</div><div class="line">touch test.file</div><div class="line">docker <span class="built_in">exec</span> -it data-container ls /tmp</div><div class="line"></div><div class="line"><span class="comment">#第二个容器的数据来自 第一个容器的数据</span></div><div class="line">docker run -d --volumes-from data-container --name web-container nginx</div><div class="line"></div><div class="line"><span class="comment">#第三个容器的数据来自 第一个容器的数据</span></div><div class="line">docker run -d --volumes-from data-container --name web-container-2 nginx</div><div class="line"><span class="comment"># 查看容器 有没有第一个容器中的文件</span></div><div class="line">docker <span class="built_in">exec</span> -it web-container ls /tmp</div><div class="line"><span class="comment"># 验证只读</span></div><div class="line">docker <span class="built_in">exec</span> -it web-container bash</div><div class="line"><span class="built_in">cd</span> /tmp</div><div class="line">touch a.txt</div><div class="line"><span class="built_in">exit</span></div><div class="line"><span class="comment"># 在宿主机添加一个新文件,相当于往三个容器分发信息.</span></div><div class="line"><span class="built_in">cd</span> /web_data</div><div class="line">touch a.txt</div></pre></td></tr></table></figure>
<h3 id="Volume分为容器卷-在Dockerfile写了VOLUME-和主机卷"><a href="#Volume分为容器卷-在Dockerfile写了VOLUME-和主机卷" class="headerlink" title="Volume分为容器卷(在Dockerfile写了VOLUME)和主机卷"></a>Volume分为容器卷(在Dockerfile写了VOLUME)和主机卷</h3><p>容器卷的定义的目录,将会自动保存在宿主机的/var/lib/docker/volumes目录下<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line">mkdir docker</div><div class="line"><span class="built_in">cd</span> docker &amp;&amp; vim Dockerfile</div><div class="line"></div><div class="line">FROM centos:7</div><div class="line">RUN yum -y install epel-release &amp;&amp; \ </div><div class="line">    yum -y install nginx &amp;&amp; \ </div><div class="line">    yum clean all</div><div class="line">EXPOSE 80 443</div><div class="line">VOLUME [<span class="string">"/usr/share/nginx/html"</span>]</div><div class="line">CMD [<span class="string">"nginx"</span>,<span class="string">"-g"</span>, <span class="string">"daemon off;"</span>]</div><div class="line"></div><div class="line"><span class="comment"># 用Dockerfile 生成镜像app</span></div><div class="line">docker build -t app .</div><div class="line"></div><div class="line"><span class="built_in">cd</span> /var/lib/docker/volumes</div><div class="line">docker rm -f web-container data-container</div><div class="line"></div><div class="line">docker run -d --name app app</div><div class="line">ll <span class="comment">#会有一个随机生成字符串的目录 VOLUME的东西,将会同步到这个目录下的_data目录下</span></div><div class="line">docker rm -f -v app <span class="comment"># -v</span></div></pre></td></tr></table></figure></p>
<h4 id="主机卷-web-data-这个不仅仅会在-var-lib-docker-volumes-usr-share-nginx-html保留-双保险"><a href="#主机卷-web-data-这个不仅仅会在-var-lib-docker-volumes-usr-share-nginx-html保留-双保险" class="headerlink" title="主机卷(/web-data),这个不仅仅会在/var/lib/docker/volumes:/usr/share/nginx/html保留,双保险."></a>主机卷(/web-data),这个不仅仅会在/var/lib/docker/volumes:/usr/share/nginx/html保留,双保险.</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">docker run -d -p 80:80 --name app -v /web-data:/tmp app</div></pre></td></tr></table></figure>
<h4 id="备份app容器中-dbdata容器巻中的数据–-gt-打包在容器中的-backup-backup-tar–-gt-将此包copy到主机的当前目录"><a href="#备份app容器中-dbdata容器巻中的数据–-gt-打包在容器中的-backup-backup-tar–-gt-将此包copy到主机的当前目录" class="headerlink" title="备份app容器中 /dbdata容器巻中的数据–&gt;打包在容器中的/backup/backup.tar–&gt;将此包copy到主机的当前目录"></a>备份app容器中 /dbdata容器巻中的数据–&gt;打包在容器中的/backup/backup.tar–&gt;将此包copy到主机的当前目录</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># 通过ubuntu这个镜像生成一个容器</span></div><div class="line"><span class="comment"># --rm 这个容器退出 就把这个容器删掉</span></div><div class="line"><span class="comment"># 使用 --volumes-from 标记来创建一个加载 dbdata 容器卷的容器:app</span></div><div class="line">docker run --rm --volume-from app -v <span class="variable">$&#123;pwd&#125;</span>:/backup ubuntu \</div><div class="line">    tar cvfz /backup/backup.tar /dbdata</div><div class="line"><span class="comment"># 1.数据恢复</span></div><div class="line">docker run --rm --volume-from app -v <span class="variable">$&#123;pwd&#125;</span>:/backup busybox \</div><div class="line">    bash -c <span class="string">"cd /dbdata &amp;&amp; tar zxvf /backup/backup.tar --strip 1"</span></div><div class="line"><span class="comment"># 2</span></div><div class="line"><span class="comment"># 如果要恢复数据到一个容器,首先创建一个带有空数据卷的容器 dbdata2</span></div><div class="line">sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash</div><div class="line"><span class="comment"># 然后创建另一个容器,挂载 dbdata2 容器卷中的数据卷</span></div><div class="line"><span class="comment"># 并使用 untar 解压备份文件到挂载的容器卷中.</span></div><div class="line">sudo docker run --volumes-from dbdata2 -v $(<span class="built_in">pwd</span>):/backup busybox tar xvf</div><div class="line">/backup/backup.tar</div><div class="line"><span class="comment">#为了查看/验证恢复的数据,可以再启动一个容器挂载同样的容器卷来查看</span></div><div class="line">sudo docker run --volumes-from dbdata2 busybox /bin/ls /dbdata</div></pre></td></tr></table></figure>
<h3 id="Docker的网络模式-nat-host-container-none-overlay"><a href="#Docker的网络模式-nat-host-container-none-overlay" class="headerlink" title="Docker的网络模式:nat,host,container,none,overlay"></a>Docker的网络模式:nat,host,container,none,overlay</h3><p>默认启动的是nat</p>
<h4 id="nat需要进行端口的管理-通过docker容器转发的功能-转发到宿主机的网卡上-每次启动容器的时候-它的IP会变"><a href="#nat需要进行端口的管理-通过docker容器转发的功能-转发到宿主机的网卡上-每次启动容器的时候-它的IP会变" class="headerlink" title="nat需要进行端口的管理,通过docker容器转发的功能,转发到宿主机的网卡上,每次启动容器的时候,它的IP会变:"></a>nat需要进行端口的管理,通过docker容器转发的功能,转发到宿主机的网卡上,每次启动容器的时候,它的IP会变:</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">docker run -d -p 80:80 --name app nginx</div><div class="line">ps -aux |grep docker</div><div class="line"><span class="comment"># 得到如下信息</span></div><div class="line">/usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 \</div><div class="line">     -container-ip 172.17.0.3 -container-port 80</div><div class="line"><span class="comment"># 但我试了两次 IP都没有变</span></div><div class="line">docker restart app</div><div class="line">/usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 \ </div><div class="line">    -container-ip 172.17.0.3 -container-port 80</div><div class="line">docker stop app</div><div class="line">docker start app</div></pre></td></tr></table></figure>
<h4 id="host-容器中的网卡直接与宿主机的网卡沟通-只能使用80端口-但可以固定容器的IP-攻击了容器也就相当于攻击了宿主机"><a href="#host-容器中的网卡直接与宿主机的网卡沟通-只能使用80端口-但可以固定容器的IP-攻击了容器也就相当于攻击了宿主机" class="headerlink" title="host:容器中的网卡直接与宿主机的网卡沟通:只能使用80端口,但可以固定容器的IP.攻击了容器也就相当于攻击了宿主机."></a>host:容器中的网卡直接与宿主机的网卡沟通:只能使用80端口,但可以固定容器的IP.攻击了容器也就相当于攻击了宿主机.</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">docker run -d --name app2 --net=host nginx</div><div class="line">docker ps -a </div><div class="line"><span class="comment"># 查看端口是否已经冲突,如果冲突则这个容器会启动失败 状态为Exited</span></div><div class="line">docker start -a app2 <span class="comment"># 端口也占用</span></div></pre></td></tr></table></figure>
<h4 id="container模式-用于容器之间经常通信的情况"><a href="#container模式-用于容器之间经常通信的情况" class="headerlink" title="container模式,用于容器之间经常通信的情况:"></a>container模式,用于容器之间经常通信的情况:</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">docker pull busybox</div><div class="line">docker run -it --name busybox1 busybox sh</div><div class="line">ip addr</div><div class="line">ctrl+p+q <span class="comment"># 不使用exit,让容器在后台运用</span></div><div class="line">docker run -it --name busybox2 --net=container:busybox1 busybox sh</div><div class="line">ip addr</div><div class="line"><span class="comment"># 此两个的容器的IP是一模一样的,而且还可以相互通信</span></div><div class="line">ping busybox1</div></pre></td></tr></table></figure>
<h4 id="none模式-没有IP"><a href="#none模式-没有IP" class="headerlink" title="none模式:没有IP"></a>none模式:没有IP</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">docker run -it --name none --net=none busybox sh</div></pre></td></tr></table></figure>
<h4 id="overlay模式-实现跨主机的通信-docker-1-10-才有的模式"><a href="#overlay模式-实现跨主机的通信-docker-1-10-才有的模式" class="headerlink" title="overlay模式,实现跨主机的通信,docker:1.10+,才有的模式."></a>overlay模式,实现跨主机的通信,docker:1.10+,才有的模式.</h4><ol>
<li><p>约定的容器启动时 会被当作一个服务被consul发现,从而分发IP</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">vim /lib/systemd/system/docker.service</div><div class="line"><span class="comment"># 注意改自己的IP地址,和网卡的名称</span></div><div class="line"><span class="comment">#  多台也是这个的一样的配置(不需要去改变IP地址和网卡名称)</span></div><div class="line"><span class="comment"># 使用hostA做为consul的服务端 hostA的IP;192.168.1.116 网卡名称为:enp2s0</span></div><div class="line"><span class="comment"># hostA hostB都要操作</span></div><div class="line">ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 \</div><div class="line">    -H unix:///var/run/docker.sock --cluster-store=consul://192.168.1.116:8500 \ </div><div class="line">    --cluster-advertise=enp2s0:2376 --insecure-registry=0.0.0.0/0</div><div class="line">systemctl daemon-reload</div><div class="line">systemctl restart docker</div><div class="line">ps -aux |grep docket</div></pre></td></tr></table></figure>
</li>
<li><p>在consul的主机执行就可以:hostA</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">docker pull progrium/consul</div><div class="line"><span class="comment"># -h 取名 -server服务端 并把ui打开</span></div><div class="line">docker run -d -p 8400:8400 -p 8500:8500 -p 8600:53/udp -h consul progrium/consul \</div><div class="line">    -server -bootstrap -ui-dir /ui</div><div class="line">docker ps -a</div><div class="line"><span class="comment"># 在浏览器中打开</span></div><div class="line">192.168.1.116:8500</div><div class="line"><span class="comment"># 在KEY/VALUE中 会显示有多少台主机进行着通信 hostA,hostB</span></div><div class="line"></div><div class="line"><span class="comment"># create overlay network 创建IP地址池 会用consul定义一个IP地址池(如10.0.9.0/24)</span></div><div class="line">docker network ls</div><div class="line"><span class="comment"># -d overlay使用overlay驱动  --subnet 网段 edu_net为名称 </span></div><div class="line"><span class="comment">#  会同步到多台主机上(hostA,hostB)</span></div><div class="line">docker network create -d overlay --subnet=10.0.9.0/24 edu-net</div></pre></td></tr></table></figure>
</li>
<li><p>当约定好的主机启动容器时,consul服务就会从地址池中取得IP,给容器使用</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="comment"># hostA</span></div><div class="line">docker run -d --name app1 --net=edu-net nginx</div><div class="line"><span class="comment"># 登陆进出</span></div><div class="line">docker <span class="built_in">exec</span> -it app1 bash</div><div class="line">ip addr</div><div class="line">ping www.baidu.com</div><div class="line"></div><div class="line"><span class="comment"># hostB 没有虚拟技术 所以没有实做</span></div><div class="line">docker run -d --name app2 --net=edu-net nginx</div><div class="line">docker <span class="built_in">exec</span> -it app2 bash</div><div class="line">ping app1</div></pre></td></tr></table></figure>
</li>
</ol>
<p><a href="https://docs.docker.com/" target="_blank" rel="external">官方文档</a></p>
<p><a href="https://yeasy.gitbooks.io/docker_practice/content/install/centos.html" target="_blank" rel="external">一个中文的docker文档</a></p>
<p><a href="https://juejin.im/post/58cb86bc61ff4b00601e7bfa" target="_blank" rel="external">对docker的解释</a></p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;docker镜像-业务代码和运行环境进行整体的打包&quot;&gt;&lt;a href=&quot;#docker镜像-业务代码和运行环境进行整体的打包&quot; class=&quot;headerlink&quot; title=&quot;docker镜像:业务代码和运行环境进行整体的打包.&quot;&gt;&lt;/a&gt;docker镜像:业
    
    </summary>
    
      <category term="docker" scheme="https://www.femn.me/categories/docker/"/>
    
    
  </entry>
  
</feed>
