Most of what you need to know about a server is written down in files. Config files say how a service is set up, and log files say what it did and what went wrong. Reading them quickly, without opening an editor, is one of the things you will do most.
By the end you can print a short file, page through a long one, look at just its start or end, and watch a log file as new lines arrive.
Printing a file with cat
cat prints a whole file to the screen:
$ cat app.conf
port=8080
host=0.0.0.0
log_level=info
The name comes from concatenate: give it several files and it prints them one after another, as if they were one.
$ cat app.conf extra.conf
port=8080
host=0.0.0.0
log_level=info
name=web
-n numbers the lines, which helps when an error message says "line 3":
$ cat -n app.conf
1 port=8080
2 host=0.0.0.0
3 log_level=info
cat is right for short files. On a file with thousands of lines, everything scrolls past and you see only the end. The errors you can expect:
$ cat nothere
cat: nothere: No such file or directory
$ cat /etc
cat: /etc: Is a directory
Only use cat on text. Programs and images are binary files, and printing one fills the screen with junk and can leave your terminal in a strange state. If that happens, type reset and press Enter.
Counting lines with wc
Before you open a file, it helps to know how big it is. wc (word count) counts lines, words and bytes; -l gives just the lines:
$ wc -l app.log
500 app.log
$ wc app.log
500 1500 9892 app.log
A file of 20 lines is fine for cat. A file of 500,000 lines is not.
Paging with less
less shows a file one screen at a time and lets you move around in it. It does not load the whole file first, so it opens huge logs quickly.
The Docker Ubuntu image does not include less. Install it first:
$ apt update && apt install -y less
Then open a file:
$ less app.log
The keys you need:
| Key | What it does |
|---|---|
| Space or f | Forward one screen |
| b | Back one screen |
| ↑ and ↓ | One line at a time |
| g and G | Jump to the start or the end |
| / then text | Search forward; n for the next match, N for the previous |
| q | Quit |
less -N app.log shows line numbers. less never changes the file, so you cannot damage anything with it. That makes it the safe way to look at a config file on a production server. man uses the same reader, so these keys work there too.
If less is missing and you cannot install it, more does a simpler job: Space to go forward and q to quit.
The start and the end: head and tail
Often you only want one end of a file. The start of a CSV file shows its column names. The end of a log shows what happened last.
head prints the first 10 lines, and tail the last 10. -n sets how many:
$ head -n 3 app.log
request 1 handled
request 2 handled
request 3 handled
$ tail -n 3 app.log
request 498 handled
request 499 handled
request 500 handled
tail -n +N is different: it prints from line N to the end. tail -n +498 app.log prints lines 498, 499 and 500.
To see a range in the middle, for example lines 100 to 105, take the first 105 lines and then the last 6 of those:
$ head -n 105 app.log | tail -n 6
request 100 handled
request 101 handled
request 102 handled
request 103 handled
request 104 handled
request 105 handled
The | sends what head prints into tail instead of to the screen. It is called a pipe, and the Pipes and text topic covers it.
Following a log as it grows
When a service is running, its log keeps growing. tail -f (follow) prints the last lines and then waits, printing each new line as it is written:
$ tail -f /var/log/app/app.log
2026-10-24 09:41:02 INFO request handled in 12 ms
2026-10-24 09:41:05 INFO request handled in 9 ms
2026-10-24 09:41:07 ERROR database connection refused
It keeps running until you press Ctrl+C. A common way to debug is to run tail -f on the log in one terminal, then make a request or restart the service in another, and watch what appears.
Logs are often rotated: when a log gets large or a day ends, it is renamed to something like app.log.1 and a new, empty app.log is started. Plain tail -f keeps following the old, renamed file and goes quiet. tail -F follows the name instead, and switches to the new file when it appears. On a server, tail -F is usually the one you want.
You can follow a log from inside less too. Press F to start following, and Ctrl+C to stop and scroll back through what arrived. Logs from services managed by systemd are read with journalctl, which the Services with systemd topic covers.
Tasks
Do these in your Linux shell. Start by creating a log with 500 lines. seq -f prints numbers into a line of text:
$ cd ~
$ seq -f "request %g handled" 1 500 > app.log
Task 1: Look at parts of a file
Using wc, head and tail, find:
- how many lines
app.loghas - its first 2 lines
- its last 4 lines
- line 250 on its own
Check your work
$ wc -l app.log
500 app.log
$ head -n 2 app.log
request 1 handled
request 2 handled
$ tail -n 4 app.log
request 497 handled
request 498 handled
request 499 handled
request 500 handled
$ head -n 250 app.log | tail -n 1
request 250 handled
For line 250, head -n 250 stops at line 250 and tail -n 1 keeps only that last line. If you used tail -n +250, you got line 250 and everything after it.
Task 2: Follow a growing log
Start something that writes a line to live.log every two seconds, twenty times, while you keep using the shell. The & at the end runs it in the background; the Processes topic explains this.
$ for i in $(seq 1 20); do echo "tick $i"; sleep 2; done >> live.log &
[1] 41
The number after [1] will differ. Now follow live.log, watch a few lines arrive, then stop following.
Check your work
$ tail -f live.log
tick 1
tick 2
tick 3
tick 4
tick 5
^C
A new tick line appears every two seconds. Ctrl+C stops tail, not the writer. Run tail -n 3 live.log a few seconds later and you will see the count has kept going. When the loop finishes, the shell prints a line starting with [1]+ Done.
If nothing new appears, check that you wrote >> live.log and that the name you follow matches exactly.
Quiz
1. You want to check the column names at the top of a CSV file with two million rows. Which command do you use, and which should you avoid?
Show answer
head -n 1 file.csv, or head for the first few rows. Avoid cat, which prints all two million rows to your screen.
2. You are on a server and users report errors right now. The service writes to /var/log/app/app.log. How do you see new lines as they are written, and how do you stop?
Show answer
tail -F /var/log/app/app.log, or tail -f. It prints the last lines and then each new one as it arrives. Press Ctrl+C to stop. -F keeps following if the log is rotated while you watch.
3. What is the difference between tail -n 5 app.log and tail -n +5 app.log?
Show answer
tail -n 5 prints the last 5 lines. tail -n +5 prints everything from line 5 to the end.
4. Inside less, how do you find the first line containing ERROR, jump to the next one, and leave?
Show answer
Type /ERROR and press Enter to jump to the first match. Press n for the next match. Press q to quit.