2012年8月8日星期三

SSH的公钥登录问题

今天公司有个妹纸的Git不能用了,提示输入密码。我查了Gitosis配置没问题,再去找她,原来她自己照着从网上搜来的一篇博文搞公钥登录,没有搞成。

Git不能用,那就说明Gitosis中的公钥和客户端的私钥不配对,她的确承认应该是把私钥搞乱了。折腾好几次,SSH的公钥登录就是不成功,服务器提示输入密码。最后试着把服务器上她的authorized_keys文件的权限由664改为600,然后就可以了。这个文件别人的确是不应该有写权限的,否则会有安全问题,不过SSH的文档里面貌似没有说权限错误会拒绝登录。

郁闷的是该同学开始没告诉我自己做了什么操作,害我从Gitosis的配置查起,后来才告诉我自己折腾了什么。

2012年7月14日星期六

Ibus的启动和退出

在Macbook Pro上新装了Ubuntu 12.04 LTS,但是进入桌面后ibus不会自动起来,就在GNOME的Startup Applications里面添加了ibus-dameon命令的启动。

如果重启Lightdm后,ibus的Language Panel出不来。发现是原来的ibus-daemon进程还在导致的。解决办法是在/etc/lightdm/lightdm.conf中加入
session-cleanup-script=/home/tux/bin/cleanloggingout
这里指定了Lightdm退出时执行的脚本cleanloggingout,内容为:
for pid in $(pgrep ^ibus); do
   kill $pid;
done
就是在退出时,杀掉所有ibus相关的进程就好了。这样不管怎么重启Lightdm,进入桌面后ibus都是正常的。

另外,Lightdm更多的配置选项可以在 /usr/share/doc/lightdm/lightdm.conf.gz看到。

2012年7月13日星期五

Ubuntu遇上Mac

现在工作用电脑选的是Macbook Pro,具体型号是15寸8,2。用了这么多年Linux桌面习惯了,而且在我看来Linux桌面的不少体验要好于Mac,这里不细表了。我装了个Ubuntu用。

参考了Ubuntu详细的帮助文档,折腾了几次,终于装上去了。传言要同时插入启动光盘和U盘才可以的,我最后成功也是这样的,但没有再试验其它方法。

即使默认安装缺少的驱动,装起来也很方便。键盘上的多功能键、触摸板的多点触控都支持,这一点比较出乎意外。外接27寸的显示器也可以搞定,只是如果拔下显示器再插上的话,需要登出一下才能让双显生效。另外,电源管理也不行,有时候闲置状态风扇也会转。Macfanctl比较好玩。

我还是喜欢Ubuntu桌面胜过Mac。

2012年6月29日星期五

Cron任务没有执行

Web方式显示服务器历史负载的图中,有几天的内容是空的。昨天我从头看代码。回家后想想既然平常能正常显示,那么程序应该不会有问题,应该直接从问题入手,先查询数据库。

今天把程序在IPython里面import了调试,发现那几天的负载数据库表不存在。往这个数据库写数据的程序是个cron任务,在syslog里面没有找到任务执行记录,在root的邮件里面也没有看到任务执行出错的邮件。然后在cron(8)手册里面,发现/etc/cron.d里面的任务名字不能带点,而入库的任务名字叫checknagios.cron

另外,某人同时用 /usr/share/doc/cron/examples/cron-tasks-review.sh检查,出现提示:
WARN: The file /etc/cron.d/checknagios.cron will not be executed by cron: Does not conform to the run-parts convention
更加确认了这一点。

貌似复杂的问题,竟然源于一个点。把任务文件名中的"."去掉就解决了。

2012年5月28日星期一

libgail加载错误

在Ubuntu 12.04下面,运行GTK或者PyGTK程序都会出现如下错误:
Gtk-Message: Failed to load module "gail"

** (ancestry.py:8295): WARNING **: (../../atk-adaptor/bridge.c:793):adaptor_init: runtime check failed: (root)
这篇文章提到类似的错误,原因是32位加载了64位的libgail库。电脑上安装的libgail.so文件只有32位的:
$ locate libgail.so
/usr/lib/i386-linux-gnu/gtk-2.0/modules/libgail.so
$ file `locate libgail.so`
/usr/lib/i386-linux-gnu/gtk-2.0/modules/libgail.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=0xaa9af3bc0239d5c04771d390b3e9ea1fe4277d03, stripped
找到对应的包:
$ dpkg -S /usr/lib/i386-linux-gnu/gtk-2.0/modules/libgail.so
libgail-common:i386: /usr/lib/i386-linux-gnu/gtk-2.0/modules/libgail.so
在Synaptic(Aptitude处理multiarch有bug)里面libgail-common有两个:libgail-common:i386libgail-common,后面这个是64位的,安装上后文章开始的错误便消失了。

2012年5月27日星期日

换行符和BOM引起的麻烦

最近整理电脑里的Python程序,有一个程序运行时出错:
$ ./absent.py
./absent.py: line 1: $'\357\273\277#!': command not found
./absent.py: line 4: $'\r': command not found
然后鼠标箭头变成了一个十字。如果如下:
$ python absent.py
用Python命令来执行是好的。这个文件的前5行如下:
#! /usr/bin/env python
# -*- encoding: utf-8 -*-
# 设置不同的文字屏保,2008年6月5日

import gtk
那个十字以前就碰到过,是用./执行时程序被当成了Shell脚本,所以Python的import gtk语句被当成ImageMagick的import工具来执行了,那个十字形鼠标箭头是import用来选取截图窗口的。

这个文件是我在原单位办公室的Windows电脑下创建的,所以马上意识到是换行符引起的。Linux下的换行符是\n,而Windows下创建的文件换行符是\r\n,所以第一行其实是这样的内容:
#! /usr/bin/env python\r\n
在Linux下,系统只把\n识别为换行符,把python\r连起来识别了。我创建了一个测试程序dos.py
#! /usr/bin/env python
# -*- encoding: utf-8 -*-

import this
然后在Shell下用
sed -i 's/$/^M/g' dos.py
把换行符转成Windows下的\r\n。^M是用Control-V和Control-M打出来的。这个文件执行出错:
$ ./dos.py
: No such file or directory
当然,用Python命令来解释是好的。上面的错误可以在Shell下用等同的命令复现:
$ /usr/bin/env python^M
: No such file or directory
如果真的有python^M这个命令会呢?在~/bin目录里创建到Python解释器的链接:
ln -s /usr/bin/python python^M
~/bin目录在路径的前面,这样python^M命令可以找到了。再执行一次就好了:
 $ ./dos.py
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
......
 其实不要用env,直接在Shebang里面指定执行文件:
#! /home/tux/bin/python
# -*- encoding: utf-8 -*-

import this
出错会更直观:
$ ./dos.py
bash: ./dos.py: /home/tux/bin/python^M: bad interpreter: No such file or directory
~/bin里面创建名为python^M的链接后,就又可以执行了。再回到开始的错误:
$ ./absent.py
./absent.py: line 1: $'\357\273\277#!': command not found
./absent.py: line 4: $'\r': command not found
这个错误和上面dos.py的不同,这'\357\273\277#!'是哪里来的呢?把absent.py文件这样打开:
$ cat -e absent.py
M-oM-;M-?#! /usr/bin/env python^M$
# -*- encoding: utf-8 -*-^M$
# M-hM-.M->M-gM-=M-.M-dM-8M-^MM-eM-^PM-^LM-gM-^ZM-^DM-fM-^VM-^GM-eM--M-^WM-eM-1M-^OM-dM-?M-^]M-oM-<M-^L2008M-eM-9M-46M-fM-^\M-^H5M-fM-^WM-%^M$
^M$
import gtk^M$
原来在#!之前还有几个字符,用bvi打开:
00000000  EF BB BF 23 21 20 2F 75 73 72 2F 62 69 6E 2F 65 ...#! /usr/bin/e
00000010  6E 76 20 70 79 74 68 6F 6E 0D 0A 23 20 2D 2A 2D nv python..# -*-
它们是0xEF, 0xBB0xBF。原来这个文件是用微软的Notepad创建的,在文件头被自动加上了UTF-8的Byte Order Mark。用cat -e absent.py打开时,在#!前面显示的是M-oM-;M-?,这是指EE BB BF是把'o', ';''?'的高位设为1,可以如下验证:
>>> print ' '.join('%X' % (ord(b) + 128) for b in 'o;?')
EF BB BF
要解决问题,必须把前三个字节删除掉,并把换行转换为Unix格式的\n才能用./absent.py正确执行程序。

2012年5月13日星期日

Python和Bash的混合

上面的图片是我写的一个粗糙的Python脚本的一部分,功能是文本处理,这不是要说的,重点要说的是第30、35、54和55行。

30行是把src字符串所指的zip文件解压缩到tmpdir目录。Python有zip文件处理的模块zipfile,但是只是解压缩有点麻烦,就用Shell下的unzip工具搞定了。

54行是截取othersrc文件的一段,这个用Python的文件处理其实更自然,但是在写脚本前面已经用过现成的Bash命令了,所以就懒得再写Python,直接把Bash命令抄过来。

55行是比较文件的,这个想也没想就用Shell下的diff命令搞定了。

35行计算文件的MD5校验和,这个首先想到的应该是Shell命令,但是Shell下md5sum命令计算出来的结果还得截取字段才能得到,而Python的hashlib直接得到校验和也很简单,就用Python来完成。

上面的例子是在Python里面混合进Bash语句。我又想到一个Bash里面用Python的实例:
第49行用Python开了一个临时的HTTP服务。

这样一会儿Python,一会儿Bash的做法,我以前觉得挺别扭的,会觉得不够纯洁。可是现实情况往往是这样的:很多问题写脚本,用Bash或者 Python都可以完成,但是应该有一个最佳的办法;对脚本里面的单一功能,也是一样的,Bash或者Python的实现总有一个更好的,比如更快实现、 更简洁、已有现成的等等。现在我觉得,更加重要的是完成事情,而不是所谓的“纯洁性”,什么好用就用什么。再说,初看开头的图片,也没觉得因为Python和Bash的混合而变得很乱吧,呵呵。