A shared device needs a queue
◈ 9 cardsWhy printing is spooled rather than immediate; submit, inspect and cancel a job in both the System V and BSD command sets; and build a one-line command that prints computed text.
Why printing is not like displaying
When you cat a file, the output goes to your terminal, and your terminal is yours. A printer is not. It is one device shared by everyone on the system, it can serve one job at a time, and it is mechanically slow — seconds per page against microseconds per screen. If printing were immediate, two people printing at once would interleave their pages, and a long report would lock the device for everyone else.
So printing is spooled, and the model has five parts worth being able to state from memory:
- Every printer has a print queue.
- Each submission becomes a job with a job ID, which is how you refer to it afterwards.
- The system takes a temporary copy of your file at submission time. What prints is the file as it was when you submitted it.
- Jobs are served first come, first served.
- A background process — the printer daemon, historically
lpd— owns the queues, feeds the device and reports status. It runs without your involvement, which is what makes it a daemon.
Point 3 has a consequence people discover the hard way in both directions. You can edit or even delete the file immediately after submitting it — the queue is not holding a path, it is holding a copy. And you cannot fix a typo by editing the file after you notice it; the copy is already made, so you must cancel the job and submit again.
Two command families for one job
UNIX printing grew up twice, and both vocabularies survive. System V gives you lp, lpstat and cancel; BSD gives you lpr, lpq and lprm, plus lpc for printer control and lptest for a ripple-pattern test page. Contemporary Linux runs CUPS, which supplies both families as front ends to the same queues — so on your own machine either spelling works, and lpc largely does not exist. The exam can ask for either, and a question that says give both forms means exactly that.
Printing two copies of report.txt on the printer named spr, in both dialects:
$ lp -d spr -n 2 report.txt # System V: -d destination, -n copies
request id is spr-431 (1 file)
$ lpr -Pspr -#2 report.txt # BSD: -P printer, -# copies
Note the shapes. System V uses -d for the destination and separates the option from its argument; BSD uses -P and jams it up against the printer name. System V prints a request ID — spr-431, the queue name and the job number — and that string is what cancel wants. BSD is silent on success and you get the job number from lpq.
Checking and cancelling, in both dialects:
$ lpstat -p spr $ lpq -P spr
$ cancel spr-431 $ lprm 431
You may cancel only your own jobs — the superuser excepted. A bare lprm - removes all of your jobs from the queue, and lprm with no argument at all removes the currently active one, if it is yours.
Worked example — printing something that does not exist yet
Here is a request that looks trivial and is not: print your username followed by today's date. There is no file to print. Both lp and lpr take files, or standard input — they cannot be handed a shell variable, and there is no option that means "print this string".
Build the text, then pipe it. Take it a piece at a time:
$ whoami
student
$ date '+%B %d, %Y'
September 03, 2026
Command substitution — $(command) — replaces a command with its output, so both can go inside one quoted string:
$ echo "$(whoami) $(date '+%B %d, %Y')"
student September 03, 2026
The double quotes keep it one argument to echo; the single quotes inside protect the format string's spaces and its percent signs from the shell. Now the only step left is to send that line to the printer instead of the screen, and that is what a pipe does: A | B connects A's standard output to B's standard input, so lpr receives the text as though it were reading a file. (Module 1 introduced the notation on dmesg | grep; module 7 develops pipes and redirection properly.)
$ echo "$(whoami) $(date '+%B %d, %Y')" | lpr
Or | lp on a System V system, or | lp -d spr to name a printer. That is the whole answer, and every part of it is load-bearing: the username is obtained, not typed; the date is formatted, not raw; the two are joined into one line of text; and the text reaches the printer through standard input, because a printer command has no way to accept a string.
One rule to close on, and the textbook is emphatic about it: never send a non-text file to a printer. A binary interpreted as text produces page after page of garbage until the queue empties. The recovery is to switch the printer off, then cancel the job.