Linux tail Command: View the End of a File and Follow Logs
tail is a Linux command used to check the end part of a file. If run without options, it outputs the last 10 lines. You can specify the number of lines with -n and continuously monitor newly added logs with -f or -F.
It is particularly useful for quickly checking logs just before an issue occurs or for observing logs of a running service. In this article, we explain the basics of the syntax, methods of tracking considering log rotation, filtering, and monitoring multiple files using real examples.
tail Command
tail outputs the last part of text input. If no file is specified or - is used in place of a file, it reads from standard input. The default output unit is lines, and without any specific options, it displays the last 10 lines.
It is convenient for checking the end part of large log files without opening the entire file. However, tail is not a tool for analyzing or archiving logs; it is a tool for reading the end of a file and following its changes.
Basic Syntax and Usage
The basic syntax is as follows. Brackets indicate optional items and should not be included in the actual command.
tail [options] [file...]
For example, to check the last 10 lines of /var/log/app.log, execute the following.
tail /var/log/app.log
If you need the last 20 lines, specify the number of lines with the -n option.
tail -n 20 /var/log/app.log
You can write it briefly like -20, but in scripts and documents, the more readable format -n 20 is clearer.
How to print only the desired range
Print the last N lines
-n N prints N lines from the end of the file. It is used to check recent requests or errors over a certain range.
tail -n 50 access.log
If you want to read the output page by page, you can pipe it to less.
tail -n 500 access.log | less
Print from the Nth line to the end
Adding a plus sign before the number -n +N has a different meaning. Instead of printing the last N lines, it prints from the Nth line of the file to the end.
tail -n +2 data.csv
This example prints from the second row of a CSV file, excluding the first row, which is the header. It can be easily used when skipping the first row in a pipeline.
Output by bytes instead of rows
-c N outputs the last N bytes instead of rows. You can use suffixes like K or M.
tail -c 1K output.bin
-c +N outputs from the Nth byte to the end. If you cut by bytes, a multibyte character may be split in the middle, so it is usually safer to use -n for multibyte text.
Continuously view newly added logs
Continuously track the file opened with -f
-f first outputs the end of the file, then continues to show any new content added to the file. The default behavior follows the open file descriptor, making it suitable for situations where logs are continuously appended to the same file.
tail -f /var/log/app.log
To stop tracking, press Ctrl+C.
Handle log rotation with -F
In an operational environment, log files may change names and be replaced with new files after reaching a certain size or period. This is called log rotation. GNU tail's -F is equivalent to --follow=name --retry, which attempts to reopen based on the file name.
tail -F /var/log/app.log
Therefore, when observing commonly rotated service logs for a long time, -F is often more practical than -f. This behavior can be checked in the official GNU Coreutils tail documentation.
Viewing only new logs without existing content
If the last 10 lines of existing content are not needed when running -f, use -n 0 together. Only lines added after the command execution will be displayed.
tail -n 0 -f /var/log/app.log
Frequently used options
| Option | Function | Usage Examples |
|---|---|---|
-n N |
Print the last N lines | tail -n 100 app.log |
-n +N |
Print from the Nth line | tail -n +2 data.csv |
-c N |
Print the last N bytes | tail -c 2K data.bin |
-f |
Track additional content of an open file | Observe a single file being continuously written |
-F |
Track and retry based on file name | Observe rotated logs |
-s N |
Set the tracking check interval to N seconds | tail -f -s 2 app.log |
--pid=PID |
End tracking after the specified process ends | Use with batch job logs |
-q |
Hide file name headers | Handle multiple file outputs as one |
-v |
Always display file name headers | Clearly distinguish source files |
The detailed support range of options may vary depending on the operating system and the tail implementation. Especially when using -F and --pid in a script, it is recommended to check support on the target system with tail --help.
Practical Examples Useful for Checking Logs
Finding Only Recent Errors
First, read only the last 200 lines, then use grep to filter error strings to reduce the need to search through large old logs.
tail -n 200 app.log | grep 'ERROR'
To ignore case, use grep -i, and if line numbers are needed, use grep -n.
Continuously Viewing Only New Errors
If you want to follow rotated logs and see only the error lines, combine the commands as follows. GNU grep's --line-buffered helps reduce output delay in the pipe by passing each line immediately.
tail -F app.log | grep --line-buffered 'ERROR'
This method only narrows what is displayed on the screen and does not modify the original log. If you need multiple conditions or structured log analysis, it is better to consider dedicated log collection and search tools.
Viewing Multiple Log Files Simultaneously
You can specify multiple files with tail. In this case, a filename header is displayed so that you can tell which file the output comes from.
tail -F access.log error.log
To make the output for each file more distinct, add -v, and if the header is unnecessary, use -q.
End the trace when the process ends
In GNU tail, you can use --pid to stop following a file after a specific process has ended. In the following example, $! is the ID of the most recently executed background process in the shell.
some_command > build.log 2>&1 & tail --pid=$! -f build.log
Checking --pid works together with -f, and termination detection may not occur immediately. In automation, you should also separately check the command's exit code and log files.
The difference between -f and -F
| Category | -f |
-F |
|---|---|---|
| Tracking criteria | Basically, an open file descriptor | The specified file name |
| File replacement | Can continue to see the previously opened file | Open a new file created with the same name again |
| File temporarily absent | Generally difficult to continue tracking | Wait for it to reappear with the --retry action |
| Recommended situations | Short-term observation of files that are not replaced | Long-term observation of rotated service logs |
-F is not always better. In special cases where a process continues writing to an existing file whose name has changed, keeping the file open with -f can better show what is needed. The choice should be based on the log generation method and rotation policy.
When tail is not suitable
- Systemd journal: If logs are stored in the journal rather than as plain text files, use
journalctl -f. For specific services, you can narrow it down withjournalctl -f -u service_name. - Checking the beginning: For the first few lines of a file,
headis more straightforward. - Reading while moving: To check both past and new contents,
less +F filenamecan be convenient. Stop following with Ctrl+C, move up and down, and resume following with F. - Periodically Updating Command Results: If you want to repeatedly check the latest results of a command rather than additional parts of a file, using the Linux watch command is better suited for this purpose.
- Large-Scale Central Logs: If you need to search, aggregate, and alert on logs from multiple servers over a long period, a central logging system or observability tool is necessary.
Points to Consider in Permissions and Operating Environment
Permission Denied Errors
If you do not have read permission for the log file, a Permission denied error will occur. First, check the owner and permissions with ls -l filename, and safely request the necessary permissions from the administrator. Avoid indiscriminately widening permissions or prefixing every command with sudo.
Sensitive Log Output
Authentication tokens, session IDs, and personal information may be included in logs. Make sure sensitive values are not exposed in screen shares, terminal histories, or copied error messages. When sharing operational logs externally, extract only the necessary scope and anonymize sensitive values.
Frequently Asked Questions
How many lines does tail display by default?
If no option is specified, it displays the last 10 lines. If you need a different number, you can specify the number of lines after -n, for example tail -n 30 filename.
How do you stop tail -f?
Press Ctrl+C to stop the running trace and return to the shell prompt. This action does not delete or modify the log file.
Why don't I see new content after log rotation?
It may be because -f continues to track the descriptor of the file before it was replaced. Try using GNU tail -F filename to reopen the new file based on the filename. If it still doesn't show, you need to check the actual log path and the service's output settings.
Can tail be used on compressed log files?
tail does not automatically decompress compressed formats. You can decompress the entire compressed file and pass it through a pipe, but this may be inefficient for large files. For example, a gzip file can be checked with zcat archive.log.gz | tail -n 50.
Summary
To quickly check recent content, use tail filename, and to specify the number of lines, use tail -n N filename. To continuously view new logs, use -f, and if the file is replaced due to log rotation, it is recommended to use GNU tail's -F.
By connecting with grep, you can filter only the necessary messages, but be cautious of permissions and exposure of sensitive information. If you want to learn other basic tools as well, you can refer to List of frequently used commands in Linux.









