Sunday, March 25, 2007

PuTTYcyg

PuTTYcgy,一个 PuTTY 的改版,可使用 PuTTY 作为本地 Cygwin 终端。

在这之前,我有两个选择。
Cygwin 的自带终端。缺点,主要是复制粘贴不方便,要同时用到鼠标和键盘。
Cygwin 的 X Term。缺点,本地要起 X Server,开销比较大。

说明一下 putty 的快捷方式的创建方法。

首先,打开 putty,修改好各项设置后保存,假设 Session 名为 cygwin。
然后,再创建一个 putty 的快捷方式,把“目标”设置为
\path\to\putty.exe -load "cygwin"

顺便提一下,hoekey 是个创建键盘快捷方式的好工具。

参考链接:
PuTTY - How can I create a Windows shortcut to start a particular saved session directly?

Wednesday, March 07, 2007

MySQL 子查询一例

到目前为止,MySQL 还不能支持这样的操作,子查询的 FROM 字句和更新/删除对象不能使用同一张表。
mysql> DELETE FROM tab1 WHERE col1 = ( SELECT MAX( col1 ) FROM tab1 );
ERROR 1093 (HY000): You can't specify target table 'tab1' for update in FROM clause

针对“同一张表”这个限制,撇开效率不谈,多数情况下都可以通过临时表来变通解决,像这样
DELETE FROM tab1
WHERE col1 = (
SELECT MAX( col1 )
FROM (
SELECT * FROM tab1
) AS t
);

参考链接:
MySQL 5.0 Reference Manual - Subquery Errors

Tuesday, March 06, 2007

Cygwin 环境设置

一、使用和当前 Windows 登录用户不同的用户名

打开 /etc/passwd,找到标示当前 Windows 登录用户,即“自己”,的那行,修改用户名,即第一项。

二、自定义 HOME 环境

打开 /etc/passwd,找到标示“自己”的那行,修改 HOME 目录。
也可以通过设置名为 HOME 的 Windows 环境变量来实现,此设定优先级更高。但主要缺点是 ssh 命令只认 /etc/passwd,经常使用 ssh 的话还是得绕回来修改 /etc/passwd。

三、自定义 HOME 文件夹

1. 使用 ln 命令创建软链接
2. 使用 mount 命令或者直接修改注册表,举个例子
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Cygnus Solutions\Cygwin\mounts v2\/home]
"flags"=dword:0000000a
"native"="D:\\home"

参考链接:
Cygwin FAQ No.13 My Windows logon name has a space in it, will this cause problems?
Cygwin FAQ No.14 My HOME environment variable is not what I want.
Cygwin User's Guide - The Cygwin Mount Table

Friday, March 02, 2007

Unknown HZ value!

Unknown HZ value! (0) Assume 100.

在 uptime 超过若干时间之后(我的遭遇是 248 天),使用 uptime, w, top 时会出现上述错误信息。直接原因是 procps 中的 libproc 在计算 HZ 不能时(其实我没有明白什么意思),打印出了一个无用警告。而这个据说是因为某个内核级 bug,也就是说取决于你用的 OS。

我的环境:
islue@localhost:~$ cat /etc/issue
Debian GNU/\s 3.0 \n \l

islue@localhost:~$ uname -a
Linux localhost 2.4.18 #1 SMP Fri Mar 11 18:50:01 JST 2005 i686 unknown

解决方案有,重启服务器,或者修改 proc/sysinfo.c 重新编译安装。
基本是无害的,随它去也无妨。

参考网址:
http://lists.debian.org/

Tuesday, February 13, 2007

靠,又被迫降级!

软件:FlashGet
版本:1.81 -> 1.73

新版本默认行为太暴力了,线程数多到泛滥,而且不容易设置。我原来的设置为 3 线程,最小分段尺寸 1MB。出于使用习惯,选择了降级,没有转投他处。

不在沉默中爆发(FlashGet),就在沉默中死亡(NetAnts),这年头,搞什么啊?

为什么说“又”?看这里

Sunday, February 04, 2007

在 DreamHost 虚拟主机上部署 Catalyst 应用

在虚拟主机上部署 Catalyst 应用的前提是用户可以自己安装 CPAN 模块,DreamHost 提供了 shell 环境,所以就完全没问题了。

如何在非 root 环境下安装 CPAN 模块,请参考 Catalyst Wiki 中的相关文章

好,在安装完 Catalyst 之后呢,那么就万事具备,只欠东风了。
虚拟主机,Catalyst 自带的 httpd 肯定是不能用的;没有 apache 的控制权限,mod_perl 也上不了;剩下还有 cgi 和 fastcgi 方式,还用想吗?当然用 fastcgi 咯~

下面就以 fastcgi 方式为例,分享一下我的一些经验。

一、部署环境
[hostname ~]$ ls -1
MyApp/ # 项目名
example.com/ # 域名

二、apache 环境
[hostname ~]$ ls -a1 example.com
.htaccess
script -> /home/islue/MyApp/script/
static -> /home/islue/MyApp/root/static/

软链接的意义很好理解,不罗嗦了,然后来看一下 .htaccess 文件。
[hostname ~]$ cat example.com/.htaccess
AddHandler fastcgi-script .pl

RewriteEngine On

# 避免屏蔽 DreamHost 提供的 Site Statistics 功能
RewriteCond %{REQUEST_URI} ^/stats/(.*)$ [OR]
RewriteCond %{REQUEST_URI} ^/failed_auth.html$
RewriteRule ^.*$ - [L]

# fastcgi 工作模式
RewriteCond %{REQUEST_URI} !^/script/myapp_fastcgi.pl
RewriteRule ^(.*)$ script/myapp_fastcgi.pl/$1 [PT,L]

很容易理解吧,也不罗嗦了。

三、定制 myapp_fastcgi.pl
[hostname ~]$ cat MyApp/script/myapp_fastcgi.pl
...

BEGIN {
$ENV{CATALYST_ENGINE} ||= 'FastCGI';
unshift @INC, qw(
/home/islue/local/lib/perl/5.8
/home/islue/local/lib/perl/5.8.4
/home/islue/local/lib/perl5
/home/islue/local/lib/perl5/i386-linux-thread-multi
/home/islue/local/share/perl/5.8
/home/islue/local/share/perl/5.8.4
);
$SIG{'TERM'} = 'IGNORE';
}

...

我原以为,修改过了 .bashrc 之后,应该不需要再用 use lib 了,但是数次实践下来,不在 myapp_fastcgi.pl 里声明用户的 lib 还真不行。要是哪位知道这里的道道,记得告诉我啊。

至于为什么要 IGNORE TERM,故事是这样的,很久很久以前,世界和平,大家都过着男耕女织的生活,不用在意什么,MyApp 也能跑得欢快。

突然有一天,电闪雷鸣,大雨瓢泼,MyApp 就再也跑不起来了,访问站点能看到的只有 Internal Server (500) 错误,翻开史册,书上如是说:
[Mon Jan 29 06:13:13 2007] [error] [client 210.151.136.180] FastCGI: comm with (dynamic) server "/home/islue/example.com/script/myapp_fastcgi.pl" aborted: (first read) idle timeout (60 sec)
[Mon Jan 29 06:13:13 2007] [error] [client 210.151.136.180] FastCGI: incomplete headers (0 bytes) received from server "/home/islue/example.com/script/myapp_fastcgi.pl"

在无数次 ps 之后,总算看到 myapp_fastcgi.pl 的身影一闪而过。是他杀,我惊醒!真相只有一个,下面公布凶手的自白书。
Dreamhost regularly kills off sleeping processes with a proc watch script. This will kill your dispatch.fcgi processes, leading to Error 500s from time to time. You'll need to make dispatch.fcgi ignore all TERM requests by changing how it responds to them.

说笑啦,上面这段是 DreamHost 客服给我的回复。IGNORE TERM 之后,世界又太平了。

四、应用启动方式

启动应用的方法就是访问站点。如果需要重启,杀掉所有 myapp_fastcgi.pl 即可,如果 IGNORE TERM 了的话,需要 kill -9。

Saturday, February 03, 2007

公告:Save You More(暂名)上线

一个提供横向实时比较各网上书店指定图书价格服务的站点。
http://sym.noticpan.org/

核心服务已经成形,拿出来晒晒先。

Saturday, January 20, 2007

ssh-agent 简介

ssh-agent 是一个保管私钥的程序。然后的故事呢是这样的,ssh-agent 在一个 X-session 或者一个 login session 的一开始启动,所有其他窗口以及程序都会作为 ssh-agent 的客户端启动。
以上译自 ssh-agent 的在线手册(man)。

按我的理解来说,ssh-agent 就是一个管理私钥的代理,受管理的私钥通过 ssh-add 来添加,所有 ssh-agent 的客户端都可以共享使用这些私钥。

用处一,不用重复输入密码。

用 ssh-add 添加私钥时,如果私钥有密码的话,照例会被要求输入一次密码,在这之后 ssh-agent 可直接使用该私钥,无需再次密码认证。

用处二,不用到处部署私钥。

假设我有私钥分别可以登录同一内网的主机 A 和主机 B,出于一些原因,不能直接登录 B。我可以通过在 A 上部署私钥或者设置 PortForwarding 来登录 B,也可以转发认证代理连接在 A 上面使用 ssh-agent 管理的私钥登录 B。

以 cygwin 环境为例,描述一下操作流程

islue@localhost $ ssh-agent bash --login -i

通过 ssh-agent 启动 bash,或者说把 bash 挂到 ssh-agent 下面

islue@localhost $ ssh-add

添加私钥,如果跳过第一步直接添加私钥,也就是说当前的 shell 并没有挂在 ssh-agent 下面,则会收到这样的错误信息

Could not open a connection to your authentication agent.

接下来登录主机 A

islue@localhost $ ssh -A HOST_A

-A 的作用就是启用转发认证代理连接

islue@HOST_A $ ssh HOST_B
islue@HOST_B $

从主机 A 上顺利登录主机 B,完毕。

更多内容请参阅 ssh 和 ssh-agent 的在线手册。

用好 MySQL 字符集

我们都知道,MySQL 支持 30 多种字符集,其中包括了我们常用的 gb2312、gbk 和 uft8 等字符集。

在很多简单应用场合下,字符集设置是可有可无的。把后台存储的视为裸数据(raw data),存入的数据可以被原封不动地取出,对于前端的处理及应用,通常是不会有问题的。

当然,不设置正确的字符集,在实际应用中也有诸多不便之处。假设情况是这样的:

前端应用:GB2312
后端存储:latin1

那么大概会得到这样的结果:

字符终端(GB2312环境):正确
phpMyAdmin:乱码
MySQL Query Browser:乱码

如果你是个完全无视 GUI 管理工具的开发者,那么无视字符集设置就是了。

设置合适的字符集,我觉得主要是可以获得 GUI 管理工具强大支持。除此以外,其实用处并不是很多,以我的使用经验为例,只是用来做文本排序。

那么以 Perl 为例,说说我的经验,怎样使用合适的字符集,情况如下

前端应用:GB2312
后端存储:utf8

设置字符集可以分为四个环节:
客户端 <-> 前端 <-> 连接 <-> 后端

客户端,这里指浏览器。当前输出内容编码为 GB2312,所以应该在 HTML 头部加入如下语句:

<meta http-equiv="Content-Type" content="text/html; charset=GB2312">

通常,即使没有上述语句,多数浏览器也能“猜”出正确编码,这是题外话,不深入了。

前端,这里指数据处理程序。因为后端存储是 utf8,所以在这里需要把数据从 GB2312 转为 UTF8,就绪。

use Encode;
Encode::from_to( $data, 'euc-cn', 'utf8' );

连接,这里指由程序创建的数据库连接。通常我们这样连接数据库:

use DBI;
my $dbh = DBI->connect('dbi:mysql:database=test;host=localhost', $user, $password);

为了加入字符集信息,需要在连接后执行下面的命令:

$dbh->do('SET NAMES utf8');

声明了输入输出使用的都是 utf8 字符集。要保证建立连接后,首先执行字符集声明。

这在某些自动重连的情况下可能会失效,我推荐用读取配置文件的方式声明连接字符集。

首先,在配置文件 /etc/my.cnf 中加入字符集设置

[client]
default-character-set=utf8

然后,连接语句相应地改为

my $dbh = DBI->connect('dbi:mysql:database=test;host=localhost;mysql_read_default_file=/etc/my.cnf', $user, $password);

或者
my $dbh = DBI->connect('dbi:mysql:database=test;host=localhost;mysql_read_default_file=/etc/my.cnf;mysql_read_default_group=client', $user, $password);

这样保证了创建连接前就能读取到字符集设置。

后端,这里指 MySQL 数据库。在建表或数据库时,声明字符集

CREATE TABLE (
...
) CHARSET utf8;

以上就是各环节字符集的设置,一些描述乃属经验记忆,难免会有错漏,还望海涵。更多请参阅 MySQL 参考手册相关章节

Monday, December 25, 2006

TortoiseSVN 共享文件夹下一样显示图标

虽然是 TortoiseSVN 既有功能,猜想很多人都不知道的。

正常情况下,如果你在一个网络共享文件夹下面 checkout 一个 subversion 控制的项目。这个项目的文件夹并不会像在本地文件夹中一样,以各式各样的图标来表示文件状态。你需要做的是稍许改一下配置:
TortoiseSVN -> Settings -> Look and Feel -> Icon Overlays -> Network Drivers

选中 Network Drivers,就能看到文件状态图标了。