Tuesday, October 11

Secure delete (Windows)

在操作系统里,文件删除后,并且从垃圾桶里清空之后,文件所在的页面被标为“可用”(unused),待下次有文件写入需要这个空间的时候,这个页面才会被改写:所以说,这时候这“已删除文件”并没有真正被删除。

好处:如果你反悔,有可能能把这些文件内容找回来。


如果你真的要删除这些文件,把这些文件内容彻底改写,在Windows环境可以使用微软出品的 sdelete (Secure Delete). 它把所有unused的页面都写上0,那些“已删除文件”被彻底抹掉:
 sdelete -cz C:  
在Linux 环境下可以用dd生成极大的文件(内容都是0)充满整个硬盘,把所有“可用”(unused)页面都用起来,然后把这个文件删除掉(scrub能做完这个事情)。

好处:1,硬盘这些空间都写上电荷0,可以减轻重量,减少环境污染。
2,如果你这个环境是一个虚拟环境(virutal machine),比如VirtualBox 或者Vmware, 而且你的虚拟硬盘是动态分布的,那么在做完这个操作,把未用空间都填0之后,在host环境可以把这些未用空间收回来,缩小这个虚拟硬盘的实际大小(它的最大空间不变,随着你以后写入文件,它的实际尺寸以后还会长大)。

用VirtualBox的话,命令是:
VBoxManage modifyvdi xxxx.vdi --compact


附注:FBI有一些硬盘探测工具能够读取硬盘磁道的残留信息,找出该扇区在被改写之前的字节,以及在那之前的字节,以及...。即使在用sdelete的时候可以用 -p 来指定写入的次数(比如说,一百次?),也不能保证你的数据百分百没有被读出的可能。

Labels: ,

Saturday, October 1

士人政府的由来

昨天提到士人政府,有必要写详细一些。

人类在进步,部落在发展,在中原(现河南一带)名为夏/商的部落的文明发展得最快,或许是因为在黄河边上,耕种容易,衣廪实则知礼节?或许是周围有一些(恰好数量的)蛮、戎的入侵,足以刺激它的发展又不至于灭族?又或许是它的位置与周围其他部落的交通方便,交流(侵略也是交流的一种)取得最多知识?总之,它最先发展了文字、礼仪,建立了一整套管理机制:一个国家诞生了。

别的部落过来取经(不排除有被夏/商打残了的部落),也纷纷成立自己的国家,并尊称夏/商为共主,文字、文化得以传播天下。在部落时期这个部落就已经是周围部落的领头羊,现在有了文字、礼仪,它的地位更尊崇,文化传播业更广远:山东山西、湖北、陕西、河北都包括进来了。

那时候的一个“国”就是一个城,本部落的人就是领导阶层,每一房有自己的分工:专事祭祀的、专事生产的、专以武力保护国家的;有一房(大房)是专门当皇帝的。俘虏、部落败坏子弟是奴隶。城外就是“野”。

这就是当时“中华”的拓扑结构:每个城邦管理着自己的子民,防范别国和蛮、戎的入侵,同时向夏/商称臣进贡,以换取文化的传播和强大的中央之国的保护(以及“不侵略”的承诺),各国之间也有一些联姻的交流。这时候的中国就是个城邦制,或者是邦联制。

这里我把夏和商合并在一起,是因为夏朝的存在还是一个假设。我们在殷墟挖到了商朝的国都,通过对其中龙骨(用于占卜的龟壳)上甲骨文的解读,以后世的记录相对印,我们知道商的确切存在,对它的发展有个大概的了解;可是我们从来没有找到商朝之前的文化古迹:所找到的商朝之前的,都是一些部落的痕迹,不足以支撑一个国家的存在。

商朝末期,纣王无道。以血缘或小圈子传承的体制一定会碰到这个问题,接位的可能有好人,但是一定会有坏人;没有监督机制的制衡,接位坏人的只会更坏,更坏,越来越坏,不能再坏。纣王就是这样一个不能更坏的接位者。陕西一个发明了易经的周王国认为自己的文化并不比商差,有心做全中华的共主,就起兵伐纣。中华当时所有诸侯国都被卷入了这场战争,有的助周,有的助商。《封神演义》很详细地记载了这场战争的各路诸侯。这本书我很多年没看了,很想念啊。

大家都知道,周赢了这场战争。镇守在西北的部队总是能从与西北蛮戎的战争中获得更多的战争经验,以及更强壮的血缘和基因。后世的秦、唐都证明了这一点。战争结束,周王朝正式开始,在灵界封神的同时(详见《封神演义》),在人世间也封诸侯国,重新洗牌,把亲属和在战争中做成贡献的将领分封到各个诸侯国,强化周在各地的统治,“封建王朝”正式开始。

周王朝共800余年,包括西周和东周;东周又分为春秋时期和战国时期。每一次分段都是周王室对各诸侯国的统治力量削弱的标志。在最后的战国时期,各国之间互相争斗,已经完全不考虑周王室的存在了。可见封建王朝分封制的失败。

在这期间一定要提的是孔子把王室专有的知识传到民间。前面说到,王室里专门有一房是专管宗庙祭祀的,他们是真正的知识分子,把握着所有的知识,父传子受,别人不得与闻。皇帝有什么问题都要跟他们商量。而孔子把他学到的知识传授给民间,“有教无类”,这是值得大书特书的事情,从此所有人都可以努力学得知识、礼仪。更多的可参看《孔子的教育家地位》。士人阶层从此出现。

秦灭诸国,合并天下之后,没有再采用分封制,而是采用中央集权的郡县制,中央政府确切地行使管理全国的职责。这是前所未有的事情:商、周都是把诸侯国里的事情丢给各诸侯管理,而现在每个郡、每个县里的情况都由中央派人管理。这是前所未有的事情。这是前所未有的事情。重要的事情要说三遍。然后书同文,车同轨,秦王政是不愧于“始皇帝”这个称呼的。

汉朝建立后,同样采用郡县制,法规也大多遵循秦制。可是,有一个东西一定要改变:
以前的诸侯国很小,本部落的人(后来就是贵族)作为领导就足够管理,后来任用士人,也是把他们当做家臣来使用,这些士人的忠诚就是为贵族、为王上的忠诚。现在采用中央集权,难度大大提高,况且疆界也比以前大了好几倍。因此大批平民出身的士人被作为职业公务员招进了政府机构,他们不再成为“家臣”的一员,而是为“天下”而工作。在朝廷上,宰相带领百官成为“外朝”,以天下为己任,与外戚、宦官所组成的“内朝”相制衡。

对不起前面说了那么长的历史,就是要介绍清楚这一点:以前的朝廷是贵族(统治部落)的“家事”,宰相(家臣)为了让君上解忧而努力;现在的朝廷终于第一次由平民的精英士人掌管外朝的权利,是"of the people, by the people, for the people"。

王莽就在这么一个恰当的位置出现了:他既是外戚,又是苦日子出身(父兄皆死),饱读经书,礼贤下士,也是士人的一员。因此内朝和外朝都把他当做自己人。


Labels: ,

王莽

秦灭诸国,合并天下之后,法规严苛,而且战争后遗症发作:上层相信军队能征服一切,下层受苦于严重的军费支出。所以由陈胜吴广在鱼肚里放入“大楚兴 陈胜王”的字样,掀起反抗暴秦的浪潮,在推翻秦朝统治后循例以内战来决定政权得主(其实是后世抗日成功后国共两党“循例”以内战决定政权),最后以流氓刘邦胜了楚国贵族项羽为终,建立了汉朝。

汉朝为了革除以前各国(战国各国,包括秦)以传统贵族和军人为统治力量的弊病,大力提拔出色的平民(当然是文人/士人),当时的宰相大多为世间大儒来担当;这些书生得了势,竟然培养出了尊重三代古制而叫嚣变法让贤的王莽。

我们知道商、周以来除了改朝换代之外,皇位都是父传子受。尧舜禹是传说中的古代部落里的英明领袖,以将大禅之位让于后辈贤者而著称。现代还没有确切的考古证据来确认他们的存在,但孔子、周子经常在著作中提及他们,羡慕他们那个时代的清明。 西汉司马迁写《史记》的时候,就用“能让天下,贤哉二君!”(指尧与舜)来结束第一章《五帝本纪》。在士人的理想社会里,君子领天命而传天下,在年老体衰时就择贤而禅让,让下一个(年轻的、贤明的)君子得以延续自己的政治生命,管理天下以达大同世界。与血缘无关。

有学者认为这些禅让制度是书生臆想出来的传承方式,比如韩非子在《说疑》一文中说:“舜逼尧,禹逼舜,汤放桀,武王伐纣,此四人者,人臣弑其君者也。”而顾颉刚指出:“禅让之说乃是战国学者受了时势的刺激,在想象中构成的乌托邦。”说这是墨家为了宣传主义而造出来的。总之,这是士人希望的理想社会的传承。

王莽是外戚,姑姑是皇后,伯父是大司马,但父兄皆死,家庭俭朴。他没有官二代的毛病,饱读诗书,礼贤下士,当官之后也善待穷人,深得民众爱戴;在汉哀帝执政期间他被迫下野,期间儿子犯了事,他逼着儿子自杀以谢天下。这时是他名声最盛的时期。后代唐朝白居易说:
周公恐惧流言日,王莽谦恭未篡时。
向使当初身便死,一生真伪复谁知?
指的就是这个时候。

公元前1年,汉哀帝死而无后,皇权回到他奶奶王莽的姑姑手上。这个奶奶把王莽召了回来,立了另一个8岁的孙子作为汉平帝。王莽当政,权倾天下,在公元5年被众政府官员向太皇太后(他姑姑)提议加九锡并接受了。这个加九锡的仪式是周代传下来的由皇帝表彰大臣的最隆重的礼节:当时历史上只有齐恒公接受了两锡。王莽是有史以来第一个九锡大臣,可见他多么深受同事、上级的信任!

同一年,14岁的汉平帝病死(或说是因反抗王莽的操弄而被害死),王莽协同他姑姑立了一个两岁的孩童为皇太子(世称“孺子婴”),而自称为“摄皇帝”。

三年之后,他根据“陈胜王”籤語的传统,收集了一些民间祥瑞,比如深井里发现石牛,或者什么地方发现什么石文,向他姑姑上了一个表章(并随后迅速得到批准),说是根据这些祥瑞和预测,我们应该改变一下。从此王莽面见太皇太后及皇太子的时候,自称“假皇帝”,而别人对王莽的称呼,就是“皇帝”。

在他收集民间祥瑞的时候,一个游手好闲的大学生看到了机会:"Opportunity is knocking!" 他造了两个铜匮,一个里面刻着说这两个金匮是汉高祖刘邦传下来的,王莽应该是真皇帝,另一个说上天派了11个大臣来辅助王莽,这十一个大臣分别是八个当前的王莽的党羽,两个他生造的名字,一个是他自己的名字“哀章”。在王莽成了“假皇帝”之后,这两个“金匮”就被进贡了,把王莽吓一跳:我还没准备好呢,这么快?想了两天后,他还是决定接受了, It's a shame to let it wasted。因此在他上一个表章的4天之后,他来到汉高祖的祠堂拜受了金匮,然后带着王冠发了诏书,受汉高祖之命接受禅让,并变法以强国富民。西汉正式结束,新的朝代叫做“新朝”,从公元8年至23年。

柏杨与钱穆认为王莽的受禅和变法,是士人要缔造强大的理想社会的伟大尝试。在受禅前,王莽已经位居高位,权倾天下,可以为所欲为,如果只是为了私欲,他不需要做这个政治冒险的,甚至在新朝之后,他的生活依然俭朴。但是为了心目中的士人理想社会,他需要这样的受禅来向天下证明“让贤”的可行。跟皇室打了这么多年交道,他很清楚皇室的肮脏:我这么贤良的人,为什么要受汉哀帝的气而下野隐居7年?为什么要把8岁的汉平帝养大来反抗自己?现在还要捧着个不懂世事的孺子婴?他们凭什么因为血缘就能比我高一级?把王位早给我,我早就把这个天下治理好了!

王莽变法的政治主要有:
1,王田,把天下田地收归国有,而平均租给耕者。我可以说在1940年后共产党就是这么做的么?
2,废奴,把奴仆解放出来。王莽这个做法也是顺应当时解放生产力的要求,打击大奴隶主、大地主。
3,盐铁专卖,从大商贾手上把这些与民众生活紧密相关的贸易抢过来。人民政府为人民啊。
4,均输,类似于平抑市价,控制市场的方法。

这些措施没有得到当时民间的拥护,钱穆称之为“书生的政治”,15年后被以刘秀为首的反动地主阶级疯狂推翻了,东汉开始。历史是由胜利者书写的,所以东汉(以及后来的统治者)把王莽称为篡位的叛臣逆子,在上位前是善于伪装的伪君子,因为这些统治者都害怕后人以王莽为榜样,把不称职的皇帝擅自改换掉。虽然《吕氏春秋》和《六韬》就有“天下非一人之天下,天下之天下也”的说法,但是统治者绝不会赞成这样的说法,而努力培养大众的奴性,加强自己的统治。

禅让在中国并没有真正地实行过,直到现代。历史上除了皇权父传子受,都是血腥的改朝换代。不过在1877年,一些华人在南洋站稳了脚跟,成立了亚洲的第一个共和国:兰芳共和国,就是以民主选举和禅让的方式传承,延续了107年后被荷兰入侵而灭亡。

清帝退位勉强算一个:“特率皇帝将统治权公诸全国,定为共和立宪国体,近慰海内厌乱望治之心,远协古圣天下为公之义。”皇室和袁世凯之间没有刀戈相见,算和平退位。但是天下没有大平,袁世凯、张勋、和各军阀随后掀起的混战,让这次“禅让”丢了分。

前面说到哀章进贡了11个大臣的名字,王莽真的接受了:那8个党羽自然顺理成章地提拔了上来,哀章也如愿以偿地进了朝廷。捏造的两个名字,也被寻访到了:一个叫做王兴的城门令史,和一个叫做王盛的街头卖饼儿,就因为名字正确 ,“两人容貌应卜相,径从布衣登用,以示神焉”,平步青云。

Labels: ,

Monday, August 1

每当变幻时


作詞:盧國沾

怀缅过去常陶醉 一半乐事 一半令人流泪
梦如人生 快乐永记取 悲苦深刻藏骨髓

韶华去 四季暗中追随 逝去了的都已逝去
啊 常见明月挂天边 每 当变幻时 便知时光去


怀缅过去常陶醉 想到旧事 欢笑面常流泪
梦如人生 试问谁能料 石头他朝成翡翠

如情侣 你我有心追随 遇到半点风雨便思退
啊 常见红日照东方 每当见夕阳 便知时光去



这首歌由1977年熏妮首唱,街知巷闻,次年1月即获得第一届香港十大中文金曲荣誉。老年南蛮都应该听过啊,这是标准的年龄暴露歌曲。

这首歌是香港的集体回忆,虽然没有别的歌星为它录音,但是许冠杰、温拿乐队、梅艳芳等都在演唱会上唱过,引起全场附和。

要是你不懂粤语,也听着这歌觉得好听,绝不奇怪!这首歌的国语版是《月光小夜曲》:


作詞:周藍萍

月亮在我窗前徜徉 透进了爱的光芒
我低头静静的想一想 猜不透你心肠
好像今晚月亮一样 忽明忽暗又忽亮
啊 到底是爱还是心慌啊 月光
月夜情境像梦一样 那甜蜜怎能相忘
细语又在耳边荡漾 怎不叫我回想
我怕见那月亮光 抬头把窗帘关上
啊 我心儿醉 我心儿慌

这首歌是台湾歌手紫薇(绿岛小夜曲的原唱)在196x年首唱,后来徐小凤、蔡琴都有唱,都是我的菜。

李克勤的粤语“月光小夜曲”跟这首歌完全无关,略过。

上面我只写了这两首歌的词作者。曲作者是古賀政男。这首曲子原是1943年在台湾出品的电影《莎韻之钟》的主题曲,而电影是关于一个名叫莎韻的土著少女,帮忙日籍老师搬行李,遇到台风失足落水。

走过这片芦苇坡,你可曾听说,有一位女孩,她留下一首歌。

For the sake of completeness, 这首《莎韻之钟》的主题曲:
西条八十作詞
古賀政男作曲
渡邊濱子演唱
歌词 (中文大意):
狂風吹落花一枝
哀哉消逝水煙中
舊社森林鳥照啼
為何妳不歸,啊啊,沙韻。


虽然李香兰在电影里饰演主角莎韻,但是这首称颂台湾皇民化的电影,还是从日本请来最出名的女星渡边滨子演唱。


光阴似箭,日月如梭,到了2007年,香港回归10年,香港连拍了三个献礼片:梁咏琪的《女人本色》,黄秋生《老港正传》,和 杨千嬅的《每当变幻时》。第一个千万别看,说的是一个成功职场女士在1997-2007这10年里如何努力工作,老公死了,孩子死了,还是相信香港明天会更好。第二个很闷,说一个左派的生活,我看不懂。第三个才是我要介绍的:它以盧國沾的《每当变幻时》作为主题曲,这就已经很够味道了。杨千嬅、 陈奕迅都是本色演出:市井生活。1997年,他们在菜市场奋斗;2007年,杨成了成功职场女性,可是,情已经不在。





每当变幻时,便知时光去。

Labels:

Thursday, October 22

Show the complete apache config file

In the Apache config file, you can use "Include" or "IncludeOptional" to include other config files. A lot of the Linux variants take advantage of that to organize the config files. For example, the default congif file of Ubuntu is in /etc/apache2/apache.conf, and it includes enabled modules, enabled sites, and configuration files this way:

IncludeOptional mods-enabled/*.conf
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf

If you really want to see all the complete config settings, there is no existing tool for that. This Stack Overflow page  answered this question pretty well: You can use apachectl -S to see the settings of Virtual Host, or apachectl -M to see the loaded modules, but to see all settings, there is no such tool, you will have to go through all the files , starting from familiar yourself with the  general structure of the httpd config files. 

So I created this python program to generate the complete apache config file:

#!/usr/bin/python2.7
# CombineApacheConfig.py 
__author__ = 'ben'
import sys, os, os.path, logging, fnmatch


def Help():
    print("Usage: python CombineApacheConfig.py inputfile[default:/etc/apache2/apache2.conf] outputfile[default:/tmp/apache2.combined.conf")


def InputParameter():
    if len(sys.argv) <> 3:
        Help()
        return "/etc/apache2/apache2.conf", "/tmp/apache2.combined.conf"
    return sys.argv[1], sys.argv[2]


def ProcessMultipleFiles(InputFiles):
    Content = ''
    LocalFolder = os.path.dirname(InputFiles)
    basenamePattern = os.path.basename(InputFiles)
    for root, dirs, files in os.walk(LocalFolder):
        for filename in fnmatch.filter(files, basenamePattern):
            Content += ProcessInput(os.path.join(root, filename))
    return Content


def RemoveExcessiveLinebreak(s):
    Length = len(s)
    s = s.replace(os.linesep + os.linesep + os.linesep, os.linesep + os.linesep)
    NewLength = len(s)
    if NewLength < Length:
        s = RemoveExcessiveLinebreak(s)
    return s


def ProcessInput(InputFile):
    Content = ''
    if logging.root.isEnabledFor(logging.DEBUG):
        Content = '# Start of ' + InputFile + os.linesep
    with open(InputFile, 'r') as infile:
        for line in infile:
            stripline = line.strip(' \t')
            if stripline.startswith('#'):
                continue
            if stripline.lower().startswith('include'):
                match = stripline.split()
                if len(match) == 2:
                    IncludeFiles = match[1]
                    IncludeFiles = IncludeFiles.strip('"') #Inserted according to V's comment.
                    if not IncludeFiles.startswith('/'):
                        LocalFolder = os.path.dirname(InputFile)
                        IncludeFiles = os.path.join(LocalFolder, IncludeFiles)

                    Content += ProcessMultipleFiles(IncludeFiles) + os.linesep
                else:
                    Content += line     # if it is not pattern of 'include(optional) path', then continue.
            else:
                Content += line
    Content = RemoveExcessiveLinebreak(Content)
    if logging.root.isEnabledFor(logging.DEBUG):
        Content += '# End of ' + InputFile + os.linesep + os.linesep
    return Content


if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s][%(levelname)s]:%(message)s')
    InputFile, OutputFile = InputParameter()
    try:
        Content = ProcessInput(InputFile)
    except Exception as e:
        logging.error("Failed to process " + InputFile,  exc_info=True)
        exit(1)

    try:
        with open(OutputFile, 'w') as outfile:
            outfile.write(Content)
    except Exception as e:
        logging.error("Failed to write to " + outfile,  exc_info=True)
        exit(1)

    logging.info("Done writing " + OutputFile)


The usage is simple: Run it as "python  CombineApacheConfig.py ". Since there is no additional parameters given, it will retrieve the default Ubuntu apache config file from  /etc/apache2/apache2.conf and generate the result complete config file in /tmp/apache2.combined.conf. If your config file is in different location, then give the input file and output file location.

Note: Apache server-info page http://127.0.0.1/server-info also provide similar information, but not in the config file format. It is in human readable format. The page works only when it is open from the same computer.


Labels:

Nice, but is there a way to dump the configs if macro_module is being used.

Thanks
 
It's a nice looking idea, but doesn't seem to be including any included files... is this working for other people?
 
Let me correct/clarify that a bit... It seems to work if the include is a full path and not a relative path to the httpd config root (which works for apache and is allowed as far as I know).

This works
Include /etc/httpd/conf/vhosts.d/*.conf

This does not work (although apache is OK with it)
Include vhosts.d/*.conf

For some reason, this does not work (from a whm/cpanel httpd.conf)
Include "/etc/apache2/conf.d/userdata/std/2_4/username/*.conf"

I'm guessing the issue in the cpanel example might be the quotations around the string

 
Hi V,

Confirmed that path with quotations will not work. But the relative path definitely works well for me.

I will update the program to deal with quotations later. With source code, you should be able to do that as well :)

 
Inserted one line "IncludeFiles = IncludeFiles.strip('"')" to deal with the config file with quotation marks according to V's comment.

Thanks, V.
 

Thursday, October 15

Python logging OnMarkRotatingFileHandler

When there is a need, there is a solution.

As explained in the previous post "The TimedRotatingFileHandler of python logging system", the handler is not doing what I am thinking to do. So I made this new handler OnMarkRotatingFileHandler to fulfill my need. For example, assuming the Interval setting is "Hour":

1, If the program starts at 8:20AM, the TimedRotatingFileHandler will restart a new log file at 9:20AM, but my OnMarkRotatingFileHandler will restart a new log file at 9:00AM.

2, If the previous log file was last modified at 8:58 AM, if you start the program with old handler after 9:58, it will rotate the log; if you start the program before 9:58, say 9:55 the program will just append the log entries into the existing log until 10:55, if your program runs for that long.
With my new handler, now at 9:00AM, when the program starts, the new handler will rotate the log file to generate new log file.


Source code:
#filename: logHandler.py
__author__ = 'ben'

import logging.handlers

class OnMarkRotatingFileHandler(logging.handlers.TimedRotatingFileHandler):

        def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False):
            #super().__init__() # in Python 2 use super(D, self).__init__()
            super(OnMarkRotatingFileHandler, self).__init__(filename, when, interval, backupCount, encoding, delay, utc)


        def floor_to(self, num, scale):
            return int(num/scale) * scale


        def computeRollover(self, currentTime):
            temp_result = super(OnMarkRotatingFileHandler, self).computeRollover(currentTime)
            if not self.when.startswith('W'):
                result = self.floor_to(temp_result, self.interval)
            else:
                result = temp_result    # need to find out the first date of time (is it 1970/1/1?), what weekday that is.

            return result


Most methods are inherited from the TimedRotatingFileHandler. The W0/W1.../W6  options are not implemented yet. But you get the ideal.

To use it, place the logHandler.py with your code, then you can either import it and load it as

    import logHandler
    h = logHandler.OnMarkRotatingFileHandler ("filename")
    logger=logging.getLogger('app')
    logger.addHandler(h)


or you can use it in the logging.ini:
    class=logHandler.OnMarkRotatingFileHandler

then load it in logging.config like every other handler does:
    logging.config.fileConfig('logging.ini')


Have fun hacking!


Labels:

The TimedRotatingFileHandler of python logging system

The name of TimedRotatingFileHandler is like the best for my need: rotate every day, keep 30 days of copy. I know the logrotate of Linux system provides the same service, but I prefer to make the program easy to install and run without System Admin (root) involving in the process. Another reason I am not using logrotate is that when my program is writing into log at midnight, logrotate would perform "mv myprogram.log myprogram.log.20151015", and my program is still writing into that file which has a new name now: myprogram.log.20151015, while I still have another program trying to access myprogram.log for display purpose, then that program will fail.


So I want to have a native logging handler to do log rotating, and change to a new file of "myprogram.log" at midnight. The TimedRotatingFileHandler looks perfect to me.


But it is not.


The TimedRotatingFileHandler only rotate the log when the program has been running for more than 24 hours (Assuming the interval setting is 1 Day ), or if the log file has not been modified (before loading) for more than 24 hours. You can check the code, but that is what it is. If your program runs every day from 1AM to 11PM, then the log is never rotate, it keep appending forever. It is using the last modified time of the log file , or current time when the file doesn't exist, to decide when to rotate.


One limitation is that in Linux there is not "file creation time" or "birth time". Most file system don't support this file attribute. I guess ext4 does, under some configuration, but we can't rely on it.





Labels:

Sunday, September 20

关于微信(其实不只是微信,几乎所有中国开发的苹果app)的恶意病毒 xcodeghost


微信跟其它许多软件一起,iOS版本都发现了问题,因为没有用正版苹果开发软件来开发,所用的盗版开发软件在编译后得到的结果软件偷偷把一些信息传给坏人。在这个安全公司的网站上有当前发 现该问题的所有软件,包括微信、滴滴打车、网易云音乐等。
http://researchcenter.paloaltonetworks.com/2015/09/malware-xcodeghost-infects-39-ios-apps-including-wechat-affecting-hundreds-of-millions-of-users/

新版本的微信声称已经解决了问题。强烈建议大家修改Apple ID密码,和所有相关的密码。我将会把这些软件卸载并修改Apple ID 密码。


一人据称是始作俑者,是他把正版苹果开发软件xcode下载之后加上一些恶意代码,放到百度云等地方,并在许多论坛里放上链接让人下载,使网易、腾讯等公司的程序员都中了招。他宣称只是一个“苦逼iOS开发者的”的"一次错误的实验",并把一段代码公布出来。

我读了一下那段代码,没有什么恶意攻击的地方,只是简单地收集一些很大众的信息并上传到一个我没办法查到有用信息的网站。

首先我怀疑这段代码是不是真的、所有的代码;其次,可能有别的黑客把这段代码加工之后做一个新的xcode,据知现在找到的恶意代码起码有三个不同版本;然后,仅就这段代码而言,编码很老练,没有什么废话;风格很成熟,不是新手所为;再有,那个网站隐藏自己很老到,所牵涉到的注册商等都在美国;它也曾在另一个iOS病毒KeyRaider里使用;而且,在各论坛里发帖,把自己的百度云下载地址拉到搜索的前面,这也很需要搜索引擎优化技术,不是普通程序员的风格。连迅雷下载拿到的都是中毒的。

联想到在国内下载正版苹果开发软件xcode很慢、且不停断线,以至于实际上不可能下载成功,我有理由怀疑这是国家行为:由网络长城来挡住正版的下载,然后用注入了恶意代码的版本来取代正版。

5年前Symantec就首先通过分析代码,提出在伊朗核设施里找到的超级病毒Stuxnet是美国、以色列、德国合作的成果。可见国家层面的恶意代码是事实存在的,并非怀疑论者的臆测。

---附: 一个记录
http://blog.jobbole.com/91646/

Labels:

Friday, September 18

历史回顾:三聚氰胺记者手记

追查三聚氰胺真相始末
2009-01-04 17:31   南方传媒研究

赵威
  南方农村报关注三聚氰胺的经历,可以追溯到去年 3月发生的美国宠物毒粮事件,最早跟进的记者就是曾进。
  去年 6月,他在南方农村报专业增刊《养殖宝典》上发表的《三聚氰胺会成为下一个“苏丹红”吗?》一文,可以认为是国内最早预测三聚氰胺将会在国内饲料行业乃至食品行业惹出事端的调查性报道。
这篇文章在当时几乎没有引起任何关注,但却成为一年后南方农村报“追查三聚氰胺”专题系列报道的重要基石。
而见报于 2008年9、10月间的一批稿件所引发的强烈震荡,确实完全出乎我们的意料。
追踪三聚氰胺
今年 9月,三鹿奶粉事件曝光后,我与曾进、麦倩明副主编组成“追查三聚氰胺”专题报道小组的核心。期间,我曾一次次地追问曾进一年前关注三聚氰胺的动机和细节,一次次地被他作为行业记者所具备的新闻敏感与专业素养所折服。
我和曾进做新闻,都是“半路出家”。我是农学理科背景出身,他更是在进入报社之前拥有在饲料行业内工作的经验,专业背景加上深厚的行业资源,成为这次报道能取得突破的重要因素。
去年 5月初,美国农业部与 FDA联合调查宠物毒粮事件结果公布,进口自中国的小麦蛋白粉和大米蛋白粉中含有化工原料三聚氰胺,是导致美国多起宠物中毒死亡的原因。
消息传到国内,并没有引起国内的广泛关注。但曾做过宠物饲料销售工作的曾进却敏感地捕捉到事件背后可能存在着严重的行业内幕。
饲料蛋白原料为什么要添加三聚氰胺?出口国外的的产品会添加,做假者难道会放过检查更加松懈的国内市场?宠物饲料中出现三聚氰胺,那么市场份额更大的畜禽饲料和水产饲料是否也存在非法添加的情况?
带着这些疑问,曾进走访了华南地区十多家饲料生产企业,出人意料的是,各企业的饲料配方师也是一头雾水,均表示“没听说过三聚氰胺”。
是不是自己的判断出现了偏差?曾进追查的脚步开始有些犹豫,直到他见到了顺德华星饲料厂的配方师王工(化名)。“你说的是不是蛋白精?”王沉思许久后的反问,第一次在媒体面前把三聚氰胺和蛋白精联系了起来。在这一刻,南方农村报一年后“追查三聚氰胺”专题的主线其实已经确定,只是当时的曾进不可能预料得到。
王工的怀疑并没有证据,但他可以肯定的是在饲料行业中蛋白原料作假的现象一定存在。他从营养学和生产成本的角度分析了饲料蛋白作假的原动力——假蛋白造成含量虚高,降低成本。王还透露,经常有业务员上门推销的蛋白精,就是饲料行业内有代表性的假蛋白,其主要成分很有可能就是三聚氰胺。
王工的案例分析坚定了曾进继续追查下去的信心。他带着蛋白精的问题再次回访曾表示“没听说过三聚氰胺”的多位饲料行业人士,这次他们不再陌生。
得到行业内的信息后,曾进又开始寻找第三方求证,中国广州分析测试中心所长何建强提供了重要的信息,自宠物毒粮事件以来,该中心陆续接到多宗样品要求检测三聚氰胺,当时平均每月有十多个样本,部分结果确实呈阳性。
随后,曾进的一个饲料行业内线人报料,顺德一家饲料企业的产品在广西被检出20ppm(mg/kg)的三聚氰胺。
以上素材构成了《“三聚氰胺”会成为下一个“苏丹红”吗?》一文的主体,这是南方农村报关注三聚氰胺的第一篇稿件,文中准确的预判,在一年后的三聚氰胺事件调查中一一得到验证。
遗憾的是,该文并没有提供充分的证据证明三聚氰胺是如何流入饲料行业的,也没有确证三聚氰胺与蛋白精之间的关系,留下缺陷的同时也为奶粉和供港鸡蛋检出三聚氰胺事件爆发后的追查预留了空间。
追查仍在继续。去年 11月,曾进在广西桂林参加中国水产学术年会时又有了意外的收获。中国海洋大学麦康森教授在大会主题报告中,开篇就讲到了三聚氰胺在饲料中的非法添加可能会带来养殖产品的质量安全问题。这是国内科研领域专家第一次在公开场合披露三聚氰胺的问题。
曾进迅速捕捉到这一信息,马上联系会后采访麦康森。当天晚上,在会议酒店房间,麦教授接受了南方农村报记者的独家专访。两个小时的采访,双方的沟通非常流畅,麦教授对记者几乎没有设防,围绕着三聚氰胺的行业内幕被层层剥出。
“三聚氰胺在国内饲料行业肯定是有(添加)的,一定是先在中国销售,然后才到国外闹事,我知道某些厂家使用的所谓的蛋白精,就是三聚氰胺,这是毫无疑问的。”
“浓缩蛋白里面一定存在三聚氰胺,国内的水产饲料甚至其他动物饲料都会存在这个问题,包括奶粉。”
来自权威专家语出惊人的预判,曾让南方农村报的记者深感震惊,“奶粉里也会有?!”一年后,预判成真,麦康森名声大振,同时也备感压力。他成为国内最早预测三聚氰胺会在乳品行业出事的专家,南方农村报的记者幸运地记录了这一时刻。
2007年 12月,南方农村报专业增刊《养殖宝典》重点对话栏目发表麦康森教授的专访《水产料最有可能成为三聚氰胺的市场》。
至此,南方农村报追查三聚氰胺的首个阶段告一段落。在这个阶段内,还需要重点讲述的是南方农村报对三聚氰胺在饲料行业内模糊标准的质疑,这也是日后追查专题的主线之一。
2007年 6月,农业部发布名为《饲料中三聚氰胺的测定》的行业标准。7月份《养殖宝典》,麦倩明副主编在《政府“模糊公告”忽悠了谁?》一文中,一针见血地指出,没有明确三聚氰胺在饲料中的限量标准,检测方法将成为一纸空文。
这是国内媒体最早对三聚氰胺的标准问题提出质疑,这个话题在一年后的问题鸡蛋事件爆发后被迅速放大,成为困扰饲料行业的焦点,至今仍没有解决。
突破蛋白精疑云
今年 9月三鹿奶粉事件曝光后,三聚氰胺成为罪魁祸首。面对这样的新闻热点,南方农村报一点都不陌生,一年前,南方农村报在三聚氰胺报道上的积累起到了重要的铺垫作用。我进入“追查三聚氰胺”专题报道组,就是从快速消化之前的这些报道起步的。
最初,我们设计的追查主线是三聚氰胺的源头,混入到奶粉中的三聚氰胺来源于哪里?在奶粉生产链上的哪个环节最可能添加?
带着这样的问题,我和我的同事迅速采访了乳制品行业和饲料行业的多位人士,包括上海光明、雀巢、完达山等国内知名乳品企业和专业生产奶牛饲料的配方师,奶牛饲料中直接添加三聚氰胺的嫌疑被初步排除,目标锁定在奶站和乳制品企业。
现在回头看,当时追查的第一步思路和判断与国内媒体几乎一致,唯一不同在于,当官方把公众的目光吸引到非法奶站环节上时,我们仍坚持发出专业的声音——《企业生产环节违法添加仍有嫌疑》。
麦康森教授一年前的观点使我们把追查的重点重新定位在饲料行业。根据他的判断,三聚氰胺绝不仅仅存在于奶粉中,国内的饲料产品一定混有这种化学物质,三聚氰胺在饲料行业内的使用已经是公开的秘密。然而,此时三聚氰胺在饲料行业和非加工类食品中存在的隐患,已经在全国人民日益高涨的对非法奶站的声讨中,被淹没和忽视。
但此时,南方农村报追查的目标已经锁定。过去几年中,采写瘦肉精、孔雀石绿、苏丹红等事件的经历,使专题组自然地把三聚氰胺和农产品质量安全联系到一起,查证两者之间的关联,成为追查的核心内容。
三聚氰胺可以在乳制品中犯案,又曾在出口饲料原料中留下前科,那么国内的饲料产品是否真的干净?产业链下游的畜禽肉蛋、水产等非加工类食品是否也会存在残留?三聚氰胺是通过什么样途径流入到养殖行业的?
为弄清楚这些问题,我和曾进深入到饲料行业和养殖行业中寻找线索。和我一起长大,现在做饲料贸易的一个死党,无意间给我提供了一个至关重要的信息。抱歉的是,在这里我还是不能暴露他的身份,就叫他死党吧。
据他透露,去年 3月份之前他曾和江苏的一个饲料添加剂供应商有生意上的往来,交易的产品就是蛋白精。这个供应商与去年“美国宠物毒粮”事件中犯案的江苏徐州安营公司的老板是亲戚,对于蛋白精生产流通的内幕一清二楚。
得到这样的信息,我欣喜若狂,马上要求死党联系那个江苏供应商见面,并用记者的职业道德、人品、二十几年的兄弟情谊等等作保证,一定会对他们的身份进行保密。
死党还是有些犹豫,我威胁他说,这件事情办不成,兄弟就没得做了!死党悠悠地说,“这年头,兄弟就是用来出卖的!”
我无言以对,只能等待。当晚 12点,死党打来电话,说江苏人不同意见面,但可以电话采访,让我马上打电话过去,担心明天一早对方反悔。
我躲进书房,拨通手机,按下录音笔,用扬声器完成了这次采访。对方的思路很清晰,开始还有些谨慎,在我一再表明我与死党的关系,他终于放下负担,知无不言。很感谢我的这位采访对象,我可以想象到他背叛行业规则、面对媒体时的压力,在采访中他一直在吸烟,我一直叫他“大哥”,现在还时常有短信问候。
“大哥”用有些拗口的江浙普通话,给我清晰地描述了一张“蛋白精”贸易流通图,并明确指出,蛋白精的主要成分就是三聚氰胺废渣。
做完这个采访已经深夜一点,我毫无睡意,满脑子想的就是那张图,还有如何证实信息的可靠性。我的采访本上至今还保留着那张草图,只有我能看懂。它的成品就是日后被国内各大门户网站和平面媒体或直接照搬,或形象化处理的“蛋白精”贸易流通图。
次日,我通过百度和 google在上网搜索“蛋白精”的信息,各种网上交易琳琅满目。我和我的同事又通过采访饲料行业、养殖企业、原料供应商、中间贸易商和化工行业人士,逐一证实我采访到的信息源。出于可以理解的原因,在我的文章中无法透露他们的真实姓名。
9月下旬,南方农村报和养殖宝典连续发表“追查三聚氰胺”专题稿件,其中以《“蛋白精”真相:三聚氰胺废渣》、《三聚氰胺丑闻大败露》为代表,用系列报道的方式,详细揭露了三聚氰胺变身蛋白精后混入饲料行业的内幕,跳出三鹿奶粉事件看待三聚氰胺对食品安全的污染,专题的前瞻性在一个月后的问题鸡蛋事件中展现得淋漓尽致.
引发强烈震荡
10月下旬,大连韩伟集团供港鸡蛋被检出三聚氰胺,在一个月前的问题奶粉事件中被忽视的饲料行业添加三聚氰胺的潜规则被骤然放大。南方农村报“追查三聚氰胺”的系列报道终于由此得到大众媒体的热点关注。
10月 30日,南方日报、南方周末同时发表我和曾进的署名文章,标题分别为《“饲料添加三聚氰胺已是“公开秘密”》和《问题鸡蛋拨开饲料业“蛋白精”疑云》。南方农村报记者庹朝均的同一天的报道《“蛋白精”出来有五年了》,由广东两位饲料企业的老总,用真实身份在媒体直陈问题,作为行业人士,他们的正直与勇气尤为可贵。
几乎就在 24小时之内,由此引发的饲料行业内的强烈震荡和社会舆论的轩然大波,完全出乎我们的意料。新华网、新浪、搜狐等门户网站纷纷转载稿件,CCTV新闻频道《新闻1+1 》、CCTV经济频道《今日观察》、中央人民广播电台中国之声《新闻纵横》等国内主流媒体栏目,均在 11 月初引用南方农村报的报道跟进追查,中央人民广播电台、中国经营报、南方都市报等众多国内媒体来电采访,并希望提供报料人的联系方式,我只能一一拒绝。
     在此期间,南方农村报一方面通过利用南方报业的媒体平台推广《追查三聚氰胺》专题报道,另一方面仍在饲料行业内深入追查,目标锁定在饲料行业中三聚氰胺限量标准的缺失。与此同时,一场饲料行业的整治风暴在全国范围内刮起,饲料企业、水产行业、养殖行业都承受了巨大的压力,我的同事曾进、庹朝均也承受了来自行业内的巨大压力。国内多家饲料、养殖企业纷纷致电给我,或质疑、或赞扬、或询问、或探讨、或谩骂。
     南方农村报“追查三聚氰胺”的专题至今历时一年半,共见报稿件17篇,先后参与报道的记者 10 人。南方农村报记者深入行业把握动态、团队作战的能力得到充分彰显。在热点新闻事件中,能够发出自己独到权威的声音,充分利用南方报业传媒集团和网络媒体的平台推广独家新闻的实践同样很有意义。
     南方农村报追查三聚氰胺的脚步没有停止。11月 13 日,香港四家鱼场的饲料中检出三聚氰胺,出自福建省福州海马饲料有限公司。这消息马上令之前国内那些一味矢口否认鸣冤叫屈的水产饲料企业收声,南方农村报一年前的预判再次得到验证。
     得到这个消息,我和曾进面面相觑,同一个问题冲口而出,为什么有问题的饲料只有在香港才能曝光?至今,中国饲料行业的三聚氰胺限量标准仍然缺位。
    感谢我的同事,我的死党,还有那些说真话的人,是他们令大众一步步逼近了三聚氰胺的真相。

历史回顾:三聚氰胺 Melamine

2007年3月,“菜单食品”公司发布了一个收回令:收回它在宠物粮市场上的6000万罐猫狗粮,原因是已经确认有16只猫狗死于它所生产的一种宠 物粮(实际死亡数量可能达上千只,但难以确证)。该宠物粮食的一种原料是从中国某公司进口的麦麸,这些麦麸中含有一种会导致动物肾衰竭的元素。
这就是三聚氰胺的首次曝光,但是没有得到中国必要的重视。反而中国当时嘲笑美国小题大做。同一时间,还有美国玩具厂商对中国生产厂的退货,原因是玩具商有些油漆含有铅。中国电视上还有一个节目,一个西装革履的(不知道是官员还是教授还是公知)笑着说,这个玩具上就眉毛这一笔误用了含铅油漆,美国竟然就退货了。他没有小孩吗?不知道小孩子啃玩具是天性吗?
总之,因为这个首次曝光,美国FDA在2007年5月25日发布了关于三聚氰胺的风险评估报告,会导致人/动物肾衰竭。现在人们都知道了,三聚氰胺本来跟食品无关,不应该放在食品里面的,所以本来也没有人专门测试食用三聚氰胺对人类的影响,也没有讨论它的容许量。可是中国一个化工教授发现了这个东西能够愚弄当时普遍用来测试蛋白质的仪表,让蛋白质指数无故升高,就把它取名为“蛋白精”,在神州大陆一时风靡无比。本来在牛奶、饲料里应该有很多蛋白质供人、动物摄入的,现在生产厂商只要加上“无毒无害”的,更重要的是很便宜的“蛋白精”,在检测蛋白质含量时就有了很好看的数字,甚至不需要放牛奶、鸡蛋进去!
中国三鹿集团从2007年底就收到客户的投诉,但是与当地政府一起压到奥运会之后。后来衞生部专家调查组成员、北大司法鉴定中心主任孙东东承认六月初已有人向衞生部举报,八月明确事件,但是直到2008年9月5日新西兰政府得知消息后(新西兰恒天然公司是三鹿集团的海外股东)下令新西兰官员绕过地方政府,直接向中国中央政府报告此次事件,中国政府才严正对待此事。
后面的事情大家都知道了。
2003年的阜阳劣质奶粉事件(大头娃娃事件)可能也和三聚氰胺有关,因为食用了蛋白质指数很高但没有足够蛋白质的奶粉,小孩头脸肥大、四肢细短、全身浮肿。但当时以“产品质量不好”盖过了所有细节,把肇事的小奶粉厂商判刑、关闭了结。