Learn › Linux Foundations › Special

Chapter 17. Special tools: true, false, : and script

Final test: Chapter 17, Special tools. Twenty-five objectives on a real Debian 12 server: true, false and the colon builtin on their own and with their exit status read, four gate lines built on them, a terminal session recorded by hand and ended with exit, five more made with -c, -a, -q, -e and no file name at all, and the reads that prove what is on them. Fifty minutes, graded from the commands you run and from the recordings you leave behind.

Chapter 17. Special tools

This chapter covers the following topics:

What you already know: Chapter 10 defined the exit status, the single number a command hands the shell when it finishes, and taught $?, && and ||. Chapter 5 taught cat, head, tail and the pager less. This chapter uses them to separate a command's result from what it prints. Then it shows how to record a terminal session, inspect the recording, and preserve the result of a failed command.

Objectives

After this chapter you can:

Use Start machine to open the shared Debian practice server. Its Terminal is a real shell. Run the commands there, inspect what it prints, and read the recordings you create. The output shown beside an exercise is a recorded example, not a report from your machine. Its date, terminal size, prompt and file sizes may differ. The prompt's colors and symbols can also differ from the older admin@server1 examples. Commands can change files on this machine. A reconnect may start a new shell, so use pwd to check where you are and cd ~ to return home. Paths beginning ~/recordings/ work from any directory; shorter recordings/ alternatives assume you are in /home/admin. The chapter assessment starts a separate fresh machine and checks its own commands and files automatically.

Pre-check 1 of 5: a command that does nothing

Five questions before the material. A wrong answer costs nothing: the explanation states the fact and names the section that teaches it.

Pre-check 2 of 5: the only thing false leaves behind

Pre-check 3 of 5: what a recorder is for

Pre-check 4 of 5: where a recording goes

Pre-check 5 of 5: a failure inside a recording

17.1 The recordings directory

The work in this chapter happens in one directory, ~/recordings. It holds a description of itself and three fixtures worth recording, and nothing else. Read the description first: it is the file ~/recordings/README.txt.

prompt: admin@server1:~$ answer: cat ~/recordings/README.txt ||| cat recordings/README.txt output: server1: the recordings directory ================================= This directory holds the terminal recordings you make in this chapter and the three small fixtures those recordings are made of.

status-report.sh prints three lines about the server. Always succeeds. fault-report.sh prints one line about a fault. Always fails. checklist.txt five lines of text, the file a recording reads out.

A recording is an ordinary text file. It holds every byte the screen showed while the recording was running, with one line of its own at the top and one at the bottom. Everything you record in this chapter belongs in this directory. hint: Section 17.1. The reading command from Chapter 5, then the path ~/recordings/README.txt.

Two programs, one text file, and an empty space for the recordings you are about to make. The two programs have fixed results: one always succeeds and one always fails, which is what makes every gate and every recorded status in this chapter knowable in advance.

17.2 Commands that only report: true and false

Chapter 10 established that every command hands the shell one number when it finishes, its exit status, and that 0 means success while any other number means a failure of some kind. Section 10.4 read that number with $?.

true prints nothing and finishes with status 0. false also prints nothing, but finishes with status 1. The shell can use that difference to choose which command to run next.

The operators in Chapter 10 look at nothing but the status. A command with a known status is therefore a fixed answer to attach an operator to, and that is why scripts use these two constantly.

Run true and watch what happens on the screen.

prompt: admin@server1:~$ answer: true output: hint: Section 17.2. The four-letter word that does no work and reports 0, alone on the line with no options and no arguments.

Nothing. No output, no error, no delay, and the prompt comes straight back. The command succeeded, and success on a Linux terminal is silent.

17.2 The command that always fails

Now the other one. Expect the same empty screen: a failing command is not a noisy one.

prompt: admin@server1:~$ answer: false output: hint: Section 17.2. The five-letter opposite of Exercise 17-2, alone on the line.

Also nothing. On the screen the two commands are identical. The difference is the number underneath, and Section 17.4 asks the shell for it.

17.2 Where true and false live

Chapter 8 taught type, which says what the shell will run for a name. The -a option shows every candidate, in the order the shell considers them.

prompt: admin@server1:~$ answer: type -a true output: true is a shell builtin true is /usr/bin/true true is /bin/true hint: Section 17.2. The Chapter 8 command that says what a name runs, the option -a for every candidate, then the name true.

Three answers for one name. The first is a builtin, a command the shell carries inside itself. The other two are programs on disk, and on Debian /bin is a link to /usr/bin, so those two lines name one file. The builtin comes first, so the builtin is what runs. The program on disk exists because other tools, find -exec among them, need a real file to run. false has the same two homes, and type -a false shows them.

History. true and false first appeared in Version 7 Unix, released in 1979. The manual page for script states that script itself appeared in 3.0BSD, the Berkeley Unix release of the same year.

17.3 The colon builtin

A single colon, :, is a command. It does nothing and succeeds, exactly like true. It is one character long, and it is what you will meet in other people's scripts as a placeholder: a line that has to hold a command but has no work to do. POSIX, the standard that says what a Unix command must do, calls it the null utility: perform no action, return the status 0.

prompt: admin@server1:~$ answer: : output: hint: Section 17.3. One colon, alone on the line, with nothing after it.

Silence again, and a new prompt. Nothing on this machine changed. The colon is a builtin only: there is no program called : on disk.

17.4 Reading the status: $?

Section 10.4 taught the rule this section depends on. $? holds the exit status of the last command that finished. Another command can replace that value, so read it before running one. We put echo $? after a semicolon on the same line in these examples to make that order easy to see. It can also be the next line if nothing else runs between them.

prompt: admin@server1:~$ answer: true; echo $? output: 0 hint: Section 17.4. The command that always succeeds, a semicolon, then echo and the variable $? from Section 10.4.

One digit. true printed nothing and handed back 0, and echo $? printed that number. This is the whole of what true does.

17.4 The status of false

The same line, aimed at the other command.

prompt: admin@server1:~$ answer: false; echo $? output: 1 hint: Section 17.4. The same shape as Exercise 17-6 with the failing command in front, then a semicolon and echo $?.

1, the number false exists to return. Any number that is not 0 means failure; false chooses the smallest one.

17.4 The status of the colon builtin

The same read once more, aimed at the colon.

prompt: admin@server1:~$ answer: : ; echo $? ||| :; echo $? output: 0 hint: Section 17.4. The colon from Exercise 17-5, a semicolon, then the same echo $? read.

0, the same as true. Two spellings of the same idea: do nothing, and report success while doing it.

17.5 Gates on an answer known in advance

Section 10.5 taught &&, which runs the next command only after a success, and Section 10.6 taught ||, which runs it only after a failure. With true and false in front of them the outcome of each line is fixed before you press Enter. The four lines below show each operator with nothing else able to affect the result. Two messages carry them: echo it worked behind the success operator, echo it failed behind the fallback.

prompt: admin@server1:~$ answer: true && echo it worked output: it worked hint: Section 17.5. The command that always succeeds, the success operator from Section 10.5, then echo it worked.

The success opened the gate and echo ran. && looks at the status of the command in front of it, sees 0, and lets the rest of the line through.

17.5 The gate that stays shut

The same line as Exercise 17-9, echo it worked and all, with the other command in front of it.

prompt: admin@server1:~$ answer: false && echo it worked output: hint: Section 17.5. The same line as Exercise 17-9, echo it worked and all, with the failing command in front of it.

Nothing printed. The status was 1, so && skipped echo. The whole line still finishes with a nonzero status, even though the shell prints no error message. Run false && echo it worked; echo $? as an optional probe if you want to see that status. It is not a separate scored exercise.

17.5 The fallback that fires

|| is the other way round: it runs the next command only when the one in front of it failed.

prompt: admin@server1:~$ answer: false || echo it failed output: it failed hint: Section 17.5. The command that always fails, the fallback operator from Section 10.6, then echo it failed.

The failure was caught and the message printed. This is how a script reacts to something going wrong without stopping.

17.5 The fallback with nothing to catch

Aim the fallback at the command that always succeeds. The line is the one from Exercise 17-11, echo it failed and all.

prompt: admin@server1:~$ answer: true || echo it failed output: hint: Section 17.5. The same line as Exercise 17-11, echo it failed and all, with the succeeding command in front of it.

Silence. The command in front succeeded, so there was nothing for || to react to and the rest of the line was skipped. Four lines, two operators, and every outcome known before you pressed Enter.

17.6 What this chapter records

The second half of the chapter records terminal sessions. A recording is worth reading only if something identifiable happened inside it, so ~/recordings holds two things worth recording. The first is ~/recordings/status-report.sh, a small program that reports on the server.

prompt: admin@server1:~$ answer: ~/recordings/status-report.sh ||| recordings/status-report.sh ||| ./recordings/status-report.sh output: status: web service running status: disk 42 percent used status: backup complete hint: Section 17.6. The path ~/recordings/status-report.sh, and nothing else.

Three lines, the same three every time, and the program succeeds. Remember the last line: status: backup complete is the line you will look for inside a recording later.

17.6 The checklist

The second thing worth recording is a plain text file, ~/recordings/checklist.txt.

prompt: admin@server1:~$ answer: cat ~/recordings/checklist.txt ||| cat recordings/checklist.txt output: server1 weekly checklist ======================== 1. run the status report 2. record the session to a file 3. keep the recording in ~/recordings hint: Section 17.6. The reading command from Chapter 5, then the path ~/recordings/checklist.txt.

Five lines, 145 bytes, fixed forever. Reading a file with cat puts its bytes on the screen, and anything on the screen during a recording is in the recording.

17.7 Recording a session: script

script writes a copy of terminal output to a file. You start it, work in the shell it opens, and end that shell. The recording then lets you inspect what appeared during the session and in what order. It can also retain sensitive output, so record only the named fixture here and review a recording before sharing it.

The file it writes is called a typescript. It is an ordinary file that cat, head, tail and less can read, though terminal control codes may make some recordings awkward to inspect. On another server, avoid entering secrets while recording and keep the file readable only by people allowed to see it.

How it captures a session is worth stating. script starts a second shell on a pseudo-terminal, a terminal made of software with script sitting behind it. Output sent by that shell towards the screen passes through script, which writes those bytes to the file.

That can include bytes you do not see. Control sequences color text, move the cursor and clear the screen; they can be written to the file too. The fixture programs here print plain text, but the shell prompt can add control codes. A recording is useful evidence, not a tamper-proof audit of every action or every secret entered.

Started with a file name and no options, script prints a message naming the file and then hands you a prompt inside the recording. The recording ends when that child shell ends. exit ends the child shell, returns you to your original prompt, and lets script write its closing line.

Predict what you will see after starting the recording: a new prompt or your original prompt with no change? Now start a recording into ~/recordings/session.log. Before moving to the next exercise, run ~/recordings/status-report.sh inside that recording, inspect its three output lines, then type exit once. Wait for Script done. and your original prompt. Do not type a second exit: at your original prompt it would close the outer shell. The ~/ path chooses the output file regardless of your current directory. If the terminal reconnects during this sequence, inspect ~/recordings/session.log before starting again so you do not overwrite useful evidence.

prompt: admin@server1:~$ answer: script ~/recordings/session.log ||| script recordings/session.log output: Script started, output log file is '/home/admin/recordings/session.log'. status: web service running status: disk 42 percent used status: backup complete Script done. hint: Section 17.7. The recorder, then the file it should write, ~/recordings/session.log.

The new prompt may look like your old one. The evidence of a finished recording is the Script done. message and the closing line in ~/recordings/session.log, which you can inspect with tail -n 1 ~/recordings/session.log. If it has no closing line yet, check whether you are still inside the child shell before typing anything else.

17.8 Recording one command: script -c

The -c option names the command to record. The recorder starts, runs that one command, and ends by itself, so there is nothing to exit from. This is the form to use when you know in advance what you want recorded.

The command goes in single quotes so the whole of it, spaces and all, reaches the recorder as one argument. The file to write comes last. Record ~/recordings/status-report.sh into ~/recordings/report.log.

prompt: admin@server1:~$ answer: script -c '~/recordings/status-report.sh' ~/recordings/report.log output: Script started, output log file is '/home/admin/recordings/report.log'. status: web service running status: disk 42 percent used status: backup complete Script done. hint: Section 17.8. The recorder, the option -c, the path ~/recordings/status-report.sh in single quotes, then the file ~/recordings/report.log.

Five lines. The first is the recorder announcing itself and naming the file it is writing, with the tilde already expanded to /home/admin by the shell. The middle three are the report, printed t

Practice Chapter 17. Special tools: true, false, : and script in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.