解决 Ubuntu 登录时用户名中不能含有“@”的问题

2009-10-07

最近的项目需要在 Linux 中配置自定义的 PAM 做用户认证。在这个 PAM 中,用户名是 Email 的形式。该 PAM 在 CentOS 5.3 下工作正常,但在 Ubuntu 9.04 下,登录过程输入用户名时一旦按下 Email 中的“@”,之前输入的字符就会被清空(相当于 Ctrl-U,kill character 的效果),导致无法登录。我开始认为这是键盘映射的问题,但用 loadkeys 恢复标准键盘映射之后问题依旧。这也不像 stty 的错误,因为在同一个终端上登录到 shell 之后再输入“@”是正常的。于是 google 之,在相关的 HOWTO 页面找到了以下信息:

Under xdm, the default erase and kill characters are # and @, as in good old Unix Version 6. At the first attempt, you are talking to getty. At the second attempt, you are talking to login, a different program.

看来“@”变成 kill character 不是无中生有,而是有历史依据的;同时输入不了“@”的关键在 getty,而不在 login(实验发现如果第一遍用户名、密码输入错误,第二遍输入用户名时是可以输入“@”的,这印证了问题确实在 getty 而不在 login)。于是我 man getty,发现了问题所在:Ubuntu 上的采用的 getty 是 agetty,而 CentOS 上采用的是 mingetty。agetty 的 Manual 指出,“@”、“#”分别被用作 kill character 和 erase character,而 mingetty 并没有这一非标准的定义。agetty 的 Manual 没有说明如何取消“@”、“#”的特殊功能,我查看了它的源代码(位于 util-linux-ng 包)才发现这个特性是写死在代码中的。看来要在用户名中输入“@”,只能设法绕开 agetty。我的方法是在 Ubuntu 中安装 mingetty,然后设置系统启动时用 mingetty 代替 agetty 开启终端(/etc/event.d/tty*):

$ sudo apt-get install mingetty
$ tail -1 /etc/event.d/tty1
exec /sbin/mingetty tty1

重启之后,就可以用 Email 形式的用户名登录了。