键盘、控制台和 VT 巡航
“这是一个 GUI,GUI,GUI,GUI 的世界!”——或者主要的操作系统制造商会让你相信这样。事实是,虽然情况确实越来越如此,但在某些时候,命令行界面 (CLI) 仍然是完成任务的非常好的选择。它速度快,通常效率高,并且是在内存或 CPU 受限的机器上的一个不错的选择。并且不要忘记,仍然有很多非常漂亮的事情可以在控制台完成。
本着这种精神,我想首先跟进 Alessandro Rubini 撰写的一篇令人愉快且内容丰富的文章,题为“没有 X 的最佳选择”,发表在 1995 年 11 月号(第 19 期)的Linux Journal上。在大量的有益想法中,Alessandro 建议将数字小键盘转换为控制台切换暂存器,以允许从一个虚拟终端 (VT) 切换到另一个虚拟终端的单键切换。我们将首先了解如何进行这种转换。我们还将了解
从这里到那里:VT 巡航的便捷方法
有用的未使用 VT:放置所有日志信息的地方,以及 X-Windows 真正结束的地方
当您完成对这些东西的修补后,我认为您会同意 CLI 毕竟不是一个糟糕的地方。此外,好消息是,您进行此转换所需的程序是大多数最新 Linux 发行版的标准组件,包括
kbd 0.91(键盘字体和实用程序)
utils 2.5(Rick Faith 的大型实用程序集合)
GNU shell-utils 1.12(shell 实用程序,包括 stty 程序)
Linux FTP 存档的列表,可以在侧边栏中找到这些实用程序。
数字小键盘是将虚拟终端切换暂存器重新映射的理想候选对象,因为我们大多数人从未学会“盲打十键”。此外,101 键键盘上的非数字功能已经由 Home、End、Page Up、Page Down、Insert、Delete 和箭头键复制。由于可能在某些情况下我们仍然希望使用小键盘进行数字输入,让我们看看如何在保留数字输入能力的同时将其设置为 VT 切换器。您需要在您的系统上安装 kbd 软件包。我们将使用的两个程序是showkey 和 loadkey。要检查它们是否安装在您的系统上,请输入
$ type loadkeys showkey
如果您使用的是 BASH shell,或者
$ which loadkeys showkey
which 程序或 BASH shell 内置函数 type 都将打印可执行文件的路径,如果它们存在于 PATH 搜索路径中。在我的机器上,这会产生
$ type showkey loadkeys showkey is /usr/bin/showkey loadkeys is /usr/bin/loadkeys
$ which showkey loadkeys /usr/bin/showkey /usr/bin/loadkeys
如果您没有安装这些程序,您需要获取 kbd 软件包源代码,并自行安装。此软件包仅以源代码形式提供,但安装非常简单,只需将其解压缩到临时目录中,然后键入
$make && make install
将小键盘转换为 VT 切换器涉及定义键盘映射并使用 loadkeys 将此信息实际加载到内核键盘转换表中。这比听起来容易——尽管您必须记住,随意修改可能会使您的键盘无法使用(需要那些可怕的冷启动之一),并且更改键盘转换表会影响所有 VT,而不仅仅是您正在使用的 VT。kbd 软件包的默认安装位置在 /usr/lib/kbd 下,密钥映射文件在 keytables 子目录中。更改到此目录并制作 defkeymap.map 文件的副本,该文件包含默认键盘映射,并且是开始的有用位置。您可以将新文件命名为您喜欢的任何名称——例如,
cp defkeymap.map custom.map
使用您喜欢的编辑器并加载复制的文件。此时,最好四处看看当前内容。这种体验很像参观那些精美的古玩店之一——看看,但不要碰!前几行可能看起来像这样
keycode 1 = Escape Escape alt keycode 1 = Meta_Escape keycode 2 = one exclam alt keycode 2 = Meta_one shift alt keycode 2 = Meta_exclam keycode 3 = two at at control keycode 3 = nul shift control keycode 3 = nul alt keycode 3 = Meta_two shift alt keycode 3 = Meta_at
我不会详细介绍如何重新映射键盘的所有细节,除了说要使用的基本格式是
keycode keynumber = keysym modifier keycode keynumber = keysym
其中 keynumber 是键的内部标识号,keysym 表示要执行的操作。现在,在您放弃我之前,让我们用简单的术语来解释一下。键盘上的每个键都由一个唯一的数字标识,该数字由 keynumber 表示。当按下或释放键时,按下或释放事件会传递到操作系统,操作系统通过执行适当的操作来响应——此处由 keysym 表示。modifier 是在按下键的同时按住的键。这些 modifier 键包括众所周知的 control、alt 和 shift 键。定义多键组合的能力扩展了每个键的可用映射。
因此,使用上面的示例,按下与 keynumber 3 关联的键实际上会导致数字 2 打印到屏幕上。如果按下键的同时按住 shift 键,则 @ 符号将打印到屏幕上,如果按下三个键组合 shift-alt-3,则输出为 Meta_at(无论它看起来像什么)。
回到手头的任务,我们希望在按下小键盘键之一时切换到指定的 VT:即,按下小键盘 1 应该切换到 VT 编号 1,按下小键盘 2 应该切换到 VT 编号 2,依此类推。在您的自定义密钥映射文件中,找到定义小键盘键的部分——它应该类似于此
keycode 71 = KP_7 alt keycode 71 = Ascii_7 keycode 72 = KP_8 alt keycode 72 = Ascii_8 keycode 73 = KP_9 alt keycode 73 = Ascii_9 [...]
现在,编辑此部分,使其读取类似于 列表 1 的内容。
在继续之前,让我们做一些观察。首先,在您进行操作时注释文件是个不错的主意。现在看起来清晰明了的东西会随着时间的推移而变得模糊不清。现在添加注释将防止您以后不得不仔细研究手册页、程序文档和杂志文章,以查找正确的语法或用法。其次,请注意,对于每个条目,都有子节,以单词 alt keycode、shift keycode 等开头。这些节定义了多键组合,其中在按下键的同时按下了 modifier 键。一个常见的例子是用于在执行期间终止程序的 crtl-c 组合。
最后,您可能会问自己,您应该如何知道哪个 keynumber 与键关联。有人知道与 ; 键关联的 keynumber 是什么吗?您可以使用 showkey 程序找到答案。在您调用程序后,showkey 将打印您按下的任何键的 keynumber,并在 10 秒钟无输入后退出。因此,现在我们已经编辑了 custom.map 文件中的相关部分,让我们看看我们如何 从头开始 到达此处。基本步骤是
查找小键盘键的 keynumber。
编辑键的自定义映射,以便按下它们会更改为相应的 VT。
编辑键的自定义映射,以便小键盘仍然可以用于数字输入(在这种情况下使用修饰键组合)。
加载自定义映射并查看它是否有效。
可选地,在系统启动时加载默认密钥映射。
为此,让我们首先调用 showkey 程序
$ showkey
现在,您按下的任何键都会导致 showkey 打印 keynumber。在我的机器上,调用 showkey 并按下小键盘键 1 到 9 会导致 列表 2 中显示的输出。您可以看到检测到按键和释放事件。另请注意,小键盘键的编号不是顺序的。数字键的格式如表 1 所示
表 1
Actual Key: Keynumber: 7 8 9 71 72 73 4 5 6 75 76 77 1 2 3 79 80 81
表 1 显示小键盘数字 1 的 keynumber 为 79,小键盘数字 2 的 keynumber 为 80,依此类推。了解这一点后,我们可以为每个键设置适当的密钥映射条目。我们感兴趣的 keysym 事件是 Console_x,其中 x 是视图切换到的 VT 的编号。将小键盘数字 1 映射到切换到 VT 1 的简单条目如下所示
keycode 79 = Console_1
如果您查看 列表 1,您会注意到这就是我们所做的。但是,假设我们想切换到大于 9 的 VT——我们该怎么做?解决方案是使用修饰键组合。再次查看上面的示例,将 shift 键与小键盘一起使用允许我们使用 Console_10 到 Console_19。我们还希望能够将数字小键盘用作数字小键盘——一种输入数字数据的方法。在上面的示例中,请注意,修饰符 alt 用于执行此操作
keycode 71 = Console_7 shift keycode 71 = Console_17 alt keycode 71 = KP_7 alt control keycode 71 = Console_7
在 keypad_7 键的这个节中,第一个条目将 keypad_7 键映射为切换到 VT 7。第二行将 shift-keypad_7 映射为切换到 VT 17,第三行将 alt-keypad_7 组合映射为 KP_7,这是数字锁定 开启 时的数字输出的 keysym。因此,要将小键盘用作数字小键盘,请按下数字锁定键,使其切换为 开启,然后在您在小键盘上输入数字时按住 alt 键。另请注意,alt-crtl-keypad 被定义为切换到与简单按下小键盘键本身相同的控制台。在这种情况下,它的作用与 alt-fn (alt-Function_key) 或 alt-crtl-fn (alt-crtl-Function key) 组合完全相同。您可能已经注意到,使用功能键是通常指示从一个 VT 切换到另一个 VT 的方式。查看功能键的节,您会注意到如下条目
keycode 59 = F1 F13 Console_13 control keycode 59 = F25 shift control keycode 59 = F37 alt keycode 59 = Console_1 control alt keycode 59 = Console_1
请注意,alt-f1 和 alt-crtl-f1 都用于切换到 VT 1。那些使用 X 的人可能已经发现,从 X 切换到 VT 需要三个键 alt-crtl-fn 键组合,而两个键 alt-fn 键组合在控制台上使用。虽然您可以更改此默认行为,但最好不要这样做。此时,我们已经为小键盘键定义了映射,以便每个键都充当切换到相同编号 VT 的开关。使用 shift-keypad_key 切换到 VT (10 + 小键盘数字),使用 alt-keypad key 并在数字锁定 开启 时输出键的数值。最后一步是实际加载新映射并试用一下。加载是使用 loadkeys 完成的,并且可以在不以 root 用户身份登录的情况下完成。要加载自定义密钥映射,请输入
$ loadkeys /usr/lib/kbd/keytables/custom.map
这将打印一条消息,指示正在加载 custom.map 文件。之后,您就一切就绪了!试一下。要恢复为默认映射,只需输入
$ loadkeys /usr/lib/kbd/keytables/defkeymap.map
默认映射将再次加载。您可以使用此编辑 -> 加载自定义映射 -> 测试 -> 加载默认映射循环来获得所需的映射。一旦您创建了自定义映射文件并希望在启动时加载它,您可以向 rc.* 文件之一(例如 rc.local)添加一个条目,以使 loadkeys 自动加载您的自定义映射
if [ -r /usr/lib/kbd/keytables/custom.map ]; then loadkeys /usr/lib/kbd/keytables/custom.map fi
此条目确保文件存在且可读,并调用 loadkeys 加载文件。再次,请记住,加载密钥映射会更改 所有 VT 的密钥表信息,而不仅仅是您当前的 VT。
现在我们已经取得了一些进展,让我们看看另一种从一个 VT 移动到另一个 VT 的方法。能够快速从一个 VT 切换到另一个 VT 的实用性应该是显而易见的:您可以在 VT 1 上编译程序,在 VT 2 上编辑文件,在 VT 3 上阅读程序文档,并在 VT 4 上显示手册页。现在您已经重新映射了小键盘,从一个 VT 切换到下一个 VT 就像按下小键盘键一样简单。但是,还有其他方便的移动方式,这些方式包括
使用 keysym 函数 Last_Console、Incr_Console 和 Decr_Console
使用 chvt 程序(它是 kbd 软件包的一部分)
Incr_Console 和 Decr_Console keysym 函数顾名思义:它们分别切换到 (VT + 1) 或 (VT - 1)。因此,如果您当前在 VT 3 上工作,Incr_Console keysym 会将您切换到 VT 4,而 Decr_Console keysym 会将您切换到 VT 2。Last_Console keysym 也顾名思义:它切换到上次使用的 VT。如果您在 VT 3 上工作并切换到 VT 6,Last_Console keysym 会将您切换回 VT 3。您可以映射键或修饰符+键组合来调用这些 keysym 函数中的任何一个。我已将这些函数映射如下
Ctrl+left arrow = Decr_Console Ctrl+right arrow = Incr_Console keypad 0 = Last_Console
显然,您可以以任何您希望的方式映射这些函数,但映射上述操作的相关条目将是
#keycode 82 = KP_0 keycode 82 = Last_Console shift keycode 82 = Console_10 alt keycode 82 = KP_0 [...] keycode 105 = Left alt keycode 105 = Decr_Console keycode 106 = Right alt keycode 106 = Incr_Console
这些条目将小键盘 0 键映射到 Last_Console keysym,并将 alt- [左箭头] 或 [右箭头] 映射到 Decr_Console 或 Incr_Console keysym。好消息是,最后两个已经是默认值,因此您只需要编辑小键盘 0 键的节。现在,您可以通过按住 alt 键并重复按左箭头或右箭头来快速循环浏览所有 VT。要在两个 VT 之间交替,您只需重复按小键盘 0 键。我发现这些特定的映射非常有用,但是,正如我之前提到的,它们可以自定义为您希望的任何内容。VT 巡航的最后一个技巧是 kbd 软件包中包含的 chvt 程序。它的使用非常简单
$ chvt 3
将更改为 VT 3。用另一个数字代替 3 允许您更改为该 VT。可以使用 shell 别名设置此操作的缩短版本
$ alias vt='chvt'
以便输入
$ vt 3
会将您切换到 VT 3。
因此,现在我们已经定义了几种从 VT 到 VT 的方法,重要的是要注意,这仅在控制台上有效,而在 X Window 系统下无效。在 X 下,X 服务器控制键盘、鼠标和显示:设置自定义键盘映射是使用 ~/.Xmodmap 文件或程序 xkeycaps 执行的,这是稍后文章的主题。
能够打开多个 VT 并在前台或后台运行程序是使运行 Linux 如此有趣的原因之一。正如老外科教授过去常斥责他的实习生,“帮帮我,帮帮我!如果我有另一双手,我会帮助自己!” Linux 给了你那另一“双手”。通常,大多数 VT 要有用,必须在其上运行 getty 进程才能登录。getty 是与终端关联的程序,它
打开 tty 行并设置其模式。
打印登录提示并获取用户名。
启动用户的登录过程。
在不深入所有细节(同样,这是稍后文章的主题)的情况下,足以说这个程序是在 /etc/inittab 文件中设置的。getty 的条目可能类似于 列表 3。
此列表中需要注意的重要事项是,agetty 程序在从 tty1 到 tty6 的每个 tty 设备上运行。因此,在系统启动时,总共有六个 getty 正在运行,允许您登录到 VT 1 到 6。那么 VT 7 及更高版本呢?它们仍然可以以任何方式使用吗?如果您重新映射了键盘——尝试按下 keypad_7——或者,按下 alt-f7——看看会发生什么。一般来说,屏幕是空白的,光标位于左上角。您可以在键盘上键入,输出会显示在屏幕上。尽管如此,仍然无法在此终端上执行程序。您无法登录的终端用途不大。但是,对于此语句有两个重要的例外。
需要注意的第一个例外是,当 X Window 系统启动时,它会显示在第一个未使用的 tty 上——一个没有在其上运行 getty 的 tty。由于前六个 tty 在其上运行 getty,因此在上面的示例中,X 将在 tty 7 上启动。现在我们知道了伟大谜题“那么 X 在哪里?”的答案,当您从 X 切换到控制台时。在 X 中按 crtl-alt-f1 会将您切换到 VT 1。如果您想返回 X,只需
如果您已将其映射到 Last_Console keysym,请按 keypad_0。
按 keypad_7 切换到 X 正在其上运行的 VT 7。
按 alt-f7 切换到 VT 7。
需要注意的另一个例外是,虽然您无法在未登录的情况下在 VT 上运行程序,但您仍然可以将输出发送到那里。作为一个简单的实验,尝试以下操作
$ echo "This is a test" > /dev/tty7
切换到 VT 7,您将看到显示“This is a test”字样。此功能在系统日志记录中变得有用。在不详细讨论系统日志记录和配置的情况下,值得注意的是,所有日志记录工具的输出都可以“转储”到未使用的 VT,这允许快速浏览诸如登录、内核消息、邮件日志记录等事件。为此,只需将以下行添加到 /etc/syslog.conf 文件(以 root 用户身份登录后)
# this one will log ALL messages to the #/dev/tty9 terminal since this is an unused # terminal at the moment. This way, we # don't need to hang a getty on it or take up # a lot of system resources. *.* /dev/tty9
一旦您将此节添加到 /etc/syslog.conf,您需要杀死并重新启动 syslog 守护程序,或者向其发送 HUP(挂断)信号。由于后一种方法相当容易,让我们这样做
$ ps -x | grep syslog 28 ? S 0:01 /usr/sbin/syslogd
将输出 syslog 守护程序的 PID(进程 ID 号),在本例中为 28。现在,只需键入
$ kill -HUP 28
其中 28 是 PID 号。syslog 守护程序将重新读取其初始化文件。从现在开始,发生的所有日志记录(无论其来源如何)都将输出到 tty9(或您指定的任何 tty 设备)。
切换到 VT 9,您可能会看到如下内容
Jul 1 10:11:37 FiskHaus kernel: Max size:342694 Log zone size:2048 Jul 1 10:11:38 FiskHaus kernel: First datazone:68 Root inode number 139264 Jul 1 10:11:38 FiskHaus kernel: ISO9660 Extensions: RRIP_1991A Jul 1 12:21:50 FiskHaus login: ROOT LOGIN ON tty2 Jul 1 17:26:56 FiskHaus login: 1 LOGIN FAILURE ON tty5, fiskjm
前三行表示安装 CD 时发生的内核消息。login 程序以及登录失败会记录 root 登录——在最后一种情况下,我故意输入了错误的密码。
所有这些日志记录的价值可能不会立即显现出来,但如果您曾经注意到您的机器正在疯狂地颠簸和交换,或者,当您在线时,当您没有做任何事情时,您的硬盘驱动器指示灯开始亮起——快速切换到 VT 9 通常可以让您了解正在发生的事情。这些说明应该可以帮助您入门。loadkeys、showkey 和 keytables 的手册页对密钥映射有更完整的技术描述。此外,kbd 软件包在其 /doc 子目录中附带了大量有用的文档。最后,不要忘记 Keyboard-HOWTO,它可以在越来越多的 Linux HOWTO 中找到 http://www.ssc.com/linux/howto.html)。
John Fisk (fiskjm@ctrvax.vanderbilt.edu) 在范德比尔特大学医疗中心担任普通外科住院医师和研究员三年后,他决定“挂起听诊器”,追求医疗信息管理事业。他目前是中田纳西州立大学的全日制学生,正在攻读计算机科学研究生学位,然后进入医疗信息学研究员职位。在他为数不多的空闲时间里,他和他的妻子 Faith 喜欢在田纳西州美丽的 Great Smoky Mountains 远足和露营。自从一年半前首次安装 Slackware 2.0.0 以来,他一直是狂热的 Linux 粉丝