I am LAZY bones ? all linux

设置python的stdout为无缓存模式

考虑以下python程序:

#!/usr/bin/env python
 
import sys
 
sys.stdout.write("stdout1 ")
sys.stderr.write("stderr1 ")
sys.stdout.write("stdout2 ")
sys.stderr.write("stderr2 ")

其中的sys.stdout.write也可以换成print。
运行这程序,你觉得会输出什么?试验一下,就会发现,其实输出并不是

stdout1 stderr1  stdout2 stderr2

而是:

stderr1 stderr2 stdout1  stdout2

究其原因,是因为缓存:虽然stderr和stdout默认都是指向屏幕的,但是stderr是无缓存的,程序往stderr输出一个字符,就会在屏幕上显示一个;而stdout是有缓存的,只有遇到换行或者积累到一定的大小,才会显示出来。这就是为什么上面的会显示两个stderr的原因了。
然而,有时候,你可能还是希望stdout的行为和stderr一样,能不能实现呢?当然是可以的,而且对于python,实现起来还特别方便,以下是两个方法:

python -u stderr_stdout.py
PYTHONUNBUFFERED=1 python stderr_stdout.py

第一种方法是给python指定 -u 参数,第二种方法是在python运行时,指定 PYTHONUNBUFFERED 环境变量,这两种方法其实是等效的。
当然,也可以在程序的第一行指定 #!/usr/bin/python -u 然后程序加可执行权限来运行,或者把 export PYTHONUNBUFFERED=1 写到 .bashrc 里去。

gentoo下的pppoe拨号

最近,无线路由坏了,所以只能先用自己的电脑拨adsl了。
其实这本也没什么,我的win7和ubuntu都只要稍微设置一下就OK了。
这里再稍微提一下ubuntu的pppoe设置:记得以前的版本(应该是6.xx的时候吧),NetworkManager是不直接支持pppoe的,还要自己手工设置,然后执行pon/poff来拨号,但是现在进步了,直接在NM里输一下用户名和密码就可以上了。
但是我的gentoo是用wicd来管理网络的,而wicd至今都还不支持pppoe,于是只能用原始的命令行来拨号了。
于是eix一搜,发现有个net-dialup/rp-pppoe,安上,看到有 pppoe-setup、pppoe-start、pppoe-stop。啥都不用说了,先pppoe-setup,再pppoe-start,本以为会很顺利,但是几次尝试都在最后一步出错了,而且提示的错误都没啥价值,不知道从何查起~
正当我无计可施,想妥协安个NetworkManager的时候,忽然灵感一现,发现了可能的错误原因,那就是──内核模块。原来,之前我的gentoo内核基本上也是按需配置的,以前我一直都有路由器拨号,所以没有在内核选项里打开ppp的支持,才导致了这一郁闷的结果,哈哈,既然发现了可能的原因,那就好办了,make menuconfig 里面选上 Device Drivers —>Network device support —>PPP (point-to-point protocol) support 下面的所有项,编译完再重启。再 pppoe-start ,果然看到了 Connected!

湿地博物馆

话说,自从我老婆孩子从老家回到杭州以后,原来刚好够我们小两口住的那个小房间,显然是住不下了。于是只能张罗着搬家和添置一些生活用品,到现在,虽然清苦(房子还是不大,也比较破旧),也总算慢慢安定下来了。
之所以在这里先说我搬家的事情,是因为我现在的住处比较偏远,靠近西溪湿地。然后,附近有一个“中国湿地博物馆”,大热天的,空调足,又免费,所以可以算是避暑胜地。今天──好吧,已经是昨天了(昨晚写这日志由于网络不好没写完)──终于有个周末可以空下来了,就去这博物馆玩了。
由于此博物馆并没有禁止拍照,所以我就拍了些照片回来,供大家观赏,以下图片都可以点击看大图~
这是门口:

点击查看全文 »

oracle里循环搜索父子关系的键

想象一下,如果有一张oracle里的表,存着的是一个linux系统当前的进程信息,有ID、父ID、进程名之类的字段,如果给定一个进程ID,要查这个进程的所有父进程(包括爷爷进程等)的ID,sql改怎么写?这就要用到 CONNECT BY PRIOR … START WITH 子句了。
下面就是这样的一个例子:

--原先的表大致是这样的:
SELECT id, parentid FROM the_table WHERE id IN (14976, 14975);
        ID   PARENTID
---------- ----------
     14975      14657
     14975      14658
     14975      14992
     14975      15047
     14976      14975
--要查所有的父进程,这么干:
SELECT DISTINCT id FROM the_table CONNECT BY PRIOR parentid = id START WITH id = 14976;
        ID
----------
         1
       110
       127
       130
       155
       163
     12930
     13812
     14656
     14657
     14658
     14949
     14950
     14951
     14975
     14976
     14992
     15047

perl 的特色

由于工作中偶尔要接触一下perl,所以我花了点时间,很粗略地看了一遍flamephoenix的perl中文教程。本文就是我在看的过程中记录下来的点点滴滴,对大家不一定有用,但是也可以让不会perl的同学对其有个直观的印象。perl果然是个非主流,哈哈。

字符串有很不同的转义,可以转义大小写。
$a = "T\LHIS IS A \ESTRING"; # same as "This is a STRING"

比较操作符有“比较”这个操作,整数是 <=> ,字符串是 cmp ,会返回 1,0,-1

字符串能进线自加(++)操作,而且逢zZ9会进位,但是不能自减。

字符串的重复操作符是x(小写字母x),对应的python操作符是 * (星号)

条件操作符可以用来选择变量:
$condvar == 43 ? $var1 : $var2 = 14;

数组变量要有个 @ 头,而且可以和普通变量重名,列表用的是(),对应python里是 []。

列表可以用..表示范围: (2, 5..7, 11) = (2, 5, 6, 7, 11) 更神奇的是,还可以用于实数: (2.1..5.3) = (2.1, 3.1 ,4.1, 5.1) 和字符串 (“aaa”..”aad”) = (“aaa”,”aab”, “aac”, “aad”) ,还可以包含变量: ($var1..$var2+5)

列表赋值给简单变量,会得到列表的长度。。。

打开文件的模式(读、写或追加)是通过在文件名前加前缀指定的,所以,我不知道如果要只读打开文件名是 “>“ 的文件该怎么写。

文件测试操作更像bash的风格。

@ARGV[0] 就是第一个参数,而不是程序名本身。

有个 <> 操作符,可以直接按参数顺序读取指定的文件,这个就得实践过才能体会了。

可以像操作普通文件那样操作管道。而且也是用的open函数。

模式(也就是 正则表达式)操作是内置的,而不用像python那样import re。这点倒是比较像javascript。

有类似 awk 的模式匹配操作符。比如: $result = $var =~ /abc/; 这个用在逻辑判断里很方便。

模式的定界符缺省是/,但是可以用m来自定义。

模式匹配以后可以用 $1 $2 $& 等引用匹配到的组。

模式匹配操作可以放在while里循环,还可以pos定位。

elsif 也比较bash。

有 foreach 的语法。foreach语法里的 循环变量 是 循环内部 的局部变量;在循环里改变循环变量,会修改数组的对应项。。。

last就是break;next就是continue;还有个redo。循环控制很强大。

以上两点,可以用这个小程序体会一下:

#!/usr/bin/env perl
 
@list = (1, 2, 3, 4, 5);
print "@list\n";
foreach $temp (@list) {
	print "temp=$temp\n";
	if($temp==2){
		$temp=20;
		next;
	}
	if($temp==3){
		$temp=30;
		redo;
	}
	if($temp==4){
		$temp=40;
		last;
	}
}
print "@list\n";

也支持goto。

单行条件,也很有特色:语法为statement keyword condexpr。其中keyword可为if、unless、while或until。尤其是短循环时,很方便。

用 sub 来定义子程序,用 &xxx 或者 do xxx 来引用。

实参用括号的传入,(&xxx(1, 2, 3)),形参不列出,在子程序里用 @_ 来引用传入的实参。

局部变量有两种, my($xxx) 的变量自在本子程序内有效。 local($xxx) 的变量在本子程序和下级的子程序内有效。

用变量和数组混合做为参数,传给子程序时,要小心有可能传到 @_ 的时,会被重组。

传参数的时候,也可以传地址,这时候,子程序里改变的变量会影响外部。

perl5里有3个预设的子程序,BEGIN、END、AUTOLOAD,这点又有点像awk。AUTOLOAD 是在找不到子程序的时候被调用。

关联数组,就是用任意变量类型做下标的数组,用 %变量名表示,可以用 foreach $key (keys(%hashlist)) 来遍历。这其实就是python的dict。 不过其 sort keys 不知道是什么语法。。。

%fruit = ("apples",17,"bananas",9,"oranges","none");
和这个等效:
%fruit = ("apples"=>17,"bananas"=>9,"oranges"=>"none");
 
可以先数组,再关联数组:
@fruit = ("apples",17,"bananas",9,"oranges","none");
%fruit = @fruit;
反之亦然:
%fruit = ("grapes",11,"lemons",27);
@fruit = %fruit;
不过@fruit可能变成 ("lemons",27,"grapes",11)

关联数组可以直接赋值增加,用 delete 函数删除。 (“lemons”,27,”grapes”,11)

keys 对应的是 values,可以取出所有的值。

可以用each更好地循环关联数组:
%records = (“Maris”, 61, “Aaron”, 755, “Young”, 511);
while (($holder, $record) = each(%records)) {
# stuff goes here
}

$~ 是个系统变量,用于指定打印格式。

@<<< 左对齐输出 尖尖的个数,就是占的位数。 @>>> 右对齐输出
@||| 中对齐输出
@##.## 固定精度数字
@* 多行文本

select 可以改变缺省文件变量,这样就可以输出内容到文件了。

format 还可以设置页眉。。。

$^是页眉格式,$=是每页行数。还有个当前页的行计数器: $-

设置系统变量$|为非零值,则输出到文件的时候不使用缓冲。

内置了一套完整的文件处理函数,基本上和linux命令是同名的,用法也类似。比如: read/getc/mkdir/readdir/rmdir/rename/link/unlink/chown/stat 等等。

perl和C类似,存在指针,也可以叫“引用”。和C的&取地址符类似的是 \ 地址可以指向所有的类型,包括子程序。

perl也是面向对象的──类是一个Perl包,其中含提供对象方法的类。方法是一个Perl子程序,类名是其第一个参数。对象是对类中数据项的引用。

与包的引用结合,可以用单引号(‘)操作符来定位类中的变量,类中成员的定位形式如:$class’$member。在Perl5中,可用双冒号替代单引号来获得引用,如:$class’$member与$class::$member相同。

一个perl程序可以用package切分成很多个“包”,各包之间有独立的命名空间,而且程序可以随时在包之间来回切换。

perl里有两个和python的import类似的语法,require和use,require更像C的宏替换,use更像import。然后和 sys.path 类似的数组叫 @INC。

还有 cpan 很强大~

Common Internet File System

Common Internet File System 是samba的一部分,用于取代 smbfs 来挂载windows的共享文件夹,cifs比smbfs应用更广。
要使用 Common Internet File System 需要linux内核开启 cifs 支持。具体是要打开 File systems —> Network File Systems —> CIFS support (advanced network filesystem, SMBFS successor) 这个选项。如果是模块的话,使用前确保加载了。
然后,挂载共享文件夹,可以用mount命令的 -t cifs 选项来调用 mount.cifs。具体是:

sudo mount -t cifs //机器名或IP/远程/目录/ 本地挂载点 -o user=域/用户名%密码,iocharset=utf8

当然,没有域的话,也可以省略域。如果要指定其他mount的选项也是可以的,比如指定uid和gid之类的,这里就不多说了。

另外,如果gnome-base/gvfs开启了samba支持的话,也可以在nautilus的地址栏里直接输入 smb://机器名或IP/远程/目录/ 来打开远程目录,有密码时会弹出对话框输入。
这两种方法各有各的好处。

Google Storage

Google Storage是一个Google旗下的云存储服务,其数据存于美国的数个数据中心。主要面向开发者,免费提供100G的空间和300G的流量,当然,如果你愿意出点钱,可以获得更多。但是目前还处于测试阶段,不能直接注册,可以在这里申请,运气好的话,过几天就会收到试用邀请了。
我有幸获得了试用资格,体验了一下,就在这里记一下感想。

首先,Google Storage把所有存在上面的数据都放在一个个的“Bucket”里面,而这个bucket的名字,是所有用户共享的,也就是说,我建了个叫bones的bucket以后,其他人就不能再建这名的bucket了。
然后bucket里,就是一个个的object了。也就是说数据其实只有 bucket/object 两层,并没有常见文件树的嵌套目录结构。幸好object的名字可以带斜杆,而且web操作上也确实可以用带斜杆的object name来模拟目录结构。

其实,Google Storage采用Key/secret对的形式来进行权限管理,一个google账号可以同时建立5个Key/secret对。这样,在保证安全性的同时,也最大程度地提供了便利性。
权限这块,好像还可以把某个bucket的权限开放给指定的用户和组(就是google group),这个要用下面介绍的 GSUtil。

另外,Google Storage还提供了一个python写的命令行工具GSUtil,不过只有linux版和mac版,当我windows下安个cygwin还是可以跑的,呵呵。安装这个工具也很方便,直接下载解压到任意目录,然后配置一下环境变量,让系统能找到gsutil及相应的库就可以了,详见这里
首次运行gsutil,程序会让你输入Key/secret对,你把web上生成的信息输入进去,就可以使用了。
目前,使用这个工具可以建立/删除 bucket和object,以及上传或重命名文件;还可以用于设置权限等。

就玩了这么多,不过它还有个python的开发库,应该是可以重点研究的,如果能写个东西把这100G空间挂载到本地目录,应该还是蛮好玩的,呵呵。

个性鼠标


这其实是一个鼠标,前几天在网上无意中看到的,觉得挺有意思,就买了来。
刚拆包的时候,感觉第一印象是做工很一般,不过想想才15块钱,也差不多就这样了吧。
试用了一下,目前感觉还不是很习惯,呵呵,左右键还可以,但是要在鼠标移动的时候双击之类的,就会有点困难了,而且移动的时候经常定位不准。
不过也有个好处就是打开一个很长的网页以后,手可以脱离桌面来操纵滚轮,这点不错。
另外,这个滚轮没法按下,这对win可能没啥,但对linux来说,就无法简单地粘帖了。。。幸好同时按下左右键这个操作还算比较方便,弥补了一下。
另外,虽然宣传说可以边用鼠标边打字,但是其实一个手指被套牢以后,打字还是会很别扭的。
为了试试可用性,特意用这鼠标去win下打了局魔兽(冰封王座,不是魔兽世界),以我这极菜的水平,还是可以勉强打赢一个简单的电脑,哈哈,就说明这个还是有潜力的。
再贴张使用时候的图:

虽然这玩意不算很完美,但是多少体现出一种创新吧,还是蛮赞的~
多一些这种个性产品,生活也会更美好的。

Chromed Bird ── Chromium下的twitter客户端

这段时间,我偶尔用pino上推,但是大部分时间都是直接用官方的web客户端了。其实感觉官方的web客户端也是挺好用的,当然前提是你要有web翻墙的手段,比如ssh或者VPN。
然后,我打算近期把主浏览器从firefox迁移到chromium,在装上了Proxy Switchy!AdBlock以后,基本的应用就没问题了,于是自然而然地试着找twitter客户端了,于是就被我发现了这个Chromed Bird,装上一看,真是有相见很晚的感觉,早知道我就早点用chromium了~
先上图:

装完以后,地址栏右边就会多出一只鸟,点击就可以开始使用了。
这个客户端,基本上包含了所有必要的优点:界面简洁、反应快速、提示合理、支持url缩短和展开,支持官方和非官方RT、连地标和list等都支持、还支持实时搜索、自定义功能强大、还同时支持API和Oauth。
总之很优秀~

========补两张图========

cryptsetup – 分区加密工具

cryptsetup是linux下的一个分区加密工具,和之前介绍过的eCryptfs不同的是:eCryptfs是文件系统级别的加密,而cryptsetup是分区级别的,比文件系统级别工作在更底层的位置,是在经过加密的块设备上,再创建文件系统,再挂载使用。这应该是纯软件能达到的最底层的加密了吧。
我折腾这玩意,是因为上篇文章说到,我要把/home的数据备份到另一个硬盘,而那个硬盘的物理安全性并不能得到充分地保证,所以只有通过加密来确保数据的安全了。如果当年陈老师也用这玩意的话,想必不会捅出这么大的篓子,呵呵。

废话不说,简单说说安装和使用的方法。
如果你是用ubuntu这类发行版的话,安装部分就很简单了,基本就是直接安装cryptsetup这个包,就完事了。
但是如果你和我一样也是用自己编译内核的发行版,比如gentoo的话,使用中可能会出现以下错误:

/proc/misc: No entry for device-mapper found
Is device-mapper driver missing from kernel?
Failure to communicate with kernel device-mapper driver.
Cannot initialize device-mapper. Is dm_mod kernel module loaded?
Command failed with code 22: Cannot initialize device-mapper. Is dm_mod kernel module loaded?

这时候你不要急着去安装 device-mapper ,因为现在 device-mapper 已经并入到更强大的 lvm2 里面了,所以你要确保装了 lvm2 和在内核选项里选择了CONFIG_DM_CRYPT,如下:

-> Device Drivers
  -> Multiple devices driver support
    -> Device mapper support
      -> Crypt target support

另外,还建议选取大文件支持的CONFIG_LBDAF和CONFIG_CRYPTO_AES两个内核选项,我这边不选取前者,会无法打开加密分区(虽然说LBDAF是2T+的单文件支持,而我的硬盘一共只有80G);后者是一个内核里的加密算法API,我们就用这个算法来加密(也可以用其他的算法)。

说说怎么使用:
建立一个加密的分区,很简单,执行下面的命令:

sudo cryptsetup --verbose --verify-passphrase -c aes-cbc-plain luksFormat /dev/sdb1

我的外接硬盘在 /dev/sdb1 ,因为这个命令会摧毁这个分区的所有数据,所以程序会让你确认,输入大写的YES,回车,就会让你输入两次密码,输完就搞定了。
话外音:其实cryptsetup不仅支持用密码加密,还支持用文件来加密,可以是任意类型的文件,不过解密的时候,要确保文件一个字节都不差,用这个特性可以方便地构建解密U盘。

好了,加密完分区以后,要使用的话,可以这样:

sudo cryptsetup luksOpen /dev/sdb1 back

其中最后的“back”,可以是任意字符串,程序会提示输入之前设置的密码,输对密码以后,文件系统里就会多出一个 /dev/mapper/back ,接下来就可以像使用 /dev/sdXX 一样地使用这个 /dev/mapper/back 了。
比如,建立一个ext4文件系统,挂载,复制文件之类:

sudo mkfs.ext4 /dev/mapper/back
sudo mount /dev/mapper/back /mnt/back/
sudo cp XXX /mnt/back/
....

使用完以后,可以这样显式地关闭加密分区:

sudo cryptsetup luksClose /dev/mapper/back

看看如果别人偷你加密后的硬盘,想挂载看你的艳照时,会怎么样?哈哈:

$ sudo mount /dev/sdb1 /mnt/back/
mount: unknown filesystem type 'crypto_LUKS'

PS: 现在ubuntu的易用性确实越来越好了,ubuntu里插入加密的硬盘后会自动判断,并直接弹出输入密码的窗口,输完自动挂载分区。