<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[Ops运维 | Mr`kang Blog｜小豆子]]></title> 
<link>https://www.cnmysql.com/index.php</link> 
<description><![CDATA[关注服务器运维技术、DB优化、Docker虚拟化、自动化运维、工作积累]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[Ops运维 | Mr`kang Blog｜小豆子]]></copyright>
<item>
<link>https://www.cnmysql.com/post/121/</link>
<title><![CDATA[如何查看进程 IO 读写情况？]]></title> 
<author>kangyang &lt;kangyang315@qq.com&gt;</author>
<category><![CDATA[Python]]></category>
<pubDate>Mon, 15 Sep 2014 07:13:44 +0000</pubDate> 
<guid>https://www.cnmysql.com/post/121/</guid> 
<description>
<![CDATA[ 
	<span style="font-family: 宋体;"><span style="font-size: 12px;"><br/>开源的可以用IOtop软件查看！<br/>Linux Kernel 2.6.20 以上的内核支持进程 IO 统计，可以用类似 iotop 这样的工具来监测每个进程对 IO 操作的情况，就像用 top 来实时查看进程内存、CPU 等占用情况那样。但是对于 2.6.20 以下的 Linux 内核版本就没那么幸运了，根据 Stack Overflow 的这篇回帖 给出的方法，VPSee 写了一个简单的 Python 脚本用来在 linux kernel < 2.6.20 下打印进程 IO 状况。<br/><br/><strong>Kernel < 2.6.20</strong><br/>这个脚本的想法很简单，把 dmesg 的结果重定向到一个文件后再解析出来，每隔1秒钟打印一次进程 IO 读写的统计信息，执行这个脚本需要 root：<br/><div class="code">#!/usr/bin/python<br/># Monitoring per-process disk I/O activity<br/># written by http://www.vpsee.com <br/><br/>import sys, os, time, signal, re<br/><br/>class DiskIO:<br/>&nbsp;&nbsp;&nbsp;&nbsp;def __init__(self, pname=None, pid=None, reads=0, writes=0):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.pname = pname <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.pid = pid<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.reads = 0<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.writes = 0<br/><br/>def main():<br/>&nbsp;&nbsp;&nbsp;&nbsp;argc = len(sys.argv)<br/>&nbsp;&nbsp;&nbsp;&nbsp;if argc != 1:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;usage: ./iotop&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.exit(0)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if os.getuid() != 0:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;must be run as root&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.exit(0)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;signal.signal(signal.SIGINT, signal_handler)<br/>&nbsp;&nbsp;&nbsp;&nbsp;os.system(&#039;echo 1 &gt; /proc/sys/vm/block_dump&#039;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;print &quot;TASK&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; READ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WRITE&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;while True:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.system(&#039;dmesg -c &gt; /tmp/diskio.log&#039;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l = &#91;&#93;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f = open(&#039;/tmp/diskio.log&#039;, &#039;r&#039;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line = f.readline()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while line:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m = re.match(&#92;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#039;^(&#92;S+)&#92;((&#92;d+)&#92;): (READ&#124;WRITE) block (&#92;d+) on (&#92;S+)&#039;, line)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if m != None:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not l:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l.append(DiskIO(m.group(1), m.group(2)))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line = f.readline() <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found = False&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for item in l:&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if item.pid == m.group(2):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;found = True&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if m.group(3) == &quot;READ&quot;:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item.reads = item.reads + 1 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elif m.group(3) == &quot;WRITE&quot;:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item.writes = item.writes + 1<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not found:&nbsp;&nbsp; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l.append(DiskIO(m.group(1), m.group(2)))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line = f.readline()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(1)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for item in l:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;%-10s %10s %10d %10d&quot; % &#92;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(item.pname, item.pid, item.reads, item.writes)<br/><br/>def signal_handler(signal, frame):<br/>&nbsp;&nbsp;&nbsp;&nbsp;os.system(&#039;echo 0 &gt; /proc/sys/vm/block_dump&#039;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;sys.exit(0)<br/><br/>if __name__==&quot;__main__&quot;:<br/>&nbsp;&nbsp;&nbsp;&nbsp;main()</div><br/><strong>Kernel >= 2.6.20</strong><br/>如果想用 iotop 来实时查看进程 IO 活动状况的话，需要下载和升级新内核（2.6.20 或以上版本）。编译新内核时需要打开 TASK_DELAY_ACCT 和 TASK_IO_ACCOUNTING 选项。解压内核后进入配置界面：<br/><div class="code"># tar jxvf linux-2.6.30.5.tar.bz2<br/># mv linux-2.6.30.5 /usr/src/<br/># cd /usr/src/linux-2.6.30.5<br/># make menuconfig</div><br/>选择 Kernel hacking –> Collect scheduler debugging info 和 Collect scheduler statistics，保存内核后编译内核：<br/><div class="code"># make; make modules; make modules_install; make install</div><br/>修改 grub，确认能正确启动新内核：<br/><div class="code"># vi /boot/grub/menu.lst</div><br/>出了新内核外，iotop 还需要 Python 2.5 或以上才能运行，所以如果当前 Python 是 2.4 的话需要下载和安装最新的 Python 包。这里使用源代码编译安装：<br/><div class="code"># tar jxvf Python-2.6.2.tar.bz2<br/># cd Python-2.6.2<br/># ./configure<br/># make; make install</div><br/>别忘了下载 setuptools：<br/>[code]# mv setuptools-0.6c9-py2.6.egg.sh setuptools-0.6c9-py2.6.egg<br/># sh setuptools-0.6c9-py2.6.egg<br/><br/></span><br/></span>
]]>
</description>
</item><item>
<link>https://www.cnmysql.com/post/120/</link>
<title><![CDATA[简单调试 Python 程序]]></title> 
<author>kangyang &lt;kangyang315@qq.com&gt;</author>
<category><![CDATA[Python]]></category>
<pubDate>Mon, 15 Sep 2014 07:04:13 +0000</pubDate> 
<guid>https://www.cnmysql.com/post/120/</guid> 
<description>
<![CDATA[ 
	<span style="font-family: 宋体;"><span style="font-size: 12px;"><br/>在 Python 中也可以像 gcc/gdb 那样调试程序，只要在运行 Python 程序时引入 pdb 模块（假设要调试的程序名为 d.py）：<br/><div class="code">$ vi d.py<br/>#!/usr/bin/python<br/><br/>def main():<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i, sum = 1, 0<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in xrange(100):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum = sum + i<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print sum<br/><br/>if __name__ == &#039;__main__&#039;:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br/><br/>$ python -m pdb d.py</div><br/>运行上面的命令后进入以下界面，可以输入类似 gdb 的命令来改变程序的执行流程：<br/><div class="code">$ python -m pdb 1.py <br/>&gt; d.py(3)()<br/>-&gt; def main():<br/>(Pdb) </div><br/>list 显示程序的最近代码段：<br/><div class="code"><br/>(Pdb) list<br/>&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;#!/usr/bin/python<br/>&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;3&nbsp;&nbsp;-&gt;&nbsp;&nbsp;def main():<br/>&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i, sum = 1, 0<br/>&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in xrange(100):<br/>&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum = sum + i<br/>&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print sum<br/>&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;if __name__ == &#039;__main__&#039;:<br/> 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br/>&#91;EOF&#93;</div><br/>next 或者 n 执行下一行代码：<br/><div class="code"><br/>(Pdb) next<br/>&gt; d.py(9)()<br/>-&gt; if __name__ == &#039;__main__&#039;:<br/></div><br/>用 break 在第6行设置一个断点：<br/><div class="code">(Pdb) break d.py:6<br/>Breakpoint 1 at d.py:6<br/><br/>(Pdb) list<br/>&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;#!/usr/bin/python<br/>&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;def main():<br/>&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i, sum = 1, 0<br/>&nbsp;&nbsp;5&nbsp;&nbsp;-&gt;&nbsp;&nbsp;&nbsp;&nbsp;for i in xrange(100):<br/>&nbsp;&nbsp;6 B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum = sum + i<br/>&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print sum<br/>&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;if __name__ == &#039;__main__&#039;:<br/> 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br/>&#91;EOF&#93;</div><br/>如果想在函数处设置断点：<br/><div class="code">(Pdb) break d.main<br/>d.py:3<br/><br/>(Pdb) list<br/>&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;#!/usr/bin/python<br/>&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;3 B&nbsp;&nbsp;def main():<br/>&nbsp;&nbsp;4&nbsp;&nbsp;-&gt;&nbsp;&nbsp;&nbsp;&nbsp;i, sum = 1, 0<br/>&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in xrange(100):<br/>&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum = sum + i<br/>&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print sum<br/>&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp; <br/>&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;if __name__ == &#039;__main__&#039;:<br/> 10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()<br/>&#91;EOF&#93;</div><br/>还可以给断点加条件，比如设置条件只有当 sum > 50 的时候才 break：<br/><div class="code">(Pdb) break d.py:6, sum &gt; 50<br/>Breakpoint 1 at d.py:6</div><br/>如果想查看某个变量的值，可以用 pp 命令打印出来：<br/><div class="code">(Pdb) step<br/>&gt; d.py(5)main()<br/>-&gt; for i in xrange(100):<br/>(Pdb) pp sum<br/>0</div><br/>可以直接在程序里使用 pdb 模块，import pdb 后 pdb.set_trace()：<br/><div class="code">#!/usr/bin/python<br/>import pdb<br/><br/>def main():<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i, sum = 1, 0<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i in xrange(100):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum = sum + i<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pdb.set_trace()<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print sum<br/><br/>if __name__ == &#039;__main__&#039;:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main()</div><br/>这样只要运行程序 ./d.py 就可以直接运行到 print sum 处：<br/><div class="code">$ ./d.py <br/>&gt; d.py(9)main()<br/>-&gt; print sum<br/>(Pdb) </div><br/>总结<br/><a href="https://www.cnmysql.com/attachment.php?fid=35" target="_blank"><img src="https://www.cnmysql.com/attachment.php?fid=35" class="insertimage" alt="点击在新窗口中浏览此图片" title="点击在新窗口中浏览此图片" border="0"/></a><br/></span><br/></span>
]]>
</description>
</item><item>
<link>https://www.cnmysql.com/post/118/</link>
<title><![CDATA[如何判断 Linux 是否运行在虚拟机上]]></title> 
<author>kangyang &lt;kangyang315@qq.com&gt;</author>
<category><![CDATA[Python]]></category>
<pubDate>Mon, 15 Sep 2014 06:44:54 +0000</pubDate> 
<guid>https://www.cnmysql.com/post/118/</guid> 
<description>
<![CDATA[ 
	<span style="font-family: 宋体;"><span style="font-size: 12px;"><br/><strong>判断 OpenVZ/Xen PV/UML</strong><br/>判断 OpenVZ/Xen PV/UML 是最容易的，直接检查 /proc 下的相关目录和文件就可以知道，比如 OpenVZ VPS 上会有 /proc/vz 这个文件；Xen PV 虚拟机上会有 /proc/xen/ 这个目录，并且目录下有一些东西；UML 上打印 /proc/cpuinfo 会找到 UML 标志。写了一个简单的 Python 脚本来检测：<br/><div class="code"><br/>#!/usr/bin/python<br/># check if a linux system running on a virtual machine (openvz/xen pv/uml)<br/># written by http://www.vpsee.com<br/><br/>import sys, os<br/><br/>def main():<br/>&nbsp;&nbsp;&nbsp;&nbsp;if os.getuid() != 0:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;must be run as root&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sys.exit(0)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;# check OpenVZ/Virtuozzo<br/>&nbsp;&nbsp;&nbsp;&nbsp;if os.path.exists(&quot;/proc/vz&quot;):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not os.path.exists(&quot;/proc/bc&quot;):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;openvz container&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;openvz node&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;# check Xen<br/>&nbsp;&nbsp;&nbsp;&nbsp;if os.path.exists(&quot;/proc/xen/capabilities&quot;):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (os.path.getsize(&quot;/proc/xen/capabilities&quot;) &gt; 0):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;xen dom0&quot;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;xen domU&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;# check User Mode Linux (UML)<br/>&nbsp;&nbsp;&nbsp;&nbsp;f = open(&quot;/proc/cpuinfo&quot;, &quot;r&quot;); t = f.read(); f.close()<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (t.find(&quot;UML&quot;) &gt; 0):<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &quot;uml&quot;<br/><br/>if __name__==&quot;__main__&quot;:<br/>&nbsp;&nbsp;&nbsp;&nbsp;main()</div><br/><br/><strong>判断 VMware/Xen HVM/KVM</strong><br/>如果使用的是 VMware/Xen HVM/KVM 这样的全虚拟就更难判断一些，最准确的办法是读取 CPUID 来判断，Xen 源代码下面有一段检测是否是 Xen 的 C 语言代码 tools/misc/xen-detect.c，这段代码提供了一个很好的例子，VPSee 重写了代码，用宏替代了函数，增加了对 VMware 和 KVM 的识别，用 gcc 编译后就可以运行：<br/><div class="code"><br/>/*<br/> * check if a linux system running on a virtual machine (vmware/xen hvm/kvm)<br/> * written by http://www.vpsee.com<br/> */<br/>#include stdio.h<br/>#include string.h<br/><br/>#define HYPERVISOR_INFO 0x40000000<br/><br/>#define CPUID(idx, eax, ebx, ecx, edx) &#92;<br/>&nbsp;&nbsp;&nbsp;&nbsp;asm volatile ( &#92;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;test %1,%1 ; jz 1f ; ud2a ; .ascii &#92;&quot;xen&#92;&quot; ; 1: cpuid&quot; &#92;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: &quot;=b&quot; (*ebx), &quot;=a&quot; (*eax), &quot;=c&quot; (*ecx), &quot;=d&quot; (*edx) &#92;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: &quot;0&quot; (idx) );<br/><br/>int main(void)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned int eax, ebx, ecx, edx;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char string&#91;13&#93;;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CPUID(HYPERVISOR_INFO, &amp;eax, &amp;ebx, &amp;ecx, &amp;edx);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*(unsigned int *)(string+0) = ebx;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*(unsigned int *)(string+4) = ecx;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*(unsigned int *)(string+8) = edx;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&#91;12&#93; = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (strncmp(string, &quot;XenVMMXenVMM&quot;, 12) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;xen hvm&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else if (strncmp(string, &quot;VMwareVMware&quot;, 12) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;vmware&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else if (strncmp(string, &quot;KVMKVMKVM&quot;, 12) == 0) &#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;kvm&#92;n&quot;);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125; else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;bare hardware&#92;n&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/>&#125;</div><br/><strong>判断 VirtualBox/Virtual PC</strong><br/>什么？这种家用桌面虚拟机自己装的还会不知道？！如果不知道的话也有办法，在 Linux 下运行 dmidecode 工具然后查找 Manufacturer: innotek GmbH, Manufacturer: Microsoft Corporation 关键字就能对应上 VirtualBox 和 Virtual PC.<br/>dmidecode -s system-product-name&nbsp;&nbsp;---查看服务器型号<br/><br/></span></span><br/>Tags - <a href="https://www.cnmysql.com/tags/xen/" rel="tag">xen</a> , <a href="https://www.cnmysql.com/tags/kvm/" rel="tag">kvm</a> , <a href="https://www.cnmysql.com/tags/dmidecode/" rel="tag">dmidecode</a>
]]>
</description>
</item><item>
<link>https://www.cnmysql.com/post/87/</link>
<title><![CDATA[Python发送邮件 (STMPLib)]]></title> 
<author>kangyang &lt;kangyang315@qq.com&gt;</author>
<category><![CDATA[Python]]></category>
<pubDate>Wed, 13 Aug 2014 10:16:07 +0000</pubDate> 
<guid>https://www.cnmysql.com/post/87/</guid> 
<description>
<![CDATA[ 
	<span style="font-size: 12px;"><span style="font-family: 宋体;">python的smtplib提供了一种很方便的途径发送电子邮件。它对smtp协议进行了简单的封装。<br/><br/>smtp协议的基本命令包括：<br/>HELO 向服务器标识用户身份<br/>MAIL 初始化邮件传输 mail from:<br/>RCPT 标识单个的邮件接收人；常在MAIL命令后面,可有多个rcpt to:<br/>DATA 在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以.结束<br/>VRFY 用于验证指定的用户/邮箱是否存在；由于安全方面的原因,服务器常禁止此命令<br/>EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用<br/>HELP 查询服务器支持什么命令<br/>NOOP 无操作,服务器应响应OK<br/>QUIT 结束会话<br/>RSET 重置会话,当前传输被取消<br/>MAIL FROM 指定发送者地址<br/>RCPT TO 指明的接收者地址<br/> <br/>Python创建 SMTP 对象:<br/><div class="code">import smtplib<br/>SMTPObj = smtplib.SMTP( &#91;host &#91;,port &#91;,local_hostname&#93;&#93;&#93; )<br/><br/>参数说明：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;host: SMTP 服务器主机。 你可以指定主机的ip地址或者域名如:i-it.info，这个是可选参数。<br/>&nbsp;&nbsp;&nbsp;&nbsp;port: 如果你提供了 host 参数, 你需要指定 SMTP 服务使用的端口号，一般情况下SMTP端口号为25。<br/>&nbsp;&nbsp;&nbsp;&nbsp;local_hostname: 如果SMTP在你的本机上，你只需要指定服务器地址为 localhost 即可。</div><br/> <br/>python smtp对象使用sendmail方法发送邮件的语法如下：<br/><div class="code">SMTP.sendmail(from_addr, to_addrs, msg&#91;, mail_options, rcpt_options)<br/><br/>参数说明：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;from_addr: 邮件发送者地址。<br/>&nbsp;&nbsp;&nbsp;&nbsp;to_addrs: 字符串列表，邮件发送地址。<br/>&nbsp;&nbsp;&nbsp;&nbsp;msg: 发送消息 <br/><br/>这里要注意一下第三个参数，msg是字符串，表示邮件。邮件一般由标题，发信人，收件人，邮件内容，附件等构成，发送邮件的时候，要注意msg的格式。这个格式就是smtp协议中定义的格式。</div><br/> <br/>一个发送邮件的小例子:<br/><div class="code">import smtplib<br/><br/>send = &#039;18717776124@163.com&#039;<br/>receivers = &#91;&#039;itchenyi@gmail.com&#039;&#93;<br/>UserPass = &#91;&#039;18717776124@163.com&#039;,&#039;%password%&#039;&#93;<br/><br/>message = &quot;&quot;&quot;From: From Person &lt;18717776124@163.com&gt;<br/>TO: To Person &lt;itchenyi@gmail.com&gt;<br/>Subject: SMTP e-mail test<br/><br/>This is a test email message.<br/>&quot;&quot;&quot;<br/><br/>try:<br/>&nbsp;&nbsp;&nbsp;&nbsp;SMTPObj = smtplib.SMTP(&quot;smtp.163.com&quot;,&quot;25&quot;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;SMTPObj.login(&#039;%s&#039;%UserPass&#91;0&#93;,&quot;%s&quot;%UserPass&#91;1&#93;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;SMTPObj.sendmail(send,receivers,message)<br/>&nbsp;&nbsp;&nbsp;&nbsp;SMTPObj.quit()<br/>&nbsp;&nbsp;&nbsp;&nbsp;print &quot;Successfully sent email&quot;<br/>except:<br/>&nbsp;&nbsp;&nbsp;&nbsp;print &quot;Error: unable to send email&quot;</div><br/> <br/>用python发送HTML格式的邮件:<br/><div class="code">###Python发送HTML格式的邮件与发送纯文本消息的邮件不同之处就是将MIMEText中_subtype设置为html###<br/>import smtplib<br/>from email.mime.text import MIMEText<br/><br/>mailto_list = &#91;&quot;itchenyi@gmail.com&quot;&#93;<br/>mail_host = &quot;smtp.163.com&quot;<br/>##smtp server##<br/>mail_user = &quot;18717776124&quot;<br/>##username##<br/>mail_pass = &quot;%password%&quot;<br/>##password##<br/>mail_postfix = &quot;163.com&quot;<br/>##后缀##<br/><br/>def send_email(to_list,sub,content):<br/>###定义收件人列表，主题，邮件内容###<br/>me = &quot;hello&quot;+&quot;&lt;&quot;+mail_user+&quot;@&quot;+mail_postfix+&quot;&gt;&quot;<br/>###hello信息###<br/>msg = MIMEText(content,_subtype=&#039;html&#039;,_charset=&#039;utf8&#039;)<br/>###创建实例，设置为html格式##<br/>msg&#91;&#039;Subject&#039;&#93; = sub<br/>###主题###<br/>msg&#91;&#039;From&#039;&#93; = me<br/>msg&#91;&#039;To&#039;&#93; = &quot;;&quot;.join(to_list)<br/>try:<br/>s = smtplib.SMTP()<br/>s.connect(mail_host)<br/>s.login(mail_user,mail_pass)<br/>s.sendmail(me,to_list,msg.as_string())<br/>s.close()<br/>return True<br/>except Exception,e:<br/>print str(e)<br/>return False<br/><br/>if __name__ == &#039;__main__&#039;:<br/>if send_email(mailto_list,&quot;hello&quot;,&quot;&lt;a href=&quot;http://www.ipython.me&quot;&gt;IT辰逸&lt;/a&gt;&quot;):<br/>print &quot;send Successfully&quot;<br/>else:<br/>print &quot;send Error&quot;</div><br/> <br/><br/>Python 发送带附件的邮件：<br/><div class="code">from email.mime.text import MIMEText<br/>from email.mime.multipart import MIMEMultipart<br/>import smtplib<br/><br/>##创建一个带附件的实例##<br/>msg = MIMEMultipart()<br/><br/>##构造附件##<br/>att_one = MIMEText(open(&#039;D:&#92;&#92;testfile&#039;,&#039;rb&#039;).read(),&#039;base64&#039;,&#039;utf8&#039;)<br/>att_one&#91;&quot;Content-Type&quot;&#93; = &#039;application/octet-stream&#039;<br/>att_one&#91;&quot;Content-Disposition&quot;&#93; = &#039;attachment; filename=&quot;testfile&quot;&#039;<br/>msg.attach(att_one)<br/><br/>##构造附件##<br/>att_two = MIMEText(open(&#039;D:&#92;&#92;testfile.zip&#039;,&#039;rb&#039;).read(),&#039;base64&#039;,&#039;utf8&#039;)<br/>att_two&#91;&quot;Content-Type&quot;&#93; = &#039;applecation/octet-stream&#039;<br/>att_two&#91;&quot;Content-Disposition&quot;&#93; = &#039;attachment; filename=&quot;testfile.zip&quot;&#039;<br/>msg.attach(att_two)<br/><br/>##邮件头##<br/>msg&#91;&#039;to&#039;&#93; = &quot;itchenyi@gmail.com&quot;<br/>msg&#91;&#039;from&#039;&#93; = &#039;18717776124@163.com&#039;<br/>msg&#91;&#039;subject&#039;&#93; = &#039;test email&#039;<br/><br/>##发送邮件##<br/>try:<br/>&nbsp;&nbsp;&nbsp;&nbsp;server = smtplib.SMTP()<br/>&nbsp;&nbsp;&nbsp;&nbsp;server.connect(&#039;smtp.163.com&#039;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;server.login(&#039;18717776124@163.com&#039;,&#039;%password%&#039;)<br/>&nbsp;&nbsp;&nbsp;&nbsp;server.sendmail(msg&#91;&#039;from&#039;&#93;,msg&#91;&#039;to&#039;&#93;,msg.as_string())<br/>&nbsp;&nbsp;&nbsp;&nbsp;server.quit()<br/>&nbsp;&nbsp;&nbsp;&nbsp;print &quot;send Successfully&quot;<br/>except Exception,e:<br/>&nbsp;&nbsp;&nbsp;&nbsp;print str(e)</div><br/> <br/>Python 发送带图片的HTML邮件：<br/><div class="code">import smtplib<br/>from email.mime.multipart import MIMEMultipart<br/>from email.mime.text import MIMEText<br/>from email.mime.image import MIMEImage<br/><br/>send = &#039;18717776124@163.com&#039;<br/>receiver = &#039;itchenyi@gmail.com&#039;<br/>subject = &#039;email test&#039;<br/>username = &#039;18717776124@163.com&#039;<br/>password = &#039;%password%&#039;<br/><br/>msg = MIMEMultipart(&#039;related&#039;)<br/>msg&#91;&#039;subject&#039;&#93; = &#039;test email&#039;<br/><br/>msgText = MIMEText(&#039;&lt;b&gt;Some &lt;i&gt;HTML&lt;/i&gt; text&lt;/b&gt; and an image.&lt;br&gt;&lt;img src=&quot;cid:image1&quot;&gt;&lt;br&gt;good!&#039;,&#039;html&#039;,&#039;utf-8&#039;)<br/>msg.attach(msgText)<br/><br/>fp = open(&#039;D:&#92;&#92;i-it.jpg&#039;,&#039;rb&#039;)<br/>msgImage = MIMEImage(fp.read())<br/>fp.close()<br/><br/>msgImage.add_header(&#039;Content-ID&#039;, &#039;&lt;image1&gt;&#039;)<br/>msg.attach(msgImage)<br/><br/>try:<br/>smtp = smtplib.SMTP()<br/>smtp.connect(&#039;smtp.163.com&#039;)<br/>smtp.login(username, password)<br/>smtp.sendmail(send, receiver, msg.as_string())<br/>smtp.quit()<br/>print &quot;send Successfully&quot;<br/>except Exception,e:<br/>print str(e)</div><br/> <br/>Python 发送包含多种元素的邮件<br/><div class="code">import smtplib<br/>from email.mime.multipart import MIMEMultipart<br/>from email.mime.text import MIMEText<br/>from email.mime.image import MIMEImage<br/><br/>send = &#039;18717776124@163.com&#039;<br/>receiver = &#039;itchenyi@gmail.com&#039;<br/>subject = &#039;python email test&#039;<br/>smtpserver = &#039;smtp.163.com&#039;<br/>username = &#039;18717776124@163.com&#039;<br/>password = &#039;%password%&#039;<br/><br/>msg = MIMEMultipart(&#039;alternative&#039;)<br/>msg&#91;&#039;Subject&#039;&#93; = &quot;Link&quot;<br/><br/>text = &quot;Hi!&#92;nHow are you?&quot;<br/>html = &quot;&quot;&quot;<br/>Hi!<br/>How are you?<br/>&quot;&quot;&quot;<br/><br/>part1 = MIMEText(text, &#039;plain&#039;)<br/>part2 = MIMEText(html, &#039;html&#039;)<br/><br/>msg.attach(part1)<br/>msg.attach(part2)<br/><br/>att = MIMEText(open(&#039;d:&#92;&#92;i-it.jpg&#039;, &#039;rb&#039;).read(), &#039;base64&#039;, &#039;utf-8&#039;)<br/>att&#91;&quot;Content-Type&quot;&#93; = &#039;application/octet-stream&#039;<br/>att&#91;&quot;Content-Disposition&quot;&#93; = &#039;attachment; filename=&quot;iit.jpg&quot;&#039;<br/>msg.attach(att)<br/><br/>try:<br/>smtp = smtplib.SMTP()<br/>smtp.connect(&#039;smtp.163.com&#039;)<br/>smtp.login(username, password)<br/>smtp.sendmail(send, receiver, msg.as_string())<br/>smtp.quit()<br/>print &quot;send Successfully&quot;<br/>except Exception,e:<br/>print str(e)</div></span></span><br/>Tags - <a href="https://www.cnmysql.com/tags/python/" rel="tag">python</a> , <a href="https://www.cnmysql.com/tags/mail/" rel="tag">mail</a> , <a href="https://www.cnmysql.com/tags/stmplib/" rel="tag">stmplib</a>
]]>
</description>
</item><item>
<link>https://www.cnmysql.com/post/86/</link>
<title><![CDATA[Python Subprocess模块]]></title> 
<author>kangyang &lt;kangyang315@qq.com&gt;</author>
<category><![CDATA[Python]]></category>
<pubDate>Wed, 13 Aug 2014 10:10:14 +0000</pubDate> 
<guid>https://www.cnmysql.com/post/86/</guid> 
<description>
<![CDATA[ 
	<span style="font-size: 12px;"><span style="font-family: 宋体;">最近接到一个需求…自动发布SVN代码…收到的代码原型大部分就是依靠subprocess 来实现的，册那…有一段时间没有用这个模块了，这个模块的能力不差，不过我已经习惯了 commands … 再复杂点有fabric也够用啦…既然要了解代码，我不得不看看subprocess ，借此机会 记录下…<br/><br/>subprocess.Popen(类):<br/><div class="code">class subprocess.Popen( args, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bufsize=0, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;executable=None,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdin=None,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stdout=None, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stderr=None, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;preexec_fn=None, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close_fds=False, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shell=False, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cwd=None, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env=None, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;universal_newlines=False, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startupinfo=None, <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;creationflags=0)<br/><br/>#########################参数########################<br/>args&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字符串或者列表<br/>bufsize&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 无缓冲,1 行缓冲,其他正值 缓冲区大小,负值 采用默认系统缓冲(一般是全缓冲)<br/>executable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; args字符串或列表第一项表示程序名<br/>stdin,stdout,stderr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;None 没有任何重定向，继承父进程,PIPE 创建管道,文件对象,文件描述符(整数),stderr 还可以设置为 STDOUT<br/>preexec_fn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 只在Unix平台下有效，用于指定一个可执行对象（callable object），它将在子进程运行之前被调用。<br/>close_fds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果close_fds被设置为True，则新创建的子进程将不会继承父进程的输入、输出、错误管 道。不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。<br/>shell&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果为真(unix下相当于args前面添加了 &quot;/bin/sh&quot; &quot;-c&quot;&#124;window下，相当于添加&quot;cmd.exe /c&quot;)<br/>cwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置工作目录<br/>env&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置环境变量<br/>universal_newlines&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 各种换行符统一处理成 &#039;&#92;n<br/>startupinfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window下传递给CreateProcess的结构体<br/>creationflags&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;windows下，传递CREATE_NEW_CONSOLE创建自己的控制台窗口</div><br/>args参数。可以是一个字符串，可以是一个包含程序参数的列表。要执行的程序一般就是这个列表的第一项，或者是字符串本身。<br/><div class="code">###可以正常工作###<br/>&gt;&gt;&gt; subprocess.Popen(&#91;&quot;cat&quot;,&quot;i-it&quot;&#93;)<br/><br/>###不可以正常工作，如果是一整个字符串，则必须是程序的路径才行(因为Unix的API函数是Exec ,接受的是字符串列表)###<br/>&gt;&gt;&gt; subprocess.Popen(&#91;&quot;cat i-it&quot;&#93;)<br/><br/>###但如果shell = True 就可以工作啦###<br/>&gt;&gt;&gt; subprocess.Popen(&quot;cat /root/i-it&quot;,shell=True)<br/>----这个相当于----(bash)<br/>&gt;&gt;&gt; subprocess.Popen(&#91;&quot;/bin/sh&quot;, &quot;-c&quot;, &quot;cat i-it&quot;&#93;)</div><br/>示例:<br/><div class="code">import subprocess<br/><br/>def runCommandWithOutput(cmd,stdinstr = &#039;&#039;):<br/>&nbsp;&nbsp;p=subprocess.Popen(cmd, shell=True, universal_newlines=True, stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.STDOUT)<br/>&nbsp;&nbsp;#p.stdin.write(stdinstr)&nbsp;&nbsp;<br/>&nbsp;&nbsp;stdoutdata, stderrdata = p.communicate(stdinstr)<br/>&nbsp;&nbsp;#p.stdin.close()<br/>&nbsp;&nbsp;return p.returncode, stdoutdata, stderrdata<br/><br/>&gt;&gt;&gt; get = runCommandWithOutput(&quot;who&quot;)<br/>&gt;&gt;&gt; print get<br/>(0, &#039;root&nbsp;&nbsp;&nbsp;&nbsp; tty1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2014-06-24 05:51&#92;nroot&nbsp;&nbsp;&nbsp;&nbsp; pts/0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2014-06-24 05:51 (1.1.1.2)&#92;n&#039;, None)</div><br/> <br/>subprocess.PIPE用于Popen的stdin 、stdout 和stderr 3个参数<br/>subprocess.STDOUT用于Popen的stderr参数的输出值<br/><div class="code">###很清晰了###<br/>&gt;&gt;&gt; test = subprocess.Popen(&quot;who&quot;,shell=True,stdout=subprocess.PIPE)<br/>&gt;&gt;&gt; test.stdout.readlines()<br/>&#91;&#039;root&nbsp;&nbsp;&nbsp;&nbsp; tty1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2014-06-24 05:51&#92;n&#039;, &#039;root&nbsp;&nbsp;&nbsp;&nbsp; pts/0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2014-06-24 05:51 (1.1.1.2)&#92;n&#039;&#93;<br/><br/>Popen.send_signal(signal)<br/>给子进程发送signal信号。<br/>注意：windows下目前只支持发送SIGTERM，等效于下面的terminate() 。<br/><br/>Popen.terminate()<br/>停止子进程。Posix下是发送SIGTERM信号。windows下是调用TerminateProcess()这个API。<br/><br/>Popen.kill()<br/>杀死子进程。Posix下是发送SIGKILL信号。windows下和terminate() 无异。<br/><br/>Popen.stdin<br/>如果stdin 参数是PIPE，此属性就是一个文件对象，否则为None 。<br/><br/>Popen.stdout<br/>如果stdout参数是PIPE，此属性就是一个文件对象，否则为None 。<br/><br/>Popen.stderr<br/>如果stderr 参数是PIPE，此属性就是一个文件对象，否则为None 。<br/><br/>Popen.pid<br/>子进程的进程号。注意，如果shell 参数为True，这属性指的是子shell的进程号。<br/>&gt;&gt;&gt; test.pid<br/>3367<br/><br/>Popen.returncode<br/>子程序的返回值，由poll()或者wait()设置，间接地也由communicate()设置。<br/>如果为None，表示子进程还没终止。<br/>如果为负数-N的话，表示子进程被N号信号终止。（仅限*nux）</div></span></span><br/>Tags - <a href="https://www.cnmysql.com/tags/python/" rel="tag">python</a> , <a href="https://www.cnmysql.com/tags/subprocess/" rel="tag">subprocess</a>
]]>
</description>
</item>
</channel>
</rss>