Where does the TERM environment variable default get set?

73,061

Solution 1

In lots of places, depending

On virtual terminals and real terminals, the TERM environment variable is set by the program that chains to login, and is inherited all of the way along to the interactive shell that executes once one has logged on. Where, precisely, this happens varies from system to system, and according to the kind of terminal.

real terminals

Real, serial, terminals can vary in type, according to what's at the other end of the wire. So conventionally the getty program is invoked with an argument that specifies the terminal type, or is passed the TERM program from a service manager's service configuration data.

  • On van Smoorenburg init systems, one can see this in /etc/inittab entries, which will read something along the lines of

    S0:3:respawn:/sbin/agetty ttyS0 9600 vt100-nav
    The last argument to agetty in that line, vt100-nav, is the terminal type set for /dev/ttyS0. So /etc/inittab is where to change the terminal type for real terminals on such systems.
  • On systemd systems, one used to be able to see this in the /usr/lib/systemd/system/[email protected] unit file (/lib/systemd/system/[email protected] on un-merged systems), which used to read

    Environment=TERM=vt100
    setting the TERM variable in the environment passed to agetty.
  • On the BSDs, init takes the terminal type from the third field of each terminal's entry in the /etc/ttys database, and sets TERM from that in the environment that it executes getty with. So /etc/ttys is where one changes the terminal type for real terminals on the BSDs.

systemd's variability

The [email protected] service unit file, or drop-in files that apply thereto, is where to change the terminal type for real terminals on systemd systems. Note that such a change applies to all terminal login services that employ this service unit template. (To change it for only individual terminals, one has to manually instantiate the template, or add drop-ins that only apply to instantiations.)

systemd has had at least four mechanisms during its lifetime for picking up the value of the TERM environment variable. At the time of first writing this answer, as can be seen, there was an Environment=TERM=something line in the template service unit files. At other times, the types linux and vt102 were hard-wired into the getty and serial-getty service unit files respectively. More recently, the environment variable has been inherited from process #1, which has set it in various ways.

As of 2020, the way that systemd decides what terminal type to specify in a service's TERM environment variable is quite complex, and not documented at all. The way to change it remains a drop-in configuration file with Environment=TERM=something. But where the default value originates from is quite variable. Subject to some fairly complex to explain rules that involve the TTYPath= settings of individual service units, it can be one of three values: a hardwired linux, a hardwired vt220 (no longer vt102), or the value of the TERM environment variable that process #1 inherited, usually from the kernel/bootstrap loader.

(Ironically, the getttyent() mechanism still exists in the GNU C library, and systemd could have re-used the /etc/ttys mechanism.)

kernel virtual terminals

Kernel virtual terminals, as you have noted, have a fixed type. Unlike NetBSD, which can vary the kernel virtual terminal type on the fly, Linux and the other BSDs have a single fixed terminal type implemented in the kernel's built-in terminal emulation program. On Linux, that type matches linux from the terminfo database. (FreeBSD's kernel terminal emulation since version 9 has been teken. Prior to version 9 it was cons25 OpenBSD's is pccon.)

  • On systems using mingetty or vc-get-tty (from the nosh package) the program "knows" that it can only be talking to a virtual terminal, and they hardwire the "known" virtual terminal types appropriate to the operating system that the program was compiled for.
  • On systemd systems, one used to be able to see this in the /usr/lib/systemd/system/[email protected] unit file (/lib/systemd/system/[email protected] on un-merged systems), which read

    Environment=TERM=linux
    setting the TERM variable in the environment passed to agetty.

For kernel virtual terminals, one does not change the terminal type. The terminal emulator program in the kernel doesn't change, after all. It is incorrect to change the type. In particular, this will screw up cursor/editing key CSI sequence recognition. The linux CSI sequences sent by the Linux kernel terminal emulator are different to the xterm or vt100 CSI sequences sent by GUI terminal emulator programs in DEC VT mode. (In fact, they are highly idiosyncratic and non-standard, and different both to all real terminals that I know of, and to pretty much all other software terminal emulators apart from the one built into Linux.)

GUI terminal emulators

Your GUI terminal emulator is one of many programs, from the SSH dæmon to screen, that uses pseudo-terminals. What the terminal type is depends from what terminal emulator program is running on the master side of the pseudo-terminal, and how it is configured. Most GUI terminal emulators will start the program on the slave side with a TERM variable whose value matches their terminal emulation on the master side. Programs like the SSH server will attempt to "pass through" the terminal type that is on the client end of the connection. Usually there is some menu or configuration option to choose amongst terminal emulations.

The gripping hand

The right way to detect colour capability is not to hardwire a list of terminal types in your script. There are an awful lot of terminal types that support colour.

The right way is to look at what termcap/terminfo says about your terminal type.

colour=0
if tput Co > /dev/null 2>&1
then
test "`tput Co`" -gt 2 && colour=1
elif tput colors > /dev/null 2>&1
then
test "`tput colors`" -gt 2 && colour=1
fi

Further reading

  • Jonathan de Boyne Pollard (2018). TERM. nosh Guide. Softwares.

Solution 2

Please see https://askubuntu.com/a/614714/398785 for my detailed answer on why I think TERM=xterm-color is the wrong approach and Ubuntu's .bashrc is obsolete. I recommend that you go with TERM=xterm-256color (which is the default since gnome-terminal 3.16, but also safe to use with older gnome-terminals), and adjust your .bashrc accordingly.

Share:
73,061

Related videos on Youtube

Andy Fusniak
Author by

Andy Fusniak

Updated on September 18, 2022

Comments

  • Andy Fusniak
    Andy Fusniak over 1 year

    When I open a terminal window with the GNOME Terminal emulator in the desktop GUI the shell TERM environment variable defaults to the value xterm.

    If I use CTL+ALT+F1 to switch to a console TTY window and echo $TERM the value is set to linux.

    My motivation for asking is that inside my ~/.bashrc file a variable is used to determine if a color shell is provided or just good old fashioned monochrome.

    # set a fancy prompt (non-color, unless we know we "want" color)
    case "$TERM" in
        xterm-color) color_prompt=yes;;
    esac
    

    In both the console shell and the Gnome Terminal emulator shell if I type

    export TERM=xterm-color
    source /.bashrc
    

    both shells change to color mode (something I'd like to have happen always in both).

    Where do the default TERM values get set please and where is the best place to change their defaults, if at all possible? There appears to be nothing in the terminal emulator GUI to select or set the default TERM value.

    I did consider just adding the line export TERM=xterm-color to the top of my ~/.bashrc file but my gut instinct tells this is not the best solution and my Google searches haven't yet led me to a good answer.

    I'm running Ubuntu 15.04 Desktop Edition (Debian Based).

  • IsaacS
    IsaacS about 7 years
    +1 for your link. Minor suggestion; the following sentence might be confusing (I first got an impression that you were saying that using .bashrc is obsolete). "Ubuntu's .bashrc is obsolete."
  • egmont
    egmont about 7 years
    @IsaacS Do you have any suggestion how to improve it? E.g. would replacing "obsolete" with "outdated" help?
  • thom_nic
    thom_nic about 7 years
    The following exists in the default .bashrc in Debian jessie: [ -x /usr/bin/tput ] && /usr/bin/tput setaf 1 >&/dev/null && color_prompt=yes. (ncurses 5.9)
  • thom_nic
    thom_nic about 7 years
    Also tput Co returns "unknown terminfo capability" in Jessie and Xenial. tput colors and tput setaf 1 both seem to work although I admit I do not understand why.
  • OrangeDog
    OrangeDog over 5 years
    It appears that xterm-256color causes htop to mess up its layout like this in Ubuntu 18.04.
  • egmont
    egmont over 5 years
    @OrangeDog In which terminal emulator? This question here and thus my response focuses on GNOME Terminal, whereas the page you linked shows Konsole. The bug looks like the terminal emulator doesn't yet support the REP escape sequence which ncurses started to use around that time. VTE (GNOME Terminal) had already added support for it in Ubuntu 18.04, chances are that Konsole had not. I suspect that your comment with the htop breakage is valid for Konsole but not for GNOME Terminal.
  • OrangeDog
    OrangeDog over 5 years
    @egmont can't speak for the original problem, but I get the same result with WSL's terminal (whatever that is).
  • JdeBP
    JdeBP about 4 years
    The clue is that I mentioned both terminfo and termcap. (-:
  • Arusekk
    Arusekk about 4 years
    Setting TERM in .bashrc is a wrong thing to do. See jdebp.eu./Softwares/nosh/guide/TERM.html#MIS-CONFIGURATION
  • Hibou57
    Hibou57 about 4 years
    “xterm-256color” does not exists in my /use/share/terminfo/xn, which causes me some troubles, so it is not always a good value.
  • Arusekk
    Arusekk almost 3 years
    @lessthanideal web.archive.org/web/20201109162759/http://jdebp.eu./Software‌​s/… archived on 2020-01-10, retrieved 2021-06-21
  • Michael Thompson
    Michael Thompson almost 3 years
    @Arusekk that works for me, thank you