head prints the start of a file and tail prints the end. On servers, tail -f is the classic way to watch logs in real time while you reproduce a problem.

head: the first lines

head file.txt            # first 10 lines
head -n 25 file.txt      # first 25 lines
head -n -5 file.txt      # everything except the last 5 lines
head -c 100 file.bin     # first 100 bytes
head -n 3 *.csv          # several files, each with a ==> name <== header

Typical uses: peek at the header of a CSV or SQL dump, or check the first lines of a config.

zcat backup.sql.gz | head -n 30      # check a compressed dump without unpacking it

tail: the last lines

tail file.log              # last 10 lines
tail -n 100 file.log       # last 100 lines
tail -n +20 file.txt       # from line 20 to the end (skip the first 19)
tail -c 1K file.bin        # last 1 KiB

tail -n +2 is a common way to drop a header line:

tail -n +2 data.csv | sort

Follow a log live: tail -f

tail -f /var/log/nginx/error.log

tail keeps printing new lines as they’re written. Press Ctrl+C to stop. Start with more history:

tail -n 200 -f /var/log/nginx/access.log

-f vs -F

Log rotation renames the log file and creates a new one. tail -f follows the old file by its descriptor and goes quiet after rotation. tail -F follows the name: it notices the new file and reopens it.

tail -F /var/log/app/app.log

Use -F for anything that runs for a while.

Follow several logs at once

tail -F /var/log/nginx/access.log /var/log/nginx/error.log

Each block of output gets a ==> filename <== header.

Filter while following

tail -F /var/log/nginx/access.log | grep --line-buffered ' 500 '
tail -F /var/log/auth.log | grep --line-buffered 'Failed password'

--line-buffered makes grep print matches immediately instead of waiting to fill a buffer. See grep examples.

Stop when a process exits

tail -f --pid=12345 build.log

Logs in the systemd journal

Many services log to journald instead of files. The equivalent of tail -f is:

journalctl -u nginx -f
journalctl -u myapp -n 100 -f

For containers, use docker logs -f --tail 100 container. See journalctl and docker logs.

Extract a range of lines

Lines 100–120 of a file:

sed -n '100,120p' file
# or
head -n 120 file | tail -n 21

sed -n is clearer and stops reading at line 120 if you add 120q: sed -n '100,120p;120q' file.

less +F: follow with scrollback

less +F file follows the file like tail -f. Press Ctrl+C to stop following and scroll or search with /pattern. Press F to resume following. This is often nicer than tail -f when you need to look back. See less.

multitail and lnav

For heavy log work, look at:

  • lnav — merges, colours and lets you query multiple logs, including compressed ones.
  • multitail — several logs in split windows.

Both are in most distributions’ repositories.

Quick reference

Task Command
First N lines head -n N file
Last N lines tail -n N file
Skip first line tail -n +2 file
All but last N head -n -N file
Follow log tail -F file
Follow and filter tail -F f | grep --line-buffered x
Lines X–Y sed -n 'X,Yp' file
Follow a service journalctl -u name -f

Related: cat and Nginx logs.

  • Linux
  • Command Line
  • Logs