星期二, 七月 31, 2007

python assemble methods at runtime?

在以前曾经讨论过一个例子:python unzip,当时在外部定义了一个函数,然后直接利用 setattr 将其加入到 ZipFile 类对象中,如下:
>>> class test:
... pass
...
>>> def func(self):
... print self.__dict__
...
>>> test.func = func
>>> t = test()
>>> t.func()
{}
>>>
但是,如果在类定义中直接使用,则不行:
>>> def func(self):
... print self.__dict__
...
>>> class test:
... def __init__(self):
... self.func = func
...
>>> t = test()
>>> t.func()
Traceback (most recent call last):
File "", line 1, in
TypeError: func() takes exactly 1 argument (0 given)
使用 setattr 也不行:
>>> def func(self):
... print self.__dict__
...
>>> class test:
... def __init__(self):
... setattr(self, 'func', func)
...
>>> t = test()
>>> t.func()
Traceback (most recent call last):
File "", line 1, in
TypeError: func() takes exactly 1 argument (0 given)
但是,是不是我放在外面定义就没有一点问题了呢?在 mirrord.py 中,我就希望在运行时再装配,因为直接在 __init__ 中定义不行,所以我这样做:
def _schedule_thread(self, Server, address):
that = threading.Thread(
target=self.__run_schedule, name='schedule', args=(Server, address))
that.setDaemon(1)
that.start()
that.join()

def _schedule_process(self, Server, address):
"""
There is a sharing problem has not been solved:
manager(WatchManager) should be shared among processes
"""
pid = os.fork()
if pid == 0: self.__run_schedule(Server, address)

class Mirrord:
...
def __run_schedule(self, Server, address):
...
Mirrord._schedule = _schedule_thread
结果在测试的时候报错:
Exception in thread mirrord:
Traceback (most recent call last):
File "/usr/lib/python2.5/threading.py", line 460, in __bootstrap
self.run()
File "/usr/lib/python2.5/threading.py", line 440, in run
self.__target(*self.__args, **self.__kwargs)
File "mirrord_ut.py", line 56, in __run_thread
self.mrd.run(('localhost', 2123))
File "/root/ulfs/cutils/trunk/lib/mirrord.py", line 497, in run
self._schedule(Server, address)
File "/root/ulfs/cutils/trunk/lib/mirrord.py", line 380, in _schedule_thread
target=self.__run_schedule, name='schedule', args=(Server, address))
AttributeError: Mirrord instance has no attribute '__run_schedule'
,而如果将那两个函数改为:
def _schedule_thread(self, Server, address):
that = threading.Thread(
target=self._Mirrord__run_schedule, name='schedule', args=(Server, address))
that.setDaemon(1)
that.start()
that.join()

def _schedule_process(self, Server, address):
"""
There is a sharing problem has not been solved:
manager(WatchManager) should be shared among processes
"""
pid = os.fork()
if pid == 0: self._Mirrord__run_schedule(Server, address)
则可以通过。但显然使用 _Mirrord__run_schedule 这种方式看上去不是太好!

python forking after threading?

现在需要对 mirrord 进行单元测试,但 mirrord 进行了 daemon switch,因此会 fork 子进程并退出父进程。而在单元测试中,我的测试程序只能通过创建子进程或子线程来运行工作代码(否则运行到 daemon 状态就阻塞进入无限循环,测试代码就没办法往下走了),为了得到工作代码的状态来进行检测,需要能够访问到工作代码的一些变量,所以简单的就是使用线程。

但问题是,如果在 threading 之后又进行了 forking,而 fork 后的父进程退出,那么线程是否退出呢?写一个原型代码看看:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import os,sys
import time
import threading

def run_thread():
pid = os.fork()
if pid == 0:
print "child process ..."
while True:
time.sleep(5)
print "child process is running ..."
print "main process exiting ..."
sys.exit(0)

that = threading.Thread(target=run_thread, name="child")
that.setDaemon(1)
that.start()
# #1:
that.join()
print "main thread end"
运行结果如下:
sh$ python mirrord_5_ut.py
child process ...
main process exiting ...
main thread end
[Ctrl^C]
sh$ child process is running ...
child process is running ...
child process is running ...
[Ctrl^C]
sh$ child process is running ...
由此可见,fork 后的子进程还在运行,但是主进程退出了,也导致调度它的线程退出了!

但有一个问题,如果在 thread code 中 fork 的子进程也退出,那么在上面 #1 后面的代码会不会执行?因为进程是复制地址空间的,例如:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

"""
If the main process exits after forking,
while the forking is execute by a child thread,
will the main/child threads end? -- Yes
Author: Roc Zhou
Date: 2007-07-31
Email: chowroc.z@gmail.com
"""

import os,sys
import time
import threading

var = 0

def run_thread():
global var
var = 1
print "var is '%d' in thread" % var
pid = os.fork()
if pid == 0:
print "child process ..."
i = 0
while i < 10:
var = i * 2
time.sleep(1)
print "child process is running %d and var is '%d' ..." % (i, var)
i += 1
else:
print "main process ..."
j = 0
while j < 10:
var = j * 2 + 1
time.sleep(1)
print "main process is running %d and var is '%d' ..." % (j, var)
j += 1
# sys.exit(0)
print "var is '%d' at the end of thread code" % var

print "var is '%d' at the beginning" % var
# #a:
# run_thread()
# ------------
# #b:
that = threading.Thread(target=run_thread, name="child")
that.setDaemon(1)
that.start()
time.sleep(5)
# #1:
that.join()
# ------------
print "var is '%d' at the main thread end" % var
当按照 #a 来运行的时候,没有启动线程,那么输出结果是:
sh$ python mirrord_5_ut.py
var is '0' at the beginning
var is '1' in thread
child process ...
main process ...
main process is running 0 and var is '1' ...
child process is running 0 and var is '0' ...
main process is running 1 and var is '3' ...
child process is running 1 and var is '2' ...
main process is running 2 and var is '5' ...
child process is running 2 and var is '4' ...
main process is running 3 and var is '7' ...
child process is running 3 and var is '6' ...
main process is running 4 and var is '9' ...
child process is running 4 and var is '8' ...
main process is running 5 and var is '11' ...
child process is running 5 and var is '10' ...
main process is running 6 and var is '13' ...
child process is running 6 and var is '12' ...
main process is running 7 and var is '15' ...
child process is running 7 and var is '14' ...
main process is running 8 and var is '17' ...
child process is running 8 and var is '16' ...
main process is running 9 and var is '19' ...
var is '19' at the end of thread code
var is '19' at the main thread end
sh$ child process is running 9 and var is '18' ...
var is '18' at the end of thread code
var is '18' at the main thread end
可以看到,最后的代码运行了两次!但是在调用线程之后就不是,按 #b 运行,输出结果如下:
sh$ python mirrord_5_ut.py
var is '0' at the beginning
var is '1' in thread
child process ...
main process ...
child process is running 0 and var is '0' ...
main process is running 0 and var is '1' ...
child process is running 1 and var is '2' ...
main process is running 1 and var is '3' ...
child process is running 2 and var is '4' ...
main process is running 2 and var is '5' ...
child process is running 3 and var is '6' ...
main process is running 3 and var is '7' ...
child process is running 4 and var is '8' ...
main process is running 4 and var is '9' ...
child process is running 5 and var is '10' ...
main process is running 5 and var is '11' ...
child process is running 6 and var is '12' ...
main process is running 6 and var is '13' ...
child process is running 7 and var is '14' ...
main process is running 7 and var is '15' ...
child process is running 8 and var is '16' ...
main process is running 8 and var is '17' ...
child process is running 9 and var is '18' ...
var is '18' at the end of thread code
main process is running 9 and var is '19' ...
var is '19' at the end of thread code
var is '19' at the main thread end
这里最后的代码只运行了一次!

另外,是否使用 #1 处的 that.join() 也是有差别的!
sh$ python mirrord_5_ut.py
var is '0' at the beginning
var is '1' in thread
child process ...
main process ...
child process is running 0 and var is '0' ...
main process is running 0 and var is '1' ...
child process is running 1 and var is '2' ...
main process is running 1 and var is '3' ...
child process is running 2 and var is '4' ...
main process is running 2 and var is '5' ...
child process is running 3 and var is '6' ...
main process is running 3 and var is '7' ...
var is '9' at the main thread end
sh$ child process is running 4 and var is '8' ...
child process is running 5 and var is '10' ...
child process is running 6 and var is '12' ...
child process is running 7 and var is '14' ...
child process is running 8 and var is '16' ...
child process is running 9 and var is '18' ...
var is '18' at the end of thread code
所以,最终,将 mirrord.py 这个 module 中的 daemon 的代码移到 mirrord 这个 script 中!

星期一, 七月 30, 2007

python list pop operation 的一个典型

下面可能可以算得上是一个 List pop 操作的典型情况,是在一段单元测试代码中,我需要对某个目录下的文件进行查找,找到所有比指定时间要新的普通文件:
basedir = "/usr/local"
txlist = ["t:%s/etc" % basedir, "t:%s/share" % basedir, "x:%s/share/man"]

expect = []
for fname in self.__find_rfiles("%s/etc" % basedir): expect.append(fname)
for fname in self.__find_rfiles("%s/share" % basedir): expect.append(fname)
for fname in self.__find_rfiles("%s/share/man" % basedir): exclude.append(fname)
for fname in exclude: expect.remove(fname)
j = random.randint(0, len(expect))
ftemp = expect[j]
temp = os.lstat(ftemp)[-1]
ttemp = datetime.datetime(*time.localtime(temp)[:6])
rmidx = []
# #1:
for fname in expect:
temp = os.lstat(fname)[-1]
fctime = datetime.datetime(*time.localtime(temp)[:6])
if fctime > ttemp: rmidx.append(fname)
# #2:
for fname in rmidx:
expect.remove(fname)

fsbk = fs_backup.FsBackup(identity='test')
fsbk.append(txlist)
_files = fsbk.find(lasttime=ttemp)
_files.sort()
expect.sort()
self.failUnlessEqual(_files, expect)
self.__clean_last(fsbk)
这里,首先无法在位置 #1 处直接对 expect 进行 remove() 或 pop() 操作,因为这个操作会对当前列表的索引产生影响,导致当前位置指针指向了错误的项,所以会漏掉下一个节点,这在:python list pop in loop 中已经说明。

一种办法是使用在 python list pop in loop, 补充 中说明的方法,对指针进行调整。而这里采用另一种方法,建立一个不同的索引,每次都对重新寻找 expect 中指定节点的位置,这样指针位置就不会错了。

如果列表很大,那么每次搜寻索引可能会导致开销很大,那么可以考虑使用 dict(hash table) 来替换列表!

星期日, 七月 29, 2007

python list pop in loop, 补充

>>> L = ['La', 'Lb', 'c', 'Ld']
>>> x = 0
>>> for i in range(len(L)):
... print i
... if x: i -= 1
... if L[i][0] == 'L': L.pop(i); x = 1
... else: x = 0
...
0
'La'
1
'Lb'
2
'Ld'
3
Traceback (most recent call last):
File "", line 4, in ?
IndexError: list index out of range
这里如果要应用在多线程情况下,我考虑应该是将 x 扩展为一个队列,并应用生产者/消费者模式

python variables sharing between threads

python list pop in loop 中说明了在循环中使用 pop 的问题,同时说明的多进程的情况。因为在 mirrod/fs_mirror 项目中必须使用共享 WatchManager,所以可以考虑先看看线程的情况。
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import sys
import threading
import time
import random

L = [ chr(i+97) for i in range(26) ]
print L

idx = 20

def run_thread():
# print "index: %d, %s" % (idx, L[idx])
for x in L:
i = L.index(x)
# print "thread: %d, %s" % (i, x)
time.sleep(1)
if i == idx:
for j in range(int(random.random() * 10000)): sys.stdout.write("*")
print
print "thread: %d, %s" % (i, x)
try:
i = L.index(x)
except ValueError:
print "index: %d, %s" % (i, L[i])
# Has been pop out
if i == idx + 1:
print "index + 1: %d, %s" % (i, L[i])
print "Child thread end"
# print "Child List:", L

srv = threading.Thread(target=run_thread, name='child')
srv.setDaemon(1)
srv.start()
# L.extend(['x', 'y', 'z'])
# time.sleep(3)
for x in L:
i = L.index(x)
# print "main: %d, %s" % (i, x)
time.sleep(1)
if i == idx:
for j in range(int(random.random() * 10000)): sys.stdout.write("-")
print
print "main: %d, %s" % (i, x)
print "pop %d, %s" % (i, L[i])
L.pop(i)
print "Main thread end"
# print "Main List:", L
srv.join()
父线程会从列表中取出 L[20],子线程在 L[20] 出打印结果,看输出结果:
sh$ python mirrord_4_sharing_thread.py
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
------...
main: 20, u
pop 20, u
******...
thread: 20, u
index: 20, v
index + 1: 21, w
Main thread end
Child thread end
可以看到,在 main thread 取出 20, 'u' 的同时,child thread 开始认为 20 是 'u',但马上由变成了 20, 'v',因为 20 在 for 中已经走过以此,因此在下一个循环中将直接进入 21,这是 'v' 就被 child thread 忽略了!

这里,必须考虑 Lock 的问题!

python list pop in loop

如果在一个列表中循环时做了 pop 操作,会有什么问题呢:
>>> L = ['a', 'b', 'c', 'd']
>>> for i in range(len(L)):
... x = L[i]
... if x == 'b': L.pop(i)
...
'b'
Traceback (most recent call last):
File "", line 2, in ?
IndexError: list index out of range
这里已经报错了。但如果换一种方法呢?
>>> L = ['a', 'b', 'c', 'd']
>>> for x in L:
... if x == 'b':
... i = L.index(x)
... L.pop(i)
...
'b'
>>> print L
['a', 'c', 'd']
这里看上去是对的,但会有潜在的问题?例如这样的情况:

>>> L = ['La', 'Lb', 'c', 'Ld']
>>> for x in L:
... if x[0] == 'L':
... i = L.index(x)
... L.pop(i)
...
'La'
'Ld'
>>> print L
['Lb', 'c']

>>> L = ['La', 'Lb', 'c', 'Ld']
>>> for x in L:
... if x[0] == 'L':
... L.remove(x)
...
>>> print L
['Lb', 'c']
那么如果是在多进程环境中呢?

看这个:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import os,time

L = [ chr(i+97) for i in range(7) ]
print L
pid = os.fork()
if pid == 0:
for x in L:
print x
time.sleep(3)
print "Child process end"
print "Child List:", L
else:
L.extend(['x', 'y', 'z'])
j = 5
L.pop(j)
print "Main process end"
print "Main List:", L
其运行结果如下:
roc@crablfs:~/ulfs/cutils/trunk/prototypes$ python Ltest.py
['a', 'b', 'c', 'd', 'e', 'f', 'g']
a
Main process end
Main List: ['a', 'b', 'c', 'd', 'e', 'g', 'x', 'y', 'z']
roc@crablfs:~/ulfs/cutils/trunk/prototypes$ b
c
d
e
f
g
Child process end
Child List: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
可以看到子进程没有受到影响,因为进程的地址空间是复制的,如果是线程 thread,就不存在这个问题。

于是,对于 mirrod/fs_mirrod 项目来说,因为 inotify 的 WatchManager 必须共享(父进程/线程写入,子进程/线程读取并根据这个变动的 manager 来建立 Processor),所以如果使用进程解决方案,就必须考虑共享问题;同时共享问题包括一个对资源的锁定问题,即父进程对共享内容的变更可能导致服务子进程/线程读取到的信息不准确!

星期五, 七月 27, 2007

python list comprehension and function

以下两种方式都是可以的!:
real_fnames.extend([os.path.normpath(f) for f in files])
real_fnames.extend(os.path.normpath(f) for f in files)

星期四, 七月 26, 2007

ulfs 项目及其文档

现在把项目的所有相关内容都放到了 sourceforge 上,SVN 在:
https://crablfs.svn.sourceforge.net/svnroot/crablfs

项目改名为 ulfs,意为:
1. Your LFS
2. Templated LFS that make use of User Based Package Management

包括三个子项目和一个文档目录:
caxes 是关于配置管理的库和工具,包括基本数据结构的定义,例如现在利用 Python 的操作符重载定义的新的数据结构 Tree,目前完成了基本定义,下一步计划要进一步完善 Tree,之后再针对树和表及序列配置编写更多的接口库,以及为主机间配置共享编写 ctemplates 工具。

cutils 是建立在 caxes 上的工具集,主要利用 caxes 来实现语法及主机配置共享。包括备份和利用 inotify 机制实现的热备份工具,不依赖于具体协议的文件传输,以及利用 libgmail 实现对 gmail 的备份等...

目前在做的是 fs_backup 和 fs_mirror/mirrord,即备份和热备份工具,可以实现廉价和低耗的热备份机制,例如用 7 台主机为一组,5 台作为生产系统,1 台作为替换系统,1 台作为热备份系统,这样当生产系统中有一台有当机时,可以迅速切换到:
Replacer
||
[Net FS] <------> Hot-Backup-System
的模式。因为拷贝一次的代价是很大的,耗时也很长,如果数据量很大,则完全不能接受。而这种模式,比之于完全的双机热备要廉价得多。

当然这并不意味着可以放弃冷备份,因为热备份主要是用来抵御硬件故障,而对于误操作、病毒、入侵和软件故障则无能为力,当某个或部分用户需要恢复到之前某一段时间的状态时,只有利用冷备份才能实现。在这里,mirrord/fs_mirror 即热备系统的服务器代理(运行在生产系统上)和客户端(运行在 Hot-Backup-System),而 fs_backup 即为冷备份系统,他也可以被 mirrord 用来做启动同步,也可以被 fs_mirror 用来做与 mirrord 的初始化同步;同时可以在 Hot-Backup-System 上面运行 mirrord,在另外起一台冷备份运行 fs_mirror 来调用 fs_backup 做同步式的冷备份,这样可以形成一个链,同时也使开销更平均,避免出现过大的峰值。

ulfs 就是原来的 crablfs,即 User Based Package Managerment System。在 caxes 配置共享和管理的基础上,可以更进一步建立模板机制。

项目文档在:
http://crablfs.sourceforge.net/

关于 Tree 数据结构的代码内文档:
http://crablfs.sourceforge.net/tree.html

另外,关于系统管理和网络设施架构的笔记和经验总结:
http://crablfs.sourceforge.net/sysadm_zh_CN.html

python main process when raise in child thread?

如果是使用 forking,子进程异常退出应该不会影响到父进程的运行。而对于线程来说,地址空间是和主线程共享的,那么在子线程中产生的异常会不会影响到主线程的运行呢。编写一段代码测试之:
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import threading

class Exc:
def __init__(self, msg): self.msg = msg

def run_thread():
raise Exc("rasie Exception in child thread")

st = threading.Thread(target=run_thread, name="child")
st.setDaemon(1)
st.start()
st.join()
print "Main Process End"

sh$ python threading_test.py
Exception in thread child:
Traceback (most recent call last):
File "/usr/lib/python2.5/threading.py", line 460, in __bootstrap
self.run()
File "/usr/lib/python2.5/threading.py", line 440, in run
self.__target(*self.__args, **self.__kwargs)
File "threading_test.py", line 10, in run_thread
raise Exc("rasie Exception in child thread")
Exc: <__main__.exc>

Main Process End
最后 Main Thread 仍然打印了 "Main Process End",说明主线程没有受到影响。

星期三, 七月 04, 2007

能够信赖你的电脑吗?

能够信赖你的电脑吗? 理查德·斯多尔曼 著
Posted by shentao at 2004-12-01 04:50 AM
http://gentoo.hsefz.com/linux/Linux%20Forum/public/794732524923/

没有警觉性的的眼睛太容易被蒙蔽了。

原文
http://www.gnu.org/philosophy/can-you-trust.cn.html

【本文是重要的 GNU 哲学页面, 请不吝於提供对於本文翻译的意见。 <chliu@gnu.org> 同时为了便於读者引用查找, 於中译文本上的每一段都附有参考标号。 我们也欢迎关於本文的各种讨论: <chinese-translators@gnu.org> 。】

Who should your computer take its orders from? Most people think their computers should obey them, not obey someone else. With a plan they call "trusted computing", large media corporations (including the movie companies and record companies), together with computer companies such as Microsoft and Intel, are planning to make your computer obey them instead of you. (Microsoft's version of this scheme is called "Palladium".) Proprietary programs have included malicious features before, but this plan would make it universal.

1 您的电脑应该听取谁的命令? 大部份的人认为他们的电脑应该服从他们而不是某个其他人。 经由一项他们称之为“可信赖的计算”(trusted computing)的打算, 大型的媒体公司(包括电影和录制公司) 以及像是 Microsoft 和 Intel 的电脑公司, 正打算要使您的电脑服从他们而不是您。 (这项方案的 Microsoft 版本称之为“安全装备”: Palladium 。) 私权的程序在以前就已经有包括了一些恶意的功能特色(features), 但是这项打算将会使其普遍化。

Proprietary software means, fundamentally, that you don't control what it does; you can't study the source code, or change it. It's not surprising that clever businessmen find ways to use their control to put you at a disadvantage. Microsoft has done this several times: one version of Windows was designed to report to Microsoft all the software on your hard disk; a recent "security" upgrade in Windows Media Player required users to agree to new restrictions. But Microsoft is not alone: the KaZaa music-sharing software is designed so that KaZaa's business partner can rent out the use of your computer to their clients. These malicious features are often secret, but even once you know about them it is hard to remove them, since you don't have the source code.

2 私权软件在本质上即表示: 您无法控制它要做些什么; 您不能研究源码或是更动它。 聪明的商人找出一些方法利用他们的控制, 来使您处於劣势的行为并不让人感到惊讶。 Microsoft 已经做过许多次了: 有一个版本的 Windows 被设计来将在您的硬碟上的所有软件回报给 Microsoft ; 一个最近在 Windows Media Player 上的“安全” 升级要求使用者同意新的限制(restrictions)。 但 Microsoft 并不孤单: KaZaa 这个音乐分享(music-sharing)软件被设计成, 使 KaZaa 的商业伙伴可以将您的电脑的使用出租给他们的客户。 这些恶意的功能特色通常是隐密的, 但是就算您发现到, 也很难将它们移除, 因为您并没有源码。

In the past, these were isolated incidents. "Trusted computing" would make it pervasive. "Treacherous computing" is a more appropriate name, because the plan is designed to make sure your computer will systematically disobey you. In fact, it is designed to stop your computer from functioning as a general-purpose computer. Every operation may require explicit permission.

3 在过去, 这些都是个别〔发生〕的事件。 “可信赖的计算”(Trusted computing)将可能使它变得普遍。 “背判了的计算”是一个较为合适的名称, 因为这项打算是设计用来确保您的电脑将会有系统地不服从您。 事实上, 它是设计用来使您的电脑无法作为一台通用的计算机(general-purpose computer)。 每一项操作都将会需要明确的许可〔才得以进行〕。

The technical idea underlying treacherous computing is that the computer includes a digital encryption and signature device, and the keys are kept secret from you. Proprietary programs will use this device to control which other programs you can run, which documents or data you can access, and what programs you can pass them to. These programs will continually download new authorization rules through the Internet, and impose those rules automatically on your work. If you don't allow your computer to obtain the new rules periodically from the Internet, some capabilities will automatically cease to function.

4 在「背判了的计算」底下的技术想法是: 电脑包括了一个数位加密(digital encryption) 以及签章(signature)装置, 而其键值(keys)对您来说则是〔无法取得的〕秘密。 私权程序将会使用这项装置来控制「您可以执行的其它程序」、 「您可以储存的文档或资料」以及「您可以传递的程序」。 这些程序将会持续地经由互联网下载新的认证规则(authorization rules), 并且自动地将那些规则加诸到您的工作上。 如果您不允许您的电脑定期地从互联网取得新的规则, 〔那么〕一些功能(capabilities)将会自动地停止作用(function)。

Of course, Hollywood and the record companies plan to use treacherous computing for "DRM" (Digital Restrictions Management), so that downloaded videos and music can be played only on one specified computer. Sharing will be entirely impossible, at least using the authorized files that you would get from those companies. You, the public, ought to have both the freedom and the ability to share these things. (I expect that someone will find a way to produce unencrypted versions, and to upload and share them, so DRM will not entirely succeed, but that is no excuse for the system.)

5 当然, 好莱坞(Hollywood)以及录制公司打算要将「背判了的计算」用到“DRM” (数位限制管理: Digital Restrictions Management)上, 这样一来下载的录像品(videos)和音乐就只能够在一台指定的电脑上播放。 分享将是完全的不可能, 至少使用您可能从那些公司下载的认证档案是如此。 您,也就是公众, 应当同时拥有自由和能力来分享这些事物。 (我期望将有某个人能找出一个制作出没有加密版本的方法, 并且上载分享它们, 这样子 DRM 将不会完全地成功, 但那不能作为这个体系〔合理化〕的藉口。)

Making sharing impossible is bad enough, but it gets worse. There are plans to use the same facility for email and documents--resulting in email that disappears in two weeks, or documents that can only be read on the computers in one company.

6 使得分享变得不可能已经是够糟的了, 但还有更糟的。 他们打算要使用同样的设施(facility)到电子邮件和文档上 -- 造成电子邮件会在两个星期内消失, 或是文档只可以在一间公司内的电脑上被阅读。

Imagine if you get an email from your boss telling you to do something that you think is risky; a month later, when it backfires, you can't use the email to show that the decision was not yours. "Getting it in writing" doesn't protect you when the order is written in disappearing ink.

7 设想如果您从您的老板那里收到一封电子邮件, 要求您去做一件您认为太过於冒险的事; 一个月后, 这事情与〔他的〕预期相反时, 您无法使用那封电子邮件来显示那个决定并不是您所作出的。 当这个命令是以会消失的墨水撰写时, “白纸黑字地写下来”并不足以保护您。

Imagine if you get an email from your boss stating a policy that is illegal or morally outrageous, such as to shred your company's audit documents, or to allow a dangerous threat to your country to move forward unchecked. Today you can send this to a reporter and expose the activity. With treacherous computing, the reporter won't be able to read the document; her computer will refuse to obey her. Treacherous computing becomes a paradise for corruption.

8 设想如果您自您的老板那里收到一封电子邮件, 陈述了一个违反了法律或道德的政策, 像是将您的公司的帐簿丢进碎纸机, 或是允许一个对您的国家的严重威胁继续进行而不受检查。 在今天您可以将这类事情送给〔新闻〕记者并揭露这个活动。 但是经由「背判了的计算」, 记者将无法阅读这份文档, 她的电脑将会拒绝服从她。 「背判了的计算」变成了舞弊的天堂。

Word processors such as Microsoft Word could use treacherous computing when they save your documents, to make sure no competing word processors can read them. Today we must figure out the secrets of Word format by laborious experiments in order to make free word processors read Word documents. If Word encrypts documents using treacherous computing when saving them, the free software community won't have a chance of developing software to read them--and if we could, such programs might even be forbidden by the Digital Millennium Copyright Act.

9 像是 Microsoft Word 的文书处理器, 可以在当它们储存您的文档时使用「背判了的计算」, 以确保没有与之竞争的文书处理器可以阅读它们。 今天我们必须费力地尝试来理解 Word 格式〔为何〕, 以制作出可以阅读 Word 文档的自由文书处理器。 如果 Word 在当它储存文档时使用「背判了的计算」, 自由软件社团将不会有机会开发出可以阅读它们的软件 -- 即便我们办得到, 这样子的程序甚至也会被“数位千禧年版权法案” (Digital Millennium Copyright Act)所禁止。

Programs that use treacherous computing will continually download new authorization rules through the Internet, and impose those rules automatically on your work. If Microsoft, or the US government, does not like what you said in a document you wrote, they could post new instructions telling all computers to refuse to let anyone read that document. Each computer would obey when it downloads the new instructions. Your writing would be subject to 1984-style retroactive erasure. You might be unable to read it yourself.

10 使用「背判了的计算」的程序, 将会持续地自互联网下载新的认证规则, 并且将这些自动地加诸到您的工作上。 如果 Microsoft 或是美国政府不喜欢在某份您所撰写的文档中所说的事, 他们可以发出新的指示, 告诉所有的电脑拒绝让任何人阅读那份文档。 每一台电脑在它下载了新的指示后都将会遵守。 您的著述将会受到有如小说《一九八四》中所描述的(1984-style) 「追溯既往而有效的删去」(retroactive erasure)。 【《一九八四》(1984)是英国作家乔治·欧威尔(George Orwell) 於一九四九年发表的科幻小说; 相对应的则是赫胥黎(Aldous Huxley) 於一九三二年所发表的《美丽新世界》(Brave New World) -- 它也是《勇敢 GNU 世界》(Brave GNU World)名称的由来。】 您有可能连您自己都无法阅读它。

You might think you can find out what nasty things a treacherous computing application does, study how painful they are, and decide whether to accept them. It would be short-sighted and foolish to accept, but the point is that the deal you think you are making won't stand still. Once you come depend on using the program, you are hooked and they know it; then they can change the deal. Some applications will automatically download upgrades that will do something different--and they won't give you a choice about whether to upgrade.

11 您也许会想: 您可以看穿「“背判了的计算”的程序在做的卑鄙事」, 研究〔使用它们〕将会付出什么代价, 然后再来决定是否要使用它们。 接受将会是短视而且愚蠢的, 重点在於您认为您所作出的协议并不会保持不变。 一旦您变得依赖於使用〔那些〕程序, 您就被套牢了(hooked), 而且他们清楚得很; 然后他们就可以更动这项协议。 一些应用程序将会自动地下载「将会做出某些不一样的事情的」升级 -- 而他们可不会给您一个是否要升级的选择。

Today you can avoid being restricted by proprietary software by not using it. If you run GNU/Linux or another free operating system, and if you avoid installing proprietary applications on it, then you are in charge of what your computer does. If a free program has a malicious feature, other developers in the community will take it out, and you can use the corrected version. You can also run free application programs and tools on non-free operating systems; this falls short of fully giving you freedom, but many users do it.

12 今天您可以经由不去使用它来避免被私权软件所限制。 如果您执行 GNU/Linux 或是其它的自由操作系统, 并且如果您避免在它上面安装私权应用程序, 那么您就换得了〔完全地掌握〕您的电脑做些什么〔的自由〕。 如果一个自由程序有一个恶意的功能特色, 在社团里的其他程序员将会把它除去, 然后您就可以使用修正过的版本了。 您也可以在不自由的操作系统上执行自由的应用程序和工具; 这并不足以给予您完全的自由, 但是有许多使用者这么做。

Treacherous computing puts the existence of free operating systems and free applications at risk, because you may not be able to run them at all. Some versions of treacherous computing would require the operating system to be specifically authorized by a particular company. Free operating systems could not be installed. Some versions of treacherous computing would require every program to be specifically authorized by the operating system developer. You could not run free applications on such a system. If you did figure out how, and told someone, that could be a crime.

13 「背判了的计算」 将自由操作系统和自由应用程序的存续置於危险的境地, 因为您将根本无法执行它们。 一些版本的「背判了的计算」, 将会需要操作系统被某个特定的公司明确地给予认证。 自由的操作系统将无法被安装。 一些版本的「背判了的计算」, 将会需要每一个程序都要被操作系统开发者明确地给予认证。 您无法在这样的一个操作系统上执行自由的应用程序。 如果您真的了解了要如何做, 并且告诉了某人, 那可能是一种犯罪行为。

There are proposals already for US laws that would require all computers to support treacherous computing, and to prohibit connecting old computers to the Internet. The CBDTPA (we call it the Consume But Don't Try Programming Act) is one of them. But even if they don't legally force you to switch to treacherous computing, the pressure to accept it may be enormous. Today people often use Word format for communication, although this causes several sorts of problems (see "We Can Put an End to Word Attachments"). If only a treacherous computing machine can read the latest Word documents, many people will switch to it, if they view the situation only in terms of individual action (take it or leave it). To oppose treacherous computing, we must join together and confront the situation as a collective choice.

14 已经有一些在美国法律上的提议: 要求所有的电脑都支持「背判了的计算」, 并且禁止将旧电脑连结到互联网上。 CBDTPA (我们称它为“消费就好,不要试著编写程序”法案: Consume But Don't Try Programming Act)就是其中之一。 但是即使他们并没有在法律上强制您切换到「背判了的计算」, 〔被迫〕接受它的压力还是很大。 今天人们通常使用 Word 格式来通信, 虽然这会造成许多类型的问题。 (请见 “我们可以终结使用 Word 附加档案”:We Can Put an End to Word Attachments) 〔但是〕如果只有「背判了的计算」的机器可以阅读最新的 Word 文档, 并且如果他们所看到的形势只是以个别的动作(接受或离开)来表现时, 许多人将会切换到它。 为了反制「背判了的计算」, 我们必须结合在一起面对这个形势, 以作为我们集体的选择。

For further information about treacherous computing, see .

15 关於「背判了的计算」的更多信息, 请见

To block treacherous computing will require large numbers of citizens to organize. We need your help! The Electronic Frontier Foundation and Public Knowledge are campaigning against treacherous computing, and so is the FSF-sponsored Digital Speech Project. Please visit these Web sites so you can sign up to support their work.

16 要阻挡「背判了的计算」将会需要很大数目的公民组织起来。 我们需要您的帮助! 电子先锋基金会(Electronic Frontier Foundation)公众知识(Public Knowledge) 正在发起对抗「背判了的计算」的活动, 由自由软件基金会资助的 数位言论工程(Digital Speech Project) 也有参与。 请拜访这些网站, 这样您就可以签名来支持他们的工作了。

You can also help by writing to the public affairs offices of Intel, IBM, HP/Compaq, or anyone you have bought a computer from, explaining that you don't want to be pressured to buy "trusted" computing systems so you don't want them to produce any. This can bring consumer power to bear. If you do this on your own, please send copies of your letters to the organizations above.

17 您也可以经由撰写给 Intel 、 IBM 、 HP/Compaq 或任何您从他那里购买电脑的人, 解释您不想要被强迫购买“可信赖”的计算系统, 因此您不希望他们制造任何这样子的系统。 这可以带给消费者维持〔自由〕的力量。 如果您自行采取行动, 请将您的信件副本送到上述的机构。

后记

  1. The GNU Project distributes the GNU Privacy Guard, a program that implements public-key encryption and digital signatures, which you can use to send secure and private email. It is useful to explore how GPG differs from treacherous computing, and see what makes one helpful and the other so dangerous.

    18 GNU 工程散布了 GNU Privacy Guard (GNU 隐私守卫), 那是一个实现了公开键加密(public-key encryption) 以及数位签章的程序, 您可以使用来送出安全且秘密的电子邮件。 浏览一下 GPG 是如何与「背判了的计算」不同是有用处的, 并且看看那些对於某人有帮助的事物〔为什么〕对其他人是如此的危险。

    When someone uses GPG to send you an encrypted document, and you use GPG to decode it, the result is an unencrypted document that you can read, forward, copy, and even re-encrypt to send it securely to someone else. A treacherous computing application would let you read the words on the screen, but would not let you produce an unencrypted document that you could use in other ways. GPG, a free software package, makes security features available to the users; they use it. Treacherous computing is designed to impose restrictions on the users; it uses them.

    19 当某人使用 GPG 送给您一份加密的文档, 并且您使用了 GPG 来将它解码, 〔所得到的〕结果是一份您可以阅读、〔进一步〕传递、 复制甚至再次加密并安全地送给某个其他人的解密文档。 一个「背判了的计算」应用程序将会让您在萤幕上阅读这些文字, 但是不让您〔能够〕制作出一份可以让您以其它方式使用的解密文档。 GPG 这个自由软件包, 让「安全的功能特色」可以为使用者所取得; 他们使用它。 「背判了的计算」则是设计来将限制加诸到使用者身上; 它利用了他们。

  2. Microsoft presents palladium as a security measure, and claims that it will protect against viruses, but this claim is evidently false. A presentation by Microsoft Research in October 2002 stated that one of the specifications of palladium is that existing operating systems and applications will continue to run; therefore, viruses will continue to be able to do all the things that they can do today.

    20 Microsoft 简报了 palladium 作为一种安全手段, 并且宣称它将会保护〔电脑〕免受病毒的侵袭, 但是证据显示这项宣称完全是站不住脚。 由 Microsoft Research (研究部门)在二○○二年十月所作的一场简报, 说明了 palladium 的其中一项规格是: 现存的操作系统以及应用程序将会继续地采用; 因此, 病毒也将能够继续地做它们今天能做的所有事情。

    When Microsoft speaks of "security" in connection with palladium, they do not mean what we normally mean by that word: protecting your machine from things you do not want. They mean protecting your copies of data on your machine from access by you in ways others do not want. A slide in the presentation listed several types of secrets palladium could be used to keep, including "third party secrets" and "user secrets"--but it put "user secrets" in quotation marks, recognizing that this somewhat of an absurdity in the context of palladium.

    21 当 Microsoft 在谈论到与 palladium 作连接的“安全”时, 他们指的「并不是」我们通常用来表示那个字的意思: 保护您的机器,使其免於受到您不想要〔的事物侵扰〕。 他们指的是保护在您的机器上的您的资料的拷贝, 使其免於被您〔自己〕以其他人不希望的方式进行存取(access)。 简报中的一个幻灯片列出了数个 palladium 可能用来维护的秘密类型, 包括了“第三团体(third party)的秘密”以及“使用者的秘密” -- 但是它将“使用者的秘密”放到引号中, 「似乎」将它认知为: 就 palladium 的〔开发〕脉络而言, 这实在有点荒谬。

    The presentation made frequent use of other terms that we frequently associate with the context of security, such as "attack", "malicious code", "spoofing", as well as "trusted". None of them means what it normally means. "Attack" doesn't mean someone trying to hurt you, it means you trying to copy music. "Malicious code" means code installed by you to do what someone else doesn't want your machine to do. "Spoofing" doesn't mean someone fooling you, it means you fooling palladium. And so on.

    22 简报中频繁地使用当我们谈到安全时, 经常会使用到的其它字眼, 像是“攻击”(attack)、 “恶意的代码”(malicious code)、 “欺骗”(spoofing)以及“可信赖的”(trusted)。 〔但是〕它们之中没有一个指的是我们通常用来表示的意思。 “攻击”并不是指某人试图要伤害您, 它是指您试图要复制音乐; “恶意的代码”指的是由您〔自己〕所安装的代码, 而这代码可能做得出某个「其他人」不希望您的机器去做的某些事; “欺骗”并不是指某人欺骗了您, 它指的是您玩弄了 palladium 。 诸如此类……。

  3. A previous statement by the palladium developers stated the basic premise that whoever developed or collected information should have total control of how you use it. This would represent a revolutionary overturn of past ideas of ethics and of the legal system, and create an unprecedented system of control. The specific problems of these systems are no accident; they result from the basic goal. It is the goal we must reject.

    23 由一个 palladium 开发者先前所作的声明, 说明了它的基本根据是: 不论是谁开发或收集了信息, 应该都对「您如何使用它」具有完全的控制权。 这是对於过去「伦理」和「法律体系」的观念的一种革命性的推翻, 并且创造了一种前所未见的控制体系。 〔关於〕这些系统的特定问题并不是出於偶然; 它们是来自於〔有意识的〕基本目标。 而这目标正是我们必须拒绝的。

Copyright © 2002 Richard Stallman.

Verbatim copying and distribution of this entire article is permitted without royalty in any medium provided this notice is preserved.
【本文允许在无须支付版税, 且不变更文档内容的前提下刊登在任何形式的媒体中, 但需保留此声明。】

prev: RHCE 实践练习(2004.5.17~31)

1. 排错
(1) kickstart 安装;
. 将 ks.cfg 文件放在本地或安装启动盘上,再在 ks.cfg 中指定使用网络安装也是可以的:
nfs --server 192.168.x.x --dir /PATH # 放置 iso 文件的目录
在安装系统的过程中十几分钟的时间怎么利用?

(2) rescue 模式的使用;

(3) 启动问题:
a. 熟记启动的详细过程,清楚各个环节:

Initrd

名称
initrd -- 由启动加载器进行初始化的RAM DISK

描述
/dev/initrd这个特殊文件是一个只读的块设备文件。/dev/initrd设备文件是一个在内核被启动之前由启动加载器进行初始化的RAM disk。

随后,内核利用/dev/initrd设备文件的内容进行两个阶段的(系统)自举。

在(系统)自举的第一个阶段,内核进行初始化,根据/dev/initrd的内容挂载一个原始根文件系统。

在第二个阶段,一些附加的驱动或者其他模块从原始的根设备中被加载。在加载完附加模块后,一个新的根文件系统(也就是常规的根文件系统)从别的设备被挂载。

自举操作流程
使用initrd进行系统自举,系统初始化如下:

1.启动加载器把内核程序以及/dev/initrd的内容加载到内存

2.在内核初始化过程中,内核把/dev/initrd设备的内容解压缩并拷贝到/dev/ram0设备上,随之释放被/dev/initrd占用的内存空间

3.接着内核以可读写的方式把/dev/ram0设备挂载为原始的根文件系统

4.如果(不知道如何翻译indicated)常规根文件系统也是原始根文件系统(举例来说,/dev/ram0),那么内核跳至最后一步正常启动

5.如果可执行文件/linuxrc存在于原始根文件系统上,/linuxrc就以uid为0的帐户身份被执行。(/linuxrc文件必须具有可执行属性,它可以是包括shell脚本在内的任何有效的可执行文件)

6.如果/linuxrc没有被执行或者当/linuxrc(的运行)终止时,常规根文件系统被挂载。(如果/linuxrc退出时在原始根文件系统上挂载了任意文件系统,那么内核的行为则是不定的。阅读注意事项以确定当前的内核行为)

7. 如果常规根文件系统存在/initrd目录,那么/dev/ram0将从/移动到/initrd。否则如果/initrd目录不存在, /dev/ram0将被卸载。(当从/移动到/initrd而/dev/ram0没有被卸载时,会导致进程仍能从/dev/ram0运行)。如果 /initrd目录不存在,并且当/linuxrc退出时任何进程仍能从/dev/ram0运行,内核的行为是不定的。阅读注意事项以确定当前内核的行 为。)

8.正常的启动过程(比如/sbin/init的调用)将在常规根文件系统上进行
...
注意事项
1.在当前内核下,当/dev/ram0从/被移动到/initrd时,任何已挂载的文件系统依然能被访问。然而,/proc/mounts条目不会被更新。
2.在当前内核下,如果/initrd不存在,如果/dev/ram0被其他进程使用中或者有任何文件系统被挂载其上,/dev/ram0将不会被完全卸载。如果/dev/ram0没有被完全卸载,那么/dev/ram0将驻留在内存

也 就是说,因为模块都编译在 /lib/modules/$(uname -r) 中,在内核启动时,一开始是没有办法挂载 / 分区的,而如果这时有一些内核选项如 SCSI 硬盘等编译成了模块,不使用 initrd 就没有办法加载了!另外,如果内核太大,既影响性能,又不利于备份。如果挂载的原始文件系统也是最终的根文件系统,系统将跳过initrd处理而继续正常 的初始化过程。


创建 /dev/initrd 文件的命令:
# mknod -m 400 /dev/initrd b 1 250
# chown root:disk /dev/initrd
要使用 initrd,编译内核时必须选择以下两项:
CON-FIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
即 RAM disk driver 不能作为模块加载。

想知道你的initrd.img中包含了哪些驱动程序吗?
# cat initrd.img | gunzip > /tmp/myinitrdfs
# mkdir /mnt/tmp
# mount -o loop -t ext2 /tmp/myinitrdfs /mnt/tmp
然后查看 /mnt/tmp 中的文件 linuxrc 中的内容即可知道启动时会装入哪些驱动程序。

你也可以更改其中的内容,假设我们想加另一种 SCSI 驱动 aic7xxx.o 进入你的 initrd.img:
# cd /mnt/tmp
# vi linuxrc 加上一行 insmod /lib/aic7xxx.o
# cp /lib/modules/`uname -r`/scsi/aic7xxx.o lib/
# cd /
# umount /mnt/tmp
# dd if=/tmp/myinitrdfs | gzip > /boot/initrd2.img
至此,新的initrd文件initrd2.img就包含了aic7xxx的驱动程序了。

http://www.linuxsir.org/bbs/showthread.php?t=113586

b. 在启动时注意出现的问题,查看启动信息;

c. grub 和 lilo 的使用和排错;

d. 一些启动的关键程序和文件被替换或丢失的情况:如 /bin/mount, /etc/inittab;

(4) 分析系统日志及系统监视:了解一些关键应用和服务在什么日志文件中,及如何使用 logwatch;
. iptables 可以使用如下方式进行日志记录:

modprobe ipt_LOG
... -j LOG --log-level 0 --log-prefix "STRING: "


(5) X Window 排错;

(6) 系统排错一般思路;
/etc/securetty root 可以登陆的终端!

2. 网络架设:
(1) 编译内核;
System.map 是内核符号表,然而很多文档提及,它并非用于内核,换言之,内核不需要它来确定函数位置;它大多用于 log 工具以及调试工具。

(2) ssh,注意结合 X Window;

(3) NIS:注意 auotfs;

3. 其他:
(1) 所有在线文档的查阅!

最后一次的讲演(补全被阉割部分)

讲演人:闻一多

  这几天,大家晓得,在昆明出现了历史上最卑劣最无耻的事情!李先生究竟犯了什么罪,竟遭此毒手?他只不过用笔写写文章,用嘴说说话,而他所写的,所说的,都无非是一个没有失掉良心的中国人的话!大家都有一枝笔,有一张嘴,有什么理由拿出来讲啊!有事实拿出来说啊!(闻先生声音激动了)为什么要打要杀,而且又不敢光明正大的来打来杀,而偷偷摸摸的来暗杀!(鼓掌)这成什么话?(鼓掌)

  今天,这里有没有特务?你站出来!是好汉的站出来!你出来讲!凭什么要杀死李先生?(厉声,热烈的鼓掌)杀死了人,又不敢承认,还要诬蔑人,说什么 “桃色事件”,说什么共产党杀共产党,无耻啊!无耻啊!(热烈的鼓掌)这是某集团的无耻,恰是李先生的光荣!李先生在昆明被暗杀,是李先生留给昆明的光荣!也是昆明人的光荣!(鼓掌)

  去年“一二。一”昆明青年学生为了反对内战,遭受屠杀,那算是青年的一代献出了他们最宝贵的生命!现在李先生为了争取民主和平而遭受了反动派的暗杀,我们骄傲一点说,这算是象我这样大年纪的一代,我们的老战友,献出了最宝贵的生命!这两桩事发生在昆明,这算是昆明无限的光荣!(热烈的鼓掌)

  反动派暗杀李先生的消息传出以后,大家听了都悲愤痛恨。我心里想,这些无耻的东西,不知他们是怎么想法,他们的心理是什么状态,他们的心怎样长的!(捶击桌子)其实简单,他们这样疯狂的来制造恐怖,正是他们自己在慌啊!在害怕啊!所以他们制造恐怖,其实是他们自己在恐怖啊!特务们,你们想想,你们还有几天?你们完了,快完了!你们以为打伤几个,杀死几个就可以了事,就可以把人民吓倒了吗?其实广大的人民是打不尽的,杀不完的!要是这样可以的话,世界上早没有人了。

  你们杀死一个李公朴,会有千百万个李公朴站起来!你们将失去千百万的人民!你们看着我们人少,没有力量?告诉我们,我们的力量大得很,强得很!看今天来的这些人都是我们的人,都是我们的力量!此外还有广大的市民!我们有这个信心:人民的力量是要胜利的,真理是永远是要胜利的,真理是永远存在的。历史上没有一个反人民的势力不被人民毁灭的!希特勒,墨索里尼,不都在人民之前倒下去了吗?翻开历史看看,你们还站得住几天!你们完了,快了!快完了!我们的光明就要出现了。我们看,光明就在我们眼前,而现在正是黎明之前那个最黑暗的时候。我们有力量打破这个黑暗,争到光明!我们光明,恰是反动派的末日!(热烈的鼓掌)

  现在司徒雷登出任美驻华大使,司徒雷登是中国人民的朋友,是教育家,他生长在中国,受的美国教育。他住在中国的时间比住在美国的时间长,他就如一个中国的留学生一样,从前在北平时,也常见面。他是一位和蔼可亲的学者,是真正知道中国人民的要求的,这不是说司徒雷登有三头六臂,能替中国人民解决一切,而是说美国人民的舆论抬头,美国才有这转变。(被删割部分)

  李先生的血不会白流的!李先生赔上了这条性命,我们要换来一个代价。“一二。一”四烈士倒下了,年青的战士们的血换来了政治协商会议的召开;现在李先生倒下了,他的血要换取政协会议的重开!(热烈的鼓掌)我们有这个信心!(鼓掌)

  “一二。一”是昆明的光荣,是云南人民的光荣。云南有光荣的历史,远的如护国,这不用说了,近的如“一二。一”,都属于云南人民的。我们要发扬云南光荣的历史!(听众表示接受)

  反动派挑拨离间,卑鄙无耻,你们看见联大走了,学生放暑假了,便以为我们没有力量了吗?特务们!你们看见今天到会的一千多青年,又握起手来了,我们昆明的青年决不会让你们这样蛮横下去的!

  反动派,你看见一个倒下去,可也看得见千百个继起的!

  正义是杀不完的,因为真理永远存在!(鼓掌)

  历史赋予昆明的任务是争取民主和平,我们昆明的青年必须完成这任务!

  我们不怕死,我们有牺牲的精神!我们随时象李先生一样,前脚跨出大门,后脚就不准备再跨进大门!(长时间的鼓掌)

prev: initrd 的作用

Initrd的作用有三:

(1).提高系统的可移植性
把更多的内核功能条目编译成模块,不仅仅是为了减小内核体积,更重要的是面对各种不同的硬件架构,可以使用initrd中的linuxrc按需进行模块加载以驱动硬件,甚至对于CPU类型或者多处理机也可以进行手工选择内核(配合syslinux这类boot loader)

(2).LIVECD(光盘上的Linux)必备的部件
现在的可启动光盘都沿用1995年制定的El Torito标准,它的启动原理在于模拟软盘启动映像,这个映像的大小一般被限制在2800KB,也就是两张软盘的大小,它包含了syslinux(也可以用 isolinux,它对映像的大小要求更宽松),syslinux的配置文件,initrd.img以及内核。这时候内核的大小就必须要有约束了(当然,也有来自1MB实模式内存空间的约束),把更多的模块压缩进initrd.img中去,可以缩小启动映像的体积。
最重要的是,linuxrc脚本对于硬盘,光驱模块的加载至关重要,因为livecd要适应尽量多的硬件架构,所以它必须能按需加载模块,这时候 initrd就派上用场了。比如说,我们在vmware里运行knoppix,knoppix的linuxrc就自动加载BusLogic.o模块(通过轮换insmod来实现)。

(3).在linuxrc脚本中可以很方便地启用个性化bootsplash

http://www.linuxsir.org/bbs/showpost.php?p=751666&postcount=20

新内核提供的内核模块自动加载不是在内核初始化过程即内核态中使用的,而是在用户态进行的(比如说,你要挂载一个ntfs盘,那么内核自动加载ntfs模块),因为要在内核态加载模块,前提是内核必须确定好根文件系统,而确定根文件系统又必须要支持相应的文件系统如ext2,这就是自举的逻辑哲学问题了,所以一定要把相应的文件系统编译进内核才行!

我个人认为,研究内核一定要有方向才能成功。当今的Linux内核很庞大,源码系统可谓盘根错乱,不容易读懂,当针对某一方面来研究,比如说中断系统,显然能事半功倍。

mutt 命令行

$ echo "STRING..." | mutt -s "SUBJECT" -i TEXTFILE -a ATTACHMENT1 -a ATTCHMENT2
-i 可以把 TEXTFILE 的内容追加到邮件中,-a 可以带附件,这是比 mail 命令方便的地方。

prev: iptables DNAT/SNAT 的概念问题

先看下面的脚本:
#!/bin/bash
# [/usr/local/sbin/]ipt08_nat_DS.sh

/sbin/modprobe ipt_MASQUERADE
/sbin/modprobe iptable_nat
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ip_nat_ftp

iptables -F
iptables -t nat -F

# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE # [5]
echo 1 > /proc/sys/net/ipv4/ip_forward

inet=220.168.98.221
ihttpd=192.168.0.2

iptables -t nat -A PREROUTING -d $inet -p tcp --dport 80 -j DNAT --to-destination $ihttpd # [1]
iptables -t nat -A POSTROUTING -s $ihttpd -p tcp --sport 80 -j SNAT --to-source $inet # [2]
iptables -t nat -A POSTROUTING -d $ihttpd -p tcp --dport 80 -j SNAT --to-source $inet # [3]
iptables -t nat -A OUTPUT -d $inet -p tcp --dport 80 -j DNAT --to-destination $ihttpd # [4]


iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state NEW -i lo -j ACCEPT
iptables -A INPUT -m state --state NEW -i ! ppp0 -j ACCEPT

iptables -A INPUT -p tcp --dport 3313 -j ACCEPT # FOR: skype
iptables -A INPUT -j REJECT

iptables -A OUTPUT -j ACCEPT

iptables -A FORWARD -j ACCEPT
[1] 定义了外部的主机访问内部 http 服务器的目标地址转换规则,而 [2] 定义了该服务器的源地址转换规则。我之前一直认为有 [1] 就必须有 [2],两者必须匹配。但实际情况是,只需要有 [1],就可以让外部主机正常访问内部飞的服务器了!这是因为,当服务器响应了 iptables 所在的网关主机后,报文到达防火墙,iptables 会根据 DNAT 规则自动做 r-DNAT 操作(照着DNAT的步骤反过来做一遍),所以不再需要 SNAT 了。事实上,只要考虑一下 MASQUERADE 的工作,就可以明白──你只需要定义一个相当于 SNAT 的 转换,而不需要反过来做一次。

[2] 的作用,就是对 server 回复的报文改装源地址,从而可以对 Internet 隐藏内部网络的真实组成情况。注意,在防火墙上用 tcpdump 嗅探不会发现源地址进行了改变,因为从 server 到防火墙的报文只会经过 PREROUTING 和 INPUT 链,而 SNAT 必须到 POSTROUTING 链才生效。

设置了 [1] 后,在内部网络和防火墙主机上使用 $inet 访问服务器,会被拒绝!为什么呢?

先来看本地网络的情况:本地 $local 发送的到 $ihttpd(http server)的请求报文,因为使用 $inet,所以会经过防火墙,于是做 DNAT 操作,但没有做 SNAT 把源地址转换成防火墙的地址。http server 接到这个请求,发现源地址就在本地网络,于是把回复包直接发送到请求包的源地址 $local。

客户机 $local 接到回复报文,但它会感到“困惑”,因为它并没有向 $ihttpd 发送报文,它只好把这个包 DROP 掉,再去等待从防火墙主机 $inet 返回的“真正”的回复包,只是这个回复永远不会到达。

[3] 就是为了解决这个问题。当然,如果内部网络的主机直接使用 $ihttpd 访问 http server,就不会有上面的问题。

对于防火墙主机本身,直接用 $inet 访问 http server,也会被拒绝,因为本地产生的报文不会经过 nat 的 PREROUTING 链,而直接从 nat 的 OUTPUT 链出去,所以 [1] 定义的 DNAT 没有作用,所以,对本地报文,OUTPUT 链相当域 PREROUTING 链。

python distutils py_modules

package_dir = {'caxes' : 'lib'},
py_modules = ['lib.tree']
应该写成 lib.tree 而不是 lib/tree.py

星期一, 七月 02, 2007

python several Tree += examples

在设计 += 即 __iadd__ operator overloading 的时候,为保持一致性,另一个操作数只能是 Tree instance 或 Tree dict,那么即要找到不是它们时的边界条件,例如:
>>> tree = reload(tree)
>>> root = tree.Tree(0)
>>> print root

+++ Tree +++
() : 0,
--- Tree ---

>>> root += [1, 2, 3]
debug: AttributeError
Traceback (most recent call last):
File "", line 1, in ?
File "tree.py", line 266, in __iadd__
raise TreeTypeExc(_("Other operand should be a Tree instance or Tree dict"))
tree.TreeTypeExc:
这个 Exception 是由于 AttributeError 被捕捉产生的,因为调用了一个 dict 的 items(),那么定义一个有 items() 的类(多态性):
>>> class temp:
... def __init__(self):
... self.data = 1
... def items(self):
... return self.data
...
>>> t = temp()
>>> t.items()
1
>>> root += t
Traceback (most recent call last):
File "", line 1, in ?
File "tree.py", line 260, in __iadd__
for pathseq, node in other.items():
TypeError: iteration over non-sequence
以及
>>> root += {'a' : 1, 'b' : 2, 'c' : 3}
Traceback (most recent call last):
File "", line 1, in ?
File "tree.py", line 261, in __iadd__
self._1_node_set(pathseq, node())
TypeError: 'int' object is not callable
那么定义一个 callable 的类:
>>> class temp:
... def __init__(self, v):
... self.data = v
... def __call__(self):
... return self.data
...
>>> root += {'a' : temp(1), 'b' : temp(2), 'c' : temp(3)}
>>> print root

+++ Tree +++
() : 0,
('a',) : 1,
('b',) : 2,
('c',) : 3,
--- Tree ---

>>> root += {'' : temp(1), 'b' : temp(2), 'c' : temp(3)}
>>> print root

+++ Tree +++
() : 1,
('a',) : 1,
('b',) : 2,
('c',) : 3,
--- Tree ---

>>> root = tree.Tree(0)
>>> root += {'' : temp(1), 'b' : temp(2), 'c' : temp(3)}
>>> root += {1 : temp(1), 'b' : temp(2), 'c' : temp(3)}
Traceback (most recent call last):
File "", line 1, in ?
File "tree.py", line 261, in __iadd__
self._1_node_set(pathseq, node())
File "tree.py", line 333, in _1_node_set
next = pathseq[0]
TypeError: unsubscriptable object

>>> root += {tree.Tree(1): temp(1), 'b' : temp(2), 'c' : temp(3)}
Traceback (most recent call last):
File "", line 1, in ?
TypeError: unhashable instance

>>> root = tree.Tree(0)
>>> root += {'' : temp(1), 'b' : temp(2), 'c' : temp(3)}
>>> print root

+++ Tree +++
() : 1,
('b',) : 2,
('c',) : 3,
--- Tree ---
所以基本上可以看到,只有两个异常是需要注意的,即:TypeError 和 AttributeError,最终成品如下:
def __iadd__(self, other):
try:
self.__update__(other)
except TreeTypeExc:
try:
for pathseq, node in other.items():
self._one_node_set(pathseq, node())
except TreeExc, trx:
# print "debug: TreeExc"
raise TreeTypeExc(trx.msg)
except (AttributeError, TypeError):
# print "debug: AttributeError or TypeError"
raise TreeTypeExc(_("Other operand should be a Tree instance or Tree dict"))
return self
因为 'b' 和 ('b',) 都是 sequence,所以两种效果一样(对 "" 和 () 同理),但 'abc' 和 ('abc',) 是不同的。

现在 Tree 的基本结构已经全部完成,可以从我的项目的 SVN 检出。

google blog 被封的非代理临时解决办法

今天发现 google 的 blogspot 的连后台 www2.blogger.com 都被封了!恼怒之余,在网上查解决办法,发现一个帖子:
http://www.williamlong.info/archives/833.html
说明了一个非代理的解决办法,即修改 hosts 文件,定位到另一个真实的服务器。由于 google 有很多服务器,这确实是一个比较好的办法。

更进一步,根据这个原理,实际上只要能够正确的设置 DNS,不使用国内的 DNS 就可以了。例如,现在的 DNS 查询结果:
C:\Documents and Settings\sysadm>nslookup chowroc.blogspot.com
Server: ns-pxb.online.sh.cn
Address: 202.96.209.6

Non-authoritative answer:
Name: blogspot.l.google.com
Address: 72.14.207.191
Aliases: chowroc.blogspot.com

C:\Documents and Settings\sysadm>nslookup chowroc.blogspot.com
Server: ns-pxb.online.sh.cn
Address: 202.96.209.6

Non-authoritative answer:
Name: blogspot.l.google.com
Address: 72.14.207.191
Aliases: chowroc.blogspot.com
而我在 hosts 文件中的设置是:
72.14.219.190 chowroc.blogspot.com
72.14.219.190 www2.blogger.com
这样前后台都能够正常访问了。

而如果这个新的地址 72.14.219.190 将来也被封了的话,那就只好找找国外的 DNS 服务器了,通常可以将那个 DNS 设置为首选 DNS 等。

当然啦,ZF 还会继续努力,争取将国内的 DNS 和国外的 DNS 彻底隔绝。那么,让我们共同等待 1984 的来临吧。

另一种方法是访问如下的 URL:
http://chowroc.blogspot.com.nyud.net:8090/

另外,使用 nslookup 或 dig 查 blogger.com 可以得到好几个地址:
64.233.163.191, 72.14.207.191, 72.14.219.191
将 chowroc.blogspot.com 和 www.blogger.com 的 hosts 解析都指到其中一个就可以了。

我试过查国外的 DNS,但得到的结果和国内一样,大概这些 DNS 是也是按照地域来区分的。但找了一个在德国的朋友查了一下,也是和国内的一样,不解ing。