12月 11

raspberry pi 自动初始化脚本

  玩了几天,打算刷一下。但是很多要升级也挺麻烦,直接写了个脚本,自动升级。大家如果还有自己需要的,也可以自行添加,这样初始就方便多了。
  先修改成亚洲的源
$ sudo mv /etc/apt/sources.list /etc/apt/sources.list.bak
$ sudo vi /etc/apt/sources.list
deb http://mirror.nus.edu.sg/raspbian/raspbian wheezy main contrib non-free rpi
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ wheezy main contrib non-free rpi

  如果直接用我的脚本命令如下:
$ wget http://www.simonzhang.net/wp-content/uploads/2012/12/pisystemupdate.py_.gz
$ gunzip pisystemupdate.py_.gz ;chmod a+x pisystemupdate.py_;python pisystemupdate.py_
不知道为什么加了个尾巴

  脚本内容如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# Revision:
# Date:        2012-12-10
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# -------------------------------
import os
import time

def SystemUpdate():   #系统升级
    try:
        os.system('sudo apt-get -y update')
        _get = 'ok'
    except:
        _get = 'ERROR'
    return _get

def Timing():   #校时
    try:
        os.system('sudo cp /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime')
        os.system('sudo apt-get install -y ntpdate')
        os.system('sudo /usr/sbin/ntpdate stdtime.gov.hk')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get


def Vncserver():    #远程桌面
    try:
        os.system('sudo apt-get install -y tightvncserver') 
        _get = 'ok'
    except:
        _get = 'ERROR'
    return _get


def DevelopTool():    #开发工具
    try:
        os.system('sudo apt-get install -y gcc make')
        _get = 'ok'
    except:
        _get = 'ERROR'
    return _get

def SystemTools():    #系统常用工具
    try:
        os.system('sudo apt-get install -y bison gawk vim chkconfig') 
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get


def PythonTools():   #python 管理工具
    try:
        os.system('wget -q http://peak.telecommunity.com/dist/ez_setup.py')
        os.system('sudo python ez_setup.py')
        os.system('sudo easy_install pygame')
        _get = 'ok'
    except:
        _get = 'ERROR'
    return _get

	
def PythonImage():    #python的图片处理
    try:
	os.system('sudo apt-get install -y libjpeg*-dev')
	os.system('sudo apt-get install -y python-imaging') 
	os.system('sudo apt-get install -y python-dev')
	os.system('sudo easy_install tornado PIL')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get


def PythonFrame():    #python框架
    try:
        os.system('sudo easy_install tornado Django')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get

def OpenCV():   #摄像头
    try:
        os.system('sudo apt-get install -y python-opencv')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get


def InstallMysql():   #数据库,密码为pi
    try:
	os.system('sudo debconf-set-selections <<< \'mysql-server-5.5 mysql-server/root_password password pi\'')
	os.system('sudo debconf-set-selections <<< \'mysql-server-5.5 mysql-server/root_password_again password pi\'')
	os.system('sudo apt-get -y install mysql-server')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get


def Installjava():   #java环境
    try:
	os.system('sudo apt-get install -y openjdk-7-jdk')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get

def ChineseFont():   #中文字体
    try:
	os.system('sudo apt-get install -y ttf-wqy-microhei')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get
	
def InputMethod():   #输入法
    try:
	os.system('sudo apt-get install -y scim scim-pinyin')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get

	
def AudioDriver():   #音频
    try:
        os.system('sudo apt-get install -y alsa-utils')
        os.system('sudo modprobe snd_bcm2835')
	_get = 'ok'
    except:
        _get = 'ERROR'
    return _get

	
def main():
    install_list = [SystemUpdate, \
                    Timing, \
                    Vncserver, \
                    DevelopTool, \
                    SystemTools, \
                    PythonTools, \
                    PythonImage, \
                    PythonFrame, \
                    OpenCV, \
                    InstallMysql, \
                    Installjava, \
                    ChineseFont, \
                    InputMethod,  \
                    AudioDriver, \
                    SystemUpdate,
                   ]
    for il in install_list:
        print '*' * 50
        print ': %s start' % il
        print '*' * 50
        install_status = il()
        nt = time.localtime()
        log_time = "%s-%s-%s %s:%s:%s" % (nt[2], nt[2], nt[3], nt[4], nt[5], nt[6])
        log_file = open("pi_install.log", "ab")
        log_file.write("%s %s install %s\n" % (log_time, il, install_status))
        log_file.close()
    os.system('sudo apt-get upgrade -y')
    print "Install all end."


if __name__ == '__main__':
    main()

pisystemupdate.py

12月 07

raspberry pi连接摄像头

  安装pygame产生窗口用,cv获取摄像头图像
$ sudo easy_install pygame
$ sudo apt-get install -y python-opencv

代码如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# -------------------------------
# Filename:   
# Revision:
# Date:        2012-12-7
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# -------------------------------
import pygame
import cv

pygame.init()
size = width, height = 640, 480
speed = [1, 1]  
black = 0, 0, 0  
  
pygame.display.set_caption('simonzhag.net')
screen = pygame.display.set_mode(size)

cam = cv.CreateCameraCapture(0)
cv.SetCaptureProperty(cam,cv.CV_CAP_PROP_FRAME_WIDTH, 640)
cv.SetCaptureProperty(cam,cv.CV_CAP_PROP_FRAME_HEIGHT, 480);

while 1:
    try:
        cv.GrabFrame(cam)
        img = cv.RetrieveFrame(cam)
        cv.SaveImage('/tmp/test.jpg', img)
    except:
        pass
    cv.WaitKey(1500)
    image = pygame.image.load('/tmp/test.jpg')
    screen.blit(image, speed)
    pygame.display.flip()

image

  如果cv.WaitKey过小或者请求太多会报select timeout。还不知道是摄像头问题、还是我的存储开始class2的问题。图像也经常获取不全,问题还未处理。
  也不是所有设想头都可以用。可以使用lsusb查看系统是否识别出usb设备,并且有/dev/video0文件。如果有就应该可以获取。

12月 04

python 源码删除注释并编译成字节码

  上线需要,将py的源码中注释删掉,然后编译成字节码,这样加载速度会比较快。写此脚本主要是为了删除注释。当然如果上线不想放py源码,则在最后增加删除源码即可。我把这个代码起名为咕噜咕噜。python 源码删除注释并编译。

#!/bin/env python
# -*- coding:utf-8 -*-
# -------------------------------
# Filename:    
# Revision:
# Date:        2012-12-3
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net 
# -------------------------------
import os
import re
import sys
import shutil
import compileall


def delete_Notes(py_file):
    # 原始文件只读打开,处理文件追加打开
    _tmp_sr_file = open(py_file, "rb").readlines()
    _tmp_de_file = open("%s.swp" % py_file, "ab")
    _skip_status = 0
    _now_line = 0
    _multi_count = 0 
    # 循环处理
    for line in _tmp_sr_file:
        # 跳过前10行,因为我的开头注释有10行
        if _now_line > 10:
            # 获取开头一位和三位
            try:
                _single_row_notes = line.strip()[0]
            except:
                _single_row_notes = ""
            try: 
                _multi_row_notes = line.strip()[0:3]
            except:
                _multi_row_notes = ""
            # 获取行是否为注释
            if _single_row_notes == "#":
                _skip_status = 1
            elif _multi_row_notes == "'''":
                if _multi_count == 0:
                    _skip_status = 1
                    _multi_count = 1
                else:
                    _skip_status = 1
                    _multi_count = 0
            elif _multi_count == 1:
                _skip_status = 1
            else:
                _skip_status = 0
        else:
            _skip_status = 0
        # 判断是否跳过写入
        if _skip_status == 0:
            _tmp_de_file.write(line)
        _now_line += 1
    _tmp_de_file.close()
    # 处理完毕将临时文件处理为原始文件
    shutil.move("%s.swp" % py_file, py_file)
        

def main():
    _get_src_path = sys.argv[1]
    _get_dec_path = sys.argv[2]
    if os.path.exists(_get_src_path):
        # 拷贝原始文件夹
        shutil.copytree(_get_src_path, _get_dec_path)
        # 删除原始文件中的注释
        find_py_file = re.compile(r"^.*\.py$")
        find_walk = os.walk(_get_dec_path)
        for path,dirs,files in find_walk:
            for f in files:
                if find_py_file.search(f):
                    delete_Notes("%s/%s" % (path, f))
        # 编译成字节码
        compileall.compile_dir(_get_dec_path)
    else:
        print "Path Error!"

if __name__ == "__main__":
    main()

使用方法,
gulugulu.py 源码路径 目标路径

python 源码删除注释并编译

12月 03

raspberry pi 初步和远程配置

  买raspberry pi主要因为推荐使用python。今天的板子总算到了,先照几张照片。
  主板的样子。
image
  外壳都是散的自己安装。
image
  组装完成。大小和鼠标差不多。
image

  系统安装和初步配置网上资料很多,就不重复了。直接来调试连接远程,方便将来开发。
首先升级一下系统,测试了一下远程连接ssh没有问题
$ sudo apt-get update
开始安装vnc,方便远程桌面开发
$ sudo apt-get install tightvncserver
启动服务
$ vncserver
查看监听端口
$ netstat -atnp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:5901 0.0.0.0:* LISTEN 2795/Xtightvnc
tcp 0 0 0.0.0.0:6001 0.0.0.0:* LISTEN 2795/Xtightvnc
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN –
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN –
tcp 0 52 192.168.1.128:22 192.168.1.73:4958 ESTABLISHED –

从图中看到vnc有两个进程,两个监控端口,端口5901是RFB协议的VNC客户端连接,端口6001是X应用程,也序可以连接到VNC服务器。因为没有5801所以不能通过浏览器访问。直接下个windows下的客户端tightvnc客户端,连接成功。下一步可以开发了。系统上安装的是python2.7 和python3
image

11月 18

tornado 使用配置文件的问题测试

  使用tornado做个能承担高负载的接口,配置部分是否要使用配置文件(ConfigParser)。现在有两个问题需要测试。第一、配置文件是否一次性加载,我可不希望,每次调用都会加载配置文件。第二、修改配置文件是否可以自动加载。在tornado中py文件可以自动加载,这样服务就不需要重启,服务也不会间断。
  首先是做一个tornado的测试页。在目录opt下建立testconfig文件夹,在testconf下编写代码。共有4个文件。

  主文件 main.py 代码如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# -------------------------------------------------------------------------------
# Filename:    main.py
# Revision:    1.0
# Date:        2012-11-18
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# -----------------------------------------------------------------------------
import tornado.ioloop
import tornado.web
from index import *
 
application = tornado.web.Application([
    (r"/", MainHandler),
])
 
if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

  主文件要调用的部分 index.py 代码如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# -------------------------------------------------------------------------------
# Filename:    main.py
# Revision:    1.0
# Date:        2012-11-18
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# -----------------------------------------------------------------------------
import tornado.ioloop
import tornado.web
import ConfigParser

# 配置进行全局加载,如果是放到类中肯定每次都有IO。
cf = ConfigParser.ConfigParser()
cf.read("config.properties")
get_index_file_path = cf.get(cf.sections()[0], "path")
 
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        read_file = open(get_index_file_path, "rb").read()
        self.write("%s" % read_file)

  配置文件名为config.properties内容如下:

[context_path]
path = index.txt

  创建一个index.txt文件,在里面写点要显示的文件。

  开始编写监控配置文件IO的脚本。监控文件变化的部分详见:http://www.simonzhang.net/?p=429。还不知道watchdog能不能做到这个。
  脚本名为 watchfile.py 代码如下:

#!/bin/env python
# -*- coding:utf-8 -*-
# -------------------------------------------------------------------------------
# Filename:    watchfile.py
# Revision:    1.0
# Date:        2012-11-17
# Author:      simonzhang
# Email:       simon-zzm@163.com
# Web:         www.simonzhang.net
# -----------------------------------------------------------------------------
import re
import pyinotify

wm = pyinotify.WatchManager()
mask = pyinotify.IN_OPEN

class EventHandler(pyinotify.ProcessEvent):
    def process_IN_OPEN(self, event):
        self.rebuild(event)
    def rebuild(self, event):
        if (event.dir == False) and (event.name == 'config.properties') :
            print "open config file"

def main():
    handler = EventHandler()
    notifier = pyinotify.Notifier(wm, handler)
    wdd = wm.add_watch('/opt/testconfig',mask, rec=True,auto_add=True )
    notifier.loop()

if __name__ == "__main__":
    main()

  最终测试结果。第一、配置文件是在服务启动时一次加载。第二、配置文件不能自动加载,修改完配置文件必须要重启服务。
  使用ConfigParser来做配置文件,自然非常方便,tornado重启速度很快,但是我还是希望能自动加载,因为在几百台服务的情况下,能自动加载自然比需要重启更方便。所以当前就是把配置直接写到代码中,然后找个文件记录配置位置。之后再研究一下能不能热重启。如果大家有好的办法也烦请请告诉我一声。