存档

文章标签 ‘command’

短信通知服务器运行状态

2010年1月14日
Comments Off

最近组上买了一台联想的 thinkcenter M8000t 做服务器,俺只好义不容辞的做管理员了(其实是我怂恿老板掏钱买滴,嘿嘿), 随时了解机器的运行状态是很重要的,当在有联网电脑的地方时还好说,但是如果你在外面而又想了解其运行状态的话就不好办咯。当然如果你的手机也能 ssh 的话就当俺没说(我可没那么高级的手机),手机虽然是次点,不过好歹能收短信吧,主意来了: 用短信收取服务器的运行状态。

说到用短信收机器信息,可能很多童鞋会想到用飞信,但是由于我前些时候写了个短信控制电脑的半成品,就不再用飞信了,我可不想做重复的工作。我就查有没有能短信通知的邮箱呢?还真有,这不,移动居然可以把手机号当成其139邮箱的用户名,而且支持邮件到达短信通知,赶紧给开通了。万事具备,开工。

我想知道的服务器信息包括 cpu 温度, 硬盘温度, 网络速度, 负载等, 其中 cpu 温度可以用 lm_sensors 来监控, 硬盘温度用 hddtemp 来监控,网络总流量可以用 cat /proc/net/dev 获取,除以时间间隔就可以得到速度,而负载就简单的一个 uptime 命令即可。

操作:

首先装上 lm_sensors 和 hddtemp, 然后启动两个服务 (arch下在这里: /etc/rc.d/sensors 和 /etc/rc.d/hddtemp) 只有启动了这两个服务才可以随时获取其提供的信息。hddtemp 提供了网络接口,可以用 netcat 查询 7634 端口获得硬盘信息,下面我写了个小 bash 脚本来集中获取所需信息,代码如下:

server_stat.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash
 
# Name:     server_stat.sh
# Author:   xiooli <xioooli[at]yahoo.com.cn>
# Site:     http://joolix.com
# Licence:  GPLv3
# Version:  100113
 
 
stat() {
	sensors | grep Core | awk '{print $1, $2, $3}' | tr -d '+'
	netcat localhost 7634 | awk -F'|' '{print $2":"$4" 度"}'
	[ -f /tmp/net-stat ] || :> /tmp/net-stat
	net_last="$(cat /tmp/net-stat)"
	net_crt="$(cat /proc/net/dev | grep eth0 | awk -F"[: ]" '{print $4,$6}')"
	crt_time="$(date +%s)"
	echo "$net_crt $crt_time" > /tmp/net-stat
	[ "$net_last" ] && {
		last_in="$(awk '{print $1}' <<< "$net_last")"
		last_out="$(awk '{print $2}' <<< "$net_last")"
		last_time="$(awk '{print $3}' <<< "$net_last")"
		crt_in="$(awk '{print $1}' <<< "$net_crt")"
		crt_out="$(awk '{print $2}' <<< "$net_crt")"
		gap="$(($crt_time-$last_time))"
		speed_in="$(bc -l <<< "scale=4;($crt_in-$last_in)/($gap*1024)")"
		speed_out="$(bc -l <<< "scale=4;($crt_out-$last_out)/($gap*1024)")"
		echo -e "speed out:$speed_out k/s\nspeed in:$speed_in k/s"
	}
	uptime
}
 
send_ok=0
s="`stat | tr '\n' '|' | sed 's|°C| 度|g' | iconv -f utf-8 -t gbk -c`"
while [ "$send_ok" = "0" -a "$s" ]; do
	python "`dirname $0`/mailnotify.py" "$s"
	[ "$?" = "0" ] && send_ok=1
	sleep 10
done

这个脚本调用了一个叫 mailnotify.py 的 python 脚本来发送邮件(当然你也可以用其他的命令行的邮件客户端)

mailnotify.py (ps: 此脚本极不规范,凑合能用而已)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name:     mailnotify.py
# Author:   xiooli <xioooli[at]yahoo.com.cn>
# Site:     http://joolix.com
# Licence:  GPLv3
# Version:  100113
 
'''发送信息到某邮箱,可以用着定时获取服务器的状态(139 邮箱支持邮件短信提醒)'''
 
import smtplib, os, time, sys
 
def send():
    smtp = 'smtp.139.com' # 可以到信短信提醒的邮件服务器 smtp 地址, 这里用 139 的
    from_ = 'status <status@xx-server>' #这样写收到的短信第一行才不会只是个[]
    to = 'xxx@139.com' # 你想发送到的账户(邮件到此账户即发送短信提醒,所以用你手机号绑定的那个账户)
    user = 'xxx' # 用户名
    password = 'yyy' # 密码
    subject = 'status of np-server ' + time.strftime('%Y-%m-%d %H:%M', time.localtime()) # 这里可以定义邮件的标题
    text = sys.argv[1].replace("|", "\r\n") #从命令行收到的信件文本,换行替换成 |, 在此地复原
 
    msg='To: ' + to + '\r\nFrom: ' + from_ + '\r\nSubject: ' + subject + '\r\n\r\n' + text
 
    s = smtplib.SMTP(smtp)
    login_stat = s.login(user, password)
    if login_stat[0] == 235:
        send_stat = s.sendmail(to, to, msg) # 之所以发件账户和收件账户一致是为了不用两个不同的邮箱,这里相当于是自己给自己发邮件,而收到自己发的邮件以后又会短信到你的手机,目的达到
        if not send_stat:
            return 0
    else:
        return 1
 
send()

然后编辑 cron 任务将命令指向 server_stat.sh 按时发送运行状态。

ps:其实你也可以将获取的新闻之类的东西按时短信给你,这在外地(比如山区)等不能上网的地方是个不错的获取实时信息的好方法诶,呵呵。

Script ,

用 python 生成和解码二维码图片

2010年1月4日

了解了一下二维码的一些知识,感到很神奇哈,指甲盖那么大一块的二维码居然可以存放 500 多个汉字,呵呵如果书籍这样印刷的话是不是要少用些纸张呢? 这个东西据说在现实中用处还挺大的,很多手机都支持拍摄和解读二维码,并且很多人把自己的个人信息也放在里面,印一张包含自己各种信息的二维码图片的名片是不是很酷呢?呵呵,鉴于可能有此需要,我就试着找了一下看看有没有什么 python 的二维码 lib,嘿嘿,还真有,pyqrcodec 就是这样一个 python lib,archlinux 下用 yaourt -S pyqrcodec 就可以安装,其他发行版的可能类似,就不详述了。

看了一下 pyqrcodec 的文档,用法其实很简单,xiooli 顺手写了一个小脚本,实现了 QR 二维码图片的生成和解码,下面是一张例图:
a
生成这张例图的命令和解码的命令如下:

xiooli@XIOOLI> python qrcode.py -e "hello,大家好,我是 xiooli!" ./a.png 
generated file: ./a.png
xiooli@XIOOLI> python qrcode.py -d ./a.png
QR_IMAGEREADER_DECODED, QR_FORMATINFO_UNRECOVERABLE,
get text: hello,大家好,我是 xiooli!

qrcode.py 的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name:     qrcode.py
# Author:   xiooli <xioooli[at]yahoo.com.cn>
# Site:     http://joolix.com
# Licence:  GPLv3
# Version:  100104
 
'''generate and decode qrcode pictures'''
 
import PyQrcodec as pqr
import sys
 
def gen_qrpic(text, file):
    '''generate a qrcode file contains the given text'''
    stat, img = pqr.encode(text)
    if stat:
        img.save(file)
        return file
    else:
        print "failed to generate qrcode picture."
def qrdecode(file):
    '''decode the qrcode picture'''
    stat, text = pqr.decode(file)
    if stat:
        return text
    else:
        print "failed to decode the qrcode picture."
 
if __name__ == "__main__":
    args = sys.argv
    if len(args) == 1 or args[1] == '-h' or args[1] == '--help':
        print "encode: " + args[0] + " -e [text] [image file]"
        print "decode: " + args[0] + " -d [imgae file]"
    elif args[1] == '-e':
        try:
            print "generated file: " + gen_qrpic(args[2],args[3])
        except:
            pass
    elif args[1] == '-d':
        try:
            print "get text: " + qrdecode(args[2])
        except:
            pass
    else:
        print 'unrecoded arguments'

想为自己名片加上二维码信息的童鞋们不用愁咯,^^

Script , ,

翻箱淘到的在线翻译脚本

2009年12月28日
Comments Off

偶尔清理我的个人可执行目录($HOME/.bin)发现了远古时代写的一个翻译脚本,牵出来遛了一遛,还可以用哈,嘿嘿,顺手给改了几下,添加了以下一些特性:

1) deamon 化(直接进后台了,不必老开着一个终端跑)
2) 三种显示方式:kdialog,notify-send 和 gnome-osd
3) 脚本名加 -k 参数剋掉后台进程

露脸一下:
dic_sh

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/bin/bash
 
# Name:     dic.sh
# Author:   xiooli <xioooli[at]yahoo.com.cn>
# Site:     http://joolix.com
# Licence:  GPLv3
# Version:  091228
 
timeout=10
 
trans() {
	str="`xsel`"
	while true ; do
	  a="`xsel`"
	  if [ "$a" != "$str" ] ; then
		str="$a"
		[ ${#a} -lt 15 ] && word="`w3m -dump -no-cookie http://dict.cn/mini.php?q="$a" \
		| sed -e '$d' -e 's/</ /g' -e 's/>/ /g'`"
		if [ "`which gnome-osd-client 2>/dev/null`" ]; then
			gnome-osd-client -f "<message id='word' osd_fake_translucent_bg='off' \
			osd_vposition='top' osd_halignment='right' animations='on' hide_timeout='10000'>\
			<span size='15000' foreground='pink'>`echo "$word"`</span></message>"
		elif [ "`which kdialog 2>/dev/null`" ]; then
			kdialog --passivepopup "$word" "${timeout:-5}" &>/dev/null
		elif [ "`which notify-send 2>/dev/null`" ]; then
			timeout=${timeout:-5}
			timeout=$((timeout*1000))
			notify-send -t "$timeout" "$word"
		fi
	  fi
	  sleep 1
	done
}
 
# daemonize
if [ "x$1" != "x--" -a "x$1" != "x-k"  -a "x$1" != "x-h" ]; then
	if [ ! "`cat /tmp/dic.pid 2>/dev/null`" ]; then
		"$0" -- 1> /dev/null 2> /dev/null &
		exit 0
	else
		echo "dic is running."
		exit 0
	fi
elif [ "x$1" = "x-k" ]; then
	pic_pid="`cat /tmp/dic.pid 2>/dev/null`"
	if [ "$pic_pid" ]; then
		kill -9 "$pic_pid" 2>/dev/null
		rm /tmp/dic.pid 2>/dev/null
		echo "dic process is terminated."
	else
		echo "no dic process is running."
	fi
	exit 0
elif [ "x$1" = "x-h" ]; then
	nm="`basename $0`"
	echo -e "$nm: run\n$nm -k: kill daemon\n$nm -h: show help"
	exit 0
fi
 
echo $$ > /tmp/dic.pid
trans

Script , , ,

shc “编译” bash 脚本的漏洞?

2009年12月28日

简介
shc 是一个能够将 bash 脚本“编译”成可执行程序的程序。
安装:
arch 下 yaourt -S shc 即可
用法:
shc -f your_script.sh

更详细的用法可以man之。运行之后会在当前目录下生成一个 your_cript.sh.c 的 c 源文件和一个 your_cript.sh.x 的可执行文件。

在 google 了 shc 之后发现很多童鞋用这个来加密自己的 bash 脚本,到底这个东东能不能加密你的脚本呢? 乍一看似乎是可以滴,但是经过 xiooli 童鞋摸啊捏阿的偶然发现这个东东的一个破绽,那就是,从 ps 的输出上是可以看到你脚本的源代码滴(连注释都不放过哦),下面来做个实验:
编写一个脚本:

1
2
3
4
5
cat test.sh
#!/bin/bash
# this is a test bash script
echo 'You can not see me.'
read anything

然后用 shc 将其编译成二进制程序:

shc -r -f test.sh

运行之:

./test.sh.x

另一个终端运行 ps:

1
2
3
4
ps -ef|grep test.sh.x
xiooli   24822 20812  0 00:46 pts/2    00:00:00 ./test.sh.x -c
#!/bin/bash?# this is a test bash script?echo 'You can not see me.'?read a
xiooli   24779 20416  0 00:35 pts/4    00:00:00 grep test.sh.x

哈哈,现原型了哦,试过了一个很复杂的 bash 脚本,仍然是能够看到那一大堆源码滴,虽然看起来有点乱,不过仔细瞧还是能瞧明白的,所以如果你要想用 shc 来加密你的 bash 脚本的话,还是早点打消这个念头吧。

Script , ,

pyinstaller 将 python 脚本打包成可执行程序

2009年12月27日

有些时候在需要将 python 写的程序部署到没有 python 运行环境的机器上的时候很麻烦,尤其是对方又不想安装 python 的时候更是如此,这时候将 python 脚本包装成可执行文件就是一个很好的解决方案。事实上有很多东西能做这个工作,常见的有 py2exe,freeze.py,pyinstaller 等,py2exe 貌似只支持 win,freeze.py 传说是将python 程序的字节码转换成 c 再编译的,这个我试了一下,转换命令行脚本时没啥问题,但是在转换一个简单的 pyqt 程序的时候,转换出来的程序不能正常运行。转向 pyinstaller, 这个就没问题了,在 linux 下和 win 下均能正确转换 pyqt 的程序。你可以在 http://www.pyinstaller.org/ 下载得到,按照 REDADME.txt 操作即可。

常用的参数(– 是两个 -):

–onefile 打包成单一文件

–onedir 制作出的文件放在同一个目录下(默认值)

–tk 包含TCL/TK的相关文件。

–windowed 制作窗口程序。(程序执行时不会有文字窗口出现,仅限 windows)

–console 制作一般的console程序。

–upx 使用UPX压缩程序。

–icon= 指定程序的图标(貌似我没有弄成功)。

–version= 指定程序的版本信息(信息写在 FILE 里面)。

–name= 指定程序的名称。若无此选项,则使用主脚本的名称。

为方便使用,我写了一个小 bash 脚本(pyinstaller.sh),用法:
pyinstaller.sh /path/to/your_script.py
代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
 
# Name:     pyinstaller.sh
# Author:   xiooli <xioooli[at]yahoo.com.cn>
# Site:     http://joolix.com
# Licence:  GPLv3
# Version:  091227
 
pyinstaller_path="/home/xiooli/Projects/pinstaller/trunk"
makespec="$pyinstaller_path/Makespec.py"
build="$pyinstaller_path/Build.py"
 
if [ "$1" ]; then
	app="`basename $1`"
	spec_dir=${app/.*}
	[ -d "$spec_dir" ] || mkdir -p "$spec_dir"
	read -p "输入额外参数:" arg
	python "$makespec" -c -o "$spec_dir" $arg $1
	python "$build" "$spec_dir/$spec_dir.spec"
fi

ps: 在 win 下弄出的程序咋要比 linux 下的小呢,囧。

Script , ,

获取所有符合条件分子式的脚本

2009年12月24日
Comments Off

在某些时候我们只知道某一个分子的分子量和大概的碳氢氧的个数范围,在这种情况下要算出符合这些条件的分子式,用手工的方法算是很麻烦的,于是就有了下面的这个脚本,其特点是:
1) 全面,无漏网之鱼
2) 用了不饱和度检测,不饱和度不正常的(如为小数)分子式均被排除
3) python 写的,可跨平台使用。

例子:

xiooli@XIOOLI> python  .bin/fmcom.py
Please input: 173 c,8,18 h,0,20 o,0,10 n,0,6
The results are as follows:
MF: C8H3O2N3   Ω: 9
MF: C8H7N5     Ω: 8
MF: C8H15O3N   Ω: 2
MF: C8H19ON3   Ω: 1
MF: C9H3O3N    Ω: 9
MF: C9H7ON3    Ω: 8
MF: C9H19O2N   Ω: 1
MF: C10H7O2N   Ω: 8
MF: C10H11N3   Ω: 7
MF: C11H11ON   Ω: 7
MF: C12H15N    Ω: 6
MF: C13H3N     Ω: 13

说明一下: 173 c,8,18 h,0,20 o,0,10
这里 173 是分子量, 后边的表达式都是一样的如:c,8,18 表示 碳原子 个数范围为 8 到 18。
注意分隔符是英文逗号。

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name:     fmcom.py
# Author:   xiooli <xioooli[at]yahoo.com.cn>
# Site:     http://joolix.com
# Licence:  GPLv3
# Version:  091224
 
'''compute out the formula of a given molecular weight'''
 
import sys
 
# dictionary for the elements: { 'element': (atomic weight, omiga factor)
edic = { 'C': (12, 1),
        'H': (1, -0.5),
        'O': (16, 0),
        'N': (14, 0.5)
        }
 
args = sys.argv
 
def gen_formula(args):
    '''Main function for generating the formula'''
 
    mw = args[0]
    e_info = []
    formula = ''
    omiga = ''
    fors = ''
    ifs =''
 
    E = lambda x, y: (y==0 and ' ') or (y==1 and x.upper()) or x.upper() + str(y)
    L = lambda x, y: (x, len(x), y)
 
    for tmp in args[1:]:
        e_info.append(tmp.split(','))
        element, num1, num2 = tmp.split(',')
        element = element.upper()
        formula += 'E("' + str(element) + '",' + element + ') + '
        fors += ' for ' + element + ' in range(' + num1 + ',' + num2 + ') '
        ifs += str(edic[element][0]) + '*' + element + ' + '
        omiga += str(edic[element][1]) + '*' + element + ' + '
 
    formula = formula.strip('+ ')
    omiga += '1'
    ifs = ifs.strip('+ ')
 
    cmd = '[ L((' + formula + ').replace(\' \',\'\'), ' + omiga + ')' + fors + \
            'if ' + ifs + ' == ' + mw + ' and int(' + omiga + ') == ' + omiga + ']'
    l = eval(cmd)
 
    if l:
        print 'The results are as follows:'
        for f in l:
            str_omiga = str(int(f[2]))
            print 'MF: ' + f[0] + ('Ω: ' + str_omiga).rjust(15 - f[1] + len(str_omiga))
    else:
        print 'No suitable molecular formula found.'
 
if __name__ == '__main__':
    if len(args) <= 1:
        input = raw_input('Please input: ')
        args = input.split(' ')
        gen_formula(args)
    elif args[1] == '-h' or args[1] == '--help':
        print args[0] + ' [molecular weight] [element1, least, most] [element2, least, most] ...'
    else:
        gen_formula(args[1:])

Chemistry, Script , ,

Bash matrix 脚本

2009年12月18日

RT
根据骨头兄滴大作改编。
matrix

代码(单行):

p(){printf "\033[%d;%dH\033[32m%c\033[m" $1 $2 "$3"};clear;N=20;for i in `seq 1 $N 2`; do x[$i]=$((RANDOM%LINES+1));y[$i]=$((RANDOM%COLUMNS+1));done;chars=({0..9} {a..z} {A..Z} '*' '&' '^' '%' '$' '#' '@' '~' '<' '>' '?' '+');while :; do for i in `seq $N`;do ran_char=${chars[$RANDOM % ${#chars[@]}]};p ${x[$i]} ${y[$i]} $ran_char;((x[$i]++));if [ ${x[$i]} -ge $LINES ]; then for j in `seq $LINES`;do p $j ${y[$i]} " ";done;x[$i]=$((RANDOM%LINES+1));y[$i]=$((RANDOM%COLUMNS+1));fi;done;sleep .02;done

代码(多行, 多行代码须用 . script.sh 的方式运行,不然会出错)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
p(){
	printf "\033[%d;%dH\033[32m%c\033[m" $1 $2 "$3"
}
clear
N=20
for i in `seq 1 $N 2`; do
	x[$i]=$((RANDOM%LINES+1))
	y[$i]=$((RANDOM%COLUMNS+1))
done
 
chars=({0..9} {a..z} {A..Z} '*' '&' '^' '%' '$' '#' '@' '~' '<' '>' '?' '+')
while :; do
	for i in `seq $N`; do
		ran_char=${chars[$RANDOM % ${#chars[@]}]}
		p ${x[$i]} ${y[$i]} $ran_char
		((x[$i]++))
		if [ ${x[$i]} -ge $LINES ]; then
			for j in `seq $LINES`; do
				p $j ${y[$i]} " "
			done
			x[$i]=$((RANDOM%LINES+1))
			y[$i]=$((RANDOM%COLUMNS+1))
		fi
	done
	sleep .02
done

Script , ,

pyqt 的溶剂比例计算器 snail

2009年11月10日

RT
开始做植化了,要用,鑫哥的那个是 for win 的,以前写了个 ruby-gtk 的不知道扔哪里去了,于是重新写了个 pyqt 的。

ps: 图形界面的程序真是浪费表情阿,真正干活的就两三行,一旦要图形界面了就几百行,这个看来是死要面子(图形界面)活受罪的真实写照阿,呵呵。

片片:
snail 抓图

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/python
# -*- coding: utf-8 -*-
 
# Form implementation generated from reading ui file 'snail.ui'
#
# Created: Tue Nov 10 17:44:47 2009
#      by: PyQt4 UI code generator 4.6.1
#
# WARNING! All changes made in this file will be lost!
 
import sys, os
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QMainWindow
from PyQt4.QtCore import pyqtSignature
 
class Ui_mainWindow(object):
    def setupUi(self, mainWindow):
        mainWindow.setObjectName("mainWindow")
        mainWindow.resize(767, 375)
        self.centralwidget = QtGui.QWidget(mainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.textEdit = QtGui.QTextEdit(self.centralwidget)
        self.textEdit.setGeometry(QtCore.QRect(170, 90, 171, 51))
        self.textEdit.setStyleSheet("font: 22pt \"Bitstream Vera Sans Mono\";")
        self.textEdit.setObjectName("textEdit")
        self.textEdit_2 = QtGui.QTextEdit(self.centralwidget)
        self.textEdit_2.setGeometry(QtCore.QRect(380, 90, 171, 51))
        self.textEdit_2.setStyleSheet("font: 22pt \"Bitstream Vera Sans Mono\";")
        self.textEdit_2.setObjectName("textEdit_2")
        self.textEdit_3 = QtGui.QTextEdit(self.centralwidget)
        self.textEdit_3.setGeometry(QtCore.QRect(590, 90, 161, 51))
        self.textEdit_3.setStyleSheet("font: 22pt \"Bitstream Vera Sans Mono\";")
        self.textEdit_3.setObjectName("textEdit_3")
        self.textEdit_4 = QtGui.QTextEdit(self.centralwidget)
        self.textEdit_4.setGeometry(QtCore.QRect(170, 180, 171, 51))
        self.textEdit_4.setStyleSheet("font: 22pt \"Bitstream Vera Sans Mono\";")
        self.textEdit_4.setObjectName("textEdit_4")
        self.textEdit_5 = QtGui.QTextEdit(self.centralwidget)
        self.textEdit_5.setGeometry(QtCore.QRect(380, 180, 171, 51))
        self.textEdit_5.setStyleSheet("font: 22pt \"Bitstream Vera Sans Mono\";")
        self.textEdit_5.setObjectName("textEdit_5")
        self.label = QtGui.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(200, 20, 131, 41))
        self.label.setStyleSheet("font: 26pt \"Bitstream Vera Sans Mono\"; 溶剂 A")
        self.label.setObjectName("label")
        self.label_2 = QtGui.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(410, 20, 131, 41))
        self.label_2.setStyleSheet("font: 26pt \"Bitstream Vera Sans Mono\"; 溶剂 A")
        self.label_2.setObjectName("label_2")
        self.label_3 = QtGui.QLabel(self.centralwidget)
        self.label_3.setGeometry(QtCore.QRect(630, 20, 131, 41))
        self.label_3.setStyleSheet("font: 26pt \"Bitstream Vera Sans Mono\"; 溶剂 A")
        self.label_3.setObjectName("label_3")
        self.label_4 = QtGui.QLabel(self.centralwidget)
        self.label_4.setGeometry(QtCore.QRect(20, 90, 151, 41))
        self.label_4.setStyleSheet("font: 26pt \"Bitstream Vera Sans Mono\"; 溶剂 A")
        self.label_4.setObjectName("label_4")
        self.label_5 = QtGui.QLabel(self.centralwidget)
        self.label_5.setGeometry(QtCore.QRect(20, 190, 151, 41))
        self.label_5.setStyleSheet("font: 26pt \"Bitstream Vera Sans Mono\"; 溶剂 A")
        self.label_5.setObjectName("label_5")
        self.pushButton = QtGui.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(590, 180, 161, 51))
        self.pushButton.setStyleSheet("font: 20pt \"Bitstream Vera Sans Mono\";")
        self.pushButton.setObjectName("pushButton")
        self.label_6 = QtGui.QLabel(self.centralwidget)
        self.label_6.setGeometry(QtCore.QRect(30, 270, 721, 71))
        self.label_6.setStyleSheet("""font: 22pt \"Bitstream Vera Sans Mono\"; color: rgb(0, 0, 255);""")
        self.label_6.setObjectName("label_6")
        self.frame = QtGui.QFrame(self.centralwidget)
        self.frame.setEnabled(True)
        self.frame.setGeometry(QtCore.QRect(20, 260, 731, 91))
        self.frame.setMouseTracking(False)
        self.frame.setAutoFillBackground(False)
        self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtGui.QFrame.Raised)
        self.frame.setObjectName("frame")
        mainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(mainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 767, 25))
        self.menubar.setObjectName("menubar")
        mainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(mainWindow)
        self.statusbar.setObjectName("statusbar")
        mainWindow.setStatusBar(self.statusbar)
 
        self.retranslateUi(mainWindow)
        #QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.label_6.)
        QtCore.QMetaObject.connectSlotsByName(mainWindow)
 
    def retranslateUi(self, mainWindow):
        mainWindow.setWindowTitle(QtGui.QApplication.translate("mainWindow", "溶剂比例计算器 -Snail", None, QtGui.QApplication.UnicodeUTF8))
        self.textEdit_3.setHtml(QtGui.QApplication.translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Bitstream Vera Sans Mono\'; font-size:22pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">1000</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
        self.label.setText(QtGui.QApplication.translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Bitstream Vera Sans Mono\'; font-size:26pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">溶剂 A</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
        self.label_2.setText(QtGui.QApplication.translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Bitstream Vera Sans Mono\'; font-size:26pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">溶剂 B</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
        self.label_3.setText(QtGui.QApplication.translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Bitstream Vera Sans Mono\'; font-size:26pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">体积</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
        self.label_4.setText(QtGui.QApplication.translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Bitstream Vera Sans Mono\'; font-size:26pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">现有溶液</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
        self.label_5.setText(QtGui.QApplication.translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Bitstream Vera Sans Mono\'; font-size:26pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">欲配溶液</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButton.setText(QtGui.QApplication.translate("mainWindow", "也来算一个!", None, QtGui.QApplication.UnicodeUTF8))
        self.label_6.setText(QtGui.QApplication.translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Bitstream Vera Sans Mono\'; font-size:22pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">欢迎使用溶剂比例计算器 Snail</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Xiooli &lt;xioooli@yahoo.com.cn&gt;</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
 
 
 
class Win(QMainWindow, Ui_mainWindow):
    def __init__(self, parent = None):
        QMainWindow.__init__(self, parent)
        self.setupUi(self)
    @pyqtSignature("")
    def on_pushButton_clicked(self):
        self.label_6_txt = ""
        try:
            now_A = float(self.textEdit.toPlainText())
            now_B = float(self.textEdit_2.toPlainText())
            now_vol = float(self.textEdit_3.toPlainText())
            want_A = float(self.textEdit_4.toPlainText())
            want_B = float(self.textEdit_5.toPlainText())
        except ValueError:
           self.label_6_txt = "错误:有输入框未输入数字,或输入了非数字字符!"
 
        if not self.label_6_txt:
            if want_A*(now_A+now_B) == 0 or want_B*(now_A+now_B) == 0:
                self.label_6_txt = "错误:试图除零!"
            elif now_A / now_B > want_A / want_B:
                vol,rst=self.textEdit_3.toPlainText(),\
                        str(round(now_vol*now_A*(want_A+want_B)/(want_A*(now_A+now_B))-now_vol,4))
                self.label_6_txt = "须向 " + vol + " ML 现有溶液中加入溶液 B " + rst + " ML"
            elif now_A / now_B == want_A / want_B:
                self.label_6_txt = "现有溶液和欲配溶液是同一种溶液,无须额外动作。"
            else:
                vol,rst=self.textEdit_3.toPlainText(),\
                        str(round(now_vol*now_B*(want_A+want_B)/(want_B*(now_A+now_B))-now_vol,4))
                self.label_6_txt = "须向 " + vol + " ML 现有溶液中加入溶液 A " + rst + " ML"
        self.label_6.setText(QtGui.QApplication.translate("mainWindow", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'Bitstream Vera Sans Mono\'; font-size:22pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">"+self.label_6_txt+"</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
 
 
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    win=Win()
    win.show()
    sys.exit(app.exec_())

Chemistry, Script , , ,

Firefox下直接观看PPS看看

2009年10月16日
Comments Off

ubuntu论坛牛人写了pps的totem插件,可以用于观看pps的节目,具体安装方法debian系的参考http://forum.ubuntu.org.cn/viewtopic.php?f=74&t=223582
archlinux用以下命令即可安装:

yaourt -S libppswrapper-git gst-plugins-pps-git totem-pps-git libpps gst-plugins-sopcast-git totem-sopcast-git

但是这样只可以在totem的窗口里面看,当然也可以点击pps看看节目右边的客户端播放,然后将其关联到totem,但是总离不了一个独立的totem窗口,于是我们的 Hello World 童鞋在自我需求的推动下写了一个greasemonkey脚本,让其可直接在frefox的窗口下播放pps看看(当然是调用totem-pps的)。

要正常使用这个油猴脚本,你需要满足几个基本条件:
1) 能正常使用的totem-pps
2) totem-plugin(arch下的包名字,其他distro.里面自己找找吧)
3) firefox 安装并启用 greasemonkey

一切就绪以后你就可以去pps上面踢馆咯,哈哈!

greasemonkey 脚本从这里下载:http://forum.ubuntu.org.cn/download/file.php?id=80735,解压后拖到firefox的窗口里面进行安装。

秀图一张:
pps-in-ff

Script , , , ,

植化流程图生成脚本

2009年9月9日

RT
做植化的同学写报告的时候常常要画分离的流程图,以往大家都是拖啊拖啊的,看起来就恼火,于是就写了这样一个脚本(以后我也要画这种东西嘛),可以将简单的描述语言直接生成流程图,比如,如下的语言就可以生成如下的图:

a#草药样品
b#粗分浸膏
a#$甲醇提取=>b#
c1#正丁醇相
c2#石油醚相
c3#…
c4#水相
b#^$有机溶剂萃取
b#=>c1#
b#=>c2#
b#=>c3#
b#=>c4#
c2#^$继续柱层析分离
c2#=>d1#成分五
c2#=>d2#成分六

生成的流程图

该描述语言语法非常简单:
#前面是 node 的名字,$后面是描述,=> 将两个 node 连接起来,在其中画箭头,可以连续连接 比如 a# => b# => c# 也是可以的,node 后面 => 前面的 $xxx 是线上的注释,如果某一个点要往下分支的话只需用 node#^ 即可,node#^ 后面可以直接加注释,很简单的,看上面那个例子结合图片就可以搞明白了。

运行该脚本需要 python-yapgvb,此脚本受弯弯同学脚本的启发并参考了部分代码(http://python.ubuntu.org.cn/viewtopic.php?f=162&t=180285&sid=e2ae53902848adb1d59c375bf2325043

使用方法:

python liuchengtu.py -o xxx.png deffile

还有很多个性化选项,请参考源码。

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
# Author: xioooli<at>yahoo.com.cn,joolix.com
# Licence GPLv2
# Version 2009.09.09
 
import sys
import yapgvb
import optparse
 
FORMATS = {"png" : yapgvb.formats.png,
        "jpg" : yapgvb.formats.jpg,
        "gif" : yapgvb.formats.gif}
ENGINES = {"dot" : yapgvb.engines.dot,
        "neato" : yapgvb.engines.neato,
        "circo" : yapgvb.engines.circo,
        "twopi" : yapgvb.engines.twopi}
 
if __name__ == '__main__':
#    args = sys.argv
#    if len(args) < 2:
#        print "Usage: python state_machine.py <def file>"
#        sys.exit(0)
 
    parser = optparse.OptionParser()
    parser.add_option("-f", "--format", dest="format",
            help="store the flow chart in FORMAT (png, svg, jpg, gif)",
            metavar="FORMAT", default="png")
    parser.add_option("-o", "--output", dest="output",
            help="save the flow chart to FILE",
            metavar="FILE")
    parser.add_option("-e", "--engine", dest="engine",
            help="the layout ENGINE to use for the flow chart (dot, neato, circo, twopi)",
            metavar="ENGINE", default="dot")
    parser.add_option("-c", "--color", dest="fillcolor",
            help="the fillcolor of the node",
            default="white")
    parser.add_option("--fs", "--font-size", dest="fontsize",
            help="the font size of the text",
            default="12")
    parser.add_option("--nfc", "--node-font-color", dest="nodefontcolor",
            help="the fillcolor of the font in node",
            default="black")
    parser.add_option("--nc", "--node-color", dest="nodecolor",
            help="the color of the node frame",
            default="black")
    parser.add_option("--ec", "--edge-color", dest="edgecolor",
            help="the color of the edge",
            default="black")
    parser.add_option("--efc", "--edge-font-color", dest="edgefontcolor",
            help="the font color of the edge text",
            default="black")
    parser.add_option("-s", "--style", dest="style",
            help="the style of the node",
            default="filled")
    parser.add_option("--ah", "--arrowhead", dest="arrowhead",
            help="the style of the arrowhead",
            default="normal")
    parser.add_option("--as", "--arrowsize", dest="arrowsize",
            help="the size of the arrow",
            default=1)
    parser.add_option("--ns", "--nodesep", dest="nodesep",
            help="the sepration between two nodes",
            default=.5)
    parser.add_option("--sp", "--shape", dest="shape",
            help="the shape of the node",
            default="box")
 
    options, args = parser.parse_args()
    if len(args) < 1:
        parser.print_usage()
        sys.exit(0)
 
    graph = yapgvb.Graph("States")
    graph.rankdir="TB"
    graph.nodesep=options.nodesep
    node_dict = {}
 
    with open(args[0]) as def_file:
        lines = [l.strip() for l in def_file.readlines()]
        for line in lines:
            nodes = line.split("=>")
            prev_node = None
            for node in nodes[::-1]:
                label = node.strip().split("#")
                if not node_dict.has_key(label[0]) and label[0] != "":
                    try:
                        lb=label[1].split("$")[0]
                    except:
                        lb=""
                    node_in_graph = graph.add_node(label=lb,
                            shape=options.shape, fillcolor=options.fillcolor,
                            fontcolor=options.nodefontcolor, fontsize=options.fontsize,
                            style=options.style, color=options.nodecolor, width=0.5)
                    node_dict[label[0]] = node_in_graph
                elif label[0] != "":
                    node_in_graph = node_dict[label[0]]
 
                try:
                       blanknode = node.strip().split("#^")
                       if len(blanknode) >= 2:
                           blanknode = blanknode[0]
                       else:
                           blanknode = ""
                except:
                       blanknode = ""
                if node_dict.has_key(blanknode) and blanknode != "":
                    node_dict[blanknode + "_0"] = node_dict[blanknode]
                    node_in_graph = graph.add_node(label="",     
                            shape="circle", fillcolor=options.edgecolor,
                            color=options.edgecolor, style="filled", height=.05, width=.05)
                    node_dict[blanknode] = node_in_graph
                    edge = node_dict[blanknode + "_0"] - node_dict[blanknode]
                    edge.color=options.edgecolor
                    try:
                        edge.label=" "+node.strip().split("$")[1]
                        edge.fontcolor=options.edgefontcolor
                        edge.fontsize=options.fontsize
                    except:
                        pass
 
                if prev_node:
                    edge = node_in_graph - prev_node
                    edge.color=options.edgecolor
                    edge.arrowhead = options.arrowhead
                    edge.arrowsize = options.arrowsize
                    try:
                        edge.label=" "+node.strip().split("$")[1]
                        edge.fontcolor=options.edgefontcolor
                        edge.fontsize=options.fontsize
                    except:
                        pass
 
                prev_node = node_in_graph
 
    graph.layout(ENGINES[options.engine])
    format = FORMATS[options.format]
    if options.output:
        out_file = options.output
    else:
        out_file = args[0] + "." + format
 
    graph.render(out_file, format)

Chemistry, Script , , ,