tail -n 20 prints the last twenty
tail reads a file from the end. By default it prints the
last ten lines, and the -n flag sets the count. So the
direct answer to the question is one command.
$ tail -n 20 /var/log/syslog
Oct 25 09:00:01 node-3 systemd[1]: Started Daily apt download.
Oct 25 09:00:01 node-3 systemd[1]: Started Daily apt upgrade.
Oct 25 09:00:02 node-3 kernel: [12345.678] eth0: link up
Oct 25 09:00:03 node-3 systemd[1]: Reloading.
Oct 25 09:00:04 node-3 kernel: [12345.679] eth0: link down
Oct 25 09:00:05 node-3 systemd[1]: Reloaded.
Oct 25 09:00:06 node-3 kernel: [12345.680] eth0: link up
Oct 25 09:00:07 node-3 systemd[1]: Started Daily apt download.
Oct 25 09:00:08 node-3 systemd[1]: Started Daily apt upgrade.
Oct 25 09:00:09 node-3 kernel: [12345.681] eth0: link up
Oct 25 09:00:10 node-3 systemd[1]: Reloading.
Oct 25 09:00:11 node-3 kernel: [12345.682] eth0: link down
Oct 25 09:00:12 node-3 systemd[1]: Reloaded.
Oct 25 09:00:13 node-3 kernel: [12345.683] eth0: link up
Oct 25 09:00:14 node-3 systemd[1]: Started Daily apt download.
Oct 25 09:00:15 node-3 systemd[1]: Started Daily apt upgrade.
Oct 25 09:00:16 node-3 kernel: [12345.684] eth0: link up
Oct 25 09:00:17 node-3 systemd[1]: Reloading.
Oct 25 09:00:18 node-3 kernel: [12345.685] eth0: link down
Oct 25 09:00:19 node-3 systemd[1]: Reloaded.
Twenty lines, the end of the file. The -n flag takes any
number, so tail -n 50 gives you the last fifty and
tail -n 200 the last two hundred. When you're debugging and
need context beyond the last ten, this is the flag.
I reach for this on the Kubernetes nodes I run. A node starts
misbehaving, and the first thing I want is the last twenty lines of the
kubelet log, not the whole thing. tail -n 20 tells me what
the node was doing right before it went sideways, in one line instead of a
scroll.
head -n 20 prints the first twenty
head is the mirror of tail. Where
tail reads from the end, head reads from the
start, the first ten lines by default. Same -n flag, same
behavior, opposite end of the file.
$ head -n 20 /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
Twenty lines, the start of the file. This is the command for the top
of a config, the header of a file, the first error in a log, without
reading the whole thing. Pair it with tail and you can
bracket a file. Need the first error and the last one? head -n
20 for the top, tail -n 20 for the bottom, and
you've got the whole story in two commands.
tail -n +N starts from a line
The -n flag has a second form, and the plus sign changes
everything. tail -n 20
counts back twenty from the end. tail -n +20 starts at line
twenty and prints to the end. Same flag, opposite meaning.
$ tail -n +100 /var/log/syslog
That prints from line 100 to the end of the file. The plus sign means
start here, not count back. It's the command for everything after a
point, which is exactly what you want when you know the interesting part
of a log started partway through.
This is the flag that makes tail more than a "last few
lines" tool. Combined with head, it turns into a way to
read any window of any file.
tail and head slice a window
Pipe tail into head and you can grab any
section of a file, not just the start or the end. tail -n +N
starts at a line, and head -n M keeps the first M lines of
what comes through.
$ tail -n +100 /var/log/syslog | head -n 20
That prints lines 100 through 119. tail starts at line
100 and sends everything after it, and head keeps only the
first twenty of that stream. The result is a clean window of the file, twenty lines in the middle,
and you never scroll.
This is the pattern behind a lot of log tooling. When you page through
a log in a tool and it shows you a slice, this is the mechanism under
the hood.
Which one to use, at a glance
Match what you need to the command.
| Command | What it does | Reach for it when |
tail -n 20 file | Prints the last twenty lines | You want the end of a log or file |
head -n 20 file | Prints the first twenty lines | You want the start of a file |
tail -n +100 file | Prints from line 100 to the end | You know the interesting part started partway through |
tail -n +100 file | head -n 20 | Prints lines 100 through 119 | You want a specific window in the middle of a file |
tail -f file | Follows the file as it grows | You want to watch a log live |
Verify it works
Run these and check the output against what you expect.
$ tail -n 20 /var/log/syslog
$ head -n 20 /etc/hostname
$ tail -n +5 /etc/hostname
$ tail -n +5 /etc/hostname | head -n 3
tail -n 20 prints the last twenty lines.
head -n 20 prints the first twenty. tail -n +5
starts at line five and prints to the end. The last one pipes that into
head -n 3, so you get lines five through seven. If each one
behaves as described, you've got it.
The honest caveat
There's one more flag worth knowing. tail -f doesn't just
print the end and stop. It keeps watching the file and prints new lines
as they're written, which is how you watch a log live while a service
writes to it. Press Ctrl+C to stop. It's the natural next
step once you're comfortable reading the end of a file.
And grep is the tool for when you know what you're
looking for instead of wanting a window of lines. It searches inside
files and prints only the matching lines. You don't need it to be
productive with tail and head, but it's the
command that comes up next when a specific problem asks for it.
One thing worth knowing. tail and head are
part of GNU coreutils, so they behave the same on every Linux box you'll
touch. Learn them once and they follow you.
The boring conclusion
Reading the end of a file is one command, tail -n 20,
and the whole family around it is just variations on the same idea.
head for the start, the plus sign to start from a line, and
a pipe to slice any window you want. Match the flag to the part of the
file you actually need.
What's the log you check every day that you still open the whole
way?
Frequently asked questions
How do I check the last 20 lines of a file in Linux?
Run tail -n 20 filename to print the last twenty lines.
The -n flag takes any number, so tail -n 50
prints the last fifty and tail -n 100 the last hundred.
What is the difference between tail -n 20 and tail -n +20?
tail -n 20 prints the last twenty lines, counting back
from the end. tail -n +20 prints from line 20 to the end,
starting at that line and going forward. The plus sign flips the meaning
from count back to start here.
How do I print the first 20 lines of a file?
Run head -n 20 filename to print the first twenty lines.
head is the mirror of tail, so
head -n 20 is the start of the file and tail -n
20 is the end.
How do I print lines 100 to 120 of a file?
Run tail -n +100 filename | head -n 20 to print lines
100 through 119. tail starts at line 100 and
head keeps the first twenty of what comes through.
How do I watch the last lines of a file as it grows?
Run tail -f filename to follow a file live, printing
new lines as they are written. Press Ctrl+C to stop. This
is how you watch a log as a service writes to it.
Resources
Two references cover everything in this article and the flags I left
out. Both are the primary sources, so what you read here matches what
the tools actually do.
This builds on how to read a file with cat, less, tail, and head. Next up is finding a file, which uses find and locate.