2008年6月16日星期一

PAM 初步

PAM(pluggable Authentication Modules)是非常有用的东西,如果某些程序需要对用户进行认证,那么通过 PAM 可以获得最大的灵活性,这是因为 PAM 是一个开放的构架,可以为每一个程序写它们的认证方式,认证方式通过模块实现,可以灵活的使用提供的模块,如利用硬件、密码、秘钥等等手段,同时仅仅需要编辑一个配置文件就能使得新的方式生效。

debian 里面 PAM 需要下面几个包:
  • libpam-runtime 含有常用的 pam 认证脚本(在 /usr/share/pam/common-*),pam_getenv(获得环境变量的程序)和一些帮助文件。
  • libpam-modules 含有常用的 pam 模块和帮助文件。
  • libpam-doc 帮助文档。
  • libpam-* 一些特殊的 pam 模块。

传统 Unix 下用户认证一般要求用户输入用户名,然后是密码。但是这限制了认证的方式,也不利于编写程序人的目的。因为往往程序编写者是为了给用户提供另外一个功能,如果需要独立实现某种认证方式,那样并不能使其他的程序获得类似的好处。PAM 的出现给出了一种解决的方案。

我们来看一个 PAM 脚本包括哪些东西。一般 /etc/pam.conf 里面是 PAM 的配置,但是为了给每个程序设定独立的 PAM 脚本,一般放在 /etc/pam.d/<程序名>。因此,可以参考一下这些文件,看看下面我们所说的东西是如何应用到一个实际的例子上的。有四种类型的任务,account 用来在给出了用户名后检查一些信息,如帐户过期否,是否存在;auth 用于认证,即要求用某种方式,如输入密码证明自己是 account 里面所声明的人;password 用于更改密码相关信息;seesion 用于建立起需要的环境,如更改 UID、GID 等。每一个任务可以用多个模块检测,我们可以设定这个检测过程的性质,如 required 表明如果失败将会最终导致 PAM 返回 failure,但是这不会中断继续测试下面的模块;requisite 表明如果 fail 直接返回,这是因为在某些情况下,如登录用户 root 在不安全的信道上,如果输入了 root 不是立即中断的话,root 密码可能就在该信道上传输了,这种情况有必要直接在 accout 上 requisite 不是 root;sufficient 是指如果通过则可以忽略 required 的 failures,如果失败也不要紧(不影响最终结果);optional 成功与否当且仅当这是唯一的一个检测;include 用于包含其他的文件。

下面我们来看几个简单的例子,这是 su:
auth          sufficient pam_rootok.so
session required pam_env.so readenv=1
session required pam_env.so readenv=1 envfile=/etc/default/locale
session optional pam_mail.so nopen
@include common-auth
@include common-account
@include common-session
第一句话说明如果是 root 调用 su,那么就返回成功。后面通过 session 建立了环境变量、locale 并检查 mail。那么 common-auth 等文件里面有什么呢?common-auth 里面是
auth    required        pam_unix.so nullok_secure
估计是要求验证,
account required        pam_unix.so
是 common-account 里面的,
session required        pam_unix.so
是 common-session 里面的。我们还可以更细致的建立自己的规则,这使用 [value=ret ...] 的形式,可选择的 value 有:success, open_err, symbol_err, service_err, system_err, buf_err, perm_denied, auth_err, cred_insufficient, authinfo_unavail, user_unknown, maxtries, new_authtok_reqd, acct_expired, session_err, cred_unavail, cred_expired, cred_err, no_module_data, conv_err, authtok_err, authtok_recover_err, authtok_lock_busy, authtok_disable_aging, try_again, ignore, abort, authtok_expired, module_unknown, bad_item, conv_again, incomplete, default。返回值有 ignore(不对结果产生影响),bad(栈内第一个模块返回失败会作为总体返回值),die(直接退栈返回失败),ok(返回将修改类似 PAM_SUCCESS 的值,但是不会影响类似 bad 的 failure),done(如果成功将直接返回)和 reset(清除前面的栈内值)。比如我们定义的几个类型可以用如下的等价形式,
required
[success=ok new_authtok_reqd=ok ignore=ignore default=bad]
requisite
[success=ok new_authtok_reqd=ok ignore=ignore default=die]
sufficient
[success=done new_authtok_reqd=done default=ignore]
optional
[success=ok new_authtok_reqd=ok default=ignore]
在 /etc/pam.conf 里面,会在如上语法前加入命令如 su 名,但是现在多用 /etc/pam.d/ 每个命令建立自己的文件的形式。

PAM 把很多功能用独立的 module 实现,这些模块有固定的格式,都放在 (/usr)/lib/security 目录里面。多数的 module 自己带有 man page,命名方式为 pam_*.so,配置文件多在 /etc/security/*.conf。下面介绍最常用的 38 个 modules:
  • pam_access.so 控制用户访问(依据 username 和 host name/ip/mac 等),并将成功与否记录在日志中,配置文件在 /etc/security/access.conf。格式为 [+-]:username:from,+- 表示允许或者不允许,username 可以用 ALL EXCEPT 匹配。可选参数为 accessfile(指定配置文件路径),debug(syslog 记录更加详尽),fieldsep 默认是上面的 :,listsep 默认是空格或者 TAB。
  • pam_cracklib.so 用于 password 的模块,可以利用 crack 对用户的密码进行要求,如避免使用老密码、使用老密码的变体(大小写变换、改动过少、回文等等)。可用参数有 debug,type(字符串,默认是 UNIX),retry(重试次数),difok(新密码与原密码不同的字符个数的最小值),difignore(有多少个字符就会忽略 difok),minlen(最小长度),dcredit(正整数表示数字获得的 credit,负数表示必须达到的个数),ucredit(大写字母),lcredit(小写字母),ocredit(其他字符),use_authtok(使用前面的 password 提供的 prompt),dictpath(cracklib 的路径)。
  • pam_dubug.so 用于调试 PAM 的栈,可以让 pam_sm_* 函数返回对应的函数值。
  • pam_deny.so 用于拒绝访问。
  • pam_echo.so 用于显示文件内容,可用 file 指定位置,里面可以用 %s 等显示特殊信息。
  • pam_env.so 用于指定环境变量或者去掉环境变量,可用 conffile 指定一个配置文件的路径,配置文件里面格式为 VAR DEFAULT=? OVERRIDE=?。另外可以用 envfile 指定 VAR=VAL 类型的环境变量表。
  • pam_exec.so 用于执行一个进程,可以设定 seteuid。
  • pam_faildelay.so 通过 delay 设定 auth 产生 faliure 时延迟的毫秒数。
  • pam_filter.so 用于 filter stdin/stdout,可以在 /etc/security/pam_filter 里面找到一些常用的 filter,并用 filter= 指定路径。
  • pam_ftp.so 用于提供一个匿名 ftp 的访问环境,但是不安全,不常使用。
  • pam_group.so 用于提供 group 的权限,它通过 /etc/security/group.conf 的配置(终端、时间),对用户在 /etc/group 里面的 group 进行审查,决定是否给予对应的权利。
  • pam_issue.so 和 pam_echo.so 类似,但是用 \d 类型指定一些变量。
  • pam_keyinit.so 可以限制调用者的 keyring。
  • pam_lastlog.so 用于显示上次登录信息。
  • pam_limits.so 用于设定用户的 ulimits。
  • pam_listfile.so 根据指定类型,如 tty、user、rhost、ruser、group、shell。可以用来确认用户如是否指定列表中所列出。
  • pam_localuser.so 可以用 file 指定对应的 passwd 文件所在。
  • pam_loginuid.so 用于指定登录后的 UID,这在登录程序中经常用到。
  • pam_mail.so 用于通知用户是否有新邮件。
  • pam_makehomedir.so 用于创建用户目录。在某些应用中,登录用户未必具有永久的 home。
  • pam_motd.so 用于显示 MOTD(message of today)。
  • pam_namespace.so 用于设定 SELinux 里面的 userspace。
  • pam_nologin.so 根据 /etc/nologin 确定是否让用户登录。
  • pam_permit.so 使得用户不管怎样都可以获得访问权。
  • pam_rhost.so 根据 rhost 文件决定是否允许获得访问权。
  • pam_rootok.so 如果是 root 则允许。
  • pam_securetty.so 如果 tty 是列在 /etc/securetty 则允许。
  • pam_selinux.so 设定 SELinux 的最基本环境。
  • pam_shells.so 根据 /etc/shells 决定是否允许登录。
  • pam_succeed_if.so 可以根据 UID、GID、shell 或者 username 进行条件运算的结果返回。
  • pam_tally.so 统计尝试登录次数,并可以拒绝超过一定次数的用户。
  • pam_time.so 登录时间进行限制。
  • pam_umask.so 设定用户 umask。
  • pam_unix.so 传统 unix 的认证方式。
  • pam_userdb.so 使用 Berkeley db 认证。
  • pam_warn.so 计入 syslog 日志。
  • pam_wheel.so 检查用户是否 wheel 组。
  • pam_xauth.so 用于传递 su 时 X server 的权限问题,即把原用户的 xauth 传递给 su 的用户。

下面,我们看看 PAM 还有那些有用的 package:
  • libpam-gnome-keyring 使得用户登录 GNOME 之后自动打开 GNOME keyring。
  • libpam-blue 对使用 blueteeth 设备进行登录认证。
  • libpam-ck-connector 对终端用户的键盘输入作日志。
  • libpam-devperm 将某些设备的属主改为登录用户。
  • libpam-dotfile 允许用户使用多于一个密码。
  • libpam-encfs 在用户登录后挂载加密文件系统。
  • libpam-fprint 对指纹识别设备的支持。
  • libpam-http 允许通过 Apache 的 http/https 登录。
  • libpam-ldap 使用 ldap 查询登录。
  • libpam-mount 在会话期间挂载文件系统。
  • libpam-mysql 使用 MySQL 数据库进行认证。
  • libpam-ncp 使用 Netware 服务器进行认证。
  • libpam-p11 使用 PCKS#11 smart card 认证。
  • libpam-passwdqc 是 pam_cracklib.so 的替代品。
  • libpam-pqsql 使用 PostgreSQL 进行认证。
  • libpam-pkcs11 类似 libpam-p11,但是似乎更完整。
  • libpam-poldi 使用 Open PGP smart card。
  • libpam-pwdfile 使用类似 /etc/passwd 文件进行认证。
  • libpam-pwgen 产生可阅读密码供用户使用。
  • libpam-rsa 使用 RSA 秘钥进行认证。
  • libpam-shiled 锁定远程尝试密码的攻击者。
  • libpam-slurm 使用 slurm 进行认证。
  • libpam-smbpass 使用 SAMBA 密码认证。
  • libpam-ssh 使用 ssh 方式,如果成功则设置 ssh-agent。
  • libpam-thinkfinger 对 ThnikPAD 的指纹识别的支持。
  • libpam-tmpdir 给每个用户设定自己的 /tmp。
  • libpam-umask 调整用户的 umask。
  • libpam-unix2 支持 blowfish 的与 pam_unix.so 兼容。
  • libpam-pamusb 支持使用 usb 设备登录。
  • libpam-chroot 登录后 chroot。
  • libpam-cracklib
  • libpam-musclecard 使用 Musclecard smartcard 进行认证。
  • libpam-opie 使用 OPIE 进行认证(一次性密码)。
  • libpam-optw 另外一种一次性密码。
  • libpam-radius-auth 使用 RADIUS 认证。
  • libpam-foreground 用户登录后为 console 进行记录,以确定程序使用的 foreground。
  • libpam-afs-session 分布式文件系统 AFS。
  • libpam-ccreds 当企业网络不可得时允许用户在本地登录。
  • libpam-heimdal 使用 Heimdal Kerberos 认证。
  • libpam-krb5 使用 Kerberos v5 认证。
  • libpam-krb5-migrate-heimdal 提供从 Heimdal 到 krb5 的迁移。
  • libpam-nufw 没看懂。
  • libpam-openafs-kaserver, libpam-openafs-session 和 AFS 相关。
  • libpam-shishi 是 Kerberos 5 的一种实现。

2008年6月15日星期日

login

login 包里面有些什么呢?
/usr/sbin/nologin
/usr/bin/faillog
/usr/bin/lastlog
/usr/bin/newgrp
/etc/pam.d/login
/etc/pam.d/su
/etc/login.defs
/etc/securetty
/bin/login
/bin/su
/usr/bin/sg
首先我们还是从一些命令上看看,nologin 是一种禁止用户登录的办法(把 login shell 改了),faillog 可以显示登录失败次数,并可以设置最大允许失败次数。lastlog 将显示所有用户最后登录的时间。newgrp 改变登录 session 的 gid。login 会显示一个文本模式下的登录界面,输入了正确的用户名和密码后就会打开对应的 shell 和用户交互。su/sg 类似,改变执行命令的 UID/GID。

下面我们来看两个重要的文件,/etc/securetty 是允许 root 登录的终端列表;/etc/login.defs 定义了很多登录相关的变量,如 MAIL_DIR 指向邮件目录,FAILLOG_ENAB 表明是否打开登录失败日志,su/sg 的日志是否打开,HUSHLOGIN_FILE 指定一个文件,若存在则登录时不会显示相关的信息,ENV_PATH 默认的 PATH,ENV_SUPATH 默认的 su 的 PATH,PASS_MAX_DAYS、PASS_MIN_DAYS、PASS_WARN_AGE 就是上篇中 chage 对应的值,UID/GID_MIN/MAX 是 useradd/groupadd 使用的,LOGIN_RETRIES 最大允许重试次数(一般会被 pam 对应的值覆盖),LOGIN_TIMEOUT 登录超时,DEFAULT_HOME 没有 home 时是否能登录。

由于 pam 的使用,login.defs 很多功能都已经 obsolete 了。

passwd

我们看看 passwd 这个基础的包为我们提供了哪些有用的命令,
/usr/bin/chage
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/expiry
/usr/bin/gpasswd
/usr/bin/passwd
/usr/sbin/chpasswd
/usr/sbin/chgpasswd
/usr/sbin/cppw
/usr/sbin/groupadd
/usr/sbin/groupdel
/usr/sbin/groupmod
/usr/sbin/grpck
/usr/sbin/grpconv
/usr/sbin/grpunconv
/usr/sbin/newusers
/usr/sbin/pwck
/usr/sbin/pwconv
/usr/sbin/pwunconv
/usr/sbin/useradd
/usr/sbin/userdel
/usr/sbin/usermod
/usr/sbin/vipw
/etc/default
/etc/default/useradd
/etc/pam.d
/etc/pam.d/passwd
/etc/pam.d/chfn
/etc/pam.d/chsh
/sbin
/sbin/shadowconfig
/usr/sbin/cpgr
/usr/sbin/vigr
让我们一个一个来 man。chage 是为了设置用户密码有效时间长度,强制用户到了时间必须更改自己的密码保证安全性。可以用 -l 列出任意一个用户相关的信息,如
$ chage -l someone
Last password change : Jun 03, 2008
Password expires : never
Password inactive : never
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7
chfn 用于更改用户的 finger 信息,如 full name,基本用法为
chfn [-f full_name] [-r room_no] [-w work_ph] [-h home_ph] [-o other] [user]
chsh 用于更改用户登录 shell,如
chsh someone -s /usr/bin/csh
将用户的登录 shell 换为 C shell。

命令 expiry 可以检查自己的帐号是否过期。gpasswd 和 passwd 分别用来设定组和用户密码。组密码的作用是 newgrp 改变自己的 GID 获得某组用户的访问权。chpasswd 和 chgpasswd 就是用来批量更新用户和组的密码,它们输入是 stdin,格式都是 username:password 或者 groupname:password,使用的 hash 算法可以在命令行上面指定,也可以用在 /etc/login.defs 里面声明的算法。cppw 和 cpgr 可以把一个 passwd 或者 group 文件类似的内容复制到 /etc/passwd 和 /etc/group(同时锁定该文件),加上 -s 后会放入对应的 shadow 文件,这在把用户转移到另外一台机器上的情况下有一定的作用。useradd/groupadd 添加新用户/组,userdel/groupdel 删除已有用户/组,usermod/groupmod 修改已有用户/组的属性,pwck/grpch 检查 etc/passwd 或 /etc/group 和 /etc/shadow 或 /etc/gshadow 的一致性。pwconv/grpconv 使用 passwd/group 创建 shadow/gshadow。un 版本反过来。vipw/vigr 进入编辑对应文件的环境。newusers 是批量创建用户的命令,可以从 stdin 输入用户名和密码。shadowconfig 决定是否使用 shadow。

相关文件:
  • login: /usr/bin/newgrp, /etc/login.defs

adduser

debian 系统里面有传统的 useradd、userdel 和 usermod,但是 debian 更推荐管理员使用 adduser 和 deluser。这些是来自于 adduser 这个包的程序。在 /etc/adduser.conf 和 /etc/deluser.conf 里面有这些程序的配置。

那么为什么需要用 adduser 的命令呢?很简单,因为在直接调用 useradd 时,很多额外的操作必须手工执行,比如如果系统用户有指定的 GID,希望放到一个 group 的目录里。通过 adduser 建立的用户目录可以用 /etc/skel 里面的文件初始化,那么我们可以预先修改 /etc/skel 的内容为用户完成最开始的配置。

相关包有:
  • passwd: useradd, userdel, usermod
  • bash: /etc/skel

2008年6月7日星期六

Debian 字体配置初步认识

在 Linux 世界里,字体的处理不如 Windows 里面那么统一,历史上流传下来的一些方法,还有后面加入改进的方法,Debian 自己还有一个 defoma。总而言之,如果稍微糊涂一点,基本上最后配置不清楚。这里称为初步认识,也就是了解一个大致的机理,一些更为高级的用法,我们会在后面的讨论中涉及。

传统的 X 程序,都是利用所谓的 X core fonts 来做事情的,这些例子有 GNU Emacs、xterm 还有 gtk1 的程序,如 xmms。X 管理 core fonts 使用的基本技术是在配置文件的 Files 段设置的 FontPath。我们一般会把自己的字体放在特定的目录里面,经过处理,这个目录就能成为 FontPath 需要的目录。让 X 知晓这些目录可以修改 xorg.conf,也可以在运行的 X 里面用 xset 命令(或者 xset -display 指定 X)。如
xset fp+ /usr/local/share/fonts/truetype/chinese,/usr/local/share/fonts/truetype/windows
那么如何建立合适的目录呢,你只需要到上述目录中 mkfontdir 即可,对于矢量字体如 true type 的,在此之前需要 mkfontscale。我们可以通过 xset q 检查 FontPath,之后可以用 xlsfonts 获得 X core fonts 的列表。

另外一种就是依靠 fontconfig,这个也更加简单,如果你完成了上述的 mkfontdir 步骤,就可以直接 fc-cache -fv 更新字体的 cache,这一般在 /usr/share/fonts、/usr/local/share/fonts 和 ~/.fonts,然后可以用 fc-list 获得列表。现在多数程序,如 gtk2、qt 的程序都是利用 fontconfig 提供的字体,还有 xetex,呵呵。

那么 defoma 是用来做什么的呢?它主要提供了一个集中的管理模式,一方面可以为 X 提供 core fonts,通过在 /var/lib/defoma/ 里面提供了一个统一的字体目录(里面是字体的符号连接,这样就只需要在这一个目录里面 mkfontdir 即可,并且 defoma 会帮你完成),也为 fontconfig 提供字体。那么 defoma 是如何知晓字体信息的呢?Debian 自己有很多 ttf 安装程序,它们都带有一个 hints 文件放在 /etc/defoma/hints 内,因此,如果我们需要安装新的字体,那么就需要为它们创建对应的 hints,本来 defoma 的确提供了这样一个脚本 defoma-hints,但是在写这篇短文的时候却不可用,原因是它所依赖的库 libft-perl 已经很长时间没有人维护了,而 perl 已经升级到 5.10 而不是原先的 5.8 版本了,因此我们迫切需要有人用 5.10 里面处理 free type 的库重写 defoma 的很多脚本。

让我们期待这天的早日到来!

2008年6月5日星期四

Compiz 初探

没想到我这么快有了一台新电脑,而很高兴的是 NVIDIA GeForce 8300 GS 的显卡让我终于可以摆弄一下传说中的 compiz 了,这个酷酷的 window manager 让桌面变得非常的 3D,哈哈... 下面列出来 debian 的相关程序包,
$ apt-cache search compiz
awn-applets-c-core - A collection of applets for avant-window-navigator
cairo-clock - An analog clock drawn with vector-graphics
compiz - OpenGL window and compositing manager
compiz-core - OpenGL window and compositing manager
compiz-dev - OpenGL window and compositing manager - development files
compiz-fusion-bcop - Compiz Fusion option code generator
compiz-fusion-plugins-extra - Compiz Fusion plugins - extra collection
compiz-fusion-plugins-main - Compiz Fusion plugins - main collection
compiz-fusion-plugins-unsupported - Compiz Fusion plugins - "unsupported" collection
compiz-gnome - OpenGL window and compositing manager - GNOME window decorator
compiz-gtk - OpenGL window and compositing manager - Gtk window decorator
compiz-kde - OpenGL window and compositing manager - KDE window decorator
compiz-plugins - OpenGL window and compositing manager - plugins
compizconfig-backend-gconf - Compiz Fusion configuration system - gconf backend
compizconfig-backend-kconfig - Compiz Fusion configuration system - kconfig backend
compizconfig-settings-manager - Compizconfig Settings Manager
fusion-icon - tray icon to launch and manage Compiz Fusion
libcm-dev - Support code for compositing managers - development files
libcm7 - Support code for compositing managers
libcompizconfig-dev - Configuration settings library for compiz-fusion - development files
libcompizconfig0 - Configuration settings library for compiz-fusion
libdecoration0 - Compiz window decoration library
libdecoration0-dev - Compiz window decoration library - development files
pdfcube - PDF document viewer with 3D effects
python-compizconfig - Compizconfig bindings for python
screenlets - Widget-like mini-applications for GNOME
我们先从实现历史说一下,印象中在 2000 年以前有人就提出过使用 OpenGL 重写 X server 的一部分,使得 X server 能够利用现代显卡的强大功能,但是一直没有真正的做起来。后来好像是 Apple 第一个实现了自己的具有 3D 加速功能的桌面系统(利用了 composite wm),这时候 Linux 里面也开始出现了第一批尝试者。提到这个就不能不谈 Xgl,它相当于为 X server 提供了一个 opengl 的backend(如 Xglx 和Xegl),然后还需要一个对应的 window manager 提供相应调用的接口给用户,实现各种窗口的特效。这样做有一定的好处,如把对显卡驱动程序的支持放到 Xgl 这部分来,上层的 X server 等可以用统一的方式实现;但是这一做法 NVIDIA 在 2006 年的一次会议上给出了反驳的理由,即使得某些特殊硬件功能不能或者难于应用,另外也不方便支持多个显示器。NVIDIA 给出了自己的解决方案,也就是 AIGLX(accelerated indirect GLX),所谓的 indirect 体现在 OpenGL 作图命令流被用一个网络中性的语言发给了 X server,由 X server 代为发给显卡进行处理。而在 Xgl 模型中 Xgl 作为 backends 直接通过 OpenGL 的库控制显卡。这样做的好处在于对 X server 本身不需要作太大的修改,另外 DRI(direct rendering infrastructure)在 AIGLX 下仍然可以被 window manager 所操纵。正因为如此,AIGLX 迅速被 Xorg 所接受,这使得我们可以直接利用 compiz 等 window manager 享受显卡带来的 3D 快感。

Compiz 就是为了利用 XGL/AIGLX 带来的新功能而设计的 window manager,中间一段时间一个分支叫 Beryl,后来两者 merge,现在一般叫 compiz fusion。在 Debian 里面安装好显卡驱动之后,在 GNOME 或者 KDE 里面就可以用 compiz 取代原来的 wm。compiz 是一种 composite window manager,和常规的 wm 不一样的地方在于,composite wm 先把每个程序的输出缓存并进行处理,然后组合成为我们看见的样子。compiz 遵循 ICCCM(inter-clients communication conventions manual),因此可以替换 metacity(gnome 的 wm)或者 kwin(KDE 的 wm)。compiz 工作很大程度上依靠显卡对 GLX_EXT_texture_from_bitmap 这个 OpenGL 函数的支持。

compiz 设计的时候就考虑了 plugin,很多效果都是依靠不同的 plugin 实现的,前面列表中有 compiz-plugins(fusion-plugins-main, -extra, -unsupported),这些 plugins 可以用几种方式配置,比较方便的就是 compizconfig-settings-manager 了。

下面介绍一些杂七杂八的东西:
  • 配置 compiz 的四种方法
  • 插件简介
  • 进入 gnome/kde 之后启动 compiz 只需要在 Run command 里面 compiz --replace 即可。
  • KDE 4 的 kwin 已经是 composite wm 了,可能以后就不用 compiz 了。