2008/1

sudo和tee

今天刘洋同学问到一个问题,为什么sudo下面的命令还是无权限

$sudo echo ‘1’ > ip_forward
bash: ip_forward: Permission denied

而以root身份就可以?

# echo ‘1’ > ip_forward

一开始没有看出原因来,后来仔细一琢磨,其实原因很简单,shell对‘>’解释干扰了对这个命令含义的判断。我们本想应该是这样的意思:让sudo执行后面的这些“echo ‘1’ > ip_forward”,而实际上是:sudo echo ‘1’ ,执行到这里,shell再把它的执行结果重定向到ip_forward里去!当然是无权限,因为流本身不会随echo那样被sudo“感染”上suid权限!

解决方法是什么?也很简单,就让后面那一串东西搁一起执行:

$sudo sh -c ‘echo 1 > ip_forward’

等等,还有没有更好的解决方法?有!刘洋同学认真思考了一下,觉得应该有这么个东西XX: echo ‘1’ | sudo XX ip_forward。我擦亮眼睛一看,我靠,这不就是tee(1)么!!没错,另一种解决方法就是:

$echo ‘1’ | sudo tee ip_forward

或者:

$echo ‘1’ | sudo tee ip_forward | cat > /dev/null

刘洋问tee(1)是不是和tea有关系?不是!tee其实取自大写字母T的发音,而T不正是最后一个命令中流的流向么?!多么形象的名字啊!

唐磊-我们的歌

数星星,数星星
我在思念你
不怕风不怕雨
有我陪着你
数星星,数星星
不要再担心
啦啦啦啦啦啦我永远爱你
我的兄弟这首歌曲你还记得吗
那些情景那些回忆都历历在目啊
你总喜欢在宿舍墙上乱抹乱画
你总喜欢在夜深人静时一个人弹着guitar
我的兄弟那段岁月你还记得吗
那些往事回想起来就好像昨天一样
你总喜欢在点名时候让我帮你应答
你总喜欢穿着破洞的牛仔在女生楼下溜达
我的兄弟这些年来你还过的好吗
那个女孩你深爱的还和你在一起吗
记得你曾说过将来一定会娶她
告诉你吧其实我也曾经暗恋过她
我的兄弟这些年来你变得坚强了么
你曾说过梦想是一朵含苞待放的花
好想回去再和你一起高声的歌唱
唱那首歌曲那段旋律唱我们的青春哪

———————-华丽的分割线———————-

很喜欢这首歌,送给所有的好哥们~!!

不知道俺下次再回学校时能否和兄弟们一起去K这首歌??

再来一些shell技巧

1. 批量删除某些指定文件

我们都知道用find,很快就可以给出:

find . -name ‘your_pattern*’ -exec rm -f {} ;

恩,不过还有更快更简洁的方法,用find自带的delete:

find . -name ‘your_pattern*’ -delete

2. 列出当前目录下的所有目录(不递归)

你能想到几种方法?我这里有三种解决方法:

(1) $ ls -l | egrep ‘^d’

(2) $ find . -maxdepth 1 -type d

(3) $ ls -d */.

最后一个是从别处看来的,很巧妙。欢迎提供其它不同的方法。

3. 打印文件的倒数第N行

以倒数第2行为例,我的通常做法是:

$ tail -2 my_file | head -1

另一种方法是:

$ gawk ‘BEGIN {RS = “none_existed_pattern”; FS = “n”}; END {print $(NF-2)}’ my_file

[注:在一些awk(不是gawk)中,RS应该是一个字符,而不能是正则表达式。]

4. 产生连续的数字

常见的方法是用seq:

比如产生1~10的数字,

$ seq 1 10

其实也可以用:

$ echo {1..10}

倒叙时这样:

$ seq 10 -1 1

或者:

$ echo {10..1}

用seq的好处是可以指定步长,但它只能针对数字; {..}虽然不能指定步长,但可以适用于字母。另外,很明显,seq的分隔符是n,而{..}是空格。

5. *grep

你最常用的很可能是grep,可是除此还有两个grep:fgrep和egrep。fgrep是Fixed grep的缩写,而不是fast grep,事实上,搜索同样的字符串时fgrep通常比grep要慢;egrep是Extended grep的所写,因为它采用了扩展的正则表达式和更好的算法,所以你应该更倾向于用egrep而不是grep。

题外话:有多少人知道grep是什么缩写?我也是最近才知道的,它其实是Global Regular Expression Print的缩写,ms也有人说是Get Regular Expression And Print。grep如此常用,以至于连词典都把它收录为一个单词了。

[Jargon File]
grep

/grep/ vi. [from the qed/ed editor idiom g/re/p, where re stands for a regular expression, to Globally search for the Regular Expression and Print the lines containing matches to it, via Unix grep(1)'] To rapidly scan a file or set of files looking for a particular string or pattern (when browsing through a large set of files, one may speak ofgrepping around’). By extension, to look for something by pattern. “Grep the bulletin board for the system backup schedule, would you?” See also vgrep.

最近看的几部电影

《苹果》:很黄。不过那不重要,重要的是这部影片的主题,深刻反映了底层人民无奈的生活,现实对他们来说太残酷了,或许只能无奈地接受。正如其英文名字:Lost in Beijing。

《电锯惊魂 4》:很暴力。我一直很喜欢《电锯惊魂》这部电影,从1一直看到4。别说我变态,看这部电影能让你认真地思考人生的意义!虽然里面的男主角使用了一种极端的手段去强迫麻木的人们去重新认识生命的意义,但回过头来想一想:是不是人类都是只有在失去后才知道珍惜? 有句话说得好,“死亡教会人一切,如同考试之后公布的结果——虽然恍然大悟,但为时晚矣!”别以为活着是理所当然,别以为你拥有的一切都是应该的,趁着自己还活着,好好珍惜,赶快去生活吧!

《当幸福来敲门》:很好。里面的一句话印象很深刻,“You got a dream, you gotta protect it. People can’t do something themselves, they wanna tell you that you can’t do it. You want something? Go get it. Period.” 保卫自己的梦想,然后努力去实现梦想,这是我们都应该学会的。

《我是传奇》:很强大。也是威尔-史密斯主演的,给我最大的感受是:如果地球上只剩你一个人,你还有勇气活下去吗?

《不能说的秘密》:很浪漫。故事情节不错,很浪漫的爱情故事。可现实是:现实远没有那么浪漫。

《大电影2.0》:很凑合。里面的一句话还算经典:“人至贱则无敌,我们就是三贱客呀!”

《投名状》:很没意思。借用网上那句经典的评价一下:“男人不可靠。”

《集结号》:很无聊。战斗场面拍得还不错,可惜故事情节老套,从开头差不多就能猜到结局。

splice(2) considered useful?

无意中发现Linux还有splice(2)这么个玩意儿,而且Linus本人对其很是赞赏,还一门心思地给它做广告……那我们就来看看它到底是何方神圣。

splice(2)绝对比我想象中要难以理解,一开始以为它的功能和dup2(2)差不多,然后觉得不对,似乎和sendfile(2)差不多,后来发现也不对!(否则还加这么一个系统调用干嘛?!)它和sendfile(2)的差别还算是比较大的,后面我们会细谈。

splice(2)这东西,其实它的名字就已经告诉我们它是做什么的了,可因为它牵扯到了pipe,所以就变得不好理解了。我们知道,Unix里的pipe有两端,一个写另一个读。我们通常都用pipe来实现进程间的fifo通信。而splice却用pipe来连接一些东西,所以,它名字就可以告诉我们,它是用来把其它fd和pipe的某一端拼接到一起的!也就是说,splice(2)的两个fd参数中必须有一个是pipe的一端,否则就会产生EINVAL。而且,当某个fd是pipe一端时,其对应的offset pointer必须是NULL。而且而且,splice(2)不会block,读不到数据时它会返回0。还有一点格外重要,一定要注意数据流动的方向,splice(2)对这个方向是很敏感的。

我们可以看出,splice(2)和dup2(2)语意差别显著,并且,当调用两次splice(2)把pipe两端连接到两个其它文件时,其功能就等价于sendfile(2),都是zero copy。进一步思考,其实splice(2)控制的是某个不可见的buffer,而dup2(2)和sendfile(2)控制的都是文件本身。

wikipedia上也有对splice(2)的解释),不怎么详细,里面给的例子还可以,我对着它做了改进,算是用splice(2)实现了sendfile(2)的功能,代码见下。

注意1:LWN上的这篇文章过时了,不用看了。

注意2:man pages里对splice(2)原型的描述是错的!那两个表示offset的参数的类型都应该是loff_t,而不是off_t!我已经做了一个补丁提交给man pages的维护者。

补丁:http://wangcong.org/down/man-2-splice-loff_t.diff

代码:http://wangcong.org/down/splice_copy.c

进一步学习git

以前仅仅掌握了git的基本用法,对git里的很多概念还是不清楚。鉴于使用git之频繁,今天决定仔细学习一下git。

简单地搜了一下,发现中文的似乎就没有很深入介绍git的,都是一些基本的东西。英文教程中,最好的当然是kernel.org官方的教程,一篇详细介绍了git的概念,可以在这里得到;另一篇介绍了一些更核心的东西,在这里

git里有两个强悍的东西,一个是object database,一个是index file。先看前面那个,所谓object database就是存放所有object的一个“数据库”,其实就是.git/objects,里面放的东西自然都是object。git里的object分四种类型:tree,blob,commit,tag。所有的object都有各自的“编号”,叫ref,就是你每次git-log时看到的里面那长长的16进制数字,比如下面这个:

$ git log
commit 03bbe082cffc4533f6557bf23f0c672307067246
Merge: 3047290… fb49161…
Author: Linus Torvalds <>
Date: Thu Jan 17 15:50:19 2008 -0800

这个object的类型显然是commit。这个数字是怎么来的呢?其实就是对object的内容,时间,作者等信息进行SHA1之后得到的。如果你上网络安全课没有睡着的话,你应该知道,这玩意儿其实是为了保证数据的完整性。这样一来保证了不同的object的“编号”不会相同,二来保证了object内容和其它信息的完整。

我们再继续看那四个类型,commit刚才已经看到,它其实就是表示对文件的修改。而一个文件的内容被称为blob,一个目录的状态被称作tree。由此可见,commit是基于tree的,它引用它的parent,表示从这个parent这个tree到历史上另一个tree的“过程”。git-cat-file可以帮助我们查找某个object的类型,或者查看它的内容。而git-ls-tree可以帮我们查看tree的内容。tag object是一个包含tag的object,而tag通常是一个指向某个tag object或commit object的ref,所以我们可以在.git/refs里看到tags。再多说一句,在commit里面,HEAD恐怕是最有名的一个了。;-)

好了,我们再接着看index file。这又是个什么东西呢?也很简单,它其实是个“子虚乌有”的东西,当你对tree里的东西做了修改后,你可以git-diff查看修改,而当你再git-add之后,不带任何参数的git-diff就查不到结果了,因为修改都放到index file里去了!index file又是实实在在存在的,它在.git/index里,以二进制的形式存放。再回头来看,不带任何参数的git-diff其实比较的是index file和当前目录内容的差异。你git-commit一次其实就是把一次git-add的内容加入历史,而git-commit -a才是把所有git-add的结果加入。

还有什么不明白的呢?恩,head,注意,这个是小写,和上面提到的大写的那个不同。head其实应该是指某个ref,不信你看.git/refs/heads。为什么这里是叫heads呢?因为一个branch一个head,branch可能有多个,heads自然就是复数了。一般我们的heads里都有个master,看看它的内容,其实就是一个ref。

这样我们就对git里的概念有了个大体了解了,至少不至于连git的man pages都看不懂了。

共享上网和NFS

有两台电脑,一个上网帐号,为了让两台电脑都能上网,得动手搭建一个小型局域网,“自己动手,丰衣足食”啊!前提是拨入网络的电脑必须配有两个网卡。

物理设备齐全后开始进行配置。先配置拨号的电脑(简称为S),两个网卡,一个用来拨号,一个用来和另一台电脑(简称为C)通信。eth0和ppp0就留作拨号,而eth1配置成192.168.1.1,和C连接。C的IP配置为192.168.1.2,网关为192.168.1.1。这还没完,此时C还够不到外网,必须还得用S做个代理,要是在Windows上恐怕得用sysgate了,可咱用的是Linux,两条命令搞定:


sudo /sbin/iptables -F #这个是把FC7自带的防火墙规则全部清掉

sudo /sbin/iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
最后在C的/etc/resolv.conf里加上DNS服务器地址就可以了。这样,两台电脑上就能同时上网了。

这样还不够,虽然它们都能上网,可它们之间共享东西还不方便,那就开nfs吧!

NFS服务器还是在S上开,把属性设置成可写就是了。先编辑exports文件:


sudo vi /etc/exports

内容如下:


/home/wangcong/ 192.168.1.2(rw,sync)

然后开启NFS需要的服务:

sudo /sbin/service rpcbind start

sudo /sbin/service nfslock start

sudo /sbin/service netfs start

sudo /sbin/service nfs start
接下来是C主机,本以为直接mount就可以,谁知得到如下错误:


$ sudo mount 192.168.1.1:/home/wangcong /mnt

mount.nfs: rpc.statd is not running but is required for remote locking

Either use “-o nolocks” to keep locks local, or start statd.
经过尝试,原来还需要开启nfslock和rpcbind,打开就是了:


sudo /sbin/service rpcbind start

sudo /sbin/service nfslock start

这样再mount就可以使用NFS了。

又是该死的网通

哎,家里也是网通的天下,没办法,上网只能装网通的~~

NND,钱都交了4,5天了连网线的影子都没看到,去了好几次营业厅,答复总是“我们这几天忙,装的人多,你再等一等。” 怒了,我交了那么多的“初装费”(这边的网通发明了这么一个概念,真tmd绝!)你还让我等?!直接一个电话投诉给山东网通总部,结果第2天一大早就马上有人过来装了!!恩,网通处理投诉的效率我很满意!

哎,猪肉涨价了,上网费也涨!!以前是3M,30¥/月,现在是2M,40¥/月!根据每1M的费用来算,翻了一倍啊!

总之,网通越来越会扯蛋了~!还有,只有反抗才能取胜!

08年的这几天

最近这几天考试很多,都没时间写博客了。

一到考试就烦,憋着一肚子不爽。既然考试都是操蛋,那我们就用扯蛋的态度去应对!还有,最好别把我惹急了,我就是没毕业证也不愁工作!少拿一个大学的破文凭来吓唬人!吓唬别人或许有用,对我来说没用!要不是照顾父母的感情,我完全可以马上就退学!

不说了,说些高兴的事儿。

在新年第一天给内核提交了一个patch set,第一次以这种形式提交,全部人工解决Cc,Subject等问题,相当得累!还好这次心比较细,没出任何错误。:-) 而且最后经过两次修改后,全部被接受。值得小庆祝一下!

另一个事情就是在走之前计划要和Dr. Chen好好谈一次话,非常期待,因为俺一直比较羡慕Dr. Chen有博士头衔,俺这辈子算是没指望当博士了。有人说,千万不要和有博士头衔的人玩扑克!真不知道和Dr. Chen打一次扑克会输多惨?-_-U

BTW1: 回家的火车票已经买好,9号下午走,系里的手续已经办好,下学期应该不会来了。有事儿的请在9号之前联系我。

BTW2:老外们圣诞节放假放到啥时候啊?!N封邮件没人回复,N个补丁没人收。。。