Git起步

我的学习路径:git basic, http webdav, git-svn, gitosis, gitweb,下面是一些学习记录。

http webdav方式访问

ubuntu下安装非常简单,用apt装上git-core包即可。git仓库的外部访问,首先就是最熟悉的用http协议走apache上的webdav服务,方便啊。git自身的身份认证和权限分配弱了一些,不过可以借助apache实现用户分配,passwd文件直接用svn的也没问题。apache配置示例如下:

Alias /git "/big2/git"
<Location /git/test.git>
    DAV on
    AuthType Basic
    AuthName "Test git freely"
    AuthUserFile "/big2/svn/svnpasswd"
    #Require user Fwolf
    Require valid-user
</Location>

但这样远不如使用ssh/git协议访问仓库速度快和稳定,但更适合公开/对外发布。另外和svn的webdav方式不同,git webdav是一种dumb transport,不仅慢而且比较傻,只能进行简单的存、取文件操作,所以hooks是不起作用的(很多文章中说的提交后要在hooks/post-update里启用git-update-server-info,指的是git/ssh方式更新后,为webdav对外发布作准备)不会自动进行和git相关的其它处理。

最好用的还是gitosis,后面会提到。有些内容先以webdav方式下来记,使用的时候根据不同的方式转换用户角色即可。

创建服务端的仓库

其实和svn创建仓库也是比较类似的,找一空目录,比如叫test.git,执行:

$ git --bare init
$ sudo chown www-data:www-data * -R

客户端就可以下载了,但还有些问题:

$ git clone https://domain.tld/git/test.git gittest
Initialized empty Git repository in /home/fwolf/dev/gittest/.git/

error: server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt

首先遇到的是证书错误,git使用curl,所以证书的处理和svn也不一样,用firefox浏览git网站,在Page Info->View Certificate->Details中把网站的根证书(Issued By/root)导出为一个pem文件,然后将这个pem文件的内容添加到/etc/ssl/certs/ca-certificates.crt的末尾就可以了。接着遇到的是401身份验证错误:

error: The requested URL returned error: 401

git不像svn会自动提示用户名/密码,因为它用的是webdav的原生功能,所以需要在$HOME下创建文件.netrc(记得将权限修改为600):

machine domain.tld
login Fwolf
password your_passwd

最后,还是仓库本身不完善的问题:

warning: remote HEAD refers to nonexistent ref, unable to checkout.

在服务器上仓库目录,执行$ git update-server-info并再次chown到www-data就行了。初次push得指明服务器上的origin对应本地master分支/branch:

$ git push origin master

而下载之前,还要设置下载后放到那个分支、与哪个分支的现有内容进行merge:

$ git config branch.master.remote origin
$ git config branch.master.merge master
$ git pull  # 注意如果服务器是新建的空repo,得随便push点东西才好pull

gitosis

还是通过apt安装,gitosis使用SSH key来认证用户,但用户不需要在主机上开账号,而是公用主机上的一个受限账号。首先创建这个账号(名称可变):

sudo adduser \
    --system \
    --shell /bin/sh \
    --gecos 'git user' \
    --group \
    --disabled-password \
    --home /big2/gitosis \
    git

然后生成自己用户的ssh密钥,可以在git用户的$HOME下操作:

ssh-keygen -t rsa

不要密码,可以起名叫git_rsa[.pub],然后用公钥来初始化gitosis的目录:

$ sudo -H -u git gitosis-init < /home/fwolf/.ssh/git_rsa.pub 
Initialized empty Git repository in /big2/gitosis/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /big2/gitosis/repositories/gitosis-admin.git/

可以看出gitosis自己也在用git仓库的形式存储东西,传递公钥进去是为了配置自动登录,将公钥写入git用户的$HOME/.ssh/authorized_keys。接下来就启用gitosis仓库的post-update hook:

$ sudo chmod 755 repositories/gitosis-admin.git/hooks/post-update

其实用apt安装的gitosis,这个post-update早已指向其它文件并具有x属性了。

一点提示:把gitosis的repositories和自己原先的git repo目录弄到一起,以后方便,因为gitosis自己的管理也是要通过git来提交的,在客户端先修改$home/.ssh/config

Host git.domain.tld
Compression yes
IdentityFile ~/.ssh/git_rsa # 注意这个是私钥,不是pub公钥

然后从客户端clone gitosis的配置文档:

$ git clone git@git.domain.tld:gitosis-admin.git

注意实际上这个gitosis-admin.git应该是在git用户的$HOME下的repositories目录下,但这么写才能下载。clone得到一个配置文件gitosis.conf和目录keydir/,对了,git配置的修改、上传也是通过git提交,并且由于刚才设置的post-update hook,立即生效。所以现在就能够远程修改、提交配置了。下面是一份比较完整的自说明的gitosis.conf

# example: http://eagain.net/gitweb/?p=gitosis.git;a=blob;f=example.conf
[gitosis]

## Allow gitweb to show all known repositories. If you want gitweb,
## you need either this or a [repo foo] section for each repository
## you want visible in gitweb.
gitweb = no

[group gitosis-admin]
writable = gitosis-admin
# member is key file name, without (.pub)
members = fwolf

# user group
[group all]
# members = jdoe alice bob @anothergroup
members = fwolf
# this user group is writeable to ... repo, eg: test.git.
# writeable = foo bar baz/thud
writeable = test
#readonly = somerepo

[repo test]
## Allow gitweb to show this repository.
gitweb = yes
## Oneline description of the project, mostly for gitweb.
description = Fwolf's test git repository
## Owner of this repository. Used in gitweb list of projects.
owner = Fwolf
## Allow git-daemon to publish this repository.
#daemon = yes
daemon = no

平时就是为其它用户添加SSH key,然后用git@git.domain.tld:repo.git来连接服务器,gitosis会自动比对服务器上的pub key,判断出用户是谁。

gitweb

用apt安装,得到/usr/lib/cgi-bin/gitweb.cgi,由于cgi-bin已经由ubuntu设置好了,apache只要设置一下资源文件路径即可:

Alias /gitweb "/usr/share/gitweb"

然后修改/etc/gitweb.conf

# path to git projects (<project>.git)
$projectroot = "/big2/git";

$site_name = "Fwolf's Git Repositories";
@git_base_url_list = ("ssh://git\@git.domain.tld");

# directory to use for temp files
$git_temp = "/tmp";

# target of the home link on top of all pages
#$home_link = $my_uri || "/";

# html text to include at home page
$home_text = "indextext.html";

# file with project list; by default, simply scan the projectroot dir.
$projects_list = "/big2/gitosis/gitosis/projects.list";
# Avoid use guess repo's address and edit url manually
$strict_export = 1;

# stylesheet to use
$stylesheet = "/gitweb/gitweb.css";
# logo to use
$logo = "/gitweb/git-logo.png";
# the 'favicon'
$favicon = "/gitweb/git-favicon.png";

重启apache后就能够用http://git.domain.tld/cgi-bin/gitweb.cgi访问了。

git-svn混用

首先还要安装git-svn包,git和svn混用的好处就是既可以用git进行本地提交和灵活的分支,又能够用svn实现集中管理和分发,缺点我想可能就是svn的revision号在git里没有了,另外git有些太灵活,不是很好入门。

首先导入svn的现有项目到一个空目录:

$ git svn clone --username your-name -s https://domain.tld/svn/repo
# older versions of git: replace "-s" with "-Ttrunk -bbranches -ttags"

就这么简单,很多工作git-svn都代劳了,剩下就当正常的git目录使用即可,比如为他们指定git仓库的位置,并下载文件:

$ git config remote.origin.url https://domain.tld/git/test.git
$ git config remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
$ git config branch.master.remote origin
$ git config branch.master.merge refs/heads/master
$ git checkout master   #回到master分支
$ git pull

向svn仓库提交:

$ git svn dcommit

从svn仓库接受更新:

$ git svn rebase

在git-svn的使用中还发现,如果在机器A上使用git-svn,但是在另外一台机器B上用纯git进行了push,那么B上的commit是不会被git-svn认出来并dcommit的,只有pull下来,然后再假commit一下才能让git-svn看到。

仓库地址变更

服务器上直接修改仓库目录名和apache设置,客户端上:

$ git config remote.origin.url https://domain.tld/git/testnew.git
$ git pull  # 这个必须要做,不然不能push
Merge made by recursive.
$ git push

git-svn方式下变更svn的地址

首先要修改所有commit中的地址:

$ git filter-branch --msg-filter 'sed "s/domain_old\/trunk/domain_new\/trunk/g"' $(cat .git/packed-refs | awk '// {print $2}' | grep -v 'pack-refs')

然后删掉缓存,修改地址,重新下载:

$ rm -rf .git/svn
# 编辑`.git/config`修改`[svn-remote "svn"]`的url。
$ git svn rebase (--all)

我还曾经遇到过这样的错误:

$ git svn rebase
Unable to determine upstream SVN information from working tree history

不太好处理,这里有些参考信息,我是在一个repo里pull另外一个仓库的内容了,照下面方式处理也不管用:

  • 从svn里重新clone出一份
  • git里创建个branch保存一下
  • git连接上服务器,pull
  • git checkout 到刚才创建的branch
  • git merge –no-ff master
  • git svn rebase/dcommit

效果不好,不仅产生大量的conflict,而且还是只能在新创建的branch上rebase/dcommit。大概是出现了两“棵”树,怎么也捏不到一起,最后只好重建仓库。

其它使用技巧/tips

  • 回上个版本 $ git reset --hard HEAD^
  • 得到一个文件5个版本以前的状态 $ git checkout HEAD~5 foo.c
  • 由于git是分布式的scm,所以$Id被彻底消灭掉了。
  • 不像svn,git能够记录文件的执行属性。
  • 为显示加上颜色 $ git config color.(branch|diff|interactive|status) auto,或者$ git config color.ui true
  • hooks不算仓库的内容,每个repo的hooks可以不同。
  • 当心svn的hooks,如果git里已经commit,却因为svn的hooks使git-svn的dcommit失败,很麻烦。
  • .gitignore里可以用config.php忽略文件,并且用!mt/config.php指明个别文件还是要归入scm管理的。
  • 从现有的客户端目录中生成仓库目录 $ git clone --bare dev_dir repo_dir 每个客户端都是一个完整备份,方便。
  • 用于ignore文件,.gitignore是要提交的版本,.git/info/exclude则是只在你本地生效的版本,不提交。
  • 仅给ssh登录的开发者push/pull的访问权限,将其shell设置为/usr/bin/git-shell(未测试).
  • info/allowed-users可以控制用户对branch/tag的访问权限(未测试)。
  • git --bare init --shared=group可以让仓库被同group的用户共享,不过有gitosis就不用这个了,我没测试。

参考

Update @ 2009-03-27

使用git-svn的时候,有时候会出现git和svn树不太同步的情况,在进行svn rebase的时候总是重新merge文件,这种现象多是由于以前没有正确rebase引起的,而rebase不成功的一种原因就是git的fast forward。简单理解一下,git是按照树形结构排下来的,如果遇到前后两个节点被判定为“重复”的,git就聪明的作了个fast forward,直接使用后者了。这在git里没事,因为都是一颗树,而对于svn就不行了,它还记录着要从前面那个节点开始呢,所以合并的时候就出现了两个源头的情况,自然会产生问题。所以大体上向svn更新的顺序应该是这样的:

  • git push # git更新
  • git pull –no-ff # 此处的–no-ff最为重要,平时可以不用,这里要用
  • git svn rebase # 准备提交到svn之前先和当前的树合并
  • git svn dcommit
  • git pull –no-ff
  • # 后面就是检查了,前面操作正常的话不会产生新的有效更新了
  • git push
  • git svn dcommit
  • git svn rebase
  • git pull
  • git push

附一张比较典型的出错后来回折腾的结果图: git-svn rebase dcommit error

参考 @ 2009-03-29

有了git track以后,新建要和服务器同步的branch:

$ git branch fwolf
Branch fwolf set up to track local branch refs/heads/master.

$ git track fwolf origin
tracking origin/fwolf

$ git checkout fwolf
Switched to branch "fwolf"

$ git push origin fwolf
Total 0 (delta 0), reused 0 (delta 0)
To git@domain.tld:repo.git
 * [new branch]      fwolf -> fwolf

而从其它客户端下载这个branch就简单多了:

$ git branch --track fwolf origin/fwolf
Branch fwolf set up to track remote branch refs/remotes/origin/fwolf.

掌握原理,不用git track也一样可以实现的。

Update @ 2009-04-18

MediaTemple使用的是CentOS,安装git也很简单:

$ rpm -Uvh http://mirror.centos.org/centos/5/os/i386/CentOS/python-iniparse-0.2.3-4.el5.noarch.rpm
$ rpm -Uvh http://mirror.centos.org/centos/5/os/i386/CentOS/yum-3.2.19-18.el5.centos.noarch.rpm http://mirror.centos.org/centos/5/os/i386/CentOS/yum-fastestmirror-1.1.16-13.el5.centos.noarch.rpm  # 版本号可能会有变化
$ rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-2.noarch.rpm
$ yum -y update
$ yum install git

参考:

Update @ 2009-04-27

升级到ubuntu 9.04 jaunty后,客户端push时会遇到错误:

$ git push
/usr/bin/gitosis-serve:5: UserWarning: Unbuilt egg for ClientCookie [unknown version] (/usr/lib/python2.6/dist-packages)
  from pkg_resources import load_entry_point
Traceback (most recent call last):
  File "/usr/bin/gitosis-serve", line 5, in <module>
    from pkg_resources import load_entry_point
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 2562, in <module>  
    working_set.require(__requires__)
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 626, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 524, in resolve
    raise DistributionNotFound(req)  # XXX put more info here
pkg_resources.DistributionNotFound: gitosis==0.2
fatal: The remote end hung up unexpectedly

半天查不出原因,只是怀疑和python的版本有关系(2.5/2.6),因为gitosis在debian包中的文件,显示应该是对应python 2.5的,不过,试着自己用python(2.6)重新下载安装了一遍gitosis,好了:

	$ git clone git://eagain.net/gitosis
	$ cd gitosis
	$ sudo python setup.py install

不懂Python太吃亏了呀。另外aptitude reinstall gitosis是没用的。

Update @ 2009-05-15

Tsung那里学来一招,可以更改 Git 默认的信息存放目录 .git :

修改 Shell 變數 GIT_DIR => "export GIT_DIR=.test"

Update @ 2010-08-03

升级到 Ubuntu 10.04 Lucid 以后,gitosis 自带的 hook 文件 post-update,就是修改权限等等 commit 后,自动出发 gitosis 更新相关配置的钩子,原来 ln 到的 /usr/share/python-support/gitosis/gitosis-0.2-py2.5.egg/gitosis/templates/admin/hooks/post-update 无效了,更换成 /usr/share/pyshared/gitosis/templates/admin/hooks/post-update 就可以了,参见Bug报告。挺让人无语的bug,我折腾了半天还以为是权限设置出了什么问题呢。

安装配置fluxbox桌面环境

安装

基本系统Ubuntu 7.10 Gutsy,Xfce桌面。直接安装源里的fluxbox:

aptitude install fluxbox

版本1.0.0-1,大小只有1058k。安装完成后,检查一下/usr/share/xsessions/fluxbox.desktop文件,里面已经有Exec=/usr/bin/startfluxbox,不用修改了。重启X,(应该会自动创建~/.fluxbox/startup配置文件。

在X登录界面,Sessions选择Fluxbox,并设置为默认session。输入用户名密码进入系统之后,只看见一个光板的桌面,下面有一条工具栏,想截屏来着,可按PrintScreen键没反应,作罢。不过说真的,进入桌面的速度真的很快。工具栏上点右键可以调出工具栏的设置,桌面上点中键可以调出虚拟桌面的设置,但在桌面上点右键没反应,原来是fluxbox默认配置的问题(害我瞎折腾半天)。

菜单

fluxbox安装完成后默认的菜单配置文件~/.fluxbox/menu内容如下:

[begin] (fluxbox)
[include] (/etc/X11/fluxbox/fluxbox-menu)
[end]

而include的这个菜单文件根本就不存在,所以就没有菜单出现喽。现在我来手工加点内容吧:

[begin] (fluxbox)
[exec] (Firefox) {/usr/bin/firefox}
[exec] (Bash) {x-terminal-emulator -T "Bash" -e /bin/bash --login}
[include] (/etc/X11/fluxbox/fluxbox-menu)
[end]

现在,不用重启或重开X,在桌面上点右键,怎么样,一个小小的菜单出来了吧,内容只有两项:Bash和Firefox,选中后会打开相应的程序。不过真要这样一个一个的把菜单配置全可就累死了,本来fluxbox自带一个菜单生成程序fluxbox-generate_menu的,但在Gutsy中没有,虽然它只是一个脚本,可以自己去下载一个单独用,不过手动一下:

sudo update-menus

然后再重启Fluxbox就好了,根据当前系统中原有桌面系统(比如Gnome、Xfce)软件安装情况,自动把menu项建好了,生成了刚才缺少的/etc/X11/fluxbox/fluxbox-menu这个文件。

利用这种方式,或者使用fluxbox-generate_menu的好处就是可以随系统中软件安装情况变化,再搭配个人的一些优化设置,使用起来就更顺手了。

关机与重启

Fluxbox菜单中的restart和exit分别对应“重启窗口管理器”和“退出X,回到GDM界面”,没有直接关机或重启的选项,需要自己手工添加:

[submenu]
    [exec] (Reboot System) {sudo /sbin/shutdown -r now}
    [exec] (Reboot System) {sudo /sbin/reboot}      #和上面一句作用相同
    [exec] (Shutdown System) {sudo /sbin/shutdown -h now}
[end]

先别着急用,命令不都带着sudo了么,还要赋予用户不需密码就能够使用/sbin/shutdown的权限,修改/etc/sudoers,添加:

Cmnd_Alias REBOOT = /sbin/reboot
Cmnd_Alias SHUTDOWN = /sbin/shutdown

fwolf ALL=(ALL) NOPASSWD: REBOOT, SHUTDOWN

再调用关机或重启,虽然使用到sudo,也不再需要输入密码,而是直接就执行了。(参考1参考2

如果一定要需要用户输入自己的密码才能关机的话,也是可以实现的,那就是通过shell来执行sudo,在新开的shell窗口中会提示用户输入sudo时的密码,输入密码不正确时就拒绝执行sudo了,比如这样(参考):

[exec] (Shutdown) {konsole -T "Shutdown" -e sudo shutdown now -h}
[exec] (Shutdown) {gnome-terminal -t "Shutdown" -e "sudo shutdown now -h"}
[exec] (Shutdown) {xfce4-terminal -t "Shutdown" -e "sudo shutdown now -h"}

挂起与休眠

首先安装hibernate,源里有的,然后用root命令运行hibernate或者hibernate-disk就是休眠(信息写入磁盘,不耗电),运行hibernate-ram就是挂起(信息写入内存,会耗一点点的电)。如果运行了gnome-power-manager(在状态栏上会有电池图标),就可以设定合上笔记本时就休眠。菜单项和sudoers文件的修改和上面的关机和重启一样:

Cmnd_Alias SUSPEND = /usr/sbin/hibernate-ram
Cmnd_Alias HIBERNATE = /usr/sbin/hibernate-disk

fwolf ALL=(ALL) NOPASSWD: REBOOT, SHUTDOWN, SUSPEND, HIBERNATE

感觉挂起没有休眠好用,有时候从挂起状态恢复时会死掉,得重启X。

rxvt-uincode的daemon模式

超节省资源的fluxbox当然要搭配同样节省资源的rxvt-unicode来使用才更好,rxvt-unicode的daemon模式就更好了,可以在菜单中这样配置:

[exec] (rxvt-unicode) {urxvtc "$@"; if [ $? -eq 2 ]; then urxvtd -q -o -f; urxvtc "$@"; fi}

这样就可以自动启动守护程序urxvcd了(参见官方文档)。使用中rxvt-unicode到gedit或者scribes这样的程序粘贴内容有点问题,Ctrl-V不管用,不过用鼠标中键可以粘贴过来,而Shift+Insert只在rxvt-unicode里起作用。也有人说可以用autocutsel来同步两个剪贴板。

其它设置

快捷键

快捷键设置的默认定义文件为$HOME/.fluxbox/keys,注意Mod1代表Alt, Control代表Ctrl, Mod4代表Windows键,Mouse2是鼠标中键,Mouse4、5则是鼠标滚轮下滚、上滚。比如音量调节:

Control Mod1 Up :Exec amixer sset Master 1+ unmute
Control Mod1 Down :Exec amixer sset Master 1- unmute
Control Mod1 Left :Exec amixer sset Master mute

界面字体

默认设置下,如果菜单中有中文,那么配置完成后只能看见两个小方框,这并不是说fluxbox菜单不支持中文,而是字体没设置好。其它窗口标题栏等地方的中文也是类似的情况。可以在$HOME/.fluxbox/overlay文件中设置字体、字号的选项(这个文件的本来作用是定义Style切换中的保留设置),比如如下的内容:

# 菜单标题的字体
menu.title.font: Simsun-10
# 菜单组标题的对齐方式
menu.title.justify: center
# 菜单项目的字体
menu.frame.font: Simsun-10
# 菜单项目的对齐方式
menu.frame.justify: left
# 窗口标题栏文字的字体
window.font: Simsun-10
# 窗口标题栏文字的对齐方式
window.justify: center
# 窗口标题聚焦时的背景颜色|5/5/f
window.label.focus.color: rgb:4e/8f/cf
window.label.focus.colorTo: rgb:4e/8f/cf
# 时钟的字体
toolbar.clock.font: Simsun-10
# 工作区名称的字体
#toolbar.workspace.font: Simsun
# 图标栏的字体
toolbar.iconbar.focused.font: Simsun-10
toolbar.iconbar.unfocused.font: Simsun-10

字体名称后面-11为字体大小,再后面跟:bold表示黑体显示,中间都没有空格。

自启动程序

自启动程序可以在$HOME/.fluxbox/startup中配置,写在exec /usr/bin/fluxbox一句的前面,并且**一定要在后面加上表示后台运行的&符号。比如为了优化GTK程序的运行,可以加上:

GSDPID=`pidof gnome-settings-daemon`
if [ "x$GSDPID" == "x" ]; then
    gnome-settings-daemon &
fi
gnome-power-manager
gnome-volume-manager -daemon=yes &

gnome-power-manager是电源管理程序,用来管理笔记本的电源,台式机可以不用;gnome-volume-manager则是卷管理器,只有加载了它,插入u盘或者移动硬盘之后才能自动挂载。

程序属性apps

$HOME/.fluxbox/apps这个文件我还是第一次见过,它可以定义窗口的各项属性,比如:

[app] (name=xfce4-terminal)
[Position]  (LOWERLEFT) {0 55}
[end]

[group]
    [app] (name=urxvt) (class=URxvt)
        [Position] (LOWERLEFT) {0 25}
[end]

第一个[app]是定义了程序xfce4-terminal启动时的窗口位置为相对于屏幕左下角0,55的坐标,这样每次启动程序的时候就不用再手工移动窗口到自己舒服的位置了。fluxbox没有gnome那样窗口自动dock到屏幕边缘的功能,这算是另外一种方式的补充。

第二个[group]则是定义在本group范围之内的app,启动之后自动tab到一起,tab是fluxbox的特有功能,有点类似xfce4-terminalgnome-terminal开多个tab的功能(我也正是利用这点来模拟rxvt-unicode的多tab),这样打开多个rxvtc的时候,就自动tab到一个窗口去了,不用再手工按鼠标中键把一个标题栏拖到另外一个标题栏上。如果再在keys文件中配上Ctrl+PageDown切换到下一个Tab的功能:

Control Prior :PrevTab
Control Next :NextTab

多Tab shell窗口功能就近乎完美了,几乎可以完全淘汰xfce4-terminal了(字体颜色设置上还略有些不太习惯)(这样还把xfce4-terminal自身的tab切换功能给屏蔽了,调成用Mod1/Alt来组合也不错)。如果你想,在group中加上其它程序也是可以的。

apps文件很重要,不过如果手工在设定窗口保存属性的话,会被系统自动改写,为了保存手工编写代码的美观性,可以把这个文件的属性设置为444,编辑时再用w!强行写入。

桌面图片随机轮换

这一点简直太适合我了,我就喜欢设定一个目录,用里面的图片随机作为桌面,只需要把下面这个命令仍到crontab里就可以了:

env DISPLAY=":0.0" fbsetbg -F -R /path/to/your/wallpaper/

注意这个目录中不能有非图片文件。记得安装feh,虽然不装的话也能用,装上以后图片显示速度和拉伸效果都更好一些。

参考

Update @ 2007-12-16

安装了feh之后,发现mutt看邮件的图片附件时也会自动调用它,并且速度与效果比原来的imagemagic要好得多。

Update @ 2008-01-25

apps文件中要用到的窗口class可以用xprop查询到。

Ubuntu FeistyFawn中文字体配置的变化

今天把Ubuntu从Edgy升级到了Feisty,如果用update-manager的话我这里太慢,直接修改apt源升级的,自行解决了一些包的依赖关系之后,升级还是非常顺利的,以前常有的驱动问题本次没有出现,明天就升级公司的那台机。

几乎升级完成第一件事就是搞定中文字体,发现Feisty的字体配置有了明显的变化,原来的一个大配置文件/etc/fonts/fonts.conf现在被分成了许多个小文件,大部分存放在/etc/fonts/conf.avail目录下,并且使用/etc/fonts/conf.d目录下的连接来调用(/etc/fonts/conf.d这个目录下也有少部分配置文件),这种机制和rc2.d以及Apache的mods-available及其相似。

所以说,我的习惯非常适合这种升级和变迁,就是把自己的特殊配置写到单独的文件中,然后ln -s/etc/fonts/local.conf,最后修改/etc/fonts/conf.avail目录下的40-generic.conf60-latin.conf这两个文件,在serif、sans-serif、monospace三系字体的定义中,把Simsun添加到DejaVuBitstream Vera之后就可以了。这样作的好处就是下次升级时所需要作的调整最小。

fonts.conf的语法仍然没有大的改变,以前已经介绍过了,不过今天又发现两篇不错的Feisty字体配置相关文章,推荐一下:

PS: 安装完成之后autoclean了一下,清理出来1.3G空间,呵呵。 PS2: 如果中文输入遇到什么问题的话,大概是需要删除scim-bridge,参考下面两篇文章:

我的办法是把/etc/X11/Xsession.d/95xinput中原来的

export GTK_IM_MODULE="scim-bridge"

改成

export GTK_IM_MODULE="scim"

还有就是scim的选字栏位置总是飘忽不定。。。

Update @ 2007-04-24

如果openoffice 2.2无法启动,编辑/usr/bin/ooffice,添加下面这行:

export GTK_IM_MODULE="xim"

还是有些怪怪的。

Apache无法解析php程序了,提示

Invalid command 'PHPIniDir', perhaps misspelled or defined by a module not included in the server configuration

原来在升级feisty的时候,/etc/apache2/mods-enabled/php5.load这个文件丢了,重新a2enmod php5一下就可以了。

Apache的Order Allow Deny心得

今天又被这两个参数小小的耍了一把,痛下决心整理一下,免得再被耽误时间。

Allow和Deny可以用于apache的conf文件或者.htaccess文件中(配合Directory, Location, Files等),用来控制目录和文件的访问授权。

所以,最常用的是:

	Order Deny,Allow
	Allow from All

注意“Deny,Allow”中间只有一个逗号,也只能有一个逗号,有空格都会出错;单词的大小写不限。上面设定的含义是先设定“先检查禁止设定,没有禁止的全部允许”,而第二句没有Deny,也就是没有禁止访问的设定,直接就是允许所有访问了。这个主要是用来确保或者覆盖上级目录的设置,开放所有内容的访问权。

按照上面的解释,下面的设定是无条件禁止访问:

	Order Allow,Deny
	Deny from All

如果要禁止部分内容的访问,其他的全部开放:

	Order Deny,Allow
	Deny from ip1 ip2

或者

	Order Allow,Deny
	Allow from all
	Deny from ip1 ip2

apache会按照order决定最后使用哪一条规则,比如上面的第二种方式,虽然第二句allow允许了访问,但由于在order中allow不是最后规则,因此还需要看有没有deny规则,于是到了第三句,符合ip1和ip2的访问就被禁止了。注意,order决定的“最后”规则非常重要,下面是两个错误的例子和改正方式:

	Order Deny,Allow
	Allow from all
	Deny from domain.org

错误:想禁止来自domain.org的访问,但是deny不是最后规则,apache在处理到第二句allow的时候就已经匹配成功,根本就不会去看第三句。 解决方法:Order Allow,Deny,后面两句不动,即可。

	Order Allow,Deny
	Allow from ip1
	Deny from all

错误:想只允许来自ip1的访问,但是,虽然第二句中设定了allow规则,由于order中deny在后,所以会以第三句deny为准,而第三句的范围中又明显包含了ip1(all include ip1),所以所有的访问都被禁止了。 解决方法一:直接去掉第三句。 解决方法二:

	Order Deny,Allow
	Deny from all
	Allow from ip1