Linux Application

SUID, SGID and sticky bit

stick bit以前表示要把这个可执行文件放到swap分区中来加快执行速度,现在这个显然用不着了,因为Linux/Unix的vm子系统会自动完成这种功能。为了“变废为宝”,这个sticky bit并没有被遗弃,现在它的功能是这样的:对于一个目录,如果它被设置了sticky bit,那么它里面的文件只能被文件所有者,目录所有者,或特权用户删除。最好的一个例子是/tmp目录,在Fedora上它的权限是:

$ ls -ld /tmp/
drwxrwxrwt 50 root root 20480 03-09 21:08 /tmp/
$ test -k /tmp
$ echo $?
0

我们可以看到最后一个x变成了t。而如果目录或者文件不具有x权限,那么t就会变成T,比如:

$ touch foo.txt
$ chmod +t foo.txt
$ ls -l foo.txt
-rw-rw-r-T 1 wangcong wangcong 0 03-09 23:53 foo.txt

suid和sgid类似,它们的符号是s或者S而不是t。suid的含义是让可执行文件执行时具有owner的权限,sgid的含义是让其具有owner所在group的权限。例如:

$ ls -l /bin/ping
-rwsr-xr-x 1 root root 41748 2007-04-06 /bin/ping

如果你用ls -l看,你会发现suid的s是在owner权限一组,sgid的s是在group权限一组。

sgid用到目录上的含义是:里面的新文件或者子目录会继承这个group id。而在Linux上,suid用在目录上是被忽略的。

参考资料:
1. http://www.zzee.com/solutions/linux-permissions.shtml#setuid
2. http://www.unixguide.net/hp/faq/5.1.9.shtml.
3. http://en.wikipedia.org/wiki/Sticky_bit
4. http://en.wikipedia.org/wiki/Setuid

给emacs安装color-theme

决定给emacs换个主题,因为默认的这个主题比较丑。

简单搜索了一下,需要安装color-theme这个package。从这里下载:

http://download.gna.org/color-theme/

下载解压缩后,需要

1) 把color-theme.el拷贝到某个load-path中,比如我的是~/.emacs.d

2) 把themes目录也要拷贝到上面的路径中

3) 在~/.emacs里添加下面几行:

(require ‘color-theme)
(color-theme-initialize)
(color-theme-oswald)

注意:网上的很多教程并没提到第2行,但是它必须有,否则会出错。
最起码在我这里如此。

第3行是我自己选择的一个主题,你可以换成你自己喜欢的,浏览里面
的主题可以用M-x color-theme-select,然后一个个地试,觉得哪个好
就把第三行替换成那个。

最后,如果你有其它主题,把它下载到themes目录里,然后再修改
~/.emacs:

(load-file “~/.emacs.d/themes/your-own-theme.el”)
(color-theme-your-own)

这样emacs看起来就很漂亮。

BTW,这里有一款为mm准备的粉红主题,很炫。不知道有没有mm使用emacs?

在emacs里写blog

搜了好大一会儿才找到emacs的这个写博客的插件——weblogger,配置很简单。
不过下载要直接从CVS上取,用如下命令:

cd ~/.emacs.d/
cvs -z3 -d:pserver:anonymous@cvs.savannah.nongnu.org:/sources/emacsweblogs
co -d weblogger weblogger/lisp

然后编辑~/.emacs:

(add-to-list ‘load-path “~/.emacs.d/weblogger”)
(require ‘weblogger)

配置博客:

M-x weblogger-setup-weblog

写博客:

M-x weblogger-start-entry

发表博客:

M-x weblogger-save-entry

保存博客:

M-x weblogger-send-entry
更多的其它命令可以查看weblogger的帮助。

这是第一篇在emacs里写的文章,作个实验。;-)

Update:这里有一个更新版本,用wordpress的同学最好使用这个。

不知道的几个技巧

以前俺好傻好天真。。。

俺以前总以为,一个文档内容要是不停地变化,查看其最新的内容就得先less foo然后不停地按End键。现在,俺终于知道了,tail这东西,它有个选项叫-f,就是干这事儿的!这就省去俺多按N次End键的工夫!

俺以前总以为,要打印某个文件第m行到第n行之间的内容必须用awk,或者head与tail的管道组合。现在,俺总算是明白了,做个事的其实是sed,它短短一句就可以完成!比如,打印第3行到第10行之间的内容就用:

sed -n ‘3,10p’ warnings.txt

俺以前总以为,查找某个进程就得ps aux | grep xxx,现在,俺知道了,其实还有个东西,它叫pgrep,所以可以这样用:

pgrep -l xxx

类似,也有个东西叫pkill。

俺以前居然不知道还有个叫disown的东西,现在,俺终于知道了,挺有用。

俺以前不知道rm还可以这样删除名字以-开头的文件:rm — -xxxx。

在emacs下使用mew

作者: 西邮 王聪

Mew是emacs里面一款很好很强大的邮件客户端插件,最近因迷恋emacs所以决定要把邮件客户端也换成emacs里面的。

在这里,我以Fedora和Gmail为例简单说一下配置过程。

首先需要安装mew,Fedora用户直接

yum install mew

就可以了。安装好之后就开始配置,不用担心,其实很简单。需要修改的配置文件就两个,一个是~/.emacs,另一个是Mew专用的~/.mew.el。虽然说这些配置项放哪个文件里都成,但是最好还是人为区分一下,免得弄得~/.emacs里一团糟。;-)

我在~/.emacs里为Mew添加了下面这些东西:

(autoload ‘mew “mew” nil t)
(autoload ‘mew-send “mew” nil t)
(if (boundp ‘read-mail-command)
(setq read-mail-command ‘mew))
(autoload ‘mew-user-agent-compose “mew” nil t)
(if (boundp ‘mail-user-agent)
(setq mail-user-agent ‘mew-user-agent))
(if (fboundp ‘define-mail-user-agent)
(define-mail-user-agent
‘mew-user-agent
‘mew-user-agent-compose
‘mew-draft-send-message
‘mew-draft-kill
‘mew-send-hook))

(set-default ‘mew-decode-quoted ‘t)
(when (boundp ‘utf-translate-cjk)
(setq utf-translate-cjk t)
(custom-set-variables
‘(utf-translate-cjk t)))
(if (fboundp ‘utf-translate-cjk-mode)
(utf-translate-cjk-mode 1))
(require ‘flyspell)

然后在编辑~/.mew.el(没有就先创建)。我用的可以在这里下载,我这个是综合了网上各路神仙的配置之后的结果。;-) 然后你根据自己需要把它修改成你自己的就行了。

配置完成后我们进入mew模式就可以收发邮件了。我再总结一下它的基本使用方法:

w 写信
M-TAB 补齐收信人信息
Q 退出mew
i 收信
g 跳转邮箱
o 对邮件进行分类
d 把邮件标记为删除

  • 作星号标记
    u 清除标记
    x 对所有标记进行处理
    a 不带引用的回复,不建议使用
    A 带引用的回复,推荐
    f 转发邮件
    y 保存邮件,会提示是保存整个邮件和是仅保存正文
    SPACE 阅读邮件
    ENTER 让阅读的邮件向上滚动一行
  • 向下滚动一行
    n 下一封邮件
    p 前一封邮件
    j 跳到某一封邮件
    N 下一封带星号的邮件
    P 上一封带星号的邮件
    S 按某个指定项目对邮件排序
    / 按指定条件搜索邮件,并进入虚拟模式
    tt 进入虚拟模式,根据线索查看,普通模式下是不可以的
    C 如果设置了多个邮箱,用此切换
    C-cC-m 编辑新邮件,放入草稿中
    C-cC-c 发送邮件
    C-cC-q 取消草稿
    C-cC-a 插入附件
    C-cTAB 插入签名
    C-cC-l 转换当前邮件的编码格式
    C-cC-y 复制部分邮件,带引用前缀
    C-cC-t 复制部分邮件,不带引用前缀
    C-cC-a 把当前的发信人加入地址薄
    C-uC-cC-a 比C-cC-a多加入昵称和名字,推荐

恩,我就知道这些,但这些也已经足够对付日常使用了。如果需要更多,可查看mew官方网站上的手册

参考资料:

1. Mew官方手册:http://www.mew.org/release/info/index.html.en

2. http://www.zhangw.com/emacs/dotmewel.html

3. http://learn.tsinghua.edu.cn:8080/2004211031/publish/GNU/mew.html

emacs的一些设置

在上一篇博客中提到emacs和gnome-terminal在alt键上的冲突,今天在摆弄发现冲突远不止这个。

最明显的一个就是和scim也有冲突!ctrl+space默认是调出scim输入法,而在emacs里其实是mark(我不想用ctrl+@,因为那要按三个键。;-)。如果在gnome-terminal下面用emacs的话就无法mark了。搜搜了,解决方法是,把mark功能映射到shift+space上,把原来的ctrl+space去了,如下:

(when window-system
(global-unset-key [?C- ])
(global-set-key [?S- ] ‘set-mark-command)
)

还有一个就是,emacs默认(最起码在fc7上如此)要在启动时显示一个启动画面,这样每次都得ctrl+l,不爽,去了它。

(setq inhibit-startup-message t)

让ctrl+y也可以粘贴来自X粘贴板的内容:

(setq x-select-enable-clipboard t)

还没完,gnome-terminal还占用着一些ctrl+*键,比如:ctrl+-,这个虽然也能屏蔽掉,但其它还有一堆。算了算了,我还是换Konsole吧~!

关于Meta键

最近在着手使用emacs,难免要和Meta键打交道。可是遇到一个小冲突。那就是,在FC上,Alt键被设置为Meta,而Alt又偏偏正好是某些窗口菜单的快捷键,比如gnome-terminal。这样问题就来了,如果我在gnome-terminal里使用emacs的话,本来是想使用M-b来移动光标,按Alt+b却调出了gnome-terminal的一个菜单,也就是说这个按键被窗口先于emacs捕捉到了。

简单搜了搜,没有太合适的方法。最理想的一个方法是把Win键映射成Meta,把Alt键上的Meta去掉。修改了一下~/.Xmodmap,倒是把Win键给映射过去了,但Alt仍然会被窗口捕捉到。估计还要修改xterm的配置,未果。最后找到的一个临时解决方法是,在gnome-terminal的“编辑->快捷键”里面把快捷键都禁用掉。反正我是基本上不会用Alt键来调用菜单~

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不正是最后一个命令中流的流向么?!多么形象的名字啊!

再来一些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.

进一步学习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都看不懂了。