Virtual Consoles are a key feature of Linux (and FreeBSD etc) and possibly the most undersold feature of the whole operating system. You get the same effect as a screenful of xterms, without running up a X11 server!
When the any Unix system first boots up, you get a normal
Unix login: prompt, so you can log in, and start X11 or do
whatever else you would do with a single Unix shell.
Linux is pretty much the same, except that instead of just
one such login:, you get several. These are accessed using the
2-key combinations <ALT><F1>,
<ALT><F2>,
<ALT><F3> etc.
Each of the "screens" with you see is known as a "Virtual Console".
Apart from the fact that you use the same screen and keyboard, each virtual console is quite independant of the others. It's a lot like having several VT100-terminals connected (except that it's much easier to switch between them). This point is emphasised by the fact that each console has it's own CAPS LOCK, NUM LOCK and SCROLL LOCK states, and this is reflected in the LED's too.
Try it: if you set CAPS LOCK on in one console, and then switch to another, the led goes out, and you're back to lower case. When you switch back, presto, you're back in CAPS LOCK mode.
Virtual Consoles have one feature which you just can't get on a regular VT100 terminal: mouse support.
Most Linux systems come bundled with a program called gpm
This allows you to copy and paste text within a console, and even
between different consoles. By default, the buttons are usually
set up to mimic those of an Xterm.
(Left=select, Middle=paste, Right=adjust).
The gpm program used to be called "selection".
The problem with having a program like gpm which reads the mouse-device, is that you cannot have more than one such program running at a time. So if, for example, you are running gpm, and want to run X11 (which also reads the mouse device), you are in trouble. Or rather, you used to be in trouble.
The current release of gpm supports a Repeater Mode where it will write
mouse-data to a named pipe, /dev/gpmdata in addition to
it's normal operation. Any other program, such as an X11 server,
can be read this pipe as if it were a regular mouse-device.
To utilise this feature, you should:
"Pointer"
section your XF86config:
Protocol "MouseSystems" Device "/dev/gpmdata"
Gpm also gives you one more important feature: Multiple Mode
the -M parameter.
This lets you can merge input
from multiple, different mouse devices.
This is particularly useful if you have a laptop computer with some exotic but frustrating pointing device, and want to connect a normal serial mouse whenever possible. Running gpm means you can do this without having to edit config files every time you change pointers.
The combination of gpm and virtual consoles is very much like having a X11-server and an number of xterms - so much so that you may not want to start up X11 at all!
The only problem with having a lot of virtual consoles is that you can get lost. There are two things I like to do to distinguish virtual consoles.
The login message consists of a banner which put up by the
getty program (or mgetty or
agetty etc), plus the login-prompt supplied by the
login program.
The banner which is supplied by getty consists of the
contents of the file /etc/issue.
This file may also contain "escapes". These allow us to include
some variable-text in the /etc/issue file, such
as the hostname, or (you guessed it) the tty name.
If you are using agetty,
use \l to insert the tty name.
If you are using mgetty,
use @L to insert the tty name.
For example, you /etc/issue file make look like this:
Welcome to \l on \n
See the man page for your getty program for details of
escapes which may be used in /etc/issue
The linux console also supports escape sequences for rendering
color text. These are used by the command ls --color
These escape sequences are common to both linux consoles and
(color) xterms, so we can use the same prompt for both environments.
The complete range of escape sequences supported by the console
is described in the man page console_codes(4)
The following line, when included in, say, /etc/csh.cshrc
will set a color-prompt for the tcsh:
set prompt = "%{\e[0;3${tty:s/tty//:s/p//}m%}%n@%m %C2 %\! %#%{\e[0;0m%} "
However, for the sake of completeness, we'll include some provision for
xterm-escapes, too.
if ( $?tcsh ) then
if ($term == xterm ) then
set xterm_hdr = '\e]2\;%m:%/\a\e]1\;%c\a'
else
set xterm_hdr
endif
set color_s = "\e[0;3${tty:s/tty//:s/p//}m"
set color_e = '\e[0;0m'
set prompt = "%{$xterm_hdr$color_s%}%n@%m %C2 %\! %#%{$color_e%} "
unset xterm_hdr color_s color_e
endif
Similarly, for bash, you can use the following in
~/.bashrc
if [ "$BASH" != "" ]; then
if [ "$TERM" == "xterm" ]; then
XTERM_HDR='\e]2;\h:\w\a\e]1;\W\a'
else
XTERM_HDR=''
fi
TTY="`tty`"
COLOR_S="\e[0;3${TTY/*[^0-9]/}m"
COLOR_E='\e[0;0m'
PS1="\[$XTERM_HDR$COLOR_S\]\u@\h \w \\! \\$\[$COLOR_E\] "
unset XTERM_HDR COLOR_S COLOR_E
fi
So far, we've only considered virtual consoles as being additional login terminals. By default, this is the way they are setup. In fact, virtual consoles can be used for other things, too.
One of the best uses for spare virtual consoles is to display system messages. The Unix system generates quite an array of possible messages, most of which are sent to the syslog facility. These messages may be anything from a simple information message that a particular kernel-module is being loaded or unloaded, to important notices, such as "the system is going down".
The syslog is handled by a deamon, syslogd which
controls the distribution of these messages based on their facility
and priority. The syslogd reads the file
/etc/syslog.conf to determine how to distribute these messages.
The priority is an indication of the "urgency" of a message. The following eight priorities are defined (in order of priority):
emerg or panic
alert
crit
error or err
warning or warn
notice
info
debug
syslogd generally treats priorities as meaning
"equal or greater than" the stated priority. Consider the
/etc/syslog.conf
entry:
*.error /var/log/error.log
This will log messages from all facilities which have a priority of
error or greater to the file /var/log/error.log
If we wanted only the messages with priority error (and not the higher priority messages), we could specify:
*.=error /var/log/error.log
The "facility" of a message is a means of categorising messages, so that we can divide them into "broad areas of interest". The following facilities are defined:
auth
authpriv
cron
daemon
kern
lpr
mail
news
security
syslog
user
uucp
local0
local1
local2
local3
local4
local5
local6
local7
Facilities are specified explicity. There is no "heirarchy" of facilities, like there is for priorities. ie
mail.warning /dev/tty10
refers to messages of priority warning or higher,
but only for the facility mail, and no others.
/etc/syslog.conf fileIt is quite simple to divide our different syslog messages amongst a
number of different, otherwise unused, virtual consoles.
I like to use tty9-tty12 for this purpose, as it doesn't interfer
with my normal "login" consoles on tty1-tty6, or the default X11 console, tty7
Note also, that directing messages towards virtual consoles does not
divert these messages away from log files. The syslogd lets you
direct messages as many (multiple) destinations as you ,like.
Here's an example of some useful additions to your default
/etc/syslog.conf:
daemon.info /dev/tty9 kern.info /dev/tty10 *.info;daemon.none;kern.none;auth.none;authpriv.none \ /dev/tty11
Don't forget to 'kill -1' your syslogd after changing
syslog.conf
I have been told that, when directing syslog output directly to
a tty like this, that pressing ^S or Scroll Lock
in the tty can "block" the syslog daemon, and any daemons which
subscribe to the syslog service. I haven't had the problem myself,
probably because I rarely use Scroll Lock.
Caution is advised, particularly if your system is being used in a
multi-user role. Using tail -f logfile may be preferable,
although it would be more complex to set up.
You may notice that, by default, /var/log is not
world-readable. This is because log files can contain security-sensitive
information, especially if debugging is turned on.
One example of happens when you type an incorrect password during login.
This results is a message to the syslog, notifying of the bad login attempt,
and quoting the userid. If it just so happens that you've pressed Enter
once too often, you may end up entering your password in the userid field.
Some versions of login may log this faithfully - and your password inadvertently
ends up in a log file! Or, just as bad, in plain view on a virtual console!
So, convinient as it is to log messages to virtual consoles, it is important to be aware of what kind of information is openly visible on your virtual consoles. This applies particularly if your computer is being shared amongst several users, or is located anywhere other than a locked room.
Adding things like auth.none;authpriv.none (in the above example) allows
us to keep sensitive information out of plain sight. Likewise, it's best
not to display debug messages, unless you are actively debugging
your system.
Given that there are 8 "spare" facility categories (local0-7),
it would be nice if we could, for example, devote one virtual console to
the tcpd messages, and another to ppp mesages, etc.
Unfortunately, most programs are hard-wired to report their
messages to a specific facility (eg daemon). This means that
you would need to recompile the program in question in order to make it
use a different syslog facility.
By default, most Linux systems are set up to run only
getty or xdm processes on virtual consoles. There
is no technical reason why you can't run something else.
For example, if you just want to run top, so that it's always "there",
right from boot-up, you just have to modify your
/etc/inittab
to include a line like this:
5:2345:respawn:/bin/open -c 5 -w -- /usr/bin/top -s
Which will run top on tty5. Don't forget to 'kill -1'
the init process after modifying /etc/inittab.
Note in particular the use of the -s flag on top. This put top into "secure mode". This mode disables the interactive commands 'kill' and 'renice'. This makes it "safe" to run in this mode. Without the '-s' flag, anyone could walk up to the computer and use top to kill other people's processes.
The "secure mode" of top is just ideal for running top in this way.
The biggest problem starting processes from init (as we did the
above example) is that the process runs with the userid root.
This is not a problem for programs like getty, which are designed
to run as root, and top, which has a special mode for this case.
But what do we do when we want to run something that wasn't designed for this kind of thing? There is a solution, though it's not a pretty one.
Let's say that we want to run a lynx web-browser in the same way as we have done
with top.
Lynx does not have a "secure-mode". It can write files to the disk, and can even
spawn shells (using the ! keystroke).
One solution is to run lynx as another user (other than root) by using:
6:23:respawn:/bin/open -c 5 -w -- /bin/su nobody --command="/usr/bin/lynx http://www.luv.asn.au/"
This runs lynx as user "nobody", by executing it via the su program.
Even this may be considered "insecure", as lynx is capable of "escaping"
to an sh(1) shell (using the ! keystroke). Once an "unfriendly" has access to
a shell, they have a "foot in the door", and can hunt for any weak-spots in
your system's security.
The best solution is to isolate such "anonymous" users, in the same
way that the ftpd does with it's anonymous users. That is, by
using chroot to isolate them in a subdirectory.
First, we create a minimal directory tree where our program can run:
mkdir /home/sandpit mkdir /home/sandpit/bin cp /usr/bin/lynx /home/sandpit/bin cp /bin/su /home/sandpit/bin mkdir /home/sandpit/etc cat <<EOF > /home/sandpit/etc/passwd root:*:0:0:root:/root:/bin/bash lynxuser:*:65534:65534:lynxuser:/:/bin/lynx EOF cat <<EOF > /home/sandpit/etc/group root:*:0:root EOF cat <<EOF > /home/sandpit/etc/hosts 127.0.0.1 localhost EOF cat <<EOF > /home/sandpit/etc/host.conf order hosts EOF mkdir -p /home/sandpit/usr/lib/terminfo/l cp /usr/lib/terminfo/l/linux /home/sandpit/usr/lib/terminfo/l
Next we copy the files needed to run our program into our newly created directory tree, and set up the most restrictive permissions we can.
cp /etc/lynx.cfg /home/sandpit/etc mkdir /home/sandpit/lib cp /lib/ld-linux.so.1 /lib/libc.so.5 /home/sandpit/lib cp /lib/libm.so.5 /usr/lib/libslang.so.0.99.34 /home/sandpit/lib chown -R root.root /home/sandpit chmod -R go= /home/sandpit chmod a+x /home/sandpit /home/sandpit/* /home/sandpit/bin/* chmod a+r /home/sandpit/etc/* /home/sandpit/lib/* chmod -R a+rX /home/sandpit/usr
Note: you may require slightly different runtime libraries
for your particular version of lynx.
Now we can safely spawn a lynx browser from init, without compromising
our system security. Our inittab entry would look like this:
6:23:respawn:/bin/open -c 6 -w -- /usr/sbin/chroot /home/sandpit /bin/su lynxuser http://www.luv.asn.au/
open(1) commandIf you like the idea of virtual consoles, but do not like going through
the login process more than once, the open command if for you.
The open command starts a new shell on the next available
virtual console, without giving a login prompt first.
This is not a security risk, as you have to login before you can use the
open command in the first place.
The only complication arises from what is considered the "next available"
virtual console. If a getty is being run on a console, it is unavailable.
Likewise, if you are logging syslog messages to a console, it is also
unavailable. So, if you are using the open command a lot,
you may wish to disable some of the getty processes in your
/etc/inittab file.
(Note: I had to start both top and lynx
by way of the open command,
since they had a tendancy to use the wrong tty if I just ran them
directly from init)
A number of different fonts are available for virtual consoles, and these are to be found in the directory:
/usr/share/consolefonts -- or -- /usr/lib/kbd/consolefonts
and are invoked by the program:
setfont
Note that there some fonts have different pixel dimensions.
If you are running in EXTENDED VGA mode (ie by using the
boot paramter "vga=2"), you will get an 8x8 font (which has quite
ugly descenders).
A better option is to use some of the SVGA modes that your video
card may support. First, you should boot your system, specifying
vga=ask. Then try the different modes one by one,
until you find one that suits you.
After booting up in a particular mode, you may want to "save" that mode by using the command:
restoretextmode -w COLSxROWS
This will save the parameters of the current video mode in the
file named COLSxROWS, such that you can switch back to that mode
without rebooting, by using:
restoretextmode -r COLSxROWS
You will still have to go through the boot-it-and-see process at least once for each video mode.
Once you have a suitable set of video mode files, named according
to the COLSxROWS convention, you can use the
command:
resizecons COLSxROWS
This will invoke restoretextmode and
invoke the appropriate stty command to ensure that the
tty driver is "aware" of the new size. (Try changing from an
80-column mode to an 132-column mode using just restoretextmode,
and you'll see what I mean).
The default keyboard map in the Linux console is defined by the file:
/usr/src/linux/drivers/char/defkeymap.mapHowever, it is not necessary (or desirable) to edit this file directly.
If you want to load a completely new map (such as a dvorak keymap) you only have to use the command:
loadkeymap /usr/share/keytables/dvorak.map
There are numerous different keymaps already available, including
all the common European ones. Use the dumpkeys command to view
the current keyboard map.
If you just want to change a few keys, you should use the command
loadkeys
For example, if you have a 104-key keyboard, you will have the special "windows" keys. You can put these to good use, by mapping them onto special functions.
loadkeys - << EOF keycode 125 = Decr_Console # Left ~# key keycode 126 = Incr_Console # Right ~# key EOF
This will remap the left and right "windows" keys, such that
they will step through the range of virtual consoles which
have been activated. To find out what the keycodes are for
any given key, use the command showkey
The other situation you may encounter is that you have some keys on your keyboard which do not generate a keycode when pressed. For example, I have a "multimedia" keyboard, which has 12 rubber buttons in addition to the 104-keys. With the default keyboard mapping, these do not generate keycodes at all. We can assign them keycodes, but first we have to find out what codes the keyboard is sending out. This is done using the command:
showkey -s
This will tell us the "scancodes" generated by our unmapped keys. Each key generates a one- or two-byte scancode when it is pressed. When the key is released, it sends the same code, but with the most significant bit set (for two-byte codes, the MSB is set on the second byte).
Next, we have to assign the scancode to a keycode. This is done
using the command setkeycodes. This requires some care,
as it is not obvious which keycodes are actually free for use.
You can get some idea by looking in the defkeymap.map
file. All the keycodes up to 83 are in use. Above that, some are
used, some aren't.
For my multimedia keyboard, I use the following command to set up the keycodes:
#!/bin/sh
#
# front<->back www Calculator Xfer
# alt-shift-tab e032 e021 e023
# 120 121 122
#
# |<< |>|| [] >>|
# e010 e022 e024 e019
# 92 93 94 95
#
# Coffee Menu Mute Vol- Vol+
# e07a e026 e020 e02e e030
# 123 124 89 90 91
#
setkeycodes e010 92 e019 95 e020 89 e021 121 \
e022 93 e023 122 e024 94 e026 124 \
e02e 90 e030 91 e032 120 e07a 123
Once I have assigned keycodes, I can map the keys to some of the special keyboard functions, or arbitrary characters or strings.
loadkeys - << EOF Alt ShiftL keycode 15 = Incr_Console Control Alt Shift keycode 15 = Decr_Console keycode 124 = Spawn_Console keycode 120 = Show_Memory keycode 121 = Show_State keycode 89 = F100 # Mute string F100 = " Mute " keycode 90 = Scroll_Forward # VolDown keycode 91 = Scroll_Backward # VolUp keycode 92 = Decr_Console # CdPrev keycode 93 = F104 # CdPlay string F104 = " CdPlay " keycode 94 = F105 # CdStop string F105 = " CdStop " keycode 90 = Scroll_Forward # VolDown keycode 91 = Scroll_Backward # VolUp keycode 92 = Decr_Console # CdPrev keycode 95 = Incr_Console # CdNext EOF
In this example, I have mapped some keys to special functions,
and some to strings. For a full description of the syntax, see the man page
keytables(5).
There is no convinient summary of what special keyboard functions are available. You need to look at:
spec_fn_table[] in the source file
/usr/src/linux/drivers/char/keyboard.c
dumpkeys
strings `which loadkeys`
This tells us the following special keyboard functions are available:
Bare_Num_Lock
Boot
Break
Caps_Lock
Caps_On
CapsShift
Shift, but also releases Caps_Lock
Compose
Console_n
<ALT><F1> <ALT><F2> etc
Decr_Console
-1
Incr_Console
+1
KeyboardSignal
kb: line in
/etc/inittab
Last_Console
Num_Lock
SAK
/usr/src/linux/drivers/char/tty_io.c
Scroll_Backward
<SHIFT><PageUp>)
Scroll_Forward
<SHIFT><PageDown>)
Scroll_Lock
Scroll Lock key
Shift_Lock
Caps_Lock, but more like the Shift_Lock
on a mechanical typewriter. It also shifts the numeric keys (where
as Caps_Lock doesn't).
Shift_Lock should be assigned to a shifted
key. It is activated by pressing
<Shift><Shift_Lock>
and is released by pressing <Shift_Lock>
Show_Memory
Show_Registers
Show_State
Spawn_Console
KeyboardSignal
VoidSymbol
The above is not a comprehensive guide to all possible keyboard mappings. It just covers some of the more exotic ones.
I had some trouble making sense of Shift_Lock.
There's probably more to it than the above brief note. I noticed
that Shift_Lock and Caps_Lock do not
co-operate: their results are additive. Shift_Lock does not
affect the Caps_Lock LED.
Virtual consoles under Linux have one more feature which you
should be aware of:
- the ability to place the keyboard leds under
software or kernel control.
By use of the ioctl() calls KDGETLED/KDSETLED
it is possible to arbitrarily control the keyboard leds
from within an application
Alternately, by use of the internal kernel function
register_leds() it is possible to use the keyboard leds
to monitor an arbitrary location in memory.
Unfortunately, direct manipulation of the keyboard leds by either of these methods defeats the normal operation of the leds in all of the virtual consoles.
Nevertheless, the benefits of this control may be worth the cost, especially if you rarely use CAPS_LOCK (like myself).
One example of such a program is the tleds program, which uses the keyboard leds to monitor network activity. The program comes in two flavors: tleds for running under the virtual consoles, and xtleds for running under X11 (additionally).
The tleds program is available from:
http://www.iki.fi/Jouni.Lohikoski/tleds.html
This document may be freely distributed.
The information contained in this document was correct at the time of writing, but may be out-of-date by the time you are reading it.
Author: George_Hansper@apana.org.au
Last modified: 8th July 1998