I am LAZY bones ? all linux

分类: '编程相关' 的归档

欧拉工程

咳咳,我做为非正常网民网瘾戒除中心砖家,正式给介绍介绍一下这个欧拉工程
呃。。。还是请我们的校长──lerosua──来介绍吧~下面引自这篇博文

欧拉工程是一个用编程来解决一连串数学问题的项目。发现它对训练数学及编程挺有作用的。网上也有许多人做上面的题目并发布自己的算法。
上面共有261题,分几个等级,一级比一级难。我看了第261题的提交,目前只是22个。完成它绝对是时间及精力及耐力及智力的较量。
于是本人决定将此作为一个项目来做,逐步进阶。
骨头与xiooli同学也并肩作战。
我们解决的问题的源码将会发布在以下svn中。欢迎审阅.
http://nrciz.googlecode.com/svn/trunk/projecteuler

其实,之前(几个月前吧)我就已经做过几题了。可以说,正是因为欧拉工程,我才喜欢上python的,当我看到第一题用一句

sum([n for n in range(1000) if n%3==0 or n%5==0])

就完美地搞定了,是多么地流畅,多么地自然,我就喜欢上了这门语言~
我们现在已经在逐步把很多题目翻译成中文了,所以,大家有空就去这里看看吧~最好是大家都能参与到其中来哦~

神一样的Quine

有个很牛B的小日本搞出来的东西

# ruby
l=92.chr;eval s="s=s.dump[r=1..-2].gsub(/("+l*4+"){4,}(?!\")/){|t|'\"+l*%d+\"'%(t
.size/2)};5.times{s=s.dump[r]};puts\"# python\\nprint(\\\"# perl\\\\nprint(\\\\\\
\"# lua"+l*4+"nprint("+l*7+"\"(* ocaml *)"+l*8+"nprint_endline"+l*15+"\"-- haskel
l"+l*16+"nimport Data.List;import Data.Bits;import Data.Char;main=putStrLn("+l*31
+"\"/* C */"+l*32+"n#include<stdio.h>"+l*32+"nint main(void){char*s[501]={"+l*31+
"\"++intercalate"+l*31+"\","+l*31+"\"(c(tail(init(show("+l*31+"\"/* Java */"+l*32
+"npublic class QuineRelay{public static void main(String[]a){String[]s={"+l*31+"
\"++intercalate"+l*31+"\","+l*31+"\"(c("+l*31+"\"brainfuck"+l*64+"n++++++++[>++++
<-]+++++++++>>++++++++++"+l*31+"\"++(concat(snd(mapAccumL h 2("+l*31+"\"110"+l*31
+"\"++g(length s)++"+l*31+"\"22111211100111112021111102011112120012"+l*31+"\"++co
ncatMap("+l*32+"c->let d=ord c in if d<11then"+l*31+"\"21002"+l*31+"\"else"+l*31+
"\"111"+l*31+"\"++g d++"+l*31+"\"22102"+l*31+"\")s++"+l*31+"\"2100211101012021122
2211211101000120211021120221102111000110120211202"+l*31+"\"))))))++"+l*31+"\","+l
*63+"\""+l*64+"n"+l*63+"\"};int i=0;for(;i<94;i++)System.out.print(s[i]);}}"+l*31
+"\")))))++"+l*31+"\",0};int i=0;for(;s[i];i++)printf("+l*63+"\"%s"+l*63+"\",s[i]
);puts("+l*63+"\""+l*63+"\");return 0;}"+l*31+"\");c s=map("+l*32+"s->"+l*31+"\""
+l*63+"\""+l*31+"\"++s++"+l*31+"\""+l*63+"\""+l*31+"\")(unfoldr t s);t[]=Nothing;
t s=Just(splitAt(if length s>w&&s!!w=='"+l*31+"\"'then 501else w)s);w=500;f 0=Not
hing;f x=Just((if x`mod`2>0then '0'else '1'),x`div`2);g x= reverse (unfoldr f x);
h p c=let d=ord c-48in(d,replicate(abs(p-d))(if d<p then '<'else '>')++"+l*31+"\"
."+l*31+"\");s="+l*31+"\"# ruby"+l*32+"n"+l*31+"\"++"+l*31+"\"l=92.chr;eval s=\"+
(z=l*31)+\"\\\"\"+s+z+\"\\\""+l*31+"\"++"+l*31+"\""+l*32+"n"+l*31+"\""+l*15+"\""+
l*7+"\")"+l*4+"n\\\\\\\")\\\")\"########### (c) Yusuke Endoh, 2009 ###########\n"

这段ruby代码,相当牛,如作者所说,运行这段ruby,生成一段python代码,再运行python代码,生成一段perl代码,再运行perl代码,生成一段lua代码。。。这样一直下去,经过11种语言,最后。。。居然又能重新得到之前的ruby代码。。
这11种语言是:ruby 1.8.7-p72、Python 2.5.2、perl v5.10.0、Lua 5.0.3、OCaml 3.10.2、ghc-6.8.2、gcc 4.3.2、java “1.5.0_17″、beef 0.0.6-2、whitespace 0.3-2、unlambda 2.0.0-5。
est这里看到了介绍,实在忍不住,把所有解释器都装上验证了一把,果然是可以的。彻底无语了,特此把中间结果都打包放上来,供大家瞻仰。
ubuntu下也想自己试试的话,得确保有这些包: ruby lunar lua50 ocaml-interp ghc6 sun-java5-jdk beef whitespace unlambda

PS: 我以为 brainfuck 就已经很BT了,没想到还有更BT的 whitespace ,彻底无语了。

Bash其实也可以做CGI用

标题其实是“废话”。因为,其实稍微熟悉web原理的都知道,理论上,所有可执行的程序/脚本,都可以被server程序(例如apache/mini_httpd/lighttpd/nginx等)调用,只要能够输出HTML,都可以成功。
而这个用bash做CGI的想法,纯属闲着无聊的时候,瞎想出来的。不过有这个想法的,我肯定不是第一人,这里这里都有类似的描述。
不过,我这个Web From Scratch的过程还颇有点波折,试了蛮久才成功,就在此记录一下。
其实,说白了都是也就一句话:扩展名不能随意取。当然这个只是针对我这个主机的apache来说的,其他的server可能有其他的规则,暂且不做定论。
之前我一直把我的脚本文件名写成index.sh,结果怎么试都不行,后来无意中改成inedx.py(虽然里面还是#!/bin/bash开头的)居然就可以了,于是我就找到原因了,现在我改成个更通用的index.cgi了,哈哈。
另外关于.htaccess,由于自己也是一知半解,就不讨论了,有兴趣的话,可以看看这里,这里只贴下我用到的代码,可以把对此域名的任何路径的请求都让index.cgi来处理。

RewriteEngine on
DirectoryIndex index.cgi
RewriteCond %{REQUEST_URI} !(index.cgi)
RewriteRule ^(.*)$ index.cgi/$1 [L]

来看看我的bash,就是简单地输出服务器信息:

#!/bin/bash
 
#下面这两行头一定要有,不然可是会引发 500 Internal Server Error 错误的。
echo "Content-type: text/html"
echo ""
 
echo "<h1>Bash CGI works!</h1>"
env | while read line;do
	echo "<b>"
	echo "$line" | cut -d= -f 1
	echo "</b>=<i>"
	echo "$line" | cut -d= -f 2-
	echo "</i><br>"
done

最近几天,可以点击 http://hzlug.org/abc?xxx=yyy 观察这个脚本运行的效果,以后可以把这个地址做它用,嘿嘿。
可以看到 REDIRECT_URL 和 QUERY_STRING 这两个环境变量分别是路径和参数,这样理论上就可以用一个脚本来完成很复杂的功能了~
至于HZLUG到底会做成什么样子,还请大家多多提意见哦~

用python来收发邮件

由于python的模块很强大,用python来收发邮件,就显得很轻松了。
python不仅有email模块,还有专门处理popsmtp甚至imap的模块。
下面就来演示一下这几个的用法,先看看怎么用pop3和email模块来收邮件。

>>> import poplib
>>> p=poplib.POP3_SSL('pop.gmail.com')  #如果服务器不需要启用SSL,那么只需要用 poplib.POP3('xxx.com') 就好了。
>>> p.user('linuxcn.ibot')
'+OK send PASS'
>>> p.pass_('密码')
'+OK Welcome.'
>>> p.stat() #统计状态,返回一个元组,第一个表示几封邮件,第二个表示一共几个字节
(2, 4543)
>>> p.list() #返回每个邮件的状态
('+OK 2 messages (4543 bytes)', ['1 3679', '2 864'], 15)
>>> p.retr(2) #获取某个邮件的全文,这个邮件就是我自己给另一个测试账号发的邮件,元组里包含了邮件头和邮件的正文。
('+OK message follows', ['Delivere
...为了排版方便,此处有删节...
e--'], 869)
>>> mailsrc='\n'.join([l for l in p.retr(2)[1]])
>>> print mailsrc #如果上面还看不出啥的话,这样看应该就明显了。
Delivered-To: linuxcn.ibot@gmail.com
Received: by 10.216.47.83 with SMTP id s61cs422102web;
        Sat, 15 Aug 2009 07:58:32 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.114.180.16 with SMTP id c16mr2819847waf.57.1250348310512; Sat, 
	15 Aug 2009 07:58:30 -0700 (PDT)
Date: Sat, 15 Aug 2009 22:58:30 +0800
Message-ID: <ae14629e0908150758n49649527xf326b8c1a60f36bf@mail.gmail.com>
Subject: =?UTF-8?B?5rWL6K+V5Li76aKY?=
From: LLY <bones7456@gmail.com>
To: linuxcn.ibot@gmail.com
Content-Type: multipart/alternative; boundary=001636417e2fe4c3a904712f669e
 
--001636417e2fe4c3a904712f669e
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64
 
5rWL6K+V5q2j5paHCg==
--001636417e2fe4c3a904712f669e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: base64
 
5rWL6K+V5q2j5paHPGJyPgo=
--001636417e2fe4c3a904712f669e--
>>> p.quit() #收完邮件了,理论上是要退出一下的
'+OK Farewell.'
>>> import email #源码得到了,现在轮到email模块登场了
>>> e=email.message_from_string(mailsrc) #这个就可以把邮件源码转换成一个email的对象了。
>>> print e['subject'] #这个是编码后的主题
=?UTF-8?B?5rWL6K+V5Li76aKY?=
>>> print email.header.decode_header(e['subject'])[0][0] #这个是解码后的主题
测试主题
>>> e.get_payload() #获取当前email的有效部分,可以看到有这个邮件有两个部分,从上面的邮件源码,我们也可以得知,此邮件确实有text/plain 和 text/html 两部分
[<email.message.Message instance at 0xb751102c>, <email.message.Message instance at 0xb751172c>]
>>> e.get_payload(0) #获取有效部分的第一个,这个还是一个email对象的实例。
<email.message.Message instance at 0xb751102c>
>>> type(e)
<type 'instance'>
>>> type(e.get_payload(0))
<type 'instance'>
>>> import base64 #解码邮件正文还得用上base64模块
>>> print base64.decodestring(e.get_payload(0).get_payload()) #解码正文的第一部分
测试正文
 
>>> print base64.decodestring(e.get_payload(1).get_payload()) #解码正文的第二部分,是html,看来只多了个br而已,哈哈
测试正文<br>

当然,上面的例子只是最简单的,复杂的附件什么的,也可以用库里的相关函数一一搞定的。另外,看文档的意思,传了get_payload的第二个参数按理应该能自动调用base64模块解码的,但是不知道为什么,我没有试验成功,只能自己手工解了~
下面,再来看看怎么用smtp发邮件,如果是复杂的邮件,也需要建立一个email对象的实例,把正文/附件等一一放上去就好,但是作为演示,我们就用邮件的源码来发一个纯手工的,哈哈

>>> import smtplib #加载模块
>>> msg='To: linuxcn.ibot@gmail.com\r\nFrom: my@localhost\r\nSubject: test\r\n\r\nthis is msg body\r\n' #邮件的源码
>>> s=smtplib.SMTP('smtp.163.com') #同样这里也有SMTP_SSL,到底用什么要看服务器的设置
>>> s.login('bones7456','密码') #一般都要登录了,才能发邮件,login里提供两个参数,用户名和密码
(235, 'Authentication successful')
>>> s.sendmail('bones7456@163.com','linuxcn.ibot@gmail.com',msg) #发送邮件,三个参数分别是 from/to/msg,就这名简单就成功了。。
{}
>>> s.quit()
(421, 'closing transmission channel')

就这么几行,一封邮件就发出去了,够简单吧。。。更详细的内容就看官方文档吧~

JSON数据格式简介

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition – December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。
以上摘自JSON官方介绍,这个格式是如此地简单,以至于光看这篇官方文档就可以完全掌握了,而无须其他过多地介绍了。
最初看到这个JSON,是在twitter上,这种小交互量的场景很适合用JSON,比XML更轻巧些。今天,看到新闻,taobao也搞了个开放平台,里面也支持JSON和xml这两种格式,所以我觉得这个格式以后会越来越流行,特发此文关注下。

折腾py2exe

序: 恩,这个确实挺折腾的,几乎一个下午都在搞py2exe,加上晚上又搞了一会儿,总算勉强让gmbox的exe可执行文件运行起来了…

首先,为什么要折腾py2exe呢? 其实就是为了那个gmbox,在设计之初,我就让它打算跨平台支持windows的.为此我也折腾过windows的python运行环境.但是如果那样的话,有windows的朋友要用gmbox,就必须安装python、GTK+库、PyCairo、PyGObject和PyGTK,这可不是一般的烦.所以有市场就会有需求,像我这样的问题我肯定不是第一个遇到的.于是就有了py2exe.
py2exe实际上是python distutils的一个扩展,使用py2exe,你必需有一个windows的环境,安装了python和你程序用到的依赖包(例如gmbox的pygtk等),也就是说,在这个”开发环境”你要能够运行起你的程序,然后下载py2exe,安装到python的lib目录下,就可以用来生成目标exe文件了,以后你只要把生成的东西复制到其他windows的机器,就可以脱离python运行环境和库的依赖了.是不是很爽呢?
虽说网上都说py2exe用起来很简单,但是我还是折腾了不少时间,可能是因为gmbox比较特殊:同时有CLI和GUI,有图标和数据文件,有自己的lib库等,当然更可能是因为我太菜了…嘿嘿..
不管怎么说,在这里记一下折腾的步骤,也许可以让后人少走点弯路:

  1. 打包文件(gmbox的打包文件在这里,建议边参考代码,边看下面的内容)最好要和你的主程序文件放在同一目录下.我曾经试着把打包文件放在上级目录,结果在搜索依赖库的时候遇到了很多麻烦.
  2. 打包文件本身其实也是一个python的程序,虽然一般只有一个setup函数.此函数可以有 name,description,version,console,windows,options,data_files 等参数.
  3. 要生成一个或多个命令行的exe,setup需要一个List型的名为console参数,指名源py文件.
  4. 要生成一个或多个GUI的exe,setup需要一个List型的名为windows参数,指名源py文件.List的每项都可以有图标等选项,就是icon_resources哪里,图标也是个Tuple的List,但是windows一般只会显示出第一个图标,所以一个就够了.
  5. 如果你想用png文件直接当图标,那很可能会在生成exe的时候,引起python崩溃,所以还是赶紧转成ico吧
  6. 如果你和我一样,生成的GUI的exe文件,在执行的时候,报 ImportError: No module named cairo ,那最好在setup函数里加上options,里面有include cairo的选项.
  7. 如果你也有数据文件(比如glade文件,图片文件等),py2exe默认并不会帮你一起打包,你需要在setup函数中加传data_files参数.data_files需要是一个List,每项可以是直接指向数据文件的字符串,也可以是一个Tuple;如果是前者,数据文件会直接在生成的dist目录下面,如果是后者,Tuple的第一个元素是目标目录,第二个元素是是个源文件名的List,效果是把所有的源文件存放在dist下的指定的目标目录下.(呃,好长好拗口…)
  8. 在py2exe生成的环境中,__file__这个应用将失效,这个问题的解决方法可以参看这里.个人觉得Alternate Solution更加靠谱.
  9. 好了,现在如果你已经写好了打包文件(win_packer.py),也对源代码进行了应有的修改,你就可以执行 python win_packer.py py2exe 来生成exe了,执行此命令会在当前目录下多出一个 dist 目录,你只要把dist目录复制出来,运行里面的exe,就可以了
  10. 最后,如果你的GUI程序还是运行不了,你还需要手工将你的GTK+安装安装目录(默认是C:\GTK)下的etc和lib目录复制到dist目录

当然,由于包含了一堆的运行环境,生成的dist目录将会是比较巨大的,现在的gmbox的exe居然有18M多,嘿嘿,应该还有优化和压缩的空间,改天再研究了~

给python增加IPC模块

前天介绍了linux进程间通信──消息队列,由于消息队列是linux内核提供的功能,所以理所当然地,C语言用起来最为方便:直接include一个sys/msg.h就可以了,所以之前的文章,我也是用C语言来做演示的.
那么我喜欢的Python能不能用IPC呢?能不能像C一样用消息队列呢?
其实,Python的内置模块里,并没有对IPC的支持,但是好在python的可扩展性超强,我们可以用swig来为python增加一个IPC模块.方法如下:
下载这个tar包(修改自这里),解压到任意目录,得到 ipc.h ipc.i Makefile 3个文件,如果你不是用的python2.6,需要修改一下 Makefile 里的路径(python3系列未测试).然后

make && make install

这样,你就可以在python里 import ipc模块了.
还是贴示例代码,保存为ipc_msg.py,并加可执行权限:

#!/usr/bin/env python
import sys,ipc
 
if len(sys.argv)==5 and sys.argv[3][0]=='s':
    ipc_key=int(sys.argv[1])
    msg_id = ipc.msgget(ipc_key,0666|ipc.IPC_CREAT)
    if 0 > msg_id:
        sys.exit(1)
    mbuf = ipc.msgbuf()
    mbuf.mtype = int(sys.argv[2])
    mbuf.mtext = sys.argv[4]
    if 0 > ipc.msgsnd(msg_id,mbuf,len(mbuf.mtext),0):
        sys.exit(3)
    print 'Send Success.'
elif len(sys.argv)==4 and sys.argv[3][0]=='r':
    ipc_key=int(sys.argv[1])
    mbuf = ipc.msgbuf()
    msg_id = ipc.msgget(ipc_key,0666)
    if 0 > msg_id:
        sys.exit(1)
    msg_len=ipc.msgrcv(msg_id,mbuf,2048,int(sys.argv[2]),ipc.IPC_NOWAIT)
    if 0 > msg_len:
        print 'No message received.'
        sys.exit(3)
    else:
        print 'Recv Success.(%d bytes):'% msg_len
        print mbuf.mtext
elif len(sys.argv)==3 and sys.argv[2][0]=='c':
    ipc_key=int(sys.argv[1])
    id_dsp = ipc.msqid_ds()
    msg_id = ipc.msgget(ipc_key,0666)
    if 0 > msg_id:
        sys.exit(1)
    if 0 > ipc.msgctl(msg_id,ipc.IPC_RMID,id_dsp):
        sys.exit(2)
else:
    print "usage: \n%s key type s message --to send message\n\
%s key type r --to receive\n\
%s key c --to clear queue"\
        %(sys.argv[0],sys.argv[0],sys.argv[0])

运行结果:

lily@LLY:~/test/ipc$ ipcs -q
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
 
lily@LLY:~/test/ipc$ ./ipc_msg.py 1 2 s abc
Send Success.
lily@LLY:~/test/ipc$ ipcs -q
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x00000001 65536      lily       666        3            1           
 
lily@LLY:~/test/ipc$ ./ipc_msg.py 1 2 r
Recv Success.(3 bytes):
abc
lily@LLY:~/test/ipc$ ipcs -q
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x00000001 65536      lily       666        0            0           
 
lily@LLY:~/test/ipc$ ./ipc_msg.py 1 c
lily@LLY:~/test/ipc$ ipcs -q
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
 
lily@LLY:~/test/ipc$

怎么样?和之前的C语言版本一模一样吧?

linux进程间通信──消息队列

linux自古以来就是一个多任务多用户的操作系统,所以linux的进程间通信(Inter-Process Communication──IPC)就显得非常重要了。
IPC是一种标准的Unix通讯机制,目前有以下几种通讯方式:管道(Pipe)、信号量(Semaphore)、互斥体(Mutex)、共享内存(Shared Memory)和消息队列(Message Queue),当然也有其他的方式,比如文件系统和dbus等。
今天我就来介绍一种简单实用的进程间通信方式:消息队列(Message Queue)。
首先说说消息队列的优缺点:
1.消息队列只适用于单台主机的进程间通信,如果是不同主机,需要用socket等其他方式,也就不属于IPC的范畴了。
2.消息队列可以实现异步通信,这似乎是优点,但说是它缺点也是可以的:通讯往往不是实时的。
3.消息队列有大小限制,通常只用于小数据量的发送。系统对用户的大小限制可以通过 ulimit -q 命令进行查询。
4.消息队列可以实现阻塞调用和非阻塞调用。
5.实现简单,且可移植性好。

下面通过一个实例来进行说明,以下文件保存成 ipc_msg.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
 
int main(int argc, char *argv[]){
	int ipc_key,msg_id,msg_len;
	long mtype;
	void * mbuf;
	if(argc==5 && argv[3][0]=='s'){
		ipc_key=atoi(argv[1]);
		mtype=atol(argv[2]);
		msg_len=strlen(argv[4]);
		if ( 0>(msg_id=msgget(ipc_key, 0666|IPC_CREAT)))return 1;
		if ( NULL==(mbuf=malloc(msg_len+sizeof(long)+1)) )return 2;
		memcpy(mbuf, (void *)&mtype, sizeof(long) );
		memcpy(mbuf+sizeof(long), (void *)argv[4], msg_len );
		if ( 0>msgsnd(msg_id, (struct msgbuf *)mbuf, msg_len, 0) )return 3;
		printf("Send Success.n");
	}else if(argc==4 && argv[3][0]=='r'){
		ipc_key=atoi(argv[1]);
		mtype=atol(argv[2]);
		if ( 0>(msg_id=msgget(ipc_key, 0666)))return 1;
		if ( NULL==(mbuf=malloc(4096)) )return 2;
		if ( 0>(msg_len=msgrcv(msg_id,(struct msgbuf *)mbuf, 4000, mtype, IPC_NOWAIT))){
			printf("No message received.n");
			return 3;
		}
		printf("Recv Success.(%d bytes):n",msg_len);
		printf("%sn",(char *)(mbuf+sizeof(long)));
	}else if(argc==3 && argv[2][0]=='c'){
		ipc_key=atoi(argv[1]);
		if ( 0>(msg_id=msgget(ipc_key, 0666)))return 1;
		if ( 0>msgctl(msg_id,IPC_RMID,(struct msqid_ds *)mbuf) )return 2;
	}else{
		printf("usage:"
			"%s key type s message --to send messagen"
			"%s key type r --to receiven"
			"%s key c --to clear queuen"
			,argv[0],argv[0],argv[0]);
	}
	return 0;
}

以上程序,实现了发数据到消息队列和从消息队列收取数据的功能。
第一个参数需要是一个整形数值,表示消息队列的Key;
第二个参数是一个长整形的数值,表示消息的Type,Key+Type 可以唯一确定一个先进先出的消息队列。
第三个参数如果是‘s’则把第四个参数发到指定消息队列,如果是‘r’则从指定消息队列收取消息,并打印。
另外,如果第二个参数是‘c’,则把Key对应的队列删除。
让我们来运行一下试试:

$ gcc -o ipc_msg ipc_msg.c
#编译
$ ipcs -q
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
#一开始系统中没有消息队列。
$ ./ipc_msg  1 2 s abc
Send Success.
#发送了一个内容为abc的消息
$ ipcs -q
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x00000001 262144     lily       666        3            1           
#发送了一个消息以后,队列里有消息了,key是1,有3个字节。
$ ./ipc_msg  1 2 r
Recv Success.(3 bytes):
abc
#从消息队列成功收到消息了。
$ ipcs -q
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x00000001 262144     lily       666        0            0           
#收完以后,空的消息队列仍然存在,不会自动消失。
 
$ ./ipc_msg  1 c
#删除队列
$ ipcs -q
 
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
#成功删除了,回到原始状态。

本文以GNU自由文档许可证发表.

python用着太顺手了

(此文纯属自言自语,基本可以忽略,呵呵.)
python用着太顺手了,其实是很久以前就有这种感觉,最近印象比较深的一次就是在做Project Euler的第一题的时候,那题比较简单,要求1000以内所有能被3或5整除的自然数之和.这题其实用什么语言都不复杂,但是用python的话,只需要一行:

sum([n for n in range(1000) if n%3==0 or n%5==0])

接近自然语言的表达看起来好舒服,而且也相当简洁.
然后今天,我又更新了一下gmbox,基本上把CLI重新写了一遍,又有同样的感觉了.gmbox的命令行,分交互式和非交互式两种,刚好用cmd和optparse两个内置模块轻松搞定.而且cmd模块支持欢迎界面/自定义提示符/readline库;optparse支持长短选项和混杂无序的选项,并自动生成帮助界面.真是太爽了.这两种模式加起来才140行左右的代码.去掉文件头,只有120行…
以后继续学习python.哈…

bones7456 WP theme 微调

看到Matrix 67的blog的主题,觉得有一点很不错:就是右侧的最新评论那里,一开始是每个评论只占据一行的位置,只有在鼠标放上去的时候,才会把内容展开.
这样的好处很明显:平时节省页面空间,布局也更漂亮,鼠标放上去的时候显示出该有的信息,也不影响使用.
于是,有样学样,把这一小细节学习了过来(呃..好吧,其实就是抄了过来…).
在实现上,没去动WP带的dynamic_sidebar函数,而是偷懒了一下,在页面基本展开完以后,用js处理了一下style,并添加事件函数.看现在是不是更好看了?
之前我都只敢放5个最新评论,因为再多,就不美观了.现在放10个也不是问题.
如果你也喜欢并想试试本WP主题,可以到这里下载最新的代码.
:-)