| napoleonu 生命可以浪费在美好的事物之上 – I LIKE IT |
| napoleonu 生命可以浪费在美好的事物之上 – I LIKE IT |
What is the difference between a processor, a chip, a socket, and a core?
来自:http://kb.iu.edu/data/avfb.html
Following are brief definitions for common terms related to supercomputers:
Cores
Recent developments in computational architecture can lead to confusion concerning what a microprocessor is. Since the advent of multi-core technology, such as dual-cores and quad-cores, the term “processor” has been used to describe a logical execution unit or a physical chip. A multi-core chip may have several cores. With the advent of multi-core technology, the term “processor” has become context-sensitive, and is largely ambiguous when describing large multi-core systems. Essentially a core comprise a logical execution unit containing an L1 cache and functional units. Cores are able to independently execute programs or threads. Supercomputers are listed as having thousands of cores.
Chips
A chip refers to a physical integrated circuit (IC) on a computer. A chip in the context of this document refers to an execution unit that can be single- or multi-core technology.
Sockets
The socket refers to a physical connector on a computer motherboard that accepts a single physical chip. Many motherboards can have multiple sockets that can in turn accept multi-core chips.
Processes
A process is an independent program running on a computer. A process has a full stack of memory associated for its own use, and does not depend on another process for execution. MPI (Message Passing Interface) processes are true processes because they can run on independent machines or the same machine.
Thread
A thread is essentially a process that does not have a full stack of memory associated for it. The thread is tied to a parent process, and is merely an offshoot of execution. Typically thread processes must run on the same computer, but can execute simultaneously on separate cores of the same node. OpenMP parallelism uses threads for child processes.
Hyper-threading
Hyper-threading is an Intel technology that originally preceded multi-core systems, and was used to make a single core appear logically as multiple cores on the same chip. Intel abandoned hyper-threading briefly during the advent of multi-core processors but reintroduced the technology in 2008. Since then, Intel has used it extensively to improve the performance of parallel computations in its multi-core processors. Hyper-threading improves performance by sharing the computational workload between multiple cores whenever possible, allowing the operating system to schedule more than one process at a time. For more, see Intel Hyper-Threading Technology.
N-ways
Multi-core compute nodes can be described by the number of execution units, or cores. A computer with 8 cores would be described as an 8-way node. This machine can have 8 independent processes running simultaneously. A 32-core system would be called a 32-way node.
Processor
As explained above, a processor could describe either a single execution core or a single physical multi-core chip. The context of use will define the meaning of the term.
This document was developed with support from National Science Foundation (NSF) grant OCI-1053575. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the NSF.
This is document avfb in domains all and xsede-all. Last modified on March 08, 2013.
Linux下如何识别物理cpu个数,几个核,是超线程还是多核心
来自:http://www.83blog.com/xeon-cpu-core.html
判断依据:
1.具有相同core id的cpu是同一个core的超线程。
2.具有相同physical id的cpu是同一颗cpu封装的线程或者cores。
英文版:
1.Physical id and core id are not necessarily consecutive but they are unique. Any cpu with the same core id are hyperthreads in the same core.
2.Any cpu with the same physical id are threads or cores in the same physical socket.
实例:
LunarPages的CPU信息:
processor : 0
vendor_id : GenuineIntel
cpu family : 15
model : 4
model name : Intel(R) Xeon(TM) CPU 3.00GHz
stepping : 3
cpu MHz : 3000.881
cache size : 2048 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe lm constant_tsc pni monitor ds_cpl cid xtpr
bogomips : 6006.73
processor : 1
vendor_id : GenuineIntel
cpu family : 15
model : 4
model name : Intel(R) Xeon(TM) CPU 3.00GHz
stepping : 3
cpu MHz : 3000.881
cache size : 2048 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe lm constant_tsc pni monitor ds_cpl cid xtpr
bogomips : 5999.40
processor : 2
vendor_id : GenuineIntel
cpu family : 15
model : 4
model name : Intel(R) Xeon(TM) CPU 3.00GHz
stepping : 3
cpu MHz : 3000.881
cache size : 2048 KB
physical id : 3
siblings : 2
core id : 3
cpu cores : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe lm constant_tsc pni monitor ds_cpl cid xtpr
bogomips : 5999.08
processor : 3
vendor_id : GenuineIntel
cpu family : 15
model : 4
model name : Intel(R) Xeon(TM) CPU 3.00GHz
stepping : 3
cpu MHz : 3000.881
cache size : 2048 KB
physical id : 3
siblings : 2
core id : 3
cpu cores : 1
fdiv_bug : no
hlt_bug : no
f00f_bug : no
coma_bug : no
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe lm constant_tsc pni monitor ds_cpl cid xtpr
bogomips : 5999.55
显示4个逻辑CPU,通过physical id ,前面两个逻辑cpu的相同,后面两个的相同,所以有两个物理CPU。前面两个的 core id相同,后面的两个core ID相同,说明这两个CPU都是单核。也就是说两个单核cpu,启用了超线程技术。
通过intel的cpu的参数可以初步判断 使用的是两个 Xeon奔腾4CPU 。
如何获得CPU的详细信息:
cat /proc/cpuinfo
用命令判断几个物理CPU,几个核等:
逻辑CPU个数:
cat /proc/cpuinfo | grep “processor” | wc -l
物理CPU个数:
cat /proc/cpuinfo | grep “physical id” | sort | uniq | wc -l
每个物理CPU中Core的个数:
cat /proc/cpuinfo | grep “cpu cores” | wc -l
是否为超线程?
如果有两个逻辑CPU具有相同的”core id”,那么超线程是打开的。
每个物理CPU中逻辑CPU(可能是core, threads或both)的个数:
cat /proc/cpuinfo | grep “siblings”
其他特征:
目前intel新的多核心cpu都会在后面显示具体的型号数字,例如:
model name : Intel(R) Xeon(R) CPU X3230 @ 2.66GHz
说明是 Xeon 3230的cpu,而不显示型号的具体数字的,大部分都是奔腾的CPU
很多主机商都骗人,用奔腾的cpu,却说是多核心的CPU。
探针看到的数据:
类型:Intel(R) Xeon(TM) CPU 2.80GHz 缓存:1024 KB
类型:Intel(R) Xeon(TM) CPU 2.80GHz 缓存:1024 KB
类型:Intel(R) Xeon(TM) CPU 2.80GHz 缓存:1024 KB
类型:Intel(R) Xeon(TM) CPU 2.80GHz 缓存:1024 KB
没有具体的型号,缓存1M,一般都是奔腾系列的cpu,或者是intel假双核的cpu,具体要根据上面说的去判断。新的多核心cpu都能看到具体的型号。
另外多核心的xeon的CPU,一般主频都不高,达到2.8和3.0的只有很少的几个高端CPU型号,一般主机商不会用这么好的。
来自http://www.taobaodba.com/html/1598_如何分析crash的backtrace.html
MySQL异常退出往往会会在error.log中打印backtrace信息,我们从这个backtrace中可以得到一些异常的原因,例如断言错误,空指针内容的访问等。顺着这些信息排查,我们一般再结合代码逻辑来做推断,写测试用例重现,再打补丁,再验证等过程。
但是,线上早期部署的MySQL编译参数不太规范,导致一些MySQL crash的backtrace看起来不是那么透明,非常难懂,甚至一点意义也没有。这给我们排查问题带来非常大的不便。当然,这个问题已经解决,我们采用google-breakpad来获取MySQL crash时的mini-dump,但这是后话,在此不展开。
那么,这种backtrace就真的没有什么信息可以挖掘吗?不一定。下面我们就以这周发线上的一个故障来分析。
线上一台5.5版本的备库跑了3月之久突然就crash,crash的backtrace为:
/u01/mysql/bin/mysqld(my_print_stacktrace+0x39)[0x7b1b69]
/u01/mysql/bin/mysqld(handle_segfault+0x43c)[0x4fa39c]
/lib64/libpthread.so.0[0x344dc0f520]
/u01/mysql/bin/mysqld[0x7fb4c1]
/lib64/libpthread.so.0[0x344dc077e1]
/lib64/libc.so.6(clone+0x6d)[0x344d8e68ed
这个backtrace就是典型早期编译部署的MySQL,backtrace信息很难看懂。但是,凭经验和一些常识,这一个调用关系非常简单的线程,因为backtrace中创建的pthread只调用了一次mysqld的函数。那么,我猜测这个线程可能是一个后台线程。mysqld层显示的地址0x7fb4c1到底是哪行代码,对我们分析问题非常关键。
猜测后就该验证了,GDB出马!用GDB在出问题的那台机器上来玩转下反汇编。注意:
1. 不要在业务高峰期执行GDB相关操作!
2. 一定要对所执行的GDB动作非常熟悉!
3. 最好通知对应的DBA!
那末,搞起!在线disass下地址0x7fb4c1先看看是哪个函数:
gdb -p 31639 -ex "disassemble 0x7fb4c1 " --ex "quit" --batch > /tmp/g1.log
Dump of assembler code from 0x7fb4c1 to 0x7fb4f1:
0x00000000007fb4c1 <srv_master_thread+5217>: cmp %esi,(%rax)
0x00000000007fb4c3 <srv_master_thread+5219>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4c5 <srv_master_thread+5221>: mov 0xc(%r8),%edi
0x00000000007fb4c9 <srv_master_thread+5225>: cmp 0x4(%rax),%edi
0x00000000007fb4cc <srv_master_thread+5228>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4ce <srv_master_thread+5230>: mov 0x60(%rax),%rdi
0x00000000007fb4d2 <srv_master_thread+5234>: cmp %rdi,0x10(%r11)
0x00000000007fb4d6 <srv_master_thread+5238>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4d8 <srv_master_thread+5240>: nopl 0x0(%rax,%rax,1)
0x00000000007fb4e0 <srv_master_thread+5248>: sub %r13,%rdx
0x00000000007fb4e3 <srv_master_thread+5251>: add (%r11),%rdx
0x00000000007fb4e6 <srv_master_thread+5254>: mov $0x0,%eax
0x00000000007fb4eb <srv_master_thread+5259>: mov %r13,(%r11)
0x00000000007fb4ee <srv_master_thread+5262>: mov (%r12),%esi
End of assembler dump.
有两点我们可以确认:
1. 这是个srv_master_thread线程.
2. 在读取异常指针作比较时,导致segfault.
那这段汇编代码上下文是什么很难看出到底是哪行代码出问题,这时我们可以把srv_master_thread函数disass下:
gdb -p 31639 -ex "disassemble srv_master_thread" --ex "quit" --batch > /tmp/g2.log
0x00000000007fb478 <+5144>: mov 0x3a8(%r10),%r12
0x00000000007fb46d <+5133>: mov %r12,-0x740(%rbp)
0x00000000007fb474 <+5140>: nopl 0x0(%rax)
0x00000000007fb486 <+5158>: test %r12,%r12
0x00000000007fb489 <+5161>: je 0x7fb908 <srv_master_thread+6312>
0x00000000007fb48f <+5167>: lea (%r9,%r9,2),%rdi
0x00000000007fb493 <+5171>: mov %r12,%rax
0x00000000007fb496 <+5174>: xor %edx,%edx
0x00000000007fb498 <+5176>: shl $0x3,%rdi
0x00000000007fb49c <+5180>: mov -0x6c8(%rbp,%rdi,1),%esi
0x00000000007fb4b4 <+5204>: test %rax,%rax
0x00000000007fb4b7 <+5207>: je 0x7fb900 <srv_master_thread+6304>
0x00000000007fb4c1 <+5217>: cmp %esi,(%rax)
0x00000000007fb4c3 <+5219>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4c5 <+5221>: mov 0xc(%r8),%edi
0x00000000007fb4c9 <+5225>: cmp 0x4(%rax),%edi
0x00000000007fb4cc <+5228>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4ce <+5230>: mov 0x60(%rax),%rdi
0x00000000007fb4d2 <+5234>: cmp %rdi,0x10(%r11)
0x00000000007fb4d6 <+5238>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4d8 <+5240>: nopl 0x0(%rax,%rax,1)
如果你汇编能力非常强,但是可以慢慢读起。但是,这往往非常累,因为这个函数太长了,并且由于编译优化,汇编代码不是和逻辑代码行级别的顺序完全对应。
对于我们这样的懒人,一般不太愿意,触发是实在没有办法。
那么,还有没有其它办法?有,答案是有的,用 disass /m 可以将汇编和代码对应起来!
gdb -p 31639 -ex "disassemble /m srv_master_thread" --ex "quit" --batch > /tmp/g3.log
3447 in /home/jiyuan/rpmbuild/BUILD/tb-mysql-5.5.18/storage/innobase/srv/srv0srv.c
0x00000000007fb478 <+5144>: mov 0x3a8(%r10),%r12
3448 in /home/jiyuan/rpmbuild/BUILD/tb-mysql-5.5.18/storage/innobase/srv/srv0srv.c
3449 in /home/jiyuan/rpmbuild/BUILD/tb-mysql-5.5.18/storage/innobase/srv/srv0srv.c
3450 in /home/jiyuan/rpmbuild/BUILD/tb-mysql-5.5.18/storage/innobase/srv/srv0srv.c
3451 in /home/jiyuan/rpmbuild/BUILD/tb-mysql-5.5.18/storage/innobase/srv/srv0srv.c
0x00000000007fb46d <+5133>: mov %r12,-0x740(%rbp)
0x00000000007fb474 <+5140>: nopl 0x0(%rax)
0x00000000007fb486 <+5158>: test %r12,%r12
0x00000000007fb489 <+5161>: je 0x7fb908 <srv_master_thread+6312>
0x00000000007fb48f <+5167>: lea (%r9,%r9,2),%rdi
0x00000000007fb493 <+5171>: mov %r12,%rax
0x00000000007fb496 <+5174>: xor %edx,%edx
0x00000000007fb498 <+5176>: shl $0x3,%rdi
0x00000000007fb49c <+5180>: mov -0x6c8(%rbp,%rdi,1),%esi
0x00000000007fb4b4 <+5204>: test %rax,%rax
0x00000000007fb4b7 <+5207>: je 0x7fb900 <srv_master_thread+6304>
3452 in /home/jiyuan/rpmbuild/BUILD/tb-mysql-5.5.18/storage/innobase/srv/srv0srv.c
0x00000000007fb4c1 <+5217>: cmp %esi,(%rax)
0x00000000007fb4c3 <+5219>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4c5 <+5221>: mov 0xc(%r8),%edi
0x00000000007fb4c9 <+5225>: cmp 0x4(%rax),%edi
0x00000000007fb4cc <+5228>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4ce <+5230>: mov 0x60(%rax),%rdi
0x00000000007fb4d2 <+5234>: cmp %rdi,0x10(%r11)
0x00000000007fb4d6 <+5238>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4d8 <+5240>: nopl 0x0(%rax,%rax,1)
是不是看起来有点感觉了?终于有对应的代码了!
但是,高兴太早了,只是显示了代码文件名,没有说明是那行代码!
这个问题的原因是mysqld是在显示的那个目录下编译的,如何rpm打包,分发到线上机器部署。而安装的时候,我们是不安装对应的编译的代码文件。
那么,接下来怎么办?
好办,将对应的源文件拷贝一份到任何一个目录下,利用GDB的substitute-path来将编译时的路径和我们拷贝的代码路径对应起来就行了。
拷贝一份对应版本的源码到/tmp下,再次disass下:
注:0x00000000007fb46d 这个地址是我随便选择的,在srv_master_thread函数中某个有些地址,在0x7fb4c1之前,没有太多实际意义。
gdb -p 31639 -ex "set substitute-path /home/jiyuan/rpmbuild/BUILD/tb-mysql-5.5.18 /tmp/alimysql-5.5.18" -ex "disassemble /m 0x00000000007fb46d " --ex "quit" --batch > /tmp/g4.log
3446 for (j = 0; j < srv_buf_pool_instances; j++) {
0x00000000007fb47f <+5151>: mov 0x3a0(%r10),%r13
3447 lint blocks_num, new_blocks_num, flushed_blocks_num;
0x00000000007fb478 <+5144>: mov 0x3a8(%r10),%r12
3448 ibool found;
3449
3450 buf_pool = buf_pool_from_array(j);
3451
0x00000000007fb46d <+5133>: mov %r12,-0x740(%rbp)
0x00000000007fb474 <+5140>: nopl 0x0(%rax)
0x00000000007fb486 <+5158>: test %r12,%r12
0x00000000007fb489 <+5161>: je 0x7fb908 <srv_master_thread+6312>
0x00000000007fb48f <+5167>: lea (%r9,%r9,2),%rdi
0x00000000007fb493 <+5171>: mov %r12,%rax
0x00000000007fb496 <+5174>: xor %edx,%edx
0x00000000007fb498 <+5176>: shl $0x3,%rdi
0x00000000007fb49c <+5180>: mov -0x6c8(%rbp,%rdi,1),%esi
0x00000000007fb4b4 <+5204>: test %rax,%rax
0x00000000007fb4b7 <+5207>: je 0x7fb900 <srv_master_thread+6304>
3452 blocks_num = UT_LIST_GET_LEN(buf_pool->flush_list);
0x00000000007fb4c1 <+5217>: cmp %esi,(%rax)
0x00000000007fb4c3 <+5219>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4c5 <+5221>: mov 0xc(%r8),%edi
0x00000000007fb4c9 <+5225>: cmp 0x4(%rax),%edi
0x00000000007fb4cc <+5228>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4ce <+5230>: mov 0x60(%rax),%rdi
0x00000000007fb4d2 <+5234>: cmp %rdi,0x10(%r11)
0x00000000007fb4d6 <+5238>: jne 0x7fb4b0 <srv_master_thread+5200>
0x00000000007fb4d8 <+5240>: nopl 0x0(%rax,%rax,1)
3453 bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
3454 new_blocks_num = 0;
0x00000000007fb4a3 <+5187>: lea -0x6d0(%rbp,%rdi,1),%r8
0x00000000007fb4ab <+5195>: jmp 0x7fb4c1 <srv_master_thread+5217>
0x00000000007fb4ad <+5197>: nopl (%rax)
3455
3456 found = FALSE;
3457 while (bpage != NULL) {
3458 if (prev_flush_info[j].space == bpage->space
3459 && prev_flush_info[j].offset == bpage->offset
0x00000000007fb4b0 <+5200>: mov 0x40(%rax),%rax
3460 && prev_flush_info[j].oldest_modification
0x00000000007fb4bd <+5213>: add $0x1,%rdx
终于看到熟悉的代码了!
可以定位到问题本质,第3452行异常导致,即buf_pool->flush_list.count访问为非法内存地址。
这段代码是srv_master_thread频繁访问的内存变量,出现这种问题,我只能说是其它地方有异常导致此处内存被污染。至于原因,没有啥思路,等下会遇到再分析。
到此,我们就能力范围内对mysql的backtrace进行了深度挖掘,揭开backtrace中地址的神秘面纱。但这个问题还是没有解决,backtrace中还有其它可以挖掘的信息,后面有高人指定也许会豁然开朗。
a.首先去 http://downloads.openwrt.org/snapshots/trunk/ar71xx/packages/ 下载LuCI需要的包
liblua_5.1.5-1_ar71xx.ipk
libubus-lua_2012-12-15-bb856ad8a9a1e786494d01e34bbfe2b4d2134021_ar71xx.ipk
libuci-lua_2012-03-28.1-1_ar71xx.ipk
lua_5.1.5-1_ar71xx.ipk
luci-i18n-english_trunk+svn9570-1_ar71xx.ipk
luci-lib-core_trunk+svn9570-1_ar71xx.ipk
luci-lib-ipkg_trunk+svn9570-1_ar71xx.ipk
luci-lib-nixio_trunk+svn9570-1_ar71xx.ipk
luci-lib-sys_trunk+svn9570-1_ar71xx.ipk
luci-lib-web_trunk+svn9570-1_ar71xx.ipk
luci-mod-admin-core_trunk+svn9570-1_ar71xx.ipk
luci-mod-admin-full_trunk+svn9570-1_ar71xx.ipk
luci-proto-core_trunk+svn9570-1_ar71xx.ipk
luci-sgi-cgi_trunk+svn9570-1_ar71xx.ipk
luci-theme-base_trunk+svn9570-1_ar71xx.ipk
luci-theme-openwrt_trunk+svn9570-1_ar71xx.ipk
uhttpd_2012-10-30-e57bf6d8bfa465a50eea2c30269acdfe751a46fd_ar71xx.ipk
b.想办法上传到OpenWrt
由于没有安装sftp-server,所以我们通过sftp上传似乎不通,我最后的办法是把这些包下载到连接到OpenWrt的电脑本地的一个目录,之后:
D:\luci-offline-packages>python27 -m SimpleHTTPServer
在本地搭建一个简易的web服务器,luci-offline-packages目录为根目录,之后再用wget下载(我LAN的IP段是10.10.0.%,网关10.10.0.1,电脑10.10.0.247):
wget http://10.10.0.247:8000/luci-i18n-english_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-lib-core_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-lib-ipkg_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-lib-nixio_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-lib-sys_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-lib-web_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-mod-admin-core_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-mod-admin-full_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-proto-core_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-sgi-cgi_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-theme-base_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/luci-theme-openwrt_trunk+svn9570-1_ar71xx.ipk
wget http://10.10.0.247:8000/libubus-lua_2012-12-15-bb856ad8a9a1e786494d01e34bbfe2b4d2134021_ar71xx.ipk
wget http://10.10.0.247:8000/lua_5.1.5-1_ar71xx.ipk
wget http://10.10.0.247:8000/libuci-lua_2012-03-28.1-1_ar71xx.ipk
wget http://10.10.0.247:8000/liblua_5.1.5-1_ar71xx.ipk
wget http://10.10.0.247:8000/uhttpd_2012-10-30-e57bf6d8bfa465a50eea2c30269acdfe751a46fd_ar71xx.ipk
Python的SimpleHTTPServer日志如下:
Serving HTTP on 0.0.0.0 port 8000 ...
OpenWrt.lan - - [01/Jan/2013 15:52:28] "GET /luci* HTTP/1.1" 404 -
OpenWrt.lan - - [01/Jan/2013 15:53:29] "GET /luci-i18n-english_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:53:33] "GET /luci-lib-core_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:53:38] "GET /luci-lib-ipkg_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:53:42] "GET /luci-lib-nixio_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:53:46] "GET /luci-lib-sys_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:53:49] "GET /luci-lib-web_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:53:52] "GET /luci-mod-admin-core_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:53:56] "GET /luci-mod-admin-full_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:53:59] "GET /luci-proto-core_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:54:02] "GET /luci-sgi-cgi_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:54:06] "GET /luci-theme-base_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:54:07] "GET /luci-theme-openwrt_trunk+svn9570-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:57:29] "GET /libubus-lua_2012-12-15-bb856ad8a9a1e786494d01e34bbfe2b4d2134021_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:57:51] "GET /lua_5.1.5-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:58:19] "GET /libuci-lua_2012-03-28.1-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 15:59:20] "GET /liblua_5.1.5-1_ar71xx.ipk HTTP/1.1" 200 -
OpenWrt.lan - - [01/Jan/2013 16:02:18] "GET /uhttpd_2012-10-30-e57bf6d8bfa465a50eea2c30269acdfe751a46fd_ar71xx.ipk HTTP/1.1" 200 -
c.安装所有包:
opkg install *
d.启动httpd服务:
/etc/init.d/uhttpd enable
/etc/init.d/uhttpd start
通过 http://10.10.0.1 访问LuCI。
使用Python smtplib发送带附件的邮件给多人的时候
#!/usr/bin/env python
#-*- coding: utf-8 -*-
#encoding = utf-8
import smtplib, mimetypes
import time
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
msg = MIMEMultipart()
msg['From'] = "mail1@163.com"
#msg['To'] = ["mail1@163.com","mail1@163.com","mail1@163.com"] 会出错
mail_to = ["mail1@163.com","mail1@163.com","mail1@163.com"]
msg['To'] = ', '.join(mail_to)
msg['Subject'] = "Report " + (time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
txt = MIMEText("User List \n\n\n")
msg.attach(txt)
fileName = r'user_list.txt'
ctype, encoding = mimetypes.guess_type(fileName)
if ctype is None or encoding is not None:
ctype = 'application/octet-stream'
maintype, subtype = ctype.split('/', 1)
att1 = MIMEImage((lambda f: (f.read(), f.close()))(open(fileName, 'rb'))[0], _subtype = subtype)
att1.add_header('Content-Disposition', 'attachment', filename = fileName)
msg.attach(att1)
smtp = smtplib.SMTP()
smtp.connect('smtp.139.com:25')
smtp.login('user', 'password')
#smtp.sendmail(msg['From'], msg['To'], msg.as_string()) 会出错
smtp.sendmail(msg['From'], mail_to, msg.as_string())
smtp.quit()
报如下错误:
Traceback (most recent call last):
File "block_user.py", line 116, in <module>
smtp.sendmail(msg['From'], msg['To'], msg.as_string())
File "D:\Python25\lib\email\message.py", line 131, in as_string
g.flatten(self, unixfrom=unixfrom)
File "D:\Python25\lib\email\generator.py", line 84, in flatten
self._write(msg)
File "D:\Python25\lib\email\generator.py", line 116, in _write
self._write_headers(msg)
File "D:\Python25\lib\email\generator.py", line 162, in _write_headers
header_name=h, continuation_ws='\t').encode()
File "D:\Python25\lib\email\header.py", line 403, in encode
return self._encode_chunks(newchunks, maxlinelen)
File "D:\Python25\lib\email\header.py", line 363, in _encode_chunks
_max_append(chunks, s, maxlinelen, extra)
File "D:\Python25\lib\email\quoprimime.py", line 97, in _max_append
L.append(s.lstrip())
AttributeError: 'list' object has no attribute 'lstrip'
E:\do_au_block_user>python25 block_user.py
查明原因如下http://bytes.com/topic/python/answers/472868-sending-emails-list-recipients:
The problem is that SMTP.sendmail and email.MIMEText need two different things.
email.MIMEText sets up the “To:” header for the body of the e-mail. It is ONLY used for displaying a result to the human being at the other end, and like all e-mail headers, must be a single string. (Note that it does not actually have to have anything to do with the people who actually receive the message.)
SMTP.sendmail, on the other hand, sets up the “envelope” of the message for the SMTP protocol. It needs a Python list of strings, each of which has a single address.
So, what you need to do is COMBINE the two replies you received. Set msg‘To’ to a single string, but pass the raw list to sendmail:
msg['To'] = ', '.join( emails )
s.sendmail( msg['From'], emails, msg.as_string() )来自http://ruby-china.org/wiki/rvm-guide
rvm是一个命令行工具,可以提供一个便捷的多版本ruby环境的管理和切换。
如果你打算学习ruby/rails, rvm是必不可少的工具之一。
这里所有的命令都是再用户权限下操作的,任何命令最好都不要用sudo.
rvm安装
$ curl -L get.rvm.io | bash -s stable
$ source ~/.bashrc
$ source ~/.bash_profile
修改 RVM 的 Ruby 安装源到国内的淘宝镜像服务器,这样能提高安装速度
$ sed -i -e 's/ftp\.ruby-lang\.org\/pub\/ruby/ruby\.taobao\.org\/mirrors\/ruby/g' ~/.rvm/config/db
ruby的安装与切换
列出已知的ruby版本
rvm list known
安装一个ruby版本
rvm install 1.9.3
这里安装了最新的1.9.3, rvm list known列表里面的都可以拿来安装。
使用一个ruby版本
rvm use 1.9.3
如果想设置为默认版本,可以这样
rvm use 1.9.3 --default
查询已经安装的ruby
rvm list
卸载一个已安装版本
rvm remove 1.9.2
gemset的使用
rvm不仅可以提供一个多ruby版本共存的环境,还可以根据项目管理不同的gemset.
gemset可以理解为是一个独立的虚拟gem环境,每一个gemset都是相互独立的。
比如你有两个项目,一个是rails 2.3 一个是 rails 3. gemset可以帮你便捷的建立两套gem开发环境,并且方便的切换。
gemset是附加在ruby语言版本下面的,例如你用了1.9.2, 建立了一个叫rails3的gemset,当切换到1.8.7的时候,rails3这个gemset并不存在。
建立gemset
rvm use 1.8.7
rvm gemset create rails23
然后可以设定已建立的gemset做为当前环境
use 可以用来切换语言,或者gemset,前提是他们已经被安装(或者建立)。并可以在list命令中看到。
rvm use 1.8.7
rvm use 1.8.7@rails23
然后所有安装的gem都是安装在这个gemset之下。
列出当前ruby的gemset
rvm gemset list
清空gemset中的gem
如果你想清空一个gemset的所有gem,想重新安装所有gem,可以这样
rvm gemset empty 1.8.7@rails23
删除一个gemset
rvm gemset delete rails2-3
项目自动加载gemset
rvm还可以自动加载gemset.
例如我们有一个rails3.1.3项目,需要1.9.3版本ruby.整个流程可以这样。
rvm install 1.9.3
rvm use 1.9.3
rvm gemset create rails313
rvm use 1.9.3@rails313
下面进入到项目目录,建立一个.rvmrc文件。
在这个文件里可以很简单的加一个命令:
rvm use 1.9.3@rails313
然后无论你当前ruby设置是什么,cd到这个项目的时候,rvm会帮你加载 ruby 1.9.3和rails313 gemset.
使用rvm来快速部署nginx+passenger
首先安装passenger
gem install passenger
然后使用passenger-install-nginx-module 来安装nginx和部署。
因为这一步需要root权限(因为要编译nginx)可以用rvmsudo这个东西。(这个东西真是个好东西)
rvmsudo passenger-install-nginx-module
然后会让你选择是下载nginx源码自动编译安装,还是自己选择nginx源码位置。
选择nginx手动安装的可以添加别的编译参数,方便自定义编译nginx。
然后一路下载安装。默认的安装位置为/opt/nginx.
然后看看nginx.conf,都给你配置好了,只需要加上root位置(yourapp/public)就可以了。
当我第一次安装完成了,就惊呼,这也太爽了吧。
ps:rvm是个好东西,做的很智能,(大部分)操作失败后会告诉你原因,然后告诉你需要安装哪些Lib等等,非常适合新手老手使用,简直是居家旅行必备良药。
| 1/18 - 89 Posts | Next Page |