Signal9Signal9 — home
online
all lessons

LPIC-1 Essential Services: Localization, Mail Basics, and Printing

Intermediate30 min6 steps
What you'll learn
  • Set the system time zone and reason about how LANG, the LC_* categories, and LC_ALL override one another
  • Redirect local mail with /etc/aliases (and newaliases) or a personal ~/.forward, and read the mail queue
  • Submit, list, and remove print jobs in CUPS using both the System V and BSD command families
  • Avoid the three classic exam traps: forgetting newaliases, expecting LANG to beat LC_ALL, and mixing the two print families
  1. Why "essential services" hang together

    Frame localization, mail, and printing as the three sysadmin chores every host eventually needs.

    LPIC-1 groups three unrelated-looking chores under "essential services" because every real server eventually has to do all three: tell time in the right time zone and language (localization), deliver mail that programs like cron and monitoring tools generate, and print (still true in offices, labs, and point-of-sale).

    Think of a freshly installed server as a new employee on their first day. Before they're useful you set their desk clock to the local time, tell them which language to file reports in, point their inbox at the right person, and show them where the printer is. That's localization, mail aliasing, and CUPS — exactly this lesson.

    The exam doesn't test deep theory here; it tests whether you know the one command that makes a change take effect and the override order when settings conflict. Those are precisely where people lose easy points.

  2. Localization: time zone and the zoneinfo database

    Set the system time zone and know where the zone data lives.

    A server logs events in its local time zone, so getting the zone wrong corrupts every timestamp in correlation and forensics. On a systemd host, timedatectl is the single tool that reads and writes the clock, the zone, and NTP sync status.

    The list of valid zones isn't magic — it's a directory of files under `/usr/share/zoneinfo`, organized as Region/City (for example America/New_York, Europe/London). Setting a zone just points /etc/localtime at the matching file in that tree.

    timedatectl
                   Local time: Tue 2026-06-23 14:02:10 UTC
               Universal time: Tue 2026-06-23 14:02:10 UTC
                     RTC time: Tue 2026-06-23 14:02:10
                    Time zone: Etc/UTC (UTC, +0000)
    System clock synchronized: yes
                  NTP service: active
    Run with no arguments, timedatectl prints the full clock report. The `Time zone:` line is the one to read first — here the host is on Etc/UTC. System clock synchronized: yes confirms NTP is keeping the clock accurate, which matters because a drifting clock breaks log correlation and TLS.
    sudo timedatectl set-timezone America/New_York
    set-timezone
    Point the system clock at a Region/City zone from /usr/share/zoneinfo and update /etc/localtime.
    set-time
    Manually set the wall-clock time (only works when NTP sync is off).
    set-ntp
    Turn automatic network time synchronization on or off (set-ntp true|false).
    Success is silent — no output means it worked. The argument must be an exact Region/City string that exists under /usr/share/zoneinfo; a typo like America/NewYork fails. Verify with timedatectl again and the Time zone: line will now read America/New_York.

    Check yourself

    Which directory holds the time-zone data files that timedatectl chooses from?

  3. Localization: LANG, the LC_* categories, and LC_ALL

    Master the locale override order — the single most testable point in localization.

    A locale controls language and cultural formatting: the language of messages, how dates and numbers are written, currency symbols, and sort order. Linux splits these into categories, each its own variable: LC_TIME (date/time format), LC_NUMERIC (decimal point vs. comma), LC_MESSAGES (program-message language), LC_COLLATE (sort order), and more.

    Three levels decide what actually applies, and the override order is the whole point:

    • `LANG` is the default for every category. Set it alone and everything follows it.
    • An individual *`LC_** variable *overrides LANG`* for just its one category.
    • `LC_ALL` is the sledgehammer: it overrides LANG and every LC_* at once.

    Think of it as "house rule, room rule, fire alarm." LANG is the house rule everyone follows by default. An LC_TIME setting is a room rule that wins inside that one room. LC_ALL is the fire alarm — when it sounds, every other rule is ignored and everyone does the one thing it says.

    locale
    LANG=en_US.UTF-8
    LC_CTYPE="en_US.UTF-8"
    LC_NUMERIC="en_US.UTF-8"
    LC_TIME="en_US.UTF-8"
    LC_COLLATE="en_US.UTF-8"
    LC_MESSAGES="en_US.UTF-8"
    LC_ALL=
    locale with no arguments shows the effective value of every category. LANG is set and every LC_* is inheriting from it (shown in quotes). Crucially, `LC_ALL=` is empty — so nothing is overriding the rest. If LC_ALL had a value, every line above it would show that value instead, regardless of LANG.
    LANG=en_US.UTF-8 LC_TIME=de_DE.UTF-8 LC_ALL=fr_FR.UTF-8 locale
    LANG=en_US.UTF-8
    LC_CTYPE="fr_FR.UTF-8"
    LC_NUMERIC="fr_FR.UTF-8"
    LC_TIME="fr_FR.UTF-8"
    LC_COLLATE="fr_FR.UTF-8"
    LC_MESSAGES="fr_FR.UTF-8"
    LC_ALL=fr_FR.UTF-8
    This is the override order made visible. We asked for LANG=en_US, LC_TIME=de_DE, and LC_ALL=fr_FR all at once. The result: every category is `fr_FR`. LC_ALL won outright — even LC_TIME, which was explicitly set to German, is forced to French. LANG is shown unchanged but it has no effect while LC_ALL is set. Remove LC_ALL and LC_TIME would become German while the rest fall back to English.

    Check yourself

    LANG=en_US.UTF-8 and LC_ALL=de_DE.UTF-8 are both set. In which language do program messages appear?

  4. Mail basics: the MTA, /etc/aliases, and ~/.forward

    Redirect local mail two ways and know which one needs newaliases.

    A Mail Transfer Agent (MTA) — Postfix, sendmail, exim — is the daemon that delivers mail to local mailboxes and relays it onward to other servers. Even a headless box runs one, because cron, the system itself, and monitoring tools all send mail to root.

    Nobody wants to log in as root to read those, so you redirect mail. There are two mechanisms, and knowing who controls which is the exam's angle:

    • `/etc/aliases` — the administrator's system-wide map. Each line is name: target, e.g. root: webadmin. It redirects mail for any local recipient.
    • `~/.forward` — a file in a user's own home directory containing a destination address. A user forwards their own mail without needing root.

    Runnable in the netsvc-postfix-relay room — that room’s setup plants the files it reads

    grep -E '^(root|postmaster):' /etc/aliases
    postmaster: root
    root: webadmin
    -E
    Extended regular expressions, so the (a|b) alternation works without backslashes.
    The aliases file maps recipients to targets. Here mail to postmaster lands on root, and root's mail is then forwarded to webadmin — so a real human reads it. Aliases can chain (postmaster → root → webadmin) and a target can be a user, another alias, a file, or a |command pipe.

    Example — not runnable on your lab box

    sudo newaliases
    /etc/aliases: 14 aliases, longest 18 bytes, 210 bytes total
    newaliases recompiles /etc/aliases into /etc/aliases.db and reports how many aliases it processed. Now the changes are live. Run this every single time you touch the aliases file.

    For a single user, ~/.forward is simpler and needs no admin and no rebuild step. The user just drops a destination into the file in their home directory:

    echo 'webadmin@example.com' > ~/.forward
    This one line forwards all of the current user's incoming local mail to webadmin@example.com. No newaliases is needed — the MTA reads ~/.forward live at delivery time. To keep a local copy as well as forward, the file would list both \username (the backslash means "deliver locally") and the external address.

    Example — not runnable on your lab box

    mailq
    Mail queue is empty
    mailq (equivalently sendmail -bp) shows mail the MTA has accepted but not yet delivered — typically because the remote server is down. An empty queue is healthy. A growing queue means delivery is stalling and is worth investigating. The plain mail command, by contrast, reads your inbox and sends new messages.

    Check yourself

    You added 'root: webadmin' to /etc/aliases but root's mail still isn't reaching webadmin. What command did you most likely forget?

  5. Printing with CUPS: two command families

    Submit, list, and remove print jobs — and keep the System V and BSD commands straight.

    CUPS (the Common Unix Printing System) is the print service on modern Linux. It runs as a daemon, maintains a queue per printer, and accepts jobs over the network or locally.

    The twist that the exam loves: there are two parallel command sets that do the same things, inherited from Unix history:

    • System V family: lp (submit), lpstat (status), cancel (remove).
    • BSD family: lpr (submit), lpq (queue), lprm (remove).

    Think of them as two languages for the same office: "submit / status / cancel" vs. "lpr / lpq / lprm." Both reach the same CUPS queue; you just have to recognize either dialect — and not mix a verb from one family expecting the other's syntax.

    Adding and configuring printers is a separate, admin-only tool: `lpadmin`.

    Example — not runnable on your lab box

    sudo lpadmin -p office-laser -E -v ipp://printserver/printers/laser -m everywhere
    -p
    Name of the printer queue to create or modify (here, office-laser).
    -E
    Enable the printer and accept jobs immediately.
    -v
    Device URI — where CUPS sends the data (here an IPP network printer).
    -m
    Driver/PPD model; 'everywhere' uses driverless IPP.
    lpadmin is the administrative tool that creates and configures printers; success is silent. After this, office-laser exists as a queue that the lp/lpr commands can target. Ordinary users never need lpadmin — they just submit to a printer an admin already set up.

    Example — not runnable on your lab box

    lp -d office-laser report.pdf
    request id is office-laser-42 (1 file(s))
    -d
    Destination printer queue. Omit it and the job goes to the default printer.
    -n
    Number of copies (e.g. -n 3).
    lp (System V) submits report.pdf to the office-laser queue and prints the job id office-laser-42 — note that id, you'll need it to cancel. The BSD equivalent is lpr -P office-laser report.pdf (note -P, capital, instead of -d).

    Example — not runnable on your lab box

    lpstat -t
    scheduler is running
    system default destination: office-laser
    device for office-laser: ipp://printserver/printers/laser
    office-laser accepting requests since Tue 23 Jun 2026
    printer office-laser is idle.  enabled since Tue 23 Jun 2026
    office-laser-42 webadmin  4096  Tue 23 Jun 2026 02:11:00 PM
    -t
    Total status: scheduler state, default printer, every printer, and all queued jobs at once.
    -p
    Show printers and whether each is enabled.
    lpstat -t is the one-stop status view: the scheduler is up, office-laser is the default and accepting jobs, and job `office-laser-42` (owned by webadmin) is queued. The BSD equivalent for just the queue is lpq -P office-laser, which lists the same job in a simpler table.

    Example — not runnable on your lab box

    cancel office-laser-42
    cancel (System V) removes job office-laser-42 from the queue; success is silent. The BSD equivalent is lprm office-laser-42. Both delete the job — cancel/lprm are the remove pair, one per family.

    Check yourself

    Which command removes a queued print job in the BSD family (the counterpart to System V's cancel)?

  6. Try it in your live terminal

    Do it, don't just read it — these are safe, read-only commands on the real sandbox to your right.

    You have a real shell. These commands only read state — they change nothing — so run them freely and compare the output to what you learned above.

    timedatectl
    Read the current clock and time zone. Find the Time zone: line — that's the setting set-timezone would change.
    localectl status 2>/dev/null || locale
    Show the system locale. localectl status reports it on systemd hosts; if that tool isn't present the fallback locale lists every category and whether LC_ALL is set.
    locale
    List the effective value of LANG and every LC_* category. Confirm whether LC_ALL is empty — if it has a value, it is overriding everything above it.
    lpstat -t 2>/dev/null || echo 'CUPS not running'
    Show the CUPS scheduler, printers, and any queued jobs. If CUPS isn't installed or running on this sandbox, the fallback message prints instead — that's fine, the syntax is what matters.
Recap
  • Locale precedence is the whole game: *LC_ALL > individual LC_ > LANG.** LC_ALL ignores everything else, so leave it unset in normal config.
  • timedatectl set-timezone sets the zone; valid zones live under /usr/share/zoneinfo as Region/City.
  • Editing /etc/aliases does nothing until newaliases rebuilds the database; ~/.forward is per-user and needs no rebuild.
  • CUPS exposes two command families for the same actions — submit (lp/lpr), status (lpstat/lpq), remove (cancel/lprm) — and lp uses -d while lpr uses -P.
Command / setting → effect
Command or settingEffectWatch for
timedatectl set-timezone ZSet system time zone to zone ZZ must exist under /usr/share/zoneinfo
LANG / LC_* / LC_ALLLocale defaults / per-category / force-allLC_ALL overrides both LANG and every LC_*
edit /etc/aliases + newaliasesSystem-wide mail redirect (admin)No newaliases = change is silently ignored
~/.forwardPer-user mail forward (self-service)No rebuild needed; \user to also keep a local copy
mailqShow undelivered mail in the queueA growing queue = delivery is stalling
lp -d / lpr -PSubmit a print job (SysV / BSD)lp uses -d, lpr uses -P — don't swap them
lpstat/lpq, cancel/lprmShow queue / remove job (SysV / BSD)Same actions, two families — recognize both