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 参考手册相关章节