Ubuntu安装KVM虚拟机

1、检查CPU是否支持虚拟化。

>> long@mylife:~$ egrep -o '(vmx|svm)' /proc/cpuinfo
>> vmx
>> vmx
>> vmx
>> vmx

2、安装KVM相关软件

>> sudo apt-get install qemu-kvm libvirt-bin virt-manager bridge-utils

3、检查安装状态

>> long@mylife:~$ lsmod | grep kvm
>> kvm_intel             143630  0
>> kvm                   452096  1 kvm_intel

4、启动虚拟系统管理器

>> virt-manager

5、提示安装新的软件包,选择“是”==>“安装"==>"继续"

6、提示无法连接到libvirt,重启

7、启动虚拟系统管理器,至此KVM安装完成

Ubuntu查看硬件配置

1. 查看系统内核

>> long@pc1:/proc$ uname -a
>> Linux pc1 3.16.0-41-generic #55~14.04.1-Ubuntu SMP Sun Jun 14 18:43:36 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

2. 查看CPU

>> long@pc1:/proc$ cat /proc/cpuinfo | grep model\ name
>> model name       : Pentium(R) Dual-Core  CPU      E5500  @ 2.80GHz
>> model name       : Pentium(R) Dual-Core  CPU      E5500  @ 2.80GHz

3. 查看内存

>> long@pc1:/proc$ cat /proc/meminfo | grep MemTotal
>> MemTotal:        4012620 kB

4. 查看显卡

>> long@pc1:/proc$ lspci | grep 'VGA'
>> 00:02.0 VGA compatible controller: Intel Corporation 4 Series Chipset Integrated Graphics Controller (rev 03)

5. 查看声卡

>> long@pc1:/proc$ lspci | grep -i 'Audio'
>> 00:1b.0 Audio device: Intel Corporation NM10/ICH7 Family High Definition Audio Controller (rev 01)

6. 查看网卡

>> long@pc1:/proc$ lspci | grep -i 'Ethernet'
>> 02:00.0 Ethernet controller: Marvell Technology Group Ltd. 88E8057 PCI-E Gigabit Ethernet Controller (rev 10)

7. 查看硬盘

>> long@pc1:/proc$ df -lh
>> Filesystem      Size  Used Avail Use% Mounted on
>> /dev/sda1       292G  4.2G  273G   2% /
>> none            4.0K     0  4.0K   0% /sys/fs/cgroup
>> udev            2.0G  4.0K  2.0G   1% /dev
>> tmpfs           392M  1.1M  391M   1% /run
>> none            5.0M     0  5.0M   0% /run/lock
>> none            2.0G   76K  2.0G   1% /run/shm
>> none            100M   32K  100M   1% /run/user

搭建本地git服务器

搭建本地git服务器的步骤如下:

1、找到一台没人用的电脑,安装上Linux系统,在这里选用的是Ubuntu 14.04。然后配置静态IP:172.16.0.110。

2、安装git服务:

>> sudo apt-get install git

3、创建一个git用户:

>> sudo adduser git

创建git用户之后,远端才可以用git clone git @......要不然这里需要换成默认用户名,总觉得有点怪异。

4、建立/home/git/.ssh/authorized_keys文件,将团队每个人的~/.ssh/id_rsa.pub文件复制到上述文件中,一行一个。

5、在/srv目录建立一个git仓库:

>> cd /srv
>> sudo git init --bare ourwiki.git

6、修改git仓库的所属者:

>> sudo chown -R git:git ourwiki.git

7、这时团队成员通过如下命令即可克隆ourwiki项目了:

>> git clone git@172.16.0.110:/srv/ourwiki.git

Ubuntu14.04部署Tornado+Nginx+Supervisor

本文主要讲述如何在Ubuntu上部署用Tornado编写的网站,涉及进程管理工具Supervisor和服务器Nginx。

前提:网站使用Python编写,采用Tornado框架和Mysql数据库,要部署网站的机器deploy为Ubuntu14.04系统,静态IP地址为192.168.122.150,要部署的网站为reciteword.tar.gz

1、安装emacs

>> sudo apt-get install emacs

2、设定静态IP

>> sudo emacs /etc/network/interfaces

3、修改eth0部分

auto eth0
iface eth0 inet static
address 192.168.122.150
netmask 255.255.255.0
gateway 192.168.122.1
dns-nameserver 202.98.198.167

4、保存文件,重启机器

>> sudo reboot

5、下载部署相关软件

>> sudo apt-get install mysql-server mysql-client python3-tornado python3-mysql.connector emacs nginx python-pip python3-pip

6、安装beautifulsoup4(这个是网站运行需要的)

>> sudo pip3 install beautifulsoup4

7、下载supervisor

>> wget https://pypi.python.org/packages/source/s/supervisor/supervisor-3.1.3.tar.gz

8、解压网站代码和supervisor

>> tar zxvf reciteword.tar.gz
>> tar zxvf supervisor-3.1.3.tar.gz

9、启动数据库

>> sudo mysqld

10、开启一个新的终端,生成数据库

>> sudo mysql -u root -p
mysql> source /home/long/reciteword/db/recitewordbase.sql;

11、安装supervisor

>> cd supervisor-3.1.3/
>> sudo python setup.py install

12、编写supervisord.conf配置文件

>> cd /home/long/reciteword/
>> echo_supervisord_conf > supervisord.conf

在supervisord.conf最后追加

[program:reciteword-8001]
command=python3 /home/long/reciteword/main.py --port=8001
directory=/home/long/reciteword
autorestart=true
redirect_stderr=true
stdout_logfile=/home/long/reciteword/reciteword_server-8001.log
stdout_logfile_maxbytes=500MB
stdout_logfile_backups=50
stdout_capture_maxbytes=1MB
stdout_events_enabled=false
loglevel=warn

[program:reciteword-8002]
command=python3 /home/long/reciteword/main.py --port=8002
directory=/home/long/reciteword
autorestart=true
redirect_stderr=true
stdout_logfile=/home/long/reciteword/reciteword_server-8002.log
stdout_logfile_maxbytes=500MB
stdout_logfile_backups=50
stdout_capture_maxbytes=1MB
stdout_events_enabled=false
loglevel=warn

[program:reciteword-8003]
command=python3 /home/long/reciteword/main.py --port=8003
directory=/home/long/reciteword
autorestart=true
redirect_stderr=true
stdout_logfile=/home/long/reciteword/reciteword_server-8003.log
stdout_logfile_maxbytes=500MB
stdout_logfile_backups=50
stdout_capture_maxbytes=1MB
stdout_events_enabled=false
loglevel=warn

[program:reciteword-8004]
command=python3 /home/long/reciteword/main.py --port=8004
directory=/home/long/reciteword
autorestart=true
redirect_stderr=true
stdout_logfile=/home/long/reciteword/reciteword_server-8004.log
stdout_logfile_maxbytes=500MB
stdout_logfile_backups=50
stdout_capture_maxbytes=1MB
stdout_events_enabled=false

13、启动supervisor

>> supervisord -c supervisord.conf

14、修改nginx配置文件

>> cd /etc/nginx/sites-available
>> sudo emacs default

注释掉所有内容

>> cd /etc/nginx
>> sudo emacs nginx.conf

在http段追加以下配置:

proxy_next_upstream error;
upstream tornadoes {
    server 192.168.122.150:8001;
    server 192.168.122.150:8002;
    server 192.168.122.150:8003;
    server 192.168.122.150:8004;
    ip_hash;
 }
server {
    listen 80;
    server_name 192.168.122.150;

    location / {
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_pass http://tornadoes;
     }
}

15、保存,重启nginx

>> sudo service nginx restart

16、浏览器访问192.168.122.150即可

通过Python的C扩展进行任意长度字符串逆序输出

本文展示如何通过Python的C扩展进行任意长度字符串逆序输出。

1、编写C扩展stringreverse.c

#include </usr/include/python3.4m/Python.h>

static PyObject * StringError;  //错误信息对象

// 自定义函数
// 实现任意长度字符串反转
int reverse(char * inputstr, int length, char * outputstr)
{
  int i;
  for(i=length; i>0; i--)
    {
      outputstr[length-i] = inputstr[i-1];
    }
  outputstr[length] = '\0';
  return 1;
}

// Python和C的接口
static PyObject * stringreverse(PyObject * self, PyObject * args)
{
  char * inputstr = NULL; // 用来接收参数的本地变量
  int length = 0;         // 用来接收参数的本地变量
  if (!PyArg_ParseTuple(args, "(si)", &inputstr, &length))  // 接收参数给本地变量
    return NULL;
  char *outputpointer = (char *) malloc(sizeof(char) * (length + 1)); // 分配返回值空间,多一位存放'\0'
  int sts;  // 判断函数是否成功执行
  sts = reverse(inputstr, length, outputpointer); // 调用自定义函数
  if (sts < 0) {
    PyErr_SetString(StringError, "Encode Error");
    return NULL;
  }
  return Py_BuildValue("s", outputpointer);  // 返回函数计算结果
}

// 声明方法调用接口
static PyMethodDef StringReverseMethods[] = {
  {"reverse", stringreverse, METH_VARARGS,
   "Reverse A String."},  // {对外函数名称, 对内函数名称, 标志位, 函数说明}
  {NULL, NULL, 0, NULL}  //哨兵变量
};
/*
  METH_VARARGS标志位,用来告诉解释器应使用调用C函数的规则。
  当此位置为值0,表示PyArg_ParseTuple()函数使用的变量是废弃的。
  当仅使用时"METH_VARARGS",表示希望参数经由PyArg_ParseTuple()被传递进来。
*/

// 声明模块包含的方法集
static struct PyModuleDef stringmodules = {
  PyModuleDef_HEAD_INIT,
  "stringreverse",
  NULL,
  -1,
  StringReverseMethods
};

// 模块初始化,包括异常处理
PyMODINIT_FUNC PyInit_stringreverse(void)
{
  PyObject *m;
  m = PyModule_Create(&stringmodules);
  if (m == NULL)
    return NULL;
  StringError = PyErr_NewException("stringreverse.error", NULL, NULL);
  Py_INCREF(StringError);
  PyModule_AddObject(m, "error", StringError);
  return m;
}

// 初始化
void main(int argc, wchar_t *argv[])
{
  PyImport_AppendInittab("stringreverse", PyInit_stringreverse);
  Py_SetProgramName(argv[0]);
  Py_Initialize();
  PyImport_ImportModule("stringreverse");
}

/*
  PyArg_ParseTuple()可以使用的格式参数
  "s" (string or Unicode object) [char *]
  "s#" (string, Unicode or any read buffer compatible object) [char *, int]
  "z" (string or None) [char *]
  "z#" (string or None or any read buffer compatible object) [char *, int]
  "u" (Unicode object) [Py_UNICODE *]
  "u#" (Unicode object) [Py_UNICODE *, int]
  "es" (string, Unicode object or character buffer compatible object) [const char *encoding, char **buffer]
  "es#" (string, Unicode object or character buffer compatible object) [const char *encoding, char **buffer, int *buffer_length]
  "b" (integer) [char]
  "h" (integer) [short int]
  "i" (integer) [int]
  "l" (integer) [long int]
  "c" (string of length 1) [char]
  "f" (float) [float]
  "d" (float) [double]
  "D" (complex) [Py_complex]
  "O" (object) [PyObject *]
  "O!" (object) [typeobject, PyObject *]
  "O&" (object) [converter, anything]
  "S" (string) [PyStringObject *]
  "U" (Unicode string) [PyUnicodeObject *]
  "t#" (read-only character buffer) [char *, int]
  "w" (read-write character buffer) [char *]
  "w#" (read-write character buffer) [char *, int]
  "(items)" (tuple) [matching-items]  ==> Py_BuildValue("(i, i)", 1, 2) (1, 2)
  "[items]" (list) [matching-items]   ==> Py_BuildValue("[i, i]", 1, 2) [1, 2]
  "{items}" (dictionary) [matching-items]  ==> Py_BuildValue("{s, i}", 'a', 2) {'a': 2}

  "|"
  Indicates that the remaining arguments in the Python argument list are optional. The C variables corresponding to optional arguments should be initialized to their default value -- when an optional argument is not specified, PyArg_ParseTuple() does not touch the contents of the corresponding C variable(s).
  ":"
  The list of format units ends here; the string after the colon is used as the function name in error messages (the ``associated value'' of the exception that PyArg_ParseTuple() raises).
  ";"
  The list of format units ends here; the string after the semicolon is used as the error message instead of the default error message. Clearly, ":" and ";" mutually exclude each other.
*/

2、将C扩展编译成动态链接库stringreverse.so

>> gcc -o stringreverse.so -shared -fPIC stringreverse.c

3、Python调用动态链接库test.py

1
2
3
import stringreverse
aimstr = "abc"
print(stringreverse.reverse((aimstr, len(aimstr))))

输出结果:

>> long@happytime:~/pythontest$ python3 test.py
>> cba

Python3向SQLite写入图片

使用Python3向SQLite写入图片。

看代码binaryread.py:

import sqlite3

with open("test.jpg", "rb") as fp:
    picbin = fp.read()

cont = sqlite3.connect("temp.db")
cur = cont.cursor()
sql = """create table pic(pic blob)"""
cur.execute(sql)
sql = """insert into pic(pic) values(?)"""
b = sqlite3.Binary(picbin)
cur.execute(sql, (b,))
cont.commit()

执行代码,程序读取当前目录下的test.jpg,写入一个新创建的数据库,文件名是temp.db。

然后读取图片数据,写入一个新的文件,看代码binarywrite.py:

1
2
3
4
5
6
7
8
9
import sqlite3

cont = sqlite3.connect("temp.db")
cur = cont.cursor()
sql = """select pic from pic"""
cur.execute(sql)
pic = cur.fetchone()[0]
with open("test1.jpg", "wb") as fp:
    fp.write(pic)

执行代码,生成了一个和test.jpg内容完全一样的test1.jpg。

综上,在涉及到二进制数据写入SQLite数据库时,要使用sqlite3.Binary将二进制转换成SQLite可以写入的参数类型。